@leafer-in/linker 2.3.0 → 2.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,567 @@
1
+ import { LineData, AroundHelper, PointHelper, Direction9, BoundsHelper, decorateLeafAttr, attr, doBoundsType, doStrokeType, PathCommandDataHelper, dataProcessor, pathType, registerUI, Line, BoundsEvent, LeafHelper, isString, isObject, Plugin, registerPointsCurve } from "@leafer-ui/draw";
2
+
3
+ import { PointHelper as PointHelper$1, PathCommandMap } from "@leafer-ui/core";
4
+
5
+ function __decorate(decorators, target, key, desc) {
6
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
7
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
8
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
9
+ }
10
+
11
+ typeof SuppressedError === "function" ? SuppressedError : function(error, suppressed, message) {
12
+ var e = new Error(message);
13
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
14
+ };
15
+
16
+ class LinkerData extends LineData {
17
+ get __usePathBox() {
18
+ return this.path || this.__pathInputed;
19
+ }
20
+ }
21
+
22
+ const {directionData: directionData} = AroundHelper;
23
+
24
+ const directionNames = [ "top-left", "top", "top-right", "right", "bottom-right", "bottom", "bottom-left", "left", "center" ];
25
+
26
+ const LinkerHelper = {
27
+ getCtrlPoint(linker, node, point, direction, ctrl, offsetAngle) {
28
+ if (node) {
29
+ point = node.getBoxPoint(point, linker);
30
+ }
31
+ let ctrlPoint;
32
+ switch (direction) {
33
+ case "left":
34
+ case "top-left":
35
+ case "bottom-left":
36
+ ctrlPoint = {
37
+ x: point.x - ctrl.x,
38
+ y: point.y
39
+ };
40
+ break;
41
+
42
+ case "top":
43
+ ctrlPoint = {
44
+ x: point.x,
45
+ y: point.y - ctrl.y
46
+ };
47
+ break;
48
+
49
+ case "right":
50
+ case "top-right":
51
+ case "bottom-right":
52
+ ctrlPoint = {
53
+ x: point.x + ctrl.x,
54
+ y: point.y
55
+ };
56
+ break;
57
+
58
+ case "bottom":
59
+ ctrlPoint = {
60
+ x: point.x,
61
+ y: point.y + ctrl.y
62
+ };
63
+ break;
64
+
65
+ default:
66
+ ctrlPoint = {
67
+ x: point.x,
68
+ y: point.y
69
+ };
70
+ }
71
+ if (offsetAngle) {
72
+ offsetAngle = offsetAngle / 180 * Math.PI;
73
+ ctrlPoint = {
74
+ x: (ctrlPoint.x - point.x) * Math.cos(offsetAngle) - (ctrlPoint.y - point.y) * Math.sin(offsetAngle) + point.x,
75
+ y: (ctrlPoint.x - point.x) * Math.sin(offsetAngle) + (ctrlPoint.y - point.y) * Math.cos(offsetAngle) + point.y
76
+ };
77
+ }
78
+ if (node) node.getWorldPointByBox(ctrlPoint, linker, undefined, true);
79
+ return ctrlPoint;
80
+ },
81
+ isOppositeDirection(from, to) {
82
+ switch (from) {
83
+ case "left":
84
+ return to == "right";
85
+
86
+ case "top":
87
+ return to == "bottom";
88
+
89
+ case "right":
90
+ return to == "left";
91
+
92
+ case "bottom":
93
+ return to == "top";
94
+
95
+ case "center":
96
+ return to == "center";
97
+
98
+ default:
99
+ return false;
100
+ }
101
+ },
102
+ getDirectionForFromPoint(from, to) {
103
+ const a = from.x - to.x;
104
+ const b = from.y - to.y;
105
+ let direction;
106
+ let angle = 180 * Math.atan2(b, a) / Math.PI;
107
+ if (angle < 0) angle = 360 + angle;
108
+ if (angle > 315 || angle < 45) {
109
+ direction = "left";
110
+ } else if (angle > 45 && angle < 135) {
111
+ direction = "top";
112
+ } else if (angle > 135 && angle < 225) {
113
+ direction = "right";
114
+ } else {
115
+ direction = "bottom";
116
+ }
117
+ return direction;
118
+ },
119
+ getRotateDirection(direction, rotation, totalDirection = 8) {
120
+ let directionIndex = Direction9[direction];
121
+ directionIndex = (directionIndex + Math.round(rotation / (360 / totalDirection))) % totalDirection;
122
+ if (directionIndex < 0) directionIndex += totalDirection;
123
+ return directionNames[directionIndex];
124
+ },
125
+ getDirection: getDirection,
126
+ getPointDirection: getPointDirection,
127
+ autoRotatePoint(point, origin, ui) {
128
+ const {rotation: rotation, scaleX: scaleX, scaleY: scaleY} = ui;
129
+ const oneFlip = scaleX * scaleY < 0;
130
+ if (rotation || oneFlip) PointHelper.rotate(point, oneFlip ? -rotation : rotation, origin);
131
+ }
132
+ };
133
+
134
+ function getPointDirection(boxPoint, bounds, eight) {
135
+ const {width: width, height: height} = bounds;
136
+ const hitRadiusX = width / 4;
137
+ const hitRadiusY = height / 4;
138
+ for (let i = 0; i < directionData.length; i++) {
139
+ const unit = directionData[i];
140
+ const px = unit.x * width;
141
+ const py = unit.y * height;
142
+ const dx = boxPoint.x - px;
143
+ const dy = boxPoint.y - py;
144
+ if (Math.abs(dx) <= hitRadiusX && Math.abs(dy) <= hitRadiusY) {
145
+ if (eight) {
146
+ if (directionNames[i] !== "center") return directionNames[i];
147
+ } else return directionNames[i];
148
+ }
149
+ }
150
+ return undefined;
151
+ }
152
+
153
+ function getDirection(boxPoint, bounds, four) {
154
+ const {width: width, height: height} = bounds;
155
+ const center = BoundsHelper.getPoint(bounds, "center", true);
156
+ const dx = boxPoint.x - center.x;
157
+ const dy = boxPoint.y - center.y;
158
+ if (!four) {
159
+ if (Math.abs(dx) < width / 4 && Math.abs(dy) < height / 4) return "center";
160
+ }
161
+ const ax = Math.abs(dx) * height;
162
+ const ay = Math.abs(dy) * width;
163
+ if (ax > ay) {
164
+ return dx > 0 ? "right" : "left";
165
+ }
166
+ return dy > 0 ? "bottom" : "top";
167
+ }
168
+
169
+ function linkerPointType(defaultValue) {
170
+ return decorateLeafAttr(defaultValue, key => attr({
171
+ set(value) {
172
+ if (this.__setAttr(key, value)) {
173
+ const layout = this.__layout;
174
+ if (!layout.linkerChanged) {
175
+ doBoundsType(this);
176
+ doStrokeType(this);
177
+ layout.linkerChanged = true;
178
+ }
179
+ }
180
+ }
181
+ }));
182
+ }
183
+
184
+ const {moveTo: moveTo, bezierCurveTo: bezierCurveTo, drawPoints: drawPoints$1} = PathCommandDataHelper;
185
+
186
+ const {isEmpty: isEmpty, getPoint: getPoint} = BoundsHelper;
187
+
188
+ const {getDistance: getDistance} = PointHelper;
189
+
190
+ const {getCtrlPoint: getCtrlPoint, getDirectionForFromPoint: getDirectionForFromPoint, isOppositeDirection: isOppositeDirection} = LinkerHelper;
191
+
192
+ const {max: max, min: min, abs: abs} = Math;
193
+
194
+ let Linker = class Linker extends Line {
195
+ get __tag() {
196
+ return "Linker";
197
+ }
198
+ constructor(data) {
199
+ super(data);
200
+ this.onStartNodeChange = this.onStartNodeChange.bind(this);
201
+ this.onEndNodeChange = this.onEndNodeChange.bind(this);
202
+ }
203
+ __updatePath() {
204
+ const layout = this.__layout;
205
+ const {startNode: startNode, endNode: endNode} = this;
206
+ if (layout.linkerChanged) {
207
+ this.updateLinkerNode("start");
208
+ this.updateLinkerNode("end");
209
+ this.updateLinkerPoint("start");
210
+ this.updateLinkerPoint("end");
211
+ if (startNode !== this.startNode) this.listenLinkerNode(this.startNode, startNode, "start");
212
+ if (endNode !== this.endNode) this.listenLinkerNode(this.endNode, endNode, "end");
213
+ layout.linkerChanged = false;
214
+ }
215
+ this.updateLinkerPath();
216
+ }
217
+ listenLinkerNode(newNode, oldNode, type) {
218
+ if (oldNode) {
219
+ oldNode.off(BoundsEvent.WORLD, type === "end" ? this.onEndNodeChange : this.onStartNodeChange);
220
+ const list = type === "end" ? oldNode.endLinker : oldNode.startLinker;
221
+ if (list) {
222
+ const index = list.indexOf(this);
223
+ if (index > -1) list.splice(index, 1);
224
+ }
225
+ }
226
+ if (newNode) {
227
+ newNode.on(BoundsEvent.WORLD, type === "end" ? this.onEndNodeChange : this.onStartNodeChange);
228
+ const list = type === "end" ? newNode.endLinker || (newNode.endLinker = []) : newNode.startLinker || (newNode.startLinker = []);
229
+ list.push(this);
230
+ }
231
+ }
232
+ onStartNodeChange() {
233
+ this.onLinkerNodeChange("start");
234
+ }
235
+ onEndNodeChange() {
236
+ this.onLinkerNodeChange("end");
237
+ }
238
+ onLinkerNodeChange(type) {
239
+ if (this.leaferIsCreated) {
240
+ const {layouter: layouter, zoomLayer: zoomLayer} = this.leafer;
241
+ if (layouter.__updatedList.has(zoomLayer)) return;
242
+ layouter.addExtra(this, true);
243
+ }
244
+ const {startData: startData, endData: endData} = this;
245
+ if (type == "start") {
246
+ this.updateLinkerPoint("start");
247
+ if (endData && endData.auto) this.updateLinkerPoint("end");
248
+ } else {
249
+ if (startData && startData.auto) this.updateLinkerPoint("start");
250
+ this.updateLinkerPoint("end");
251
+ }
252
+ this.__layout.boxChange();
253
+ LeafHelper.updateBounds(this);
254
+ }
255
+ updateLinkerNode(type) {
256
+ const {startPoint: startPoint, endPoint: endPoint} = this;
257
+ const nowPoint = type === "end" ? endPoint : startPoint;
258
+ if (nowPoint) {
259
+ const {id: id} = nowPoint;
260
+ const ui = id && (isString(id) ? this.app.findId(id) : id);
261
+ type === "end" ? this.endNode = ui : this.startNode = ui;
262
+ }
263
+ }
264
+ getLinkerNodeCenter(type) {
265
+ const {startPoint: startPoint, endPoint: endPoint, startNode: startNode, endNode: endNode, startData: startData, endData: endData} = this;
266
+ const node = type === "end" ? endNode : startNode;
267
+ const data = type === "end" ? endData || endPoint : startData || startPoint;
268
+ if (node) {
269
+ const {worldRenderBounds: worldRenderBounds} = node;
270
+ if (isEmpty(worldRenderBounds)) LeafHelper.updateBounds(node);
271
+ return getPoint(node.worldRenderBounds, "center");
272
+ } else {
273
+ return data && isObject(data.point) && this.getWorldPointByLocal(data.point);
274
+ }
275
+ }
276
+ updateLinkerPoint(type) {
277
+ const {startPoint: startPoint, endPoint: endPoint} = this;
278
+ const nowPoint = type === "end" ? endPoint : startPoint;
279
+ if (nowPoint) {
280
+ const data = {};
281
+ const {id: id, offset: offset} = nowPoint;
282
+ let {direction: direction, point: point} = nowPoint;
283
+ if (direction === "center" || !direction && id && !point) {
284
+ const start = this.getLinkerNodeCenter("start");
285
+ const end = this.getLinkerNodeCenter("end");
286
+ const from = type === "end" ? end : start;
287
+ const to = type === "end" ? start : end;
288
+ if (from && to) direction = getDirectionForFromPoint(from, to);
289
+ data.auto = true;
290
+ }
291
+ if (!direction && isString(point)) direction = point;
292
+ data.direction = direction;
293
+ const ui = type === "end" ? this.endNode : this.startNode;
294
+ let p;
295
+ if (ui) {
296
+ if (!point) point = direction;
297
+ if (point) {
298
+ const {boxBounds: boxBounds} = ui;
299
+ if (isEmpty(boxBounds)) LeafHelper.updateBounds(ui);
300
+ p = getPoint(boxBounds, point, true);
301
+ ui.getWorldPointByBox(p, this, false, true);
302
+ }
303
+ } else {
304
+ if (isObject(point)) p = point;
305
+ }
306
+ if (p && offset) {
307
+ const o = Object.assign({}, offset);
308
+ if (!offset.x) o.x = 0;
309
+ if (!offset.y) o.y = 0;
310
+ if (ui) ui.getWorldPoint(o, this, true, true);
311
+ PointHelper.move(p, o);
312
+ }
313
+ data.point = p;
314
+ type === "end" ? this.endData = p && data : this.startData = p && data;
315
+ }
316
+ }
317
+ updateLinkerPath() {
318
+ const data = this.__;
319
+ const path = data.path = [];
320
+ const hasPoints = data.points && data.points.length;
321
+ const {startData: startData, endData: endData, startNode: startNode, endNode: endNode} = this;
322
+ if (!startData || !endData) {
323
+ return;
324
+ }
325
+ const startPoint = startData.point, endPoint = endData.point;
326
+ const startDirection = startData.direction, endDirection = endData.direction;
327
+ const half = {
328
+ x: abs((startPoint.x - endPoint.x) / 2),
329
+ y: abs((startPoint.y - endPoint.y) / 2)
330
+ };
331
+ const arrowWidth = this.__.strokeWidth * 8;
332
+ let minCtrl;
333
+ if (this.__.__useArrow) {
334
+ const ratio = min(getDistance(startPoint, endPoint) / (arrowWidth * 25), 1);
335
+ minCtrl = max(arrowWidth * ratio * 12, arrowWidth * 3);
336
+ } else {
337
+ minCtrl = arrowWidth * 2;
338
+ }
339
+ if (endDirection) {
340
+ if (isOppositeDirection(startDirection, endDirection) && startDirection === getDirectionForFromPoint(startPoint, endPoint)) {
341
+ minCtrl = arrowWidth * 2;
342
+ }
343
+ }
344
+ half.x = max(minCtrl, half.x);
345
+ half.y = max(minCtrl, half.y);
346
+ if (hasPoints) {
347
+ minCtrl *= .6;
348
+ const points = PointHelper.toNumberPoints(data.points);
349
+ drawPoints$1(path, [ startPoint.x, startPoint.y, ...points, endPoint.x, endPoint.y ], data.curve, false, data);
350
+ if (startDirection) {
351
+ const handleX = path[4];
352
+ const handleY = path[5];
353
+ half.x = max(minCtrl, abs(handleX - startPoint.x));
354
+ half.y = max(minCtrl, abs(handleY - startPoint.y));
355
+ const startCtrlPoint = getCtrlPoint(this, startNode, startPoint, startDirection, half);
356
+ path[4] = startCtrlPoint.x;
357
+ path[5] = startCtrlPoint.y;
358
+ }
359
+ const len = path.length;
360
+ if (endDirection) {
361
+ const handleX = path[len - 4];
362
+ const handleY = path[len - 3];
363
+ half.x = max(minCtrl, abs(handleX - endPoint.x));
364
+ half.y = max(minCtrl, abs(handleY - endPoint.y));
365
+ const endCtrlPoint = getCtrlPoint(this, endNode, endPoint, endDirection, half);
366
+ path[len - 4] = endCtrlPoint.x;
367
+ path[len - 3] = endCtrlPoint.y;
368
+ } else {
369
+ path[len - 4] = endPoint.x;
370
+ path[len - 3] = endPoint.y;
371
+ }
372
+ } else {
373
+ const startCtrlPoint = startDirection ? getCtrlPoint(this, startNode, startPoint, startDirection, half) : startPoint;
374
+ const endCtrlPoint = endDirection ? getCtrlPoint(this, endNode, endPoint, endDirection, half) : endPoint;
375
+ moveTo(path, startPoint.x, startPoint.y);
376
+ bezierCurveTo(path, startCtrlPoint.x, startCtrlPoint.y, endCtrlPoint.x, endCtrlPoint.y, endPoint.x, endPoint.y);
377
+ }
378
+ }
379
+ createStartPoint(worldPoint, node, options) {
380
+ const data = this.createLinkerPoint(worldPoint, node, options);
381
+ this.startPoint = data;
382
+ return data;
383
+ }
384
+ createEndPoint(worldPoint, node, options) {
385
+ const data = this.createLinkerPoint(worldPoint, node, options);
386
+ this.endPoint = data;
387
+ return data;
388
+ }
389
+ createLinkerPoint(worldPoint, node, options) {
390
+ const data = {};
391
+ if (node && node.id) {
392
+ const point = node.getBoxPoint(worldPoint);
393
+ const {boxBounds: boxBounds} = node;
394
+ const mode = options && options.mode;
395
+ const edge = mode === "edge" || !mode;
396
+ const four = mode === "four";
397
+ const auto = mode === "auto";
398
+ const free = mode === "free";
399
+ if (!auto) {
400
+ if (four) {
401
+ data.point = LinkerHelper.getDirection(point, boxBounds, four);
402
+ } else {
403
+ data.direction = LinkerHelper.getDirection(point, boxBounds, edge);
404
+ data.point = LinkerHelper.getPointDirection(point, boxBounds, edge) || data.direction;
405
+ if (data.point === data.direction) delete data.direction;
406
+ if (free || edge) {
407
+ const snapPoint = BoundsHelper.getPoint(boxBounds, data.point);
408
+ const offsetX = point.x - snapPoint.x;
409
+ const offsetY = point.y - snapPoint.y;
410
+ const snapRadius = options && options.snapRadius || 10;
411
+ if (Math.abs(offsetX) > snapRadius || Math.abs(offsetY) > snapRadius) {
412
+ const offset = data.offset = {
413
+ x: Math.abs(offsetX) > snapRadius ? offsetX : 0,
414
+ y: Math.abs(offsetY) > snapRadius ? offsetY : 0
415
+ };
416
+ if (edge && (offset.x || offset.y)) {
417
+ switch (data.direction || data.point) {
418
+ case "top":
419
+ case "bottom":
420
+ offset.y = 0;
421
+ break;
422
+
423
+ case "right":
424
+ case "left":
425
+ offset.x = 0;
426
+ break;
427
+
428
+ default:
429
+ if (offset.x > offset.y) offset.y = 0; else offset.x = 0;
430
+ }
431
+ }
432
+ }
433
+ }
434
+ }
435
+ }
436
+ data.id = node.id;
437
+ } else {
438
+ data.point = this.getLocalPoint(worldPoint);
439
+ }
440
+ return data;
441
+ }
442
+ };
443
+
444
+ __decorate([ dataProcessor(LinkerData) ], Linker.prototype, "__", void 0);
445
+
446
+ __decorate([ linkerPointType() ], Linker.prototype, "startPoint", void 0);
447
+
448
+ __decorate([ linkerPointType() ], Linker.prototype, "endPoint", void 0);
449
+
450
+ __decorate([ pathType({
451
+ type: "C",
452
+ value: .5
453
+ }) ], Linker.prototype, "curve", void 0);
454
+
455
+ Linker = __decorate([ registerUI() ], Linker);
456
+
457
+ const {toNumberPoints: toNumberPoints} = PointHelper$1;
458
+
459
+ const {M: M, L: L, C: C, Z: Z} = PathCommandMap;
460
+
461
+ function drawPoints(data, originPoints, curve, close) {
462
+ const points = toNumberPoints(originPoints);
463
+ const count = points.length >> 1;
464
+ if (count < 2) return;
465
+ data.push(M, points[0], points[1]);
466
+ if (!curve || count < 3) {
467
+ for (let i = 1; i < count; i++) {
468
+ data.push(L, points[i * 2], points[i * 2 + 1]);
469
+ }
470
+ if (close) data.push(Z);
471
+ return;
472
+ }
473
+ let tension = curve === true ? .5 : curve;
474
+ if (tension < 0) tension = 0; else if (tension > 1) tension = 1;
475
+ const end = close ? count : count - 1;
476
+ let lastOutX = points[0];
477
+ let lastOutY = points[1];
478
+ {
479
+ const dx = points[2] - points[0];
480
+ const dy = points[3] - points[1];
481
+ const len = Math.sqrt(dx * dx + dy * dy);
482
+ if (len) {
483
+ lastOutX = points[0] + dx / len * len * tension;
484
+ lastOutY = points[1] + dy / len * len * tension;
485
+ }
486
+ }
487
+ for (let i = 0; i < end; i++) {
488
+ const index = i + 1 === count ? 0 : i + 1;
489
+ const bx = points[index * 2];
490
+ const by = points[index * 2 + 1];
491
+ const prev = index === 0 ? count - 1 : index - 1;
492
+ const next = index + 1 === count ? 0 : index + 1;
493
+ const ax = points[prev * 2];
494
+ const ay = points[prev * 2 + 1];
495
+ const cx = points[next * 2];
496
+ const cy = points[next * 2 + 1];
497
+ let bax = ax - bx;
498
+ let bay = ay - by;
499
+ let bcx = cx - bx;
500
+ let bcy = cy - by;
501
+ const ab = Math.sqrt(bax * bax + bay * bay);
502
+ const bc = Math.sqrt(bcx * bcx + bcy * bcy);
503
+ let inX = bx;
504
+ let inY = by;
505
+ let outX = bx;
506
+ let outY = by;
507
+ if (ab || bc) {
508
+ let ux = 0;
509
+ let uy = 0;
510
+ if (ab) {
511
+ ux += bax / ab;
512
+ uy += bay / ab;
513
+ }
514
+ if (bc) {
515
+ ux += bcx / bc;
516
+ uy += bcy / bc;
517
+ }
518
+ let uLen = Math.sqrt(ux * ux + uy * uy);
519
+ if (!uLen) {
520
+ if (bc) {
521
+ ux = bcx / bc;
522
+ uy = bcy / bc;
523
+ } else {
524
+ ux = bax / ab;
525
+ uy = bay / ab;
526
+ }
527
+ uLen = 1;
528
+ }
529
+ ux /= uLen;
530
+ uy /= uLen;
531
+ let tx = -uy;
532
+ let ty = ux;
533
+ if (bc) {
534
+ if (tx * bcx + ty * bcy < 0) {
535
+ tx = -tx;
536
+ ty = -ty;
537
+ }
538
+ }
539
+ let cos = 0;
540
+ if (ab && bc) {
541
+ cos = (bax * bcx + bay * bcy) / (ab * bc);
542
+ if (cos > 1) cos = 1; else if (cos < -1) cos = -1;
543
+ }
544
+ let angleFactor = Math.sqrt(Math.sqrt(Math.max(0, 1 - cos * cos)));
545
+ if (angleFactor < .15) angleFactor = .15;
546
+ let inLength = ab * tension * angleFactor;
547
+ let outLength = bc * tension * angleFactor;
548
+ const maxLength = Math.min(ab || bc, bc || ab) * .5;
549
+ if (inLength > maxLength) inLength = maxLength;
550
+ if (outLength > maxLength) outLength = maxLength;
551
+ inX = bx - tx * inLength;
552
+ inY = by - ty * inLength;
553
+ outX = bx + tx * outLength;
554
+ outY = by + ty * outLength;
555
+ }
556
+ data.push(C, lastOutX, lastOutY, inX, inY, bx, by);
557
+ lastOutX = outX;
558
+ lastOutY = outY;
559
+ }
560
+ if (close) data.push(Z);
561
+ }
562
+
563
+ Plugin.add("linker");
564
+
565
+ registerPointsCurve("C", drawPoints);
566
+
567
+ export { Linker, LinkerData };
@@ -0,0 +1,2 @@
1
+ import{LineData as t,AroundHelper as e,PointHelper as n,Direction9 as o,BoundsHelper as i,decorateLeafAttr as r,attr as s,doBoundsType as a,doStrokeType as d,PathCommandDataHelper as h,dataProcessor as c,pathType as u,registerUI as l,Line as p,BoundsEvent as f,LeafHelper as y,isString as g,isObject as x,Plugin as P,registerPointsCurve as k}from"@leafer-ui/draw";import{PointHelper as b,PathCommandMap as L}from"@leafer-ui/core";function N(t,e,n,o){var i,r=arguments.length,s=r<3?e:null===o?o=Object.getOwnPropertyDescriptor(e,n):o;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(t,e,n,o);else for(var a=t.length-1;a>=0;a--)(i=t[a])&&(s=(r<3?i(s):r>3?i(e,n,s):i(e,n))||s);return r>3&&s&&Object.defineProperty(e,n,s),s}"function"==typeof SuppressedError&&SuppressedError;class m extends t{get __usePathBox(){return this.path||this.__pathInputed}}const{directionData:C}=e,M=["top-left","top","top-right","right","bottom-right","bottom","bottom-left","left","center"],_={getCtrlPoint(t,e,n,o,i,r){let s;switch(e&&(n=e.getBoxPoint(n,t)),o){case"left":case"top-left":case"bottom-left":s={x:n.x-i.x,y:n.y};break;case"top":s={x:n.x,y:n.y-i.y};break;case"right":case"top-right":case"bottom-right":s={x:n.x+i.x,y:n.y};break;case"bottom":s={x:n.x,y:n.y+i.y};break;default:s={x:n.x,y:n.y}}return r&&(r=r/180*Math.PI,s={x:(s.x-n.x)*Math.cos(r)-(s.y-n.y)*Math.sin(r)+n.x,y:(s.x-n.x)*Math.sin(r)+(s.y-n.y)*Math.cos(r)+n.y}),e&&e.getWorldPointByBox(s,t,void 0,!0),s},isOppositeDirection(t,e){switch(t){case"left":return"right"==e;case"top":return"bottom"==e;case"right":return"left"==e;case"bottom":return"top"==e;case"center":return"center"==e;default:return!1}},getDirectionForFromPoint(t,e){const n=t.x-e.x,o=t.y-e.y;let i,r=180*Math.atan2(o,n)/Math.PI;return r<0&&(r=360+r),i=r>315||r<45?"left":r>45&&r<135?"top":r>135&&r<225?"right":"bottom",i},getRotateDirection(t,e,n=8){let i=o[t];return i=(i+Math.round(e/(360/n)))%n,i<0&&(i+=n),M[i]},getDirection:function(t,e,n){const{width:o,height:r}=e,s=i.getPoint(e,"center",!0),a=t.x-s.x,d=t.y-s.y;if(!n&&Math.abs(a)<o/4&&Math.abs(d)<r/4)return"center";const h=Math.abs(a)*r,c=Math.abs(d)*o;if(h>c)return a>0?"right":"left";return d>0?"bottom":"top"},getPointDirection:function(t,e,n){const{width:o,height:i}=e,r=o/4,s=i/4;for(let e=0;e<C.length;e++){const a=C[e],d=a.x*o,h=a.y*i,c=t.x-d,u=t.y-h;if(Math.abs(c)<=r&&Math.abs(u)<=s){if(!n)return M[e];if("center"!==M[e])return M[e]}}return},autoRotatePoint(t,e,o){const{rotation:i,scaleX:r,scaleY:s}=o,a=r*s<0;(i||a)&&n.rotate(t,a?-i:i,e)}};function D(t){return r(t,t=>s({set(e){if(this.__setAttr(t,e)){const t=this.__layout;t.linkerChanged||(a(this),d(this),t.linkerChanged=!0)}}}))}const{moveTo:B,bezierCurveTo:v,drawPoints:w}=h,{isEmpty:E,getPoint:R}=i,{getDistance:O}=n,{getCtrlPoint:S,getDirectionForFromPoint:W,isOppositeDirection:q}=_,{max:I,min:j,abs:F}=Math;let z=class extends p{get __tag(){return"Linker"}constructor(t){super(t),this.onStartNodeChange=this.onStartNodeChange.bind(this),this.onEndNodeChange=this.onEndNodeChange.bind(this)}__updatePath(){const t=this.__layout,{startNode:e,endNode:n}=this;t.linkerChanged&&(this.updateLinkerNode("start"),this.updateLinkerNode("end"),this.updateLinkerPoint("start"),this.updateLinkerPoint("end"),e!==this.startNode&&this.listenLinkerNode(this.startNode,e,"start"),n!==this.endNode&&this.listenLinkerNode(this.endNode,n,"end"),t.linkerChanged=!1),this.updateLinkerPath()}listenLinkerNode(t,e,n){if(e){e.off(f.WORLD,"end"===n?this.onEndNodeChange:this.onStartNodeChange);const t="end"===n?e.endLinker:e.startLinker;if(t){const e=t.indexOf(this);e>-1&&t.splice(e,1)}}if(t){t.on(f.WORLD,"end"===n?this.onEndNodeChange:this.onStartNodeChange);("end"===n?t.endLinker||(t.endLinker=[]):t.startLinker||(t.startLinker=[])).push(this)}}onStartNodeChange(){this.onLinkerNodeChange("start")}onEndNodeChange(){this.onLinkerNodeChange("end")}onLinkerNodeChange(t){if(this.leaferIsCreated){const{layouter:t,zoomLayer:e}=this.leafer;if(t.__updatedList.has(e))return;t.addExtra(this,!0)}const{startData:e,endData:n}=this;"start"==t?(this.updateLinkerPoint("start"),n&&n.auto&&this.updateLinkerPoint("end")):(e&&e.auto&&this.updateLinkerPoint("start"),this.updateLinkerPoint("end")),this.__layout.boxChange(),y.updateBounds(this)}updateLinkerNode(t){const{startPoint:e,endPoint:n}=this,o="end"===t?n:e;if(o){const{id:e}=o,n=e&&(g(e)?this.app.findId(e):e);"end"===t?this.endNode=n:this.startNode=n}}getLinkerNodeCenter(t){const{startPoint:e,endPoint:n,startNode:o,endNode:i,startData:r,endData:s}=this,a="end"===t?i:o,d="end"===t?s||n:r||e;if(a){const{worldRenderBounds:t}=a;return E(t)&&y.updateBounds(a),R(a.worldRenderBounds,"center")}return d&&x(d.point)&&this.getWorldPointByLocal(d.point)}updateLinkerPoint(t){const{startPoint:e,endPoint:o}=this,i="end"===t?o:e;if(i){const e={},{id:o,offset:r}=i;let{direction:s,point:a}=i;if("center"===s||!s&&o&&!a){const n=this.getLinkerNodeCenter("start"),o=this.getLinkerNodeCenter("end"),i="end"===t?o:n,r="end"===t?n:o;i&&r&&(s=W(i,r)),e.auto=!0}!s&&g(a)&&(s=a),e.direction=s;const d="end"===t?this.endNode:this.startNode;let h;if(d){if(a||(a=s),a){const{boxBounds:t}=d;E(t)&&y.updateBounds(d),h=R(t,a,!0),d.getWorldPointByBox(h,this,!1,!0)}}else x(a)&&(h=a);if(h&&r){const t=Object.assign({},r);r.x||(t.x=0),r.y||(t.y=0),d&&d.getWorldPoint(t,this,!0,!0),n.move(h,t)}e.point=h,"end"===t?this.endData=h&&e:this.startData=h&&e}}updateLinkerPath(){const t=this.__,e=t.path=[],o=t.points&&t.points.length,{startData:i,endData:r,startNode:s,endNode:a}=this;if(!i||!r)return;const d=i.point,h=r.point,c=i.direction,u=r.direction,l={x:F((d.x-h.x)/2),y:F((d.y-h.y)/2)},p=8*this.__.strokeWidth;let f;if(this.__.__useArrow){const t=j(O(d,h)/(25*p),1);f=I(p*t*12,3*p)}else f=2*p;if(u&&q(c,u)&&c===W(d,h)&&(f=2*p),l.x=I(f,l.x),l.y=I(f,l.y),o){f*=.6;const o=n.toNumberPoints(t.points);if(w(e,[d.x,d.y,...o,h.x,h.y],t.curve,!1,t),c){const t=e[4],n=e[5];l.x=I(f,F(t-d.x)),l.y=I(f,F(n-d.y));const o=S(this,s,d,c,l);e[4]=o.x,e[5]=o.y}const i=e.length;if(u){const t=e[i-4],n=e[i-3];l.x=I(f,F(t-h.x)),l.y=I(f,F(n-h.y));const o=S(this,a,h,u,l);e[i-4]=o.x,e[i-3]=o.y}else e[i-4]=h.x,e[i-3]=h.y}else{const t=c?S(this,s,d,c,l):d,n=u?S(this,a,h,u,l):h;B(e,d.x,d.y),v(e,t.x,t.y,n.x,n.y,h.x,h.y)}}createStartPoint(t,e,n){const o=this.createLinkerPoint(t,e,n);return this.startPoint=o,o}createEndPoint(t,e,n){const o=this.createLinkerPoint(t,e,n);return this.endPoint=o,o}createLinkerPoint(t,e,n){const o={};if(e&&e.id){const r=e.getBoxPoint(t),{boxBounds:s}=e,a=n&&n.mode,d="edge"===a||!a,h="four"===a,c="free"===a;if(!("auto"===a))if(h)o.point=_.getDirection(r,s,h);else if(o.direction=_.getDirection(r,s,d),o.point=_.getPointDirection(r,s,d)||o.direction,o.point===o.direction&&delete o.direction,c||d){const t=i.getPoint(s,o.point),e=r.x-t.x,a=r.y-t.y,h=n&&n.snapRadius||10;if(Math.abs(e)>h||Math.abs(a)>h){const t=o.offset={x:Math.abs(e)>h?e:0,y:Math.abs(a)>h?a:0};if(d&&(t.x||t.y))switch(o.direction||o.point){case"top":case"bottom":t.y=0;break;case"right":case"left":t.x=0;break;default:t.x>t.y?t.y=0:t.x=0}}}o.id=e.id}else o.point=this.getLocalPoint(t);return o}};N([c(m)],z.prototype,"__",void 0),N([D()],z.prototype,"startPoint",void 0),N([D()],z.prototype,"endPoint",void 0),N([u({type:"C",value:.5})],z.prototype,"curve",void 0),z=N([l()],z);const{toNumberPoints:A}=b,{M:T,L:H,C:X,Z:Y}=L;P.add("linker"),k("C",function(t,e,n,o){const i=A(e),r=i.length>>1;if(r<2)return;if(t.push(T,i[0],i[1]),!n||r<3){for(let e=1;e<r;e++)t.push(H,i[2*e],i[2*e+1]);return void(o&&t.push(Y))}let s=!0===n?.5:n;s<0?s=0:s>1&&(s=1);const a=o?r:r-1;let d=i[0],h=i[1];{const t=i[2]-i[0],e=i[3]-i[1],n=Math.sqrt(t*t+e*e);n&&(d=i[0]+t/n*n*s,h=i[1]+e/n*n*s)}for(let e=0;e<a;e++){const n=e+1===r?0:e+1,o=i[2*n],a=i[2*n+1],c=0===n?r-1:n-1,u=n+1===r?0:n+1;let l=i[2*c]-o,p=i[2*c+1]-a,f=i[2*u]-o,y=i[2*u+1]-a;const g=Math.sqrt(l*l+p*p),x=Math.sqrt(f*f+y*y);let P=o,k=a,b=o,L=a;if(g||x){let t=0,e=0;g&&(t+=l/g,e+=p/g),x&&(t+=f/x,e+=y/x);let n=Math.sqrt(t*t+e*e);n||(x?(t=f/x,e=y/x):(t=l/g,e=p/g),n=1),t/=n,e/=n;let i=-e,r=t;x&&i*f+r*y<0&&(i=-i,r=-r);let d=0;g&&x&&(d=(l*f+p*y)/(g*x),d>1?d=1:d<-1&&(d=-1));let h=Math.sqrt(Math.sqrt(Math.max(0,1-d*d)));h<.15&&(h=.15);let c=g*s*h,u=x*s*h;const N=.5*Math.min(g||x,x||g);c>N&&(c=N),u>N&&(u=N),P=o-i*c,k=a-r*c,b=o+i*u,L=a+r*u}t.push(X,d,h,P,k,o,a),d=b,h=L}o&&t.push(Y)});export{z as Linker,m as LinkerData};
2
+ //# sourceMappingURL=linker.esm.min.js.map