@leafer-ui/core 1.0.0-rc.3 → 1.0.0-rc.30

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,1559 @@
1
+ import { Leafer, State, UI, ImageManager, Rect, Group } from '@leafer-ui/draw';
2
+ export * from '@leafer-ui/draw';
3
+ import { registerUI, Creator, PropertyEvent, Debug, DataHelper, canvasSizeAttrs, LayoutEvent, RenderEvent, Event, EventCreator, registerUIEvent, LeafList, BoundsHelper, PointHelper, Bounds, ResizeEvent, LeaferEvent, CanvasManager, Leaf, Matrix, Platform, tempBounds, LeaferCanvasBase } from '@leafer/core';
4
+
5
+ /******************************************************************************
6
+ Copyright (c) Microsoft Corporation.
7
+
8
+ Permission to use, copy, modify, and/or distribute this software for any
9
+ purpose with or without fee is hereby granted.
10
+
11
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
12
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
14
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
16
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17
+ PERFORMANCE OF THIS SOFTWARE.
18
+ ***************************************************************************** */
19
+ /* global Reflect, Promise, SuppressedError, Symbol */
20
+
21
+
22
+ function __decorate(decorators, target, key, desc) {
23
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
24
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
25
+ 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;
26
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
27
+ }
28
+
29
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
30
+ var e = new Error(message);
31
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
32
+ };
33
+
34
+ let App = class App extends Leafer {
35
+ get __tag() { return 'App'; }
36
+ get isApp() { return true; }
37
+ constructor(userConfig, data) {
38
+ super(userConfig, data);
39
+ }
40
+ init(userConfig, parentApp) {
41
+ super.init(userConfig, parentApp);
42
+ if (userConfig) {
43
+ const { ground, tree, sky, editor } = userConfig;
44
+ if (ground)
45
+ this.ground = this.addLeafer(ground);
46
+ if (tree || editor)
47
+ this.tree = this.addLeafer(tree);
48
+ if (sky || editor)
49
+ this.sky = this.addLeafer(sky || { type: 'draw', usePartRender: false });
50
+ if (editor) {
51
+ this.editor = Creator.editor(editor);
52
+ this.sky.add(this.editor);
53
+ }
54
+ }
55
+ }
56
+ __setApp() {
57
+ const { canvas } = this;
58
+ const { realCanvas, view } = this.config;
59
+ if (realCanvas || view === this.canvas.view || !canvas.parentView) {
60
+ this.realCanvas = true;
61
+ }
62
+ else {
63
+ canvas.unrealCanvas();
64
+ }
65
+ this.leafer = this;
66
+ this.watcher.disable();
67
+ this.layouter.disable();
68
+ this.__eventIds.push(this.on_(PropertyEvent.CHANGE, this.__onPropertyChange, this));
69
+ }
70
+ start() {
71
+ super.start();
72
+ this.children.forEach(leafer => leafer.start());
73
+ }
74
+ stop() {
75
+ this.children.forEach(leafer => leafer.stop());
76
+ super.stop();
77
+ }
78
+ unlockLayout() {
79
+ super.unlockLayout();
80
+ this.children.forEach(leafer => leafer.unlockLayout());
81
+ }
82
+ lockLayout() {
83
+ super.lockLayout();
84
+ this.children.forEach(leafer => leafer.lockLayout());
85
+ }
86
+ forceRender(bounds) {
87
+ this.children.forEach(leafer => leafer.forceRender(bounds));
88
+ }
89
+ addLeafer(merge) {
90
+ const leafer = new Leafer(merge);
91
+ this.add(leafer);
92
+ return leafer;
93
+ }
94
+ add(leafer, index) {
95
+ if (!leafer.view) {
96
+ if (this.realCanvas && !this.canvas.bounds) {
97
+ setTimeout(() => this.add(leafer, index), 10);
98
+ return;
99
+ }
100
+ leafer.init(this.__getChildConfig(leafer.userConfig), this);
101
+ }
102
+ super.add(leafer, index);
103
+ if (index !== undefined)
104
+ leafer.canvas.childIndex = index;
105
+ this.__listenChildEvents(leafer);
106
+ }
107
+ __onPropertyChange() {
108
+ if (Debug.showHitView)
109
+ this.children.forEach(leafer => leafer.forceUpdate('surface'));
110
+ }
111
+ __onCreated() {
112
+ this.created = this.children.every(child => child.created);
113
+ }
114
+ __onReady() {
115
+ if (this.children.every(child => child.ready))
116
+ super.__onReady();
117
+ }
118
+ __onViewReady() {
119
+ if (this.children.every(child => child.viewReady))
120
+ super.__onViewReady();
121
+ }
122
+ __onChildRenderEnd(e) {
123
+ this.renderer.addBlock(e.renderBounds);
124
+ if (this.viewReady)
125
+ this.renderer.update();
126
+ }
127
+ __render(canvas, options) {
128
+ if (options.matrix) {
129
+ const { a, b, c, d, e, f } = options.matrix;
130
+ canvas.setTransform(a, b, c, d, e, f);
131
+ }
132
+ this.children.forEach(leafer => canvas.copyWorld(leafer.canvas));
133
+ }
134
+ __onResize(event) {
135
+ this.children.forEach(leafer => leafer.resize(event));
136
+ super.__onResize(event);
137
+ }
138
+ __checkUpdateLayout() {
139
+ this.children.forEach(leafer => leafer.__layout.update());
140
+ }
141
+ __getChildConfig(userConfig) {
142
+ let config = Object.assign({}, this.config);
143
+ config.hittable = config.realCanvas = undefined;
144
+ if (userConfig)
145
+ DataHelper.assign(config, userConfig);
146
+ if (this.autoLayout)
147
+ DataHelper.copyAttrs(config, this, canvasSizeAttrs);
148
+ config.view = this.realCanvas ? undefined : this.view;
149
+ config.fill = undefined;
150
+ return config;
151
+ }
152
+ __listenChildEvents(leafer) {
153
+ leafer.once(LayoutEvent.END, () => this.__onReady());
154
+ leafer.once(RenderEvent.START, () => this.__onCreated());
155
+ leafer.once(RenderEvent.END, () => this.__onViewReady());
156
+ if (this.realCanvas)
157
+ this.__eventIds.push(leafer.on_(RenderEvent.END, this.__onChildRenderEnd, this));
158
+ }
159
+ };
160
+ App = __decorate([
161
+ registerUI()
162
+ ], App);
163
+
164
+ const downKeyMap = {};
165
+ const Keyboard = {
166
+ isHoldSpaceKey() {
167
+ return Keyboard.isHold('Space');
168
+ },
169
+ isHold(code) {
170
+ return downKeyMap[code];
171
+ },
172
+ setDownCode(code) {
173
+ if (!downKeyMap[code])
174
+ downKeyMap[code] = true;
175
+ },
176
+ setUpCode(code) {
177
+ downKeyMap[code] = false;
178
+ }
179
+ };
180
+
181
+ const PointerButton = {
182
+ LEFT: 1,
183
+ RIGHT: 2,
184
+ MIDDLE: 4,
185
+ defaultLeft(event) { if (!event.buttons)
186
+ event.buttons = 1; },
187
+ left(event) { return event.buttons === 1; },
188
+ right(event) { return event.buttons === 2; },
189
+ middle(event) { return event.buttons === 4; }
190
+ };
191
+
192
+ class UIEvent extends Event {
193
+ get spaceKey() { return Keyboard.isHoldSpaceKey(); }
194
+ get left() { return PointerButton.left(this); }
195
+ get right() { return PointerButton.right(this); }
196
+ get middle() { return PointerButton.middle(this); }
197
+ constructor(params) {
198
+ super(params.type);
199
+ this.bubbles = true;
200
+ Object.assign(this, params);
201
+ }
202
+ getPage() {
203
+ return this.current.getPagePoint(this);
204
+ }
205
+ getInner(relative) {
206
+ if (!relative)
207
+ relative = this.current;
208
+ return relative.getInnerPoint(this);
209
+ }
210
+ getLocal(relative) {
211
+ if (!relative)
212
+ relative = this.current;
213
+ return relative.getLocalPoint(this);
214
+ }
215
+ static changeName(oldName, newName) {
216
+ EventCreator.changeName(oldName, newName);
217
+ }
218
+ }
219
+
220
+ let PointerEvent = class PointerEvent extends UIEvent {
221
+ };
222
+ PointerEvent.POINTER = 'pointer';
223
+ PointerEvent.BEFORE_DOWN = 'pointer.before_down';
224
+ PointerEvent.BEFORE_MOVE = 'pointer.before_move';
225
+ PointerEvent.BEFORE_UP = 'pointer.before_up';
226
+ PointerEvent.DOWN = 'pointer.down';
227
+ PointerEvent.MOVE = 'pointer.move';
228
+ PointerEvent.UP = 'pointer.up';
229
+ PointerEvent.OVER = 'pointer.over';
230
+ PointerEvent.OUT = 'pointer.out';
231
+ PointerEvent.ENTER = 'pointer.enter';
232
+ PointerEvent.LEAVE = 'pointer.leave';
233
+ PointerEvent.TAP = 'tap';
234
+ PointerEvent.DOUBLE_TAP = 'double_tap';
235
+ PointerEvent.CLICK = 'click';
236
+ PointerEvent.DOUBLE_CLICK = 'double_click';
237
+ PointerEvent.LONG_PRESS = 'long_press';
238
+ PointerEvent.LONG_TAP = 'long_tap';
239
+ PointerEvent.MENU = 'pointer.menu';
240
+ PointerEvent.MENU_TAP = 'pointer.menu_tap';
241
+ PointerEvent = __decorate([
242
+ registerUIEvent()
243
+ ], PointerEvent);
244
+
245
+ const move = {};
246
+ let DragEvent = class DragEvent extends PointerEvent {
247
+ static setList(data) {
248
+ this.list = data instanceof LeafList ? data : new LeafList(data);
249
+ }
250
+ static setData(data) {
251
+ this.data = data;
252
+ }
253
+ static getValidMove(leaf, start, total) {
254
+ const { draggable, dragBounds, x, y } = leaf;
255
+ const move = leaf.getLocalPoint(total, null, true);
256
+ move.x += start.x - x;
257
+ move.y += start.y - y;
258
+ if (dragBounds)
259
+ this.getMoveInDragBounds(leaf.__local, dragBounds === 'parent' ? leaf.parent.boxBounds : dragBounds, move, true);
260
+ if (draggable === 'x')
261
+ move.y = 0;
262
+ if (draggable === 'y')
263
+ move.x = 0;
264
+ return move;
265
+ }
266
+ static getMoveInDragBounds(childBox, dragBounds, move, change) {
267
+ const x = childBox.x + move.x, y = childBox.y + move.y;
268
+ const right = x + childBox.width, bottom = y + childBox.height;
269
+ const boundsRight = dragBounds.x + dragBounds.width, boundsBottom = dragBounds.y + dragBounds.height;
270
+ if (!change)
271
+ move = Object.assign({}, move);
272
+ if (BoundsHelper.includes(childBox, dragBounds)) {
273
+ if (x > dragBounds.x)
274
+ move.x += dragBounds.x - x;
275
+ else if (right < boundsRight)
276
+ move.x += boundsRight - right;
277
+ if (y > dragBounds.y)
278
+ move.y += dragBounds.y - y;
279
+ else if (bottom < boundsBottom)
280
+ move.y += boundsBottom - bottom;
281
+ }
282
+ else {
283
+ if (x < dragBounds.x)
284
+ move.x += dragBounds.x - x;
285
+ else if (right > boundsRight)
286
+ move.x += boundsRight - right;
287
+ if (y < dragBounds.y)
288
+ move.y += dragBounds.y - y;
289
+ else if (bottom > boundsBottom)
290
+ move.y += boundsBottom - bottom;
291
+ }
292
+ return move;
293
+ }
294
+ getPageMove(total) {
295
+ this.assignMove(total);
296
+ return this.current.getPagePoint(move, null, true);
297
+ }
298
+ getInnerMove(relative, total) {
299
+ if (!relative)
300
+ relative = this.current;
301
+ this.assignMove(total);
302
+ return relative.getInnerPoint(move, null, true);
303
+ }
304
+ getLocalMove(relative, total) {
305
+ if (!relative)
306
+ relative = this.current;
307
+ this.assignMove(total);
308
+ return relative.getLocalPoint(move, null, true);
309
+ }
310
+ getPageTotal() {
311
+ return this.getPageMove(true);
312
+ }
313
+ getInnerTotal(relative) {
314
+ return this.getInnerMove(relative, true);
315
+ }
316
+ getLocalTotal(relative) {
317
+ return this.getLocalMove(relative, true);
318
+ }
319
+ getPageBounds() {
320
+ const total = this.getPageTotal();
321
+ const start = this.getPage();
322
+ const bounds = {};
323
+ BoundsHelper.set(bounds, start.x - total.x, start.y - total.y, total.x, total.y);
324
+ BoundsHelper.unsign(bounds);
325
+ return bounds;
326
+ }
327
+ assignMove(total) {
328
+ move.x = total ? this.totalX : this.moveX;
329
+ move.y = total ? this.totalY : this.moveY;
330
+ }
331
+ };
332
+ DragEvent.BEFORE_DRAG = 'drag.before_drag';
333
+ DragEvent.START = 'drag.start';
334
+ DragEvent.DRAG = 'drag';
335
+ DragEvent.END = 'drag.end';
336
+ DragEvent.OVER = 'drag.over';
337
+ DragEvent.OUT = 'drag.out';
338
+ DragEvent.ENTER = 'drag.enter';
339
+ DragEvent.LEAVE = 'drag.leave';
340
+ DragEvent = __decorate([
341
+ registerUIEvent()
342
+ ], DragEvent);
343
+
344
+ let DropEvent = class DropEvent extends PointerEvent {
345
+ static setList(data) {
346
+ DragEvent.setList(data);
347
+ }
348
+ static setData(data) {
349
+ DragEvent.setData(data);
350
+ }
351
+ };
352
+ DropEvent.DROP = 'drop';
353
+ DropEvent = __decorate([
354
+ registerUIEvent()
355
+ ], DropEvent);
356
+
357
+ let MoveEvent = class MoveEvent extends DragEvent {
358
+ };
359
+ MoveEvent.BEFORE_MOVE = 'move.before_move';
360
+ MoveEvent.START = 'move.start';
361
+ MoveEvent.MOVE = 'move';
362
+ MoveEvent.END = 'move.end';
363
+ MoveEvent = __decorate([
364
+ registerUIEvent()
365
+ ], MoveEvent);
366
+
367
+ let RotateEvent = class RotateEvent extends UIEvent {
368
+ };
369
+ RotateEvent.BEFORE_ROTATE = 'rotate.before_rotate';
370
+ RotateEvent.START = 'rotate.start';
371
+ RotateEvent.ROTATE = 'rotate';
372
+ RotateEvent.END = 'rotate.end';
373
+ RotateEvent = __decorate([
374
+ registerUIEvent()
375
+ ], RotateEvent);
376
+
377
+ let SwipeEvent = class SwipeEvent extends DragEvent {
378
+ };
379
+ SwipeEvent.SWIPE = 'swipe';
380
+ SwipeEvent.LEFT = 'swipe.left';
381
+ SwipeEvent.RIGHT = 'swipe.right';
382
+ SwipeEvent.UP = 'swipe.up';
383
+ SwipeEvent.DOWN = 'swipe.down';
384
+ SwipeEvent = __decorate([
385
+ registerUIEvent()
386
+ ], SwipeEvent);
387
+
388
+ let ZoomEvent = class ZoomEvent extends UIEvent {
389
+ };
390
+ ZoomEvent.BEFORE_ZOOM = 'zoom.before_zoom';
391
+ ZoomEvent.START = 'zoom.start';
392
+ ZoomEvent.ZOOM = 'zoom';
393
+ ZoomEvent.END = 'zoom.end';
394
+ ZoomEvent = __decorate([
395
+ registerUIEvent()
396
+ ], ZoomEvent);
397
+
398
+ let KeyEvent = class KeyEvent extends UIEvent {
399
+ };
400
+ KeyEvent.DOWN = 'key.down';
401
+ KeyEvent.HOLD = 'key.hold';
402
+ KeyEvent.UP = 'key.up';
403
+ KeyEvent = __decorate([
404
+ registerUIEvent()
405
+ ], KeyEvent);
406
+
407
+ function addInteractionWindow(leafer) {
408
+ if (leafer.isApp)
409
+ return;
410
+ leafer.__eventIds.push(leafer.on_(MoveEvent.BEFORE_MOVE, (e) => {
411
+ leafer.zoomLayer.move(leafer.getValidMove(e.moveX, e.moveY));
412
+ }), leafer.on_(ZoomEvent.BEFORE_ZOOM, (e) => {
413
+ const { zoomLayer } = leafer;
414
+ const changeScale = leafer.getValidScale(e.scale);
415
+ if (changeScale !== 1) {
416
+ PointHelper.scaleOf(zoomLayer, e, changeScale);
417
+ zoomLayer.scale = zoomLayer.__.scaleX * changeScale;
418
+ }
419
+ }));
420
+ }
421
+
422
+ function document(leafer) {
423
+ addInteractionWindow(leafer);
424
+ leafer.config.move.scroll = 'limit';
425
+ leafer.config.zoom.min = 1;
426
+ }
427
+
428
+ const debug$1 = Debug.get('LeaferTypeCreator');
429
+ const LeaferTypeCreator = {
430
+ list: {},
431
+ register(name, fn) {
432
+ if (list[name]) {
433
+ debug$1.repeat(name);
434
+ }
435
+ else {
436
+ list[name] = fn;
437
+ }
438
+ },
439
+ run(name, leafer) {
440
+ const fn = list[name];
441
+ if (fn) {
442
+ fn(leafer);
443
+ }
444
+ else {
445
+ debug$1.error('no', name);
446
+ }
447
+ }
448
+ };
449
+ const { list, register } = LeaferTypeCreator;
450
+ register('draw', () => { });
451
+ register('custom', () => { });
452
+ register('design', addInteractionWindow);
453
+ register('document', document);
454
+
455
+ const leafer = Leafer.prototype;
456
+ leafer.initType = function (type) {
457
+ LeaferTypeCreator.run(type, this);
458
+ };
459
+ leafer.getValidMove = function (moveX, moveY) {
460
+ const { scroll, disabled } = this.app.config.move;
461
+ if (scroll) {
462
+ if (Math.abs(moveX) > Math.abs(moveY))
463
+ moveY = 0;
464
+ else
465
+ moveX = 0;
466
+ if (scroll === 'limit') {
467
+ const { x, y, width, height } = new Bounds(this.__world).addPoint(this.zoomLayer);
468
+ const right = x + width - this.width, bottom = y + height - this.height;
469
+ if (x >= 0 && right <= 0)
470
+ moveX = 0;
471
+ else if (moveX > 0) {
472
+ if (x + moveX > 0)
473
+ moveX = -x;
474
+ }
475
+ else if (moveX < 0 && right + moveX < 0)
476
+ moveX = -right;
477
+ if (y >= 0 && bottom <= 0)
478
+ moveY = 0;
479
+ else if (moveY > 0) {
480
+ if (y + moveY > 0)
481
+ moveY = -y;
482
+ }
483
+ else if (moveY < 0 && bottom + moveY < 0)
484
+ moveY = -bottom;
485
+ }
486
+ }
487
+ return { x: disabled ? 0 : moveX, y: disabled ? 0 : moveY };
488
+ };
489
+ leafer.getValidScale = function (changeScale) {
490
+ const { scaleX } = this.zoomLayer.__, { min, max, disabled } = this.app.config.zoom, absScale = Math.abs(scaleX * changeScale);
491
+ if (absScale < min)
492
+ changeScale = min / scaleX;
493
+ else if (absScale > max)
494
+ changeScale = max / scaleX;
495
+ return disabled ? 1 : changeScale;
496
+ };
497
+
498
+ class Transformer {
499
+ constructor(interaction) {
500
+ this.interaction = interaction;
501
+ }
502
+ move(data) {
503
+ const { interaction } = this;
504
+ if (!this.moveData) {
505
+ const { path } = interaction.selector.getByPoint(data, interaction.hitRadius);
506
+ data.path = path;
507
+ this.moveData = Object.assign(Object.assign({}, data), { moveX: 0, moveY: 0 });
508
+ interaction.cancelHover();
509
+ interaction.emit(MoveEvent.START, this.moveData);
510
+ }
511
+ data.path = this.moveData.path;
512
+ interaction.emit(MoveEvent.BEFORE_MOVE, data);
513
+ interaction.emit(MoveEvent.MOVE, data);
514
+ this.transformEndWait();
515
+ }
516
+ zoom(data) {
517
+ const { interaction } = this;
518
+ if (!this.zoomData) {
519
+ const { path } = interaction.selector.getByPoint(data, interaction.hitRadius);
520
+ data.path = path;
521
+ this.zoomData = Object.assign(Object.assign({}, data), { scale: 1 });
522
+ interaction.cancelHover();
523
+ interaction.emit(ZoomEvent.START, this.zoomData);
524
+ }
525
+ data.path = this.zoomData.path;
526
+ interaction.emit(ZoomEvent.BEFORE_ZOOM, data);
527
+ interaction.emit(ZoomEvent.ZOOM, data);
528
+ this.transformEndWait();
529
+ }
530
+ rotate(data) {
531
+ const { interaction } = this;
532
+ if (!this.rotateData) {
533
+ const { path } = interaction.selector.getByPoint(data, interaction.hitRadius);
534
+ data.path = path;
535
+ this.rotateData = Object.assign(Object.assign({}, data), { rotation: 0 });
536
+ interaction.cancelHover();
537
+ interaction.emit(RotateEvent.START, this.rotateData);
538
+ }
539
+ data.path = this.rotateData.path;
540
+ interaction.emit(RotateEvent.BEFORE_ROTATE, data);
541
+ interaction.emit(RotateEvent.ROTATE, data);
542
+ this.transformEndWait();
543
+ }
544
+ transformEndWait() {
545
+ clearTimeout(this.transformTimer);
546
+ this.transformTimer = setTimeout(() => {
547
+ this.transformEnd();
548
+ }, this.interaction.config.pointer.transformTime);
549
+ }
550
+ transformEnd() {
551
+ this.moveEnd();
552
+ this.zoomEnd();
553
+ this.rotateEnd();
554
+ }
555
+ moveEnd() {
556
+ if (this.moveData) {
557
+ this.interaction.emit(MoveEvent.END, this.moveData);
558
+ this.moveData = null;
559
+ }
560
+ }
561
+ zoomEnd() {
562
+ if (this.zoomData) {
563
+ this.interaction.emit(ZoomEvent.END, this.zoomData);
564
+ this.zoomData = null;
565
+ }
566
+ }
567
+ rotateEnd() {
568
+ if (this.rotateData) {
569
+ this.interaction.emit(RotateEvent.END, this.rotateData);
570
+ this.rotateData = null;
571
+ }
572
+ }
573
+ destroy() {
574
+ this.zoomData = this.moveData = this.rotateData = null;
575
+ }
576
+ }
577
+
578
+ const InteractionHelper = {
579
+ getMoveEventData(center, move, event) {
580
+ return Object.assign(Object.assign({}, event), { x: center.x, y: center.y, moveX: move.x, moveY: move.y });
581
+ },
582
+ getRotateEventData(center, angle, event) {
583
+ return Object.assign(Object.assign({}, event), { x: center.x, y: center.y, rotation: angle });
584
+ },
585
+ getZoomEventData(center, scale, event) {
586
+ return Object.assign(Object.assign({}, event), { x: center.x, y: center.y, scale });
587
+ },
588
+ getDragEventData(startPoint, lastPoint, event) {
589
+ return Object.assign(Object.assign({}, event), { x: event.x, y: event.y, moveX: event.x - lastPoint.x, moveY: event.y - lastPoint.y, totalX: event.x - startPoint.x, totalY: event.y - startPoint.y });
590
+ },
591
+ getDropEventData(event, list, data) {
592
+ return Object.assign(Object.assign({}, event), { list,
593
+ data });
594
+ },
595
+ getSwipeDirection(angle) {
596
+ if (angle < -45 && angle > -135) {
597
+ return SwipeEvent.UP;
598
+ }
599
+ else if (angle > 45 && angle < 135) {
600
+ return SwipeEvent.DOWN;
601
+ }
602
+ else if (angle <= 45 && angle >= -45) {
603
+ return SwipeEvent.RIGHT;
604
+ }
605
+ else {
606
+ return SwipeEvent.LEFT;
607
+ }
608
+ },
609
+ getSwipeEventData(startPoint, lastDragData, event) {
610
+ return Object.assign(Object.assign({}, event), { moveX: lastDragData.moveX, moveY: lastDragData.moveY, totalX: event.x - startPoint.x, totalY: event.y - startPoint.y, type: I.getSwipeDirection(PointHelper.getAngle(startPoint, event)) });
611
+ },
612
+ getBase(e) {
613
+ const pointerUpButtons = e.button === 1 ? 4 : e.button;
614
+ return {
615
+ altKey: e.altKey,
616
+ ctrlKey: e.ctrlKey,
617
+ shiftKey: e.shiftKey,
618
+ metaKey: e.metaKey,
619
+ buttons: e.buttons === undefined ? 1 : (e.buttons === 0 ? pointerUpButtons : e.buttons),
620
+ origin: e
621
+ };
622
+ },
623
+ pathHasEventType(path, type) {
624
+ const { list } = path;
625
+ for (let i = 0, len = list.length; i < len; i++) {
626
+ if (list[i].hasEvent(type))
627
+ return true;
628
+ }
629
+ return false;
630
+ },
631
+ filterPathByEventType(path, type) {
632
+ const find = new LeafList();
633
+ const { list } = path;
634
+ for (let i = 0, len = list.length; i < len; i++) {
635
+ if (list[i].hasEvent(type))
636
+ find.add(list[i]);
637
+ }
638
+ return find;
639
+ }
640
+ };
641
+ const I = InteractionHelper;
642
+
643
+ const emptyList = new LeafList();
644
+ const { getDragEventData, getDropEventData, getSwipeEventData } = InteractionHelper;
645
+ class Dragger {
646
+ constructor(interaction) {
647
+ this.interaction = interaction;
648
+ }
649
+ setDragData(data) {
650
+ if (this.animateWait)
651
+ this.dragEndReal();
652
+ this.downData = this.interaction.downData;
653
+ this.dragData = getDragEventData(data, data, data);
654
+ this.canAnimate = this.canDragOut = true;
655
+ }
656
+ getList() {
657
+ const { proxy } = this.interaction.selector;
658
+ return this.dragging && (!proxy || !proxy.list.length) ? (DragEvent.list || this.dragableList || emptyList) : emptyList;
659
+ }
660
+ checkDrag(data, canDrag) {
661
+ const { interaction } = this;
662
+ if (this.moving && data.buttons < 1) {
663
+ this.canAnimate = false;
664
+ interaction.pointerCancel();
665
+ return;
666
+ }
667
+ if (!this.moving && canDrag) {
668
+ if (this.moving = interaction.canMove(this.downData) || interaction.isHoldRightKey || interaction.isMobileDragEmpty)
669
+ interaction.emit(MoveEvent.START, this.dragData);
670
+ }
671
+ if (!this.moving) {
672
+ this.dragStart(data, canDrag);
673
+ }
674
+ this.drag(data);
675
+ }
676
+ dragStart(data, canDrag) {
677
+ if (!this.dragging) {
678
+ this.dragging = canDrag && PointerButton.left(data);
679
+ if (this.dragging) {
680
+ this.interaction.emit(DragEvent.START, this.dragData);
681
+ this.getDragableList(this.dragData.path);
682
+ this.setDragStartPoints(this.realDragableList = this.getList());
683
+ }
684
+ }
685
+ }
686
+ setDragStartPoints(list) {
687
+ this.dragStartPoints = {};
688
+ list.forEach(leaf => this.dragStartPoints[leaf.innerId] = { x: leaf.x, y: leaf.y });
689
+ }
690
+ getDragableList(path) {
691
+ let leaf;
692
+ for (let i = 0, len = path.length; i < len; i++) {
693
+ leaf = path.list[i];
694
+ if ((leaf.__.draggable || leaf.__.editable) && leaf.__.hitSelf && !leaf.__.locked) {
695
+ this.dragableList = new LeafList(leaf);
696
+ break;
697
+ }
698
+ }
699
+ }
700
+ drag(data) {
701
+ const { interaction, dragData, downData } = this;
702
+ const { path, throughPath } = downData;
703
+ this.dragData = getDragEventData(downData, dragData, data);
704
+ if (throughPath)
705
+ this.dragData.throughPath = throughPath;
706
+ this.dragData.path = path;
707
+ if (this.moving) {
708
+ interaction.emit(MoveEvent.BEFORE_MOVE, this.dragData);
709
+ interaction.emit(MoveEvent.MOVE, this.dragData);
710
+ }
711
+ else if (this.dragging) {
712
+ this.dragReal();
713
+ interaction.emit(DragEvent.BEFORE_DRAG, this.dragData);
714
+ interaction.emit(DragEvent.DRAG, this.dragData);
715
+ }
716
+ }
717
+ dragReal() {
718
+ const { running } = this.interaction;
719
+ const list = this.realDragableList;
720
+ if (list.length && running) {
721
+ const { totalX, totalY } = this.dragData;
722
+ list.forEach(leaf => leaf.draggable && leaf.move(DragEvent.getValidMove(leaf, this.dragStartPoints[leaf.innerId], { x: totalX, y: totalY })));
723
+ }
724
+ }
725
+ dragOverOrOut(data) {
726
+ const { interaction } = this;
727
+ const { dragOverPath } = this;
728
+ const { path } = data;
729
+ this.dragOverPath = path;
730
+ if (dragOverPath) {
731
+ if (path.indexAt(0) !== dragOverPath.indexAt(0)) {
732
+ interaction.emit(DragEvent.OUT, data, dragOverPath);
733
+ interaction.emit(DragEvent.OVER, data, path);
734
+ }
735
+ }
736
+ else {
737
+ interaction.emit(DragEvent.OVER, data, path);
738
+ }
739
+ }
740
+ dragEnterOrLeave(data) {
741
+ const { interaction } = this;
742
+ const { dragEnterPath } = this;
743
+ const { path } = data;
744
+ interaction.emit(DragEvent.LEAVE, data, dragEnterPath, path);
745
+ interaction.emit(DragEvent.ENTER, data, path, dragEnterPath);
746
+ this.dragEnterPath = path;
747
+ }
748
+ dragEnd(data, speed) {
749
+ if (!this.dragging && !this.moving)
750
+ return;
751
+ const { moveX, moveY } = this.dragData;
752
+ if (this.interaction.config.move.dragAnimate && this.canAnimate && this.moving && (Math.abs(moveX) > 1 || Math.abs(moveY) > 1)) {
753
+ data = Object.assign({}, data);
754
+ speed = (speed || (data.pointerType === 'touch' ? 2 : 1)) * 0.9;
755
+ PointHelper.move(data, moveX * speed, moveY * speed);
756
+ this.drag(data);
757
+ this.animate(() => { this.dragEnd(data, 1); });
758
+ }
759
+ else {
760
+ this.dragEndReal(data);
761
+ }
762
+ }
763
+ dragEndReal(data) {
764
+ const { interaction, downData, dragData } = this;
765
+ if (!data)
766
+ data = dragData;
767
+ const { path, throughPath } = downData;
768
+ const endDragData = getDragEventData(downData, data, data);
769
+ if (throughPath)
770
+ endDragData.throughPath = throughPath;
771
+ endDragData.path = path;
772
+ if (this.moving) {
773
+ this.moving = false;
774
+ interaction.emit(MoveEvent.END, endDragData);
775
+ }
776
+ if (this.dragging) {
777
+ const dropList = this.getList();
778
+ this.dragging = false;
779
+ interaction.emit(DragEvent.END, endDragData);
780
+ this.swipe(data, downData, dragData, endDragData);
781
+ this.drop(data, dropList, this.dragEnterPath);
782
+ }
783
+ this.autoMoveCancel();
784
+ this.dragReset();
785
+ this.animate(null, 'off');
786
+ }
787
+ animate(func, off) {
788
+ const animateWait = func || this.animateWait;
789
+ if (animateWait)
790
+ this.interaction.target.nextRender(animateWait, null, off);
791
+ this.animateWait = func;
792
+ }
793
+ swipe(data, downData, dragData, endDragData) {
794
+ const { interaction } = this;
795
+ if (PointHelper.getDistance(downData, data) > interaction.config.pointer.swipeDistance) {
796
+ const swipeData = getSwipeEventData(downData, dragData, endDragData);
797
+ this.interaction.emit(swipeData.type, swipeData);
798
+ }
799
+ }
800
+ drop(data, dropList, dragEnterPath) {
801
+ const dropData = getDropEventData(data, dropList, DragEvent.data);
802
+ dropData.path = dragEnterPath;
803
+ this.interaction.emit(DropEvent.DROP, dropData);
804
+ this.interaction.emit(DragEvent.LEAVE, data, dragEnterPath);
805
+ }
806
+ dragReset() {
807
+ DragEvent.list = DragEvent.data = this.dragableList = this.dragData = this.downData = this.dragOverPath = this.dragEnterPath = null;
808
+ }
809
+ checkDragOut(data) {
810
+ const { interaction } = this;
811
+ this.autoMoveCancel();
812
+ if (this.dragging && !interaction.shrinkCanvasBounds.hitPoint(data))
813
+ this.autoMoveOnDragOut(data);
814
+ }
815
+ autoMoveOnDragOut(data) {
816
+ const { interaction, downData, canDragOut } = this;
817
+ const { autoDistance, dragOut } = interaction.config.move;
818
+ if (!dragOut || !canDragOut || !autoDistance)
819
+ return;
820
+ const bounds = interaction.shrinkCanvasBounds;
821
+ const { x, y } = bounds;
822
+ const right = BoundsHelper.maxX(bounds);
823
+ const bottom = BoundsHelper.maxY(bounds);
824
+ const moveX = data.x < x ? autoDistance : (right < data.x ? -autoDistance : 0);
825
+ const moveY = data.y < y ? autoDistance : (bottom < data.y ? -autoDistance : 0);
826
+ let totalX = 0, totalY = 0;
827
+ this.autoMoveTimer = setInterval(() => {
828
+ totalX += moveX;
829
+ totalY += moveY;
830
+ PointHelper.move(downData, moveX, moveY);
831
+ PointHelper.move(this.dragData, moveX, moveY);
832
+ interaction.move(Object.assign(Object.assign({}, data), { moveX, moveY, totalX, totalY }));
833
+ interaction.pointerMoveReal(data);
834
+ }, 10);
835
+ }
836
+ autoMoveCancel() {
837
+ if (this.autoMoveTimer) {
838
+ clearInterval(this.autoMoveTimer);
839
+ this.autoMoveTimer = 0;
840
+ }
841
+ }
842
+ destroy() {
843
+ this.dragReset();
844
+ }
845
+ }
846
+
847
+ const debug = Debug.get('emit');
848
+ function emit(type, data, path, excludePath) {
849
+ if (!path && !data.path)
850
+ return;
851
+ let leaf;
852
+ data.type = type;
853
+ if (path) {
854
+ data = Object.assign(Object.assign({}, data), { path });
855
+ }
856
+ else {
857
+ path = data.path;
858
+ }
859
+ data.target = path.indexAt(0);
860
+ try {
861
+ for (let i = path.length - 1; i > -1; i--) {
862
+ leaf = path.list[i];
863
+ if (emitEvent(leaf, type, data, true, excludePath))
864
+ return;
865
+ if (leaf.isApp)
866
+ emitAppChildren(leaf, type, data, true, excludePath);
867
+ }
868
+ for (let i = 0, len = path.length; i < len; i++) {
869
+ leaf = path.list[i];
870
+ if (leaf.isApp)
871
+ emitAppChildren(leaf, type, data, false, excludePath);
872
+ if (emitEvent(leaf, type, data, false, excludePath))
873
+ return;
874
+ }
875
+ }
876
+ catch (e) {
877
+ debug.error(e);
878
+ }
879
+ }
880
+ const allowTypes = ['move', 'zoom', 'rotate', 'key'];
881
+ function emitAppChildren(leaf, type, data, capture, excludePath) {
882
+ if (allowTypes.some(name => type.startsWith(name)) && leaf.__.hitChildren && !exclude(leaf, excludePath)) {
883
+ let child;
884
+ for (let i = 0, len = leaf.children.length; i < len; i++) {
885
+ child = leaf.children[i];
886
+ if (!data.path.has(child) && child.__.hittable)
887
+ emitEvent(child, type, data, capture, excludePath);
888
+ }
889
+ }
890
+ }
891
+ function emitEvent(leaf, type, data, capture, excludePath) {
892
+ if (leaf.destroyed)
893
+ return false;
894
+ if (leaf.__.hitSelf && !exclude(leaf, excludePath)) {
895
+ if (State.updateEventStyle)
896
+ State.updateEventStyle(leaf, type);
897
+ if (leaf.hasEvent(type, capture)) {
898
+ data.phase = capture ? 1 : ((leaf === data.target) ? 2 : 3);
899
+ const event = EventCreator.get(type, data);
900
+ leaf.emitEvent(event, capture);
901
+ if (event.isStop)
902
+ return true;
903
+ }
904
+ }
905
+ return false;
906
+ }
907
+ function exclude(leaf, excludePath) {
908
+ return excludePath && excludePath.has(leaf);
909
+ }
910
+
911
+ const MultiTouchHelper = {
912
+ getData(list) {
913
+ const a = list[0];
914
+ const b = list[1];
915
+ const lastCenter = PointHelper.getCenter(a.from, b.from);
916
+ const center = PointHelper.getCenter(a.to, b.to);
917
+ const move = { x: center.x - lastCenter.x, y: center.y - lastCenter.y };
918
+ const lastDistance = PointHelper.getDistance(a.from, b.from);
919
+ const distance = PointHelper.getDistance(a.to, b.to);
920
+ const scale = distance / lastDistance;
921
+ const angle = PointHelper.getRotation(a.from, b.from, a.to, b.to);
922
+ return { move, scale, angle, center };
923
+ }
924
+ };
925
+
926
+ const config = {
927
+ wheel: {
928
+ zoomSpeed: 0.5,
929
+ moveSpeed: 0.5,
930
+ rotateSpeed: 0.5,
931
+ delta: { x: 80 / 4, y: 8.0 },
932
+ preventDefault: true
933
+ },
934
+ pointer: {
935
+ hitRadius: 5,
936
+ tapTime: 120,
937
+ longPressTime: 800,
938
+ transformTime: 500,
939
+ hover: true,
940
+ dragHover: true,
941
+ dragDistance: 2,
942
+ swipeDistance: 20,
943
+ preventDefaultMenu: true
944
+ },
945
+ cursor: true,
946
+ keyEvent: true
947
+ };
948
+
949
+ const { pathHasEventType, getMoveEventData, getZoomEventData, getRotateEventData } = InteractionHelper;
950
+ class InteractionBase {
951
+ get dragging() { return this.dragger.dragging; }
952
+ get moveMode() { return this.config.move.drag || this.isHoldSpaceKey || this.isHoldMiddleKey || (this.isHoldRightKey && this.dragger.moving) || this.isDragEmpty; }
953
+ get isDragEmpty() { return this.config.move.dragEmpty && this.isRootPath(this.hoverData) && (!this.downData || this.isRootPath(this.downData)); }
954
+ get isMobileDragEmpty() { return this.config.move.dragEmpty && !this.config.pointer.hover && this.downData && this.isTreePath(this.downData); }
955
+ get isHoldMiddleKey() { return this.config.move.holdMiddleKey && this.downData && PointerButton.middle(this.downData); }
956
+ get isHoldRightKey() { return this.config.move.holdRightKey && this.downData && PointerButton.right(this.downData); }
957
+ get isHoldSpaceKey() { return this.config.move.holdSpaceKey && Keyboard.isHoldSpaceKey(); }
958
+ get hitRadius() { return this.config.pointer.hitRadius; }
959
+ constructor(target, canvas, selector, userConfig) {
960
+ this.config = config;
961
+ this.tapCount = 0;
962
+ this.downKeyMap = {};
963
+ this.target = target;
964
+ this.canvas = canvas;
965
+ this.selector = selector;
966
+ this.defaultPath = new LeafList(target);
967
+ this.transformer = new Transformer(this);
968
+ this.dragger = new Dragger(this);
969
+ if (userConfig)
970
+ this.config = DataHelper.default(userConfig, this.config);
971
+ this.__listenEvents();
972
+ }
973
+ start() {
974
+ this.running = true;
975
+ }
976
+ stop() {
977
+ this.running = false;
978
+ }
979
+ receive(_event) { }
980
+ pointerDown(data, useDefaultPath) {
981
+ if (!data)
982
+ data = this.hoverData;
983
+ if (!data)
984
+ return;
985
+ PointerButton.defaultLeft(data);
986
+ this.updateDownData(data);
987
+ this.checkPath(data, useDefaultPath);
988
+ this.downTime = Date.now();
989
+ this.emit(PointerEvent.BEFORE_DOWN, data);
990
+ this.emit(PointerEvent.DOWN, data);
991
+ if (PointerButton.left(data)) {
992
+ this.tapWait();
993
+ this.longPressWait(data);
994
+ }
995
+ this.waitMenuTap = PointerButton.right(data);
996
+ this.dragger.setDragData(data);
997
+ if (!this.isHoldRightKey)
998
+ this.updateCursor(data);
999
+ }
1000
+ pointerMove(data) {
1001
+ if (!data)
1002
+ data = this.hoverData;
1003
+ if (!data)
1004
+ return;
1005
+ const { downData } = this;
1006
+ if (downData)
1007
+ PointerButton.defaultLeft(data);
1008
+ const hit = this.canvas.bounds.hitPoint(data);
1009
+ if (hit || downData) {
1010
+ this.pointerMoveReal(data);
1011
+ if (downData)
1012
+ this.dragger.checkDragOut(data);
1013
+ }
1014
+ }
1015
+ pointerMoveReal(data) {
1016
+ const { dragHover, dragDistance } = this.config.pointer;
1017
+ this.emit(PointerEvent.BEFORE_MOVE, data, this.defaultPath);
1018
+ if (this.downData) {
1019
+ const canDrag = PointHelper.getDistance(this.downData, data) > dragDistance;
1020
+ if (canDrag) {
1021
+ if (this.waitTap)
1022
+ this.pointerWaitCancel();
1023
+ this.waitMenuTap = false;
1024
+ }
1025
+ this.dragger.checkDrag(data, canDrag);
1026
+ }
1027
+ if (!this.dragger.moving) {
1028
+ this.updateHoverData(data);
1029
+ this.checkPath(data);
1030
+ this.emit(PointerEvent.MOVE, data);
1031
+ if (!(this.dragging && !dragHover))
1032
+ this.pointerHover(data);
1033
+ if (this.dragger.dragging) {
1034
+ this.dragger.dragOverOrOut(data);
1035
+ this.dragger.dragEnterOrLeave(data);
1036
+ }
1037
+ }
1038
+ this.updateCursor(this.downData || data);
1039
+ }
1040
+ pointerUp(data) {
1041
+ const { downData } = this;
1042
+ if (!data)
1043
+ data = downData;
1044
+ if (!downData)
1045
+ return;
1046
+ PointerButton.defaultLeft(data);
1047
+ this.findPath(data);
1048
+ const upData = Object.assign(Object.assign({}, data), { path: data.path.clone() });
1049
+ data.path.addList(downData.path.list);
1050
+ this.checkPath(data);
1051
+ this.downData = null;
1052
+ this.emit(PointerEvent.BEFORE_UP, data);
1053
+ this.emit(PointerEvent.UP, data);
1054
+ this.touchLeave(data);
1055
+ if (!data.isCancel) {
1056
+ this.tap(data);
1057
+ this.menuTap(data);
1058
+ }
1059
+ this.dragger.dragEnd(data);
1060
+ this.updateCursor(upData);
1061
+ }
1062
+ pointerCancel() {
1063
+ const data = Object.assign({}, this.dragger.dragData);
1064
+ data.isCancel = true;
1065
+ this.pointerUp(data);
1066
+ }
1067
+ multiTouch(data, list) {
1068
+ const { move, angle, scale, center } = MultiTouchHelper.getData(list);
1069
+ this.rotate(getRotateEventData(center, angle, data));
1070
+ this.zoom(getZoomEventData(center, scale, data));
1071
+ this.move(getMoveEventData(center, move, data));
1072
+ }
1073
+ menu(data) {
1074
+ this.findPath(data);
1075
+ this.emit(PointerEvent.MENU, data);
1076
+ }
1077
+ menuTap(data) {
1078
+ if (this.waitMenuTap)
1079
+ this.emit(PointerEvent.MENU_TAP, data);
1080
+ }
1081
+ move(data) {
1082
+ this.transformer.move(data);
1083
+ }
1084
+ zoom(data) {
1085
+ this.transformer.zoom(data);
1086
+ }
1087
+ rotate(data) {
1088
+ this.transformer.rotate(data);
1089
+ }
1090
+ transformEnd() {
1091
+ this.transformer.transformEnd();
1092
+ }
1093
+ keyDown(data) {
1094
+ if (!this.config.keyEvent)
1095
+ return;
1096
+ const { code } = data;
1097
+ if (!this.downKeyMap[code]) {
1098
+ this.downKeyMap[code] = true;
1099
+ Keyboard.setDownCode(code);
1100
+ this.emit(KeyEvent.HOLD, data, this.defaultPath);
1101
+ if (this.moveMode) {
1102
+ this.cancelHover();
1103
+ this.updateCursor();
1104
+ }
1105
+ }
1106
+ this.emit(KeyEvent.DOWN, data, this.defaultPath);
1107
+ }
1108
+ keyUp(data) {
1109
+ if (!this.config.keyEvent)
1110
+ return;
1111
+ const { code } = data;
1112
+ this.downKeyMap[code] = false;
1113
+ Keyboard.setUpCode(code);
1114
+ this.emit(KeyEvent.UP, data, this.defaultPath);
1115
+ if (this.cursor === 'grab')
1116
+ this.updateCursor();
1117
+ }
1118
+ pointerHover(data) {
1119
+ if (this.config.pointer.hover) {
1120
+ this.pointerOverOrOut(data);
1121
+ this.pointerEnterOrLeave(data);
1122
+ }
1123
+ }
1124
+ pointerOverOrOut(data) {
1125
+ const { path } = data;
1126
+ const { overPath } = this;
1127
+ this.overPath = path;
1128
+ if (overPath) {
1129
+ if (path.indexAt(0) !== overPath.indexAt(0)) {
1130
+ this.emit(PointerEvent.OUT, data, overPath);
1131
+ this.emit(PointerEvent.OVER, data, path);
1132
+ }
1133
+ }
1134
+ else {
1135
+ this.emit(PointerEvent.OVER, data, path);
1136
+ }
1137
+ }
1138
+ pointerEnterOrLeave(data) {
1139
+ let { path } = data;
1140
+ if (this.downData && !this.moveMode) {
1141
+ path = path.clone();
1142
+ this.downData.path.forEach(leaf => path.add(leaf));
1143
+ }
1144
+ const { enterPath } = this;
1145
+ this.enterPath = path;
1146
+ this.emit(PointerEvent.LEAVE, data, enterPath, path);
1147
+ this.emit(PointerEvent.ENTER, data, path, enterPath);
1148
+ }
1149
+ touchLeave(data) {
1150
+ if (data.pointerType === 'touch') {
1151
+ if (this.enterPath) {
1152
+ this.emit(PointerEvent.LEAVE, data);
1153
+ if (this.dragger.dragging)
1154
+ this.emit(DropEvent.LEAVE, data);
1155
+ }
1156
+ }
1157
+ }
1158
+ tap(data) {
1159
+ const { pointer } = this.config;
1160
+ const hasLong = this.longTap(data);
1161
+ if (!pointer.tapMore && hasLong)
1162
+ return;
1163
+ if (!this.waitTap)
1164
+ return;
1165
+ if (pointer.tapMore)
1166
+ this.emitTap(data);
1167
+ const useTime = Date.now() - this.downTime;
1168
+ const hasDouble = [PointerEvent.DOUBLE_TAP, PointerEvent.DOUBLE_CLICK].some(type => pathHasEventType(data.path, type));
1169
+ if (useTime < pointer.tapTime + 50 && hasDouble) {
1170
+ this.tapCount++;
1171
+ if (this.tapCount === 2) {
1172
+ this.tapWaitCancel();
1173
+ this.emitDoubleTap(data);
1174
+ }
1175
+ else {
1176
+ clearTimeout(this.tapTimer);
1177
+ this.tapTimer = setTimeout(() => {
1178
+ if (!pointer.tapMore) {
1179
+ this.tapWaitCancel();
1180
+ this.emitTap(data);
1181
+ }
1182
+ }, pointer.tapTime);
1183
+ }
1184
+ }
1185
+ else {
1186
+ if (!pointer.tapMore) {
1187
+ this.tapWaitCancel();
1188
+ this.emitTap(data);
1189
+ }
1190
+ }
1191
+ }
1192
+ findPath(data, options) {
1193
+ const { hitRadius, through } = this.config.pointer;
1194
+ const { bottomList } = this;
1195
+ const find = this.selector.getByPoint(data, hitRadius, Object.assign({ bottomList, name: data.type }, (options || { through })));
1196
+ if (find.throughPath)
1197
+ data.throughPath = find.throughPath;
1198
+ data.path = find.path;
1199
+ return find.path;
1200
+ }
1201
+ isRootPath(data) {
1202
+ return data && data.path.list[0].isLeafer;
1203
+ }
1204
+ isTreePath(data) {
1205
+ const app = this.target.app;
1206
+ if (!app || !app.isApp)
1207
+ return false;
1208
+ return app.editor && (!data.path.has(app.editor) && data.path.has(app.tree) && !data.target.syncEventer);
1209
+ }
1210
+ checkPath(data, useDefaultPath) {
1211
+ if (useDefaultPath || this.canMove(data))
1212
+ data.path = this.defaultPath;
1213
+ }
1214
+ canMove(data) {
1215
+ return this.moveMode && data && data.path.list.every(item => !item.isOutside);
1216
+ }
1217
+ isDrag(leaf) {
1218
+ return this.dragger.getList().has(leaf);
1219
+ }
1220
+ isPress(leaf) {
1221
+ return this.downData && this.downData.path.has(leaf);
1222
+ }
1223
+ isHover(leaf) {
1224
+ return this.enterPath && this.enterPath.has(leaf);
1225
+ }
1226
+ isFocus(leaf) {
1227
+ return this.focusData === leaf;
1228
+ }
1229
+ cancelHover() {
1230
+ const { hoverData } = this;
1231
+ if (hoverData) {
1232
+ hoverData.path = this.defaultPath;
1233
+ this.pointerHover(hoverData);
1234
+ }
1235
+ }
1236
+ updateDownData(data, options, merge) {
1237
+ const { downData } = this;
1238
+ if (!data && downData)
1239
+ data = downData;
1240
+ if (!data)
1241
+ return;
1242
+ this.findPath(data, options);
1243
+ if (merge && downData)
1244
+ data.path.addList(downData.path.list);
1245
+ this.downData = data;
1246
+ }
1247
+ updateHoverData(data) {
1248
+ if (!data)
1249
+ data = this.hoverData;
1250
+ if (!data)
1251
+ return;
1252
+ this.findPath(data, { exclude: this.dragger.getList(), name: PointerEvent.MOVE });
1253
+ this.hoverData = data;
1254
+ }
1255
+ updateCursor(data) {
1256
+ if (!this.config.cursor || !this.config.pointer.hover)
1257
+ return;
1258
+ if (!data) {
1259
+ this.updateHoverData();
1260
+ data = this.downData || this.hoverData;
1261
+ }
1262
+ if (this.dragger.moving) {
1263
+ return this.setCursor('grabbing');
1264
+ }
1265
+ else if (this.canMove(data)) {
1266
+ return this.setCursor(this.downData ? 'grabbing' : 'grab');
1267
+ }
1268
+ else if (!data)
1269
+ return;
1270
+ let leaf, cursor;
1271
+ const { path } = data;
1272
+ for (let i = 0, len = path.length; i < len; i++) {
1273
+ leaf = path.list[i];
1274
+ cursor = leaf.syncEventer ? leaf.syncEventer.cursor : leaf.cursor;
1275
+ if (cursor)
1276
+ break;
1277
+ }
1278
+ this.setCursor(cursor);
1279
+ }
1280
+ setCursor(cursor) {
1281
+ this.cursor = cursor;
1282
+ }
1283
+ getLocal(clientPoint, updateClient) {
1284
+ const clientBounds = this.canvas.getClientBounds(updateClient);
1285
+ return { x: clientPoint.clientX - clientBounds.x, y: clientPoint.clientY - clientBounds.y };
1286
+ }
1287
+ emitTap(data) {
1288
+ this.emit(PointerEvent.TAP, data);
1289
+ this.emit(PointerEvent.CLICK, data);
1290
+ }
1291
+ emitDoubleTap(data) {
1292
+ this.emit(PointerEvent.DOUBLE_TAP, data);
1293
+ this.emit(PointerEvent.DOUBLE_CLICK, data);
1294
+ }
1295
+ pointerWaitCancel() {
1296
+ this.tapWaitCancel();
1297
+ this.longPressWaitCancel();
1298
+ }
1299
+ tapWait() {
1300
+ clearTimeout(this.tapTimer);
1301
+ this.waitTap = true;
1302
+ }
1303
+ tapWaitCancel() {
1304
+ clearTimeout(this.tapTimer);
1305
+ this.waitTap = false;
1306
+ this.tapCount = 0;
1307
+ }
1308
+ longPressWait(data) {
1309
+ clearTimeout(this.longPressTimer);
1310
+ this.longPressTimer = setTimeout(() => {
1311
+ this.longPressed = true;
1312
+ this.emit(PointerEvent.LONG_PRESS, data);
1313
+ }, this.config.pointer.longPressTime);
1314
+ }
1315
+ longTap(data) {
1316
+ let hasLong;
1317
+ if (this.longPressed) {
1318
+ this.emit(PointerEvent.LONG_TAP, data);
1319
+ if (pathHasEventType(data.path, PointerEvent.LONG_TAP) || pathHasEventType(data.path, PointerEvent.LONG_PRESS))
1320
+ hasLong = true;
1321
+ }
1322
+ this.longPressWaitCancel();
1323
+ return hasLong;
1324
+ }
1325
+ longPressWaitCancel() {
1326
+ clearTimeout(this.longPressTimer);
1327
+ this.longPressed = false;
1328
+ }
1329
+ __onResize() {
1330
+ this.shrinkCanvasBounds = new Bounds(this.canvas.bounds);
1331
+ this.shrinkCanvasBounds.spread(-2);
1332
+ }
1333
+ __listenEvents() {
1334
+ const { target } = this;
1335
+ this.__eventIds = [target.on_(ResizeEvent.RESIZE, this.__onResize, this)];
1336
+ target.once(LeaferEvent.READY, () => this.__onResize());
1337
+ }
1338
+ __removeListenEvents() {
1339
+ this.target.off_(this.__eventIds);
1340
+ this.__eventIds.length = 0;
1341
+ }
1342
+ emit(type, data, path, excludePath) {
1343
+ if (this.running)
1344
+ emit(type, data, path, excludePath);
1345
+ }
1346
+ destroy() {
1347
+ if (this.__eventIds.length) {
1348
+ this.stop();
1349
+ this.__removeListenEvents();
1350
+ this.dragger.destroy();
1351
+ this.transformer.destroy();
1352
+ this.downData = this.overPath = this.enterPath = null;
1353
+ }
1354
+ }
1355
+ }
1356
+
1357
+ class Cursor {
1358
+ static set(name, value) {
1359
+ this.custom[name] = value;
1360
+ }
1361
+ static get(name) {
1362
+ return this.custom[name];
1363
+ }
1364
+ }
1365
+ Cursor.custom = {};
1366
+
1367
+ class HitCanvasManager extends CanvasManager {
1368
+ constructor() {
1369
+ super(...arguments);
1370
+ this.maxTotal = 1000;
1371
+ this.pathList = new LeafList();
1372
+ this.pixelList = new LeafList();
1373
+ }
1374
+ getPixelType(leaf, config) {
1375
+ this.__autoClear();
1376
+ this.pixelList.add(leaf);
1377
+ return Creator.hitCanvas(config);
1378
+ }
1379
+ getPathType(leaf) {
1380
+ this.__autoClear();
1381
+ this.pathList.add(leaf);
1382
+ return Creator.hitCanvas();
1383
+ }
1384
+ clearImageType() {
1385
+ this.__clearLeafList(this.pixelList);
1386
+ }
1387
+ clearPathType() {
1388
+ this.__clearLeafList(this.pathList);
1389
+ }
1390
+ __clearLeafList(leafList) {
1391
+ if (leafList.length) {
1392
+ leafList.forEach(leaf => {
1393
+ if (leaf.__hitCanvas) {
1394
+ leaf.__hitCanvas.destroy();
1395
+ leaf.__hitCanvas = null;
1396
+ }
1397
+ });
1398
+ leafList.reset();
1399
+ }
1400
+ }
1401
+ __autoClear() {
1402
+ if (this.pathList.length + this.pixelList.length > this.maxTotal)
1403
+ this.clear();
1404
+ }
1405
+ clear() {
1406
+ this.clearPathType();
1407
+ this.clearImageType();
1408
+ }
1409
+ }
1410
+
1411
+ const { toInnerRadiusPointOf, copy, setRadius } = PointHelper;
1412
+ const inner = {};
1413
+ const leaf = Leaf.prototype;
1414
+ leaf.__hitWorld = function (point) {
1415
+ if (!this.__.hitSelf)
1416
+ return false;
1417
+ if (this.__.hitRadius) {
1418
+ copy(inner, point), point = inner;
1419
+ setRadius(point, this.__.hitRadius);
1420
+ }
1421
+ toInnerRadiusPointOf(point, this.__world, inner);
1422
+ const { width, height } = this.__world;
1423
+ const isSmall = width < 10 && height < 10;
1424
+ if (this.__.hitBox || isSmall) {
1425
+ if (BoundsHelper.hitRadiusPoint(this.__layout.boxBounds, inner))
1426
+ return true;
1427
+ if (isSmall)
1428
+ return false;
1429
+ }
1430
+ if (this.__layout.hitCanvasChanged || !this.__hitCanvas) {
1431
+ this.__updateHitCanvas();
1432
+ if (!this.__layout.boundsChanged)
1433
+ this.__layout.hitCanvasChanged = false;
1434
+ }
1435
+ return this.__hit(inner);
1436
+ };
1437
+ leaf.__hitFill = function (inner) { var _a; return (_a = this.__hitCanvas) === null || _a === void 0 ? void 0 : _a.hitFill(inner, this.__.windingRule); };
1438
+ leaf.__hitStroke = function (inner, strokeWidth) { var _a; return (_a = this.__hitCanvas) === null || _a === void 0 ? void 0 : _a.hitStroke(inner, strokeWidth); };
1439
+ leaf.__hitPixel = function (inner) { var _a; return (_a = this.__hitCanvas) === null || _a === void 0 ? void 0 : _a.hitPixel(inner, this.__layout.renderBounds, this.__hitCanvas.hitScale); };
1440
+ leaf.__drawHitPath = function (canvas) { if (canvas)
1441
+ this.__drawRenderPath(canvas); };
1442
+
1443
+ const matrix = new Matrix();
1444
+ const ui$2 = UI.prototype;
1445
+ ui$2.__updateHitCanvas = function () {
1446
+ const data = this.__, { hitCanvasManager } = this.leafer;
1447
+ const isHitPixelFill = (data.__pixelFill || data.__isCanvas) && data.hitFill === 'pixel';
1448
+ const isHitPixelStroke = data.__pixelStroke && data.hitStroke === 'pixel';
1449
+ const isHitPixel = isHitPixelFill || isHitPixelStroke;
1450
+ if (!this.__hitCanvas)
1451
+ this.__hitCanvas = isHitPixel ? hitCanvasManager.getPixelType(this, { contextSettings: { willReadFrequently: true } }) : hitCanvasManager.getPathType(this);
1452
+ const h = this.__hitCanvas;
1453
+ if (isHitPixel) {
1454
+ const { renderBounds } = this.__layout;
1455
+ const size = Platform.image.hitCanvasSize;
1456
+ const scale = h.hitScale = tempBounds.set(0, 0, size, size).getFitMatrix(renderBounds, 0.5).a;
1457
+ const { x, y, width, height } = tempBounds.set(renderBounds).scale(scale);
1458
+ h.resize({ width, height, pixelRatio: 1 });
1459
+ h.clear();
1460
+ ImageManager.patternLocked = true;
1461
+ this.__renderShape(h, { matrix: matrix.setWith(this.__world).scaleWith(1 / scale).invertWith().translate(-x, -y) }, !isHitPixelFill, !isHitPixelStroke);
1462
+ ImageManager.patternLocked = false;
1463
+ h.resetTransform();
1464
+ data.__isHitPixel = true;
1465
+ }
1466
+ else {
1467
+ data.__isHitPixel && (data.__isHitPixel = false);
1468
+ }
1469
+ this.__drawHitPath(h);
1470
+ h.setStrokeOptions(data);
1471
+ };
1472
+ ui$2.__hit = function (inner) {
1473
+ if (Platform.name === 'miniapp')
1474
+ this.__drawHitPath(this.__hitCanvas);
1475
+ const data = this.__;
1476
+ if (data.__isHitPixel && this.__hitPixel(inner))
1477
+ return true;
1478
+ const { hitFill } = data;
1479
+ const needHitFillPath = ((data.fill || data.__isCanvas) && (hitFill === 'path' || (hitFill === 'pixel' && !(data.__pixelFill || data.__isCanvas)))) || hitFill === 'all';
1480
+ if (needHitFillPath && this.__hitFill(inner))
1481
+ return true;
1482
+ const { hitStroke, __strokeWidth } = data;
1483
+ const needHitStrokePath = (data.stroke && (hitStroke === 'path' || (hitStroke === 'pixel' && !data.__pixelStroke))) || hitStroke === 'all';
1484
+ if (!needHitFillPath && !needHitStrokePath)
1485
+ return false;
1486
+ const radiusWidth = inner.radiusX * 2;
1487
+ let hitWidth = radiusWidth;
1488
+ if (needHitStrokePath) {
1489
+ switch (data.strokeAlign) {
1490
+ case 'inside':
1491
+ hitWidth += __strokeWidth * 2;
1492
+ if (!needHitFillPath && this.__hitFill(inner) && this.__hitStroke(inner, hitWidth))
1493
+ return true;
1494
+ hitWidth = radiusWidth;
1495
+ break;
1496
+ case 'center':
1497
+ hitWidth += __strokeWidth;
1498
+ break;
1499
+ case 'outside':
1500
+ hitWidth += __strokeWidth * 2;
1501
+ if (!needHitFillPath) {
1502
+ if (!this.__hitFill(inner) && this.__hitStroke(inner, hitWidth))
1503
+ return true;
1504
+ hitWidth = radiusWidth;
1505
+ }
1506
+ break;
1507
+ }
1508
+ }
1509
+ return hitWidth ? this.__hitStroke(inner, hitWidth) : false;
1510
+ };
1511
+
1512
+ const ui$1 = new UI();
1513
+ const rect = Rect.prototype;
1514
+ rect.__updateHitCanvas = function () {
1515
+ if (this.stroke || this.cornerRadius || ((this.fill || this.__.__isCanvas) && this.hitFill === 'pixel') || this.hitStroke === 'all')
1516
+ ui$1.__updateHitCanvas.call(this);
1517
+ else if (this.__hitCanvas)
1518
+ this.__hitCanvas = null;
1519
+ };
1520
+ rect.__hitFill = function (inner) {
1521
+ return this.__hitCanvas ? ui$1.__hitFill.call(this, inner) : BoundsHelper.hitRadiusPoint(this.__layout.boxBounds, inner);
1522
+ };
1523
+
1524
+ const ui = UI.prototype, group = Group.prototype;
1525
+ ui.find = function (condition, options) {
1526
+ return this.leafer ? this.leafer.selector.getBy(condition, this, false, options) : [];
1527
+ };
1528
+ ui.findOne = function (condition, options) {
1529
+ return this.leafer ? this.leafer.selector.getBy(condition, this, true, options) : null;
1530
+ };
1531
+ group.pick = function (hitPoint, options) {
1532
+ this.__layout.update();
1533
+ if (!options)
1534
+ options = {};
1535
+ return this.leafer ? this.leafer.selector.getByPoint(hitPoint, options.hitRadius || 0, Object.assign(Object.assign({}, options), { target: this })) : null;
1536
+ };
1537
+
1538
+ const canvas = LeaferCanvasBase.prototype;
1539
+ canvas.hitFill = function (point, fillRule) {
1540
+ return fillRule ? this.context.isPointInPath(point.x, point.y, fillRule) : this.context.isPointInPath(point.x, point.y);
1541
+ };
1542
+ canvas.hitStroke = function (point, strokeWidth) {
1543
+ this.strokeWidth = strokeWidth;
1544
+ return this.context.isPointInStroke(point.x, point.y);
1545
+ };
1546
+ canvas.hitPixel = function (radiusPoint, offset, scale = 1) {
1547
+ let { x, y, radiusX, radiusY } = radiusPoint;
1548
+ if (offset)
1549
+ x -= offset.x, y -= offset.y;
1550
+ tempBounds.set(x - radiusX, y - radiusY, radiusX * 2, radiusY * 2).scale(scale).ceil();
1551
+ const { data } = this.context.getImageData(tempBounds.x, tempBounds.y, tempBounds.width || 1, tempBounds.height || 1);
1552
+ for (let i = 0, len = data.length; i < len; i += 4) {
1553
+ if (data[i + 3] > 0)
1554
+ return true;
1555
+ }
1556
+ return data[3] > 0;
1557
+ };
1558
+
1559
+ export { App, Cursor, DragEvent, DropEvent, HitCanvasManager, InteractionBase, InteractionHelper, KeyEvent, Keyboard, LeaferTypeCreator, MoveEvent, MultiTouchHelper, PointerButton, PointerEvent, RotateEvent, SwipeEvent, UIEvent, ZoomEvent, addInteractionWindow };