ngx-svg-graphics 2.0.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/ng-package.json +7 -0
  2. package/package.json +4 -21
  3. package/src/lib/components/arrows/arrow-between-boxes/arrow-between-boxes.component.css +0 -0
  4. package/src/lib/components/arrows/arrow-between-boxes/arrow-between-boxes.component.spec.ts +32 -0
  5. package/src/lib/components/arrows/arrow-between-boxes/arrow-between-boxes.component.svg +12 -0
  6. package/src/lib/components/arrows/arrow-between-boxes/arrow-between-boxes.component.ts +60 -0
  7. package/src/lib/components/arrows/arrow-between-elems/arrow-between-elems.component.css +0 -0
  8. package/src/lib/components/arrows/arrow-between-elems/arrow-between-elems.component.spec.ts +23 -0
  9. package/src/lib/components/arrows/arrow-between-elems/arrow-between-elems.component.svg +9 -0
  10. package/src/lib/components/arrows/arrow-between-elems/arrow-between-elems.component.ts +96 -0
  11. package/src/lib/components/arrows/arrow-between-points/arrow-between-points.component.css +0 -0
  12. package/src/lib/components/arrows/arrow-between-points/arrow-between-points.component.spec.ts +23 -0
  13. package/src/lib/components/arrows/arrow-between-points/arrow-between-points.component.svg +15 -0
  14. package/src/lib/components/arrows/arrow-between-points/arrow-between-points.component.ts +39 -0
  15. package/src/lib/components/draggable/draggable.component.css +0 -0
  16. package/src/lib/components/draggable/draggable.component.spec.ts +33 -0
  17. package/src/lib/components/draggable/draggable.component.svg +8 -0
  18. package/src/lib/components/draggable/draggable.component.ts +49 -0
  19. package/src/lib/components/rectangle/rectangle.component.css +0 -0
  20. package/src/lib/components/rectangle/rectangle.component.spec.ts +23 -0
  21. package/src/lib/components/rectangle/rectangle.component.svg +3 -0
  22. package/src/lib/components/rectangle/rectangle.component.ts +14 -0
  23. package/src/lib/components/text-area-svg/text-area-svg.component.css +0 -0
  24. package/src/lib/components/text-area-svg/text-area-svg.component.spec.ts +59 -0
  25. package/src/lib/components/text-area-svg/text-area-svg.component.svg +6 -0
  26. package/src/lib/components/text-area-svg/text-area-svg.component.ts +57 -0
  27. package/src/lib/models/arrow-style-configuration.ts +8 -0
  28. package/src/lib/models/bounding-box.ts +7 -0
  29. package/src/lib/models/dragger.spec.ts +9 -0
  30. package/src/lib/models/dragger.ts +54 -0
  31. package/{lib/models/identifiable.d.ts → src/lib/models/identifiable.ts} +1 -1
  32. package/src/lib/models/positionable.ts +8 -0
  33. package/src/lib/services/arrow-style-configuration.service.spec.ts +16 -0
  34. package/{lib/services/arrow-style-configuration.service.d.ts → src/lib/services/arrow-style-configuration.service.ts} +16 -7
  35. package/src/lib/services/svg-access.service.spec.ts +16 -0
  36. package/src/lib/services/svg-access.service.ts +35 -0
  37. package/src/lib/utils/path-layouter.spec.ts +7 -0
  38. package/src/lib/utils/path-layouter.ts +41 -0
  39. package/src/lib/utils/position-helper.spec.ts +140 -0
  40. package/src/lib/utils/position-helper.ts +45 -0
  41. package/src/lib/utils/text-distributor.spec.ts +96 -0
  42. package/src/lib/utils/text-distributor.ts +68 -0
  43. package/{public-api.d.ts → src/public-api.ts} +12 -5
  44. package/tsconfig.lib.json +15 -0
  45. package/tsconfig.lib.prod.json +11 -0
  46. package/tsconfig.spec.json +15 -0
  47. package/fesm2022/ngx-svg-graphics.mjs +0 -541
  48. package/fesm2022/ngx-svg-graphics.mjs.map +0 -1
  49. package/index.d.ts +0 -5
  50. package/lib/components/arrows/arrow-between-boxes/arrow-between-boxes.component.d.ts +0 -24
  51. package/lib/components/arrows/arrow-between-elems/arrow-between-elems.component.d.ts +0 -33
  52. package/lib/components/arrows/arrow-between-points/arrow-between-points.component.d.ts +0 -20
  53. package/lib/components/draggable/draggable.component.d.ts +0 -19
  54. package/lib/components/text-area-svg/text-area-svg.component.d.ts +0 -19
  55. package/lib/models/arrow-style-configuration.d.ts +0 -6
  56. package/lib/models/bounding-box.d.ts +0 -6
  57. package/lib/models/dragger.d.ts +0 -13
  58. package/lib/models/positionable.d.ts +0 -6
  59. package/lib/services/svg-access.service.d.ts +0 -13
  60. package/lib/utils/path-layouter.d.ts +0 -7
  61. package/lib/utils/position-helper.d.ts +0 -9
  62. package/lib/utils/text-distributor.d.ts +0 -7
@@ -0,0 +1,7 @@
1
+ {
2
+ "$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
3
+ "dest": "../../dist/svg-graphics",
4
+ "lib": {
5
+ "entryFile": "src/public-api.ts"
6
+ }
7
+ }
package/package.json CHANGED
@@ -1,14 +1,8 @@
1
1
  {
2
2
  "name": "ngx-svg-graphics",
3
- "version": "2.0.0",
3
+ "version": "2.1.0",
4
4
  "description": "Small svg library to link components or svg elements with arrows and allow to drag components.",
5
- "keywords": [
6
- "Drag",
7
- "Arrows",
8
- "SVG",
9
- "Angular",
10
- "EMF"
11
- ],
5
+ "keywords": ["Drag","Arrows", "SVG", "Angular", "EMF"],
12
6
  "author": {
13
7
  "name": "Susanne Göbel",
14
8
  "email": "goebel@uni-koblenz.de"
@@ -25,16 +19,5 @@
25
19
  "dependencies": {
26
20
  "tslib": "^2.3.0"
27
21
  },
28
- "sideEffects": false,
29
- "module": "fesm2022/ngx-svg-graphics.mjs",
30
- "typings": "index.d.ts",
31
- "exports": {
32
- "./package.json": {
33
- "default": "./package.json"
34
- },
35
- ".": {
36
- "types": "./index.d.ts",
37
- "default": "./fesm2022/ngx-svg-graphics.mjs"
38
- }
39
- }
40
- }
22
+ "sideEffects": false
23
+ }
@@ -0,0 +1,32 @@
1
+ import {ComponentFixture, TestBed} from '@angular/core/testing';
2
+
3
+ import {ArrowBetweenBoxesComponent} from './arrow-between-boxes.component';
4
+ import {NO_ERRORS_SCHEMA} from "@angular/core";
5
+ import {BoundingBox} from "../../../models/bounding-box";
6
+
7
+ describe('ArrowBetweenBoxesComponent', () => {
8
+ let component: ArrowBetweenBoxesComponent;
9
+ let fixture: ComponentFixture<ArrowBetweenBoxesComponent>;
10
+
11
+ beforeEach(async () => {
12
+ await TestBed.configureTestingModule({
13
+ imports: [ArrowBetweenBoxesComponent],
14
+ schemas: [NO_ERRORS_SCHEMA],
15
+ })
16
+ .compileComponents();
17
+
18
+ let start: BoundingBox = {x: 50, y: -20, w: 200, h: 80}
19
+ let end: BoundingBox = {x: 80, y: 20, w: 100, h: 200}
20
+
21
+ fixture = TestBed.createComponent(ArrowBetweenBoxesComponent);
22
+ component = fixture.componentInstance;
23
+ component.start = start
24
+ component.end = end
25
+ fixture.detectChanges();
26
+ });
27
+
28
+ it('should create', () => {
29
+ expect(component).toBeTruthy();
30
+ });
31
+
32
+ });
@@ -0,0 +1,12 @@
1
+ <svg:g>
2
+ <g arrow-between-points
3
+ [startX]="x1"
4
+ [startY]="y1"
5
+ [endX]="x2"
6
+ [endY]="y2"
7
+ [text]="text"
8
+ [arrowType]="arrowType"
9
+ [style]="style"
10
+ >
11
+ </g>
12
+ </svg:g>
@@ -0,0 +1,60 @@
1
+ import { AfterViewInit, ChangeDetectorRef, Component, Input, OnChanges,} from '@angular/core';
2
+ import { Point } from "@angular/cdk/drag-drop";
3
+ import {v4 as uuidv4} from "uuid";
4
+ import {BoundingBox} from "../../../models/bounding-box";
5
+ import {PathLayouter} from "../../../utils/path-layouter";
6
+ import {ArrowBetweenPointsComponent} from "../arrow-between-points/arrow-between-points.component";
7
+
8
+ @Component({
9
+ selector: '[arrow-between-boxes]',
10
+ templateUrl: './arrow-between-boxes.component.svg',
11
+ styleUrl: './arrow-between-boxes.component.css',
12
+ imports: [ArrowBetweenPointsComponent]
13
+ })
14
+ export class ArrowBetweenBoxesComponent implements OnChanges, AfterViewInit {
15
+ @Input() start!: BoundingBox;
16
+ @Input() end!: BoundingBox;
17
+ @Input() arrowType?: string;
18
+ @Input() text?: string;
19
+ @Input() style?: string;
20
+
21
+
22
+ x1: number = 0;
23
+ y1: number = 0;
24
+ x2: number = 5;
25
+ y2: number = 5;
26
+
27
+ id = uuidv4();
28
+
29
+ positioned= false;
30
+
31
+ constructor(
32
+ private cdr: ChangeDetectorRef,
33
+ ) {}
34
+
35
+ ngAfterViewInit() {
36
+ this.computePositions()
37
+ this.positioned = true;
38
+ this.cdr.detectChanges();
39
+ }
40
+
41
+ ngOnChanges() {
42
+ if(this.positioned) {
43
+ this.computePositions()
44
+ }
45
+ }
46
+
47
+
48
+ private computePositions() {
49
+ let res = PathLayouter.bestPoints(this.start, this.end);
50
+ this.applyBestPoints(res)
51
+ }
52
+
53
+ private applyBestPoints(res: Point[]) {
54
+ this.x1 = res[0].x;
55
+ this.y1 = res[0].y;
56
+ this.x2 = res[1].x;
57
+ this.y2 = res[1].y;
58
+ }
59
+
60
+ }
@@ -0,0 +1,23 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+
3
+ import { ArrowBetweenElemsComponent } from './arrow-between-elems.component';
4
+
5
+ describe('ArrowBetweenElemsComponent', () => {
6
+ let component: ArrowBetweenElemsComponent;
7
+ let fixture: ComponentFixture<ArrowBetweenElemsComponent>;
8
+
9
+ beforeEach(async () => {
10
+ await TestBed.configureTestingModule({
11
+ imports: [ArrowBetweenElemsComponent]
12
+ })
13
+ .compileComponents();
14
+
15
+ fixture = TestBed.createComponent(ArrowBetweenElemsComponent);
16
+ component = fixture.componentInstance;
17
+ fixture.detectChanges();
18
+ });
19
+
20
+ it('should create', () => {
21
+ expect(component).toBeTruthy();
22
+ });
23
+ });
@@ -0,0 +1,9 @@
1
+ <svg:g #arrow>
2
+ <g arrow-between-boxes *ngIf="start && end"
3
+ [start]="start"
4
+ [end]="end"
5
+ [arrowType]="arrowType"
6
+ [text]="text"
7
+ [style]="style">
8
+ </g>
9
+ ></svg:g>
@@ -0,0 +1,96 @@
1
+ import {
2
+ AfterViewInit,
3
+ ChangeDetectorRef,
4
+ Component, ElementRef,
5
+ Input, OnChanges, OnDestroy,
6
+ OnInit, SimpleChanges,
7
+ ViewChild
8
+ } from '@angular/core';
9
+ import {Observable, Subscription} from "rxjs";
10
+ import { NgIf } from '@angular/common';
11
+ import {BoundingBox} from "../../../models/bounding-box";
12
+ import {ArrowBetweenBoxesComponent} from "../arrow-between-boxes/arrow-between-boxes.component";
13
+ import {SVGAccessService} from "../../../services/svg-access.service";
14
+
15
+ @Component({
16
+ selector: '[arrowElems]',
17
+ templateUrl: './arrow-between-elems.component.svg',
18
+ styleUrl: './arrow-between-elems.component.css',
19
+ imports: [NgIf, ArrowBetweenBoxesComponent]
20
+ })
21
+ export class ArrowBetweenElemsComponent implements OnInit, AfterViewInit, OnChanges, OnDestroy {
22
+
23
+ @Input() startGID!: string;
24
+ @Input() startSuffix!: string;
25
+ @Input() endGID!: string;
26
+ @Input() endSuffix!: string;
27
+ @Input() arrowType?: string;
28
+
29
+ @Input() breaks: BoundingBox[] = [];
30
+ @Input() text?: string;
31
+ @Input() style?: string; //todo move into ArrowStyleConfig?
32
+
33
+ startId!: string;
34
+ endId!: string;
35
+
36
+ start?: BoundingBox;
37
+ end?: BoundingBox;
38
+
39
+ positioned= false;
40
+ @ViewChild('arrow') node!: ElementRef<SVGGraphicsElement>;
41
+
42
+ changeNotifier: Observable<string>;
43
+ changeSubscription: Subscription;
44
+
45
+ //idea: compute the two input positions as relative to the current elem
46
+ constructor(
47
+ private svgAccessService: SVGAccessService,
48
+ private cdr: ChangeDetectorRef) {
49
+ this.changeNotifier = this.svgAccessService.listenToPositionChange()
50
+ this.changeSubscription = this.changeNotifier.subscribe(nextString => {
51
+ if (nextString == this.startGID || nextString == this.endGID) {
52
+ setTimeout(() => {
53
+ this.computePositionsByIds()
54
+ this.cdr.detectChanges()
55
+ }, 0)
56
+ }
57
+ })
58
+ }
59
+
60
+ ngOnInit() {
61
+ this.startId = this.startGID+this.startSuffix;
62
+ this.endId = this.endGID+this.endSuffix;
63
+ }
64
+
65
+ ngOnChanges(_: SimpleChanges) {
66
+ this.startId = this.startGID+this.startSuffix;
67
+ this.endId = this.endGID+this.endSuffix;
68
+ this.computePositionsByIds()
69
+ this.cdr.detectChanges()
70
+ }
71
+
72
+ ngAfterViewInit() {
73
+ this.positioned = true;
74
+ this.computePositionsByIds()
75
+ this.cdr.detectChanges()
76
+ }
77
+
78
+ private computePositionsByIds() {
79
+ if (this.node?.nativeElement){
80
+ let rel = this.node.nativeElement as SVGGraphicsElement
81
+ let startOpt = this.svgAccessService.getRelativePosition(this.startId, rel)
82
+ if (startOpt) {
83
+ this.start = startOpt
84
+ }
85
+ let endOpt = this.svgAccessService.getRelativePosition(this.endId, rel)
86
+ if (endOpt) {
87
+ this.end = endOpt
88
+ }
89
+ } else console.log('No native element yet')
90
+ }
91
+
92
+ ngOnDestroy() {
93
+ this.changeSubscription.unsubscribe();
94
+ }
95
+
96
+ }
@@ -0,0 +1,23 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+
3
+ import { ArrowBetweenPointsComponent } from './arrow-between-points.component';
4
+
5
+ describe('ArrowBetweenPointsComponent', () => {
6
+ let component: ArrowBetweenPointsComponent;
7
+ let fixture: ComponentFixture<ArrowBetweenPointsComponent>;
8
+
9
+ beforeEach(async () => {
10
+ await TestBed.configureTestingModule({
11
+ imports: [ArrowBetweenPointsComponent]
12
+ })
13
+ .compileComponents();
14
+
15
+ fixture = TestBed.createComponent(ArrowBetweenPointsComponent);
16
+ component = fixture.componentInstance;
17
+ fixture.detectChanges();
18
+ });
19
+
20
+ it('should create', () => {
21
+ expect(component).toBeTruthy();
22
+ });
23
+ });
@@ -0,0 +1,15 @@
1
+ <svg:g>
2
+ <path [attr.id]="id+'-path'"
3
+ [attr.d]="'M '+startX+','+startY+' L '+endX+','+endY"
4
+ [attr.stroke]="arrowStyleConfiguration.color"
5
+ [attr.stroke-dasharray]="arrowStyleConfiguration.dashed"
6
+ [attr.marker-start]='"url(#"+arrowStyleConfiguration.startPointer+")"'
7
+ [attr.marker-end]='"url(#"+arrowStyleConfiguration.endPointer+")"'
8
+ style="{{style}}">
9
+ </path>
10
+ <text *ngIf="text">
11
+ <textPath [attr.href]="'#'+id+'-path'">
12
+ {{text}}
13
+ </textPath>
14
+ </text>
15
+ </svg:g>
@@ -0,0 +1,39 @@
1
+ import {Component, Input, OnChanges} from '@angular/core';
2
+ import {NgIf} from "@angular/common";
3
+ import {ArrowStyleConfigurationService} from "../../../services/arrow-style-configuration.service";
4
+ import {ArrowStyleConfiguration} from "../../../models/arrow-style-configuration";
5
+ import {v4 as uuidv4} from "uuid";
6
+
7
+ @Component({
8
+ selector: '[arrow-between-points]',
9
+ imports: [
10
+ NgIf
11
+ ],
12
+ templateUrl: './arrow-between-points.component.svg',
13
+ styleUrl: './arrow-between-points.component.css'
14
+ })
15
+ export class ArrowBetweenPointsComponent implements OnChanges {
16
+
17
+ @Input() startX!: number;
18
+ @Input() startY!: number;
19
+ @Input() endX!: number;
20
+ @Input() endY!: number;
21
+ @Input() text?: string;
22
+ @Input() style?: string;
23
+
24
+ @Input() arrowType?: string;
25
+
26
+ arrowStyleConfiguration: ArrowStyleConfiguration;
27
+ id = uuidv4();
28
+
29
+ constructor(
30
+ private arrowStyleConfigService: ArrowStyleConfigurationService,) {
31
+
32
+ this.arrowStyleConfiguration = this.arrowStyleConfigService.styleArrow()
33
+ }
34
+
35
+ ngOnChanges() {
36
+ this.arrowStyleConfiguration = this.arrowStyleConfigService.styleArrow(this.arrowType)
37
+ }
38
+
39
+ }
@@ -0,0 +1,33 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+
3
+ import { DraggableComponent } from './draggable.component';
4
+ import {Draggable} from "../../models/positionable";
5
+ import {SVGAccessService} from "../../services/svg-access.service";
6
+
7
+ describe('DraggableComponent', () => {
8
+ let example = {$gId: "id", position: { x: 1, y: 2, w: 2, h: 1 }};
9
+ let component: DraggableComponent<Draggable>;
10
+ let fixture: ComponentFixture<DraggableComponent<Draggable>>;
11
+
12
+ class DraggableTestComponent<T extends Draggable> extends DraggableComponent<T> {
13
+ constructor(svgAccessService: SVGAccessService) {
14
+ super(svgAccessService);
15
+ }
16
+ }
17
+
18
+ beforeEach(async () => {
19
+ await TestBed.configureTestingModule({
20
+ imports: [DraggableComponent]
21
+ })
22
+ .compileComponents();
23
+
24
+ fixture = TestBed.createComponent(DraggableTestComponent<Draggable>);
25
+ component = fixture.componentInstance;
26
+ component.elem = example;
27
+ fixture.detectChanges();
28
+ });
29
+
30
+ it('should create', () => {
31
+ expect(component).toBeTruthy();
32
+ });
33
+ });
@@ -0,0 +1,8 @@
1
+ <svg:g>
2
+ <g [attr.id]="elem.$gId"
3
+ (mousedown)="startDrag($event)"
4
+ (mousemove)="drag($event)"
5
+ (mouseup)="endDrag($event)"
6
+ (click)="clickElem($event)">
7
+ </g>
8
+ </svg:g>
@@ -0,0 +1,49 @@
1
+ import {AfterViewInit, Component, EventEmitter, Output} from '@angular/core';
2
+ import {SVGAccessService} from '../../services/svg-access.service';
3
+ import { Draggable } from '../../models/positionable';
4
+ import {Dragger} from "../../models/dragger";
5
+
6
+ @Component({
7
+ imports: [],
8
+ selector: '[draggable]',
9
+ templateUrl: './draggable.component.svg',
10
+ styleUrl: './draggable.component.css'
11
+ })
12
+ export abstract class DraggableComponent<T extends Draggable> implements AfterViewInit {
13
+
14
+ @Output() chooseElem = new EventEmitter<T>();
15
+ //the caller must initialize both required elements (elem and elementDragger) either in the constructor
16
+ // (or if they are inputs) in the ngOnInit life cycle hook
17
+ elem!: T;
18
+ elemDragger!: Dragger<T>;
19
+
20
+ protected constructor(
21
+ protected svgAccessService: SVGAccessService
22
+ ) {}
23
+
24
+
25
+ ngAfterViewInit() {
26
+ this.svgAccessService.notifyPositionChange(this.elem.$gId)
27
+ }
28
+
29
+ startDrag(event: MouseEvent) {
30
+ this.elemDragger.startDrag(event);
31
+ }
32
+
33
+ drag(event: MouseEvent) {
34
+ if (this.elemDragger.drag(event)) {
35
+ this.svgAccessService.notifyPositionChange(this.elem.$gId)
36
+ }
37
+ }
38
+
39
+ endDrag(event: MouseEvent) {
40
+ this.elemDragger.endDrag(event);
41
+ }
42
+
43
+ clickElem(event: MouseEvent) {
44
+ if (this.elemDragger.clickElem(event)) {
45
+ this.chooseElem.emit(this.elem);
46
+ }
47
+ }
48
+
49
+ }
@@ -0,0 +1,23 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+
3
+ import { RectangleComponent } from './rectangle.component';
4
+
5
+ describe('RectangleComponent', () => {
6
+ let component: RectangleComponent;
7
+ let fixture: ComponentFixture<RectangleComponent>;
8
+
9
+ beforeEach(async () => {
10
+ await TestBed.configureTestingModule({
11
+ imports: [RectangleComponent]
12
+ })
13
+ .compileComponents();
14
+
15
+ fixture = TestBed.createComponent(RectangleComponent);
16
+ component = fixture.componentInstance;
17
+ fixture.detectChanges();
18
+ });
19
+
20
+ it('should create', () => {
21
+ expect(component).toBeTruthy();
22
+ });
23
+ });
@@ -0,0 +1,3 @@
1
+ <svg:g>
2
+ <rect [attr.x]="position.x" [attr.y]="position.y" [attr.width]="position.w" [attr.height]="position.h" [attr.fill]="color"></rect>
3
+ </svg:g>
@@ -0,0 +1,14 @@
1
+ import {Component, Input} from '@angular/core';
2
+ import {BoundingBox} from "../../models/bounding-box";
3
+
4
+ @Component({
5
+ selector: '[rectangleG]',
6
+ imports: [],
7
+ templateUrl: './rectangle.component.svg',
8
+ styleUrl: './rectangle.component.css'
9
+ })
10
+ export class RectangleComponent {
11
+ @Input() position!: BoundingBox
12
+ @Input() color: string = '#ccffff';
13
+
14
+ }
@@ -0,0 +1,59 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+
3
+ import { TextAreaSvgComponent } from './text-area-svg.component';
4
+
5
+ describe('TextAreaSvgComponent', () => {
6
+ let component: TextAreaSvgComponent;
7
+ let fixture: ComponentFixture<TextAreaSvgComponent>;
8
+
9
+ beforeEach(async () => {
10
+ await TestBed.configureTestingModule({
11
+ imports: [TextAreaSvgComponent]
12
+ }).compileComponents();
13
+
14
+ fixture = TestBed.createComponent(TextAreaSvgComponent);
15
+ component = fixture.componentInstance;
16
+ fixture.detectChanges();
17
+ });
18
+
19
+ it('should create', () => {
20
+ expect(component).toBeTruthy();
21
+ });
22
+
23
+ function initializeDistributedText() {
24
+ component.x = 20
25
+ component.y = 40
26
+ component.h = 50
27
+ component.w = 200
28
+
29
+ }
30
+
31
+ function verifyDistributedText(text: string, distributedText: string[]) {
32
+ component.text = text;
33
+ component.distributeText()
34
+ expect(component.distributedText).toEqual(distributedText)
35
+ }
36
+
37
+ it('Should set a two line distributed text', () => {
38
+ initializeDistributedText();
39
+
40
+ verifyDistributedText(
41
+ 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam',
42
+ ['Lorem ipsum dolor sit', 'amet, consetetur ...']
43
+ )
44
+ })
45
+
46
+ it('Should set a short distributed text after setting a longer one', () => {
47
+ initializeDistributedText();
48
+
49
+ verifyDistributedText(
50
+ 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam',
51
+ ['Lorem ipsum dolor sit', 'amet, consetetur ...']
52
+ ) //first set two lines, next set a shorter one
53
+ verifyDistributedText(
54
+ 'Short',
55
+ ['Short']
56
+ )
57
+ })
58
+
59
+ });
@@ -0,0 +1,6 @@
1
+ <svg:text [attr.x]="x" [attr.y]="y" [attr.width]="w" [attr.height]="h" dy="0" [attr.style]="" (click)="handleClick()">
2
+ <tspan dy="1.2em" [attr.x]="x" *ngFor="let line of distributedText">{{line}}</tspan>
3
+ </svg:text>
4
+ <svg:foreignObject *ngIf="isActive" [attr.x]="x" [attr.y]="y" [attr.width]="w" [attr.height]="h">
5
+ <input id="text-area" type="text" [(ngModel)]="this.text" (focusout)="leaveTextInput()"/>
6
+ </svg:foreignObject>
@@ -0,0 +1,57 @@
1
+ import {
2
+ Component,
3
+ EventEmitter,
4
+ Input,
5
+ OnChanges,
6
+ Output,
7
+ } from '@angular/core';
8
+ import { FormsModule } from '@angular/forms';
9
+ import { NgFor, NgIf } from '@angular/common';
10
+ import {TextDistributor} from "../../utils/text-distributor";
11
+
12
+ @Component({
13
+ selector: '[text-area-svg]',
14
+ templateUrl: './text-area-svg.component.svg',
15
+ styleUrl: './text-area-svg.component.css',
16
+ imports: [NgFor, NgIf, FormsModule]
17
+ })
18
+ export class TextAreaSvgComponent implements OnChanges {
19
+ /*
20
+ a fixed size svg. If the text exceeds the possible size, we will do a ... for now
21
+ */
22
+
23
+ @Input() text!: string
24
+ @Input() x!: number
25
+ @Input() y!: number
26
+ @Input() w!: number
27
+ @Input() h!: number
28
+ @Input() singleEdit: boolean = false
29
+ @Output() textChange = new EventEmitter<string>();
30
+ //only with singleEdit since that opens an overlay where one can change the text in place
31
+
32
+ distributedText: string[] = []
33
+ isActive: boolean = false;
34
+
35
+
36
+ ngOnChanges() {
37
+ this.distributeText();
38
+ }
39
+
40
+ handleClick() {
41
+ if(this.singleEdit) {
42
+ this.isActive = true
43
+ }
44
+ }
45
+
46
+ leaveTextInput() {
47
+ this.textChange.emit(this.text)
48
+ this.isActive = false;
49
+ }
50
+
51
+ distributeText(){
52
+ this.distributedText = TextDistributor.distributeText(
53
+ this.text, this.w, this.h
54
+ )
55
+ }
56
+
57
+ }
@@ -0,0 +1,8 @@
1
+ export interface ArrowStyleConfiguration {
2
+ color: string;
3
+ dashed: number[];
4
+ //style?: string
5
+
6
+ startPointer?: string;
7
+ endPointer?: string;
8
+ }
@@ -0,0 +1,7 @@
1
+ export interface BoundingBox {
2
+ x: number;
3
+ y: number;
4
+ w: number;
5
+ h: number;
6
+
7
+ }
@@ -0,0 +1,9 @@
1
+ import { Dragger } from './dragger';
2
+
3
+ describe('Dragger', () => {
4
+ it('should create an instance', () => {
5
+ let example = {gId: "id", position: { x: 1, y: 2, w: 2, h: 1 }};
6
+
7
+ expect(new Dragger(example)).toBeTruthy();
8
+ });
9
+ });