@plait/common 0.1.0-next.1 → 0.1.0-next.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/constants/default.d.ts +1 -0
- package/constants/media.d.ts +3 -0
- package/constants/resize.d.ts +1 -1
- package/core/image-base.component.d.ts +29 -0
- package/core/plugin-element.d.ts +7 -0
- package/{esm2020 → esm2022}/constants/default.mjs +2 -1
- package/esm2022/constants/media.mjs +8 -0
- package/esm2022/constants/resize.mjs +19 -0
- package/esm2022/core/image-base.component.mjs +93 -0
- package/esm2022/core/plugin-element.mjs +14 -0
- package/esm2022/generators/active.generator.mjs +46 -0
- package/esm2022/generators/generator.mjs +42 -0
- package/esm2022/generators/image.generator.mjs +54 -0
- package/esm2022/generators/index.mjs +4 -0
- package/esm2022/plugins/index.mjs +3 -0
- package/esm2022/plugins/text-options.mjs +2 -0
- package/esm2022/plugins/with-resize.mjs +101 -0
- package/esm2022/public-api.mjs +12 -0
- package/esm2022/shapes/common.mjs +14 -0
- package/esm2022/shapes/index.mjs +2 -0
- package/esm2022/transforms/common.mjs +15 -0
- package/esm2022/transforms/index.mjs +2 -0
- package/esm2022/transforms/property.mjs +21 -0
- package/esm2022/utils/creation-mode.mjs +19 -0
- package/esm2022/utils/direction.mjs +95 -0
- package/esm2022/utils/hot-key.mjs +29 -0
- package/esm2022/utils/image.mjs +40 -0
- package/esm2022/utils/index.mjs +9 -0
- package/esm2022/utils/line-path.mjs +146 -0
- package/esm2022/utils/rectangle.mjs +16 -0
- package/esm2022/utils/resize.mjs +61 -0
- package/esm2022/utils/text.mjs +11 -0
- package/fesm2022/plait-common.mjs +840 -0
- package/fesm2022/plait-common.mjs.map +1 -0
- package/{generator → generators}/active.generator.d.ts +4 -2
- package/{generator → generators}/generator.d.ts +1 -0
- package/generators/image.generator.d.ts +23 -0
- package/{generator → generators}/index.d.ts +1 -0
- package/package.json +7 -12
- package/plugins/index.d.ts +1 -0
- package/plugins/text-options.d.ts +5 -0
- package/plugins/with-resize.d.ts +12 -14
- package/public-api.d.ts +4 -3
- package/{shape → shapes}/common.d.ts +1 -1
- package/transforms/common.d.ts +2 -0
- package/transforms/index.d.ts +1 -3
- package/transforms/property.d.ts +8 -0
- package/utils/creation-mode.d.ts +9 -0
- package/utils/direction.d.ts +29 -0
- package/utils/hot-key.d.ts +6 -0
- package/utils/image.d.ts +12 -0
- package/utils/index.d.ts +7 -0
- package/utils/line-path.d.ts +17 -0
- package/utils/rectangle.d.ts +7 -0
- package/utils/resize.d.ts +12 -10
- package/utils/text.d.ts +3 -0
- package/esm2020/constants/media.mjs +0 -5
- package/esm2020/constants/resize.mjs +0 -19
- package/esm2020/generator/active.generator.mjs +0 -40
- package/esm2020/generator/generator.mjs +0 -29
- package/esm2020/generator/index.mjs +0 -3
- package/esm2020/plugins/index.mjs +0 -2
- package/esm2020/plugins/with-resize.mjs +0 -93
- package/esm2020/public-api.mjs +0 -11
- package/esm2020/rectangle.mjs +0 -16
- package/esm2020/shape/common.mjs +0 -6
- package/esm2020/shape/index.mjs +0 -2
- package/esm2020/transforms/element.mjs +0 -17
- package/esm2020/transforms/index.mjs +0 -5
- package/esm2020/utils/index.mjs +0 -2
- package/esm2020/utils/resize.mjs +0 -69
- package/fesm2015/plait-common.mjs +0 -304
- package/fesm2015/plait-common.mjs.map +0 -1
- package/fesm2020/plait-common.mjs +0 -304
- package/fesm2020/plait-common.mjs.map +0 -1
- package/rectangle.d.ts +0 -4
- package/transforms/element.d.ts +0 -2
- /package/{esm2020 → esm2022}/constants/index.mjs +0 -0
- /package/{esm2020 → esm2022}/plait-common.mjs +0 -0
- /package/{shape → shapes}/index.d.ts +0 -0
|
@@ -0,0 +1,840 @@
|
|
|
1
|
+
import { createG, RectangleClient, drawRectangle, drawCircle, PlaitBoard, createForeignObject, updateForeignObject, getSelectedElements, PlaitElement, Transforms, PlaitPointerType, isMainPointer, transformPoint, toPoint, preventTouchMove, distanceBetweenPointAndPoint, PRESS_AND_MOVE_BUFFER, throttleRAF, handleTouchTarget, MERGING, Direction, hotkeys, PlaitContextService, PlaitPluginElementComponent, isSelectionMoving, ACTIVE_STROKE_WIDTH } from '@plait/core';
|
|
2
|
+
import { isKeyHotkey } from 'is-hotkey';
|
|
3
|
+
import * as i0 from '@angular/core';
|
|
4
|
+
import { Directive, Input } from '@angular/core';
|
|
5
|
+
|
|
6
|
+
const BASE = 4;
|
|
7
|
+
const PRIMARY_COLOR = '#6698FF';
|
|
8
|
+
const RESIZE_HANDLE_DIAMETER = 8;
|
|
9
|
+
const WithTextPluginKey = 'plait-text-plugin-key';
|
|
10
|
+
|
|
11
|
+
var MediaKeys;
|
|
12
|
+
(function (MediaKeys) {
|
|
13
|
+
MediaKeys["image"] = "image";
|
|
14
|
+
})(MediaKeys || (MediaKeys = {}));
|
|
15
|
+
const PICTURE_ACCEPTED_UPLOAD_SIZE = 20;
|
|
16
|
+
const acceptImageTypes = ['png', 'jpeg', 'gif', 'bmp'];
|
|
17
|
+
const WithCommonPluginKey = 'plait-common-plugin-key';
|
|
18
|
+
|
|
19
|
+
var ResizeCursorClass;
|
|
20
|
+
(function (ResizeCursorClass) {
|
|
21
|
+
ResizeCursorClass["ew"] = "ew-resize";
|
|
22
|
+
ResizeCursorClass["ns"] = "ns-resize";
|
|
23
|
+
ResizeCursorClass["nesw"] = "nesw-resize";
|
|
24
|
+
ResizeCursorClass["nwse"] = "nwse-resize";
|
|
25
|
+
})(ResizeCursorClass || (ResizeCursorClass = {}));
|
|
26
|
+
var ResizeHandle;
|
|
27
|
+
(function (ResizeHandle) {
|
|
28
|
+
ResizeHandle["ne"] = "ne";
|
|
29
|
+
ResizeHandle["n"] = "n";
|
|
30
|
+
ResizeHandle["nw"] = "nw";
|
|
31
|
+
ResizeHandle["e"] = "w";
|
|
32
|
+
ResizeHandle["se"] = "se";
|
|
33
|
+
ResizeHandle["s"] = "s";
|
|
34
|
+
ResizeHandle["sw"] = "sw";
|
|
35
|
+
ResizeHandle["w"] = "w";
|
|
36
|
+
})(ResizeHandle || (ResizeHandle = {}));
|
|
37
|
+
|
|
38
|
+
class Generator {
|
|
39
|
+
constructor(board, options) {
|
|
40
|
+
this.board = board;
|
|
41
|
+
this.options = options;
|
|
42
|
+
}
|
|
43
|
+
draw(element, parentG, data) {
|
|
44
|
+
if (this.canDraw && this.canDraw(element, data)) {
|
|
45
|
+
const g = this.baseDraw(element, data);
|
|
46
|
+
if (g) {
|
|
47
|
+
if (this.g) {
|
|
48
|
+
this.g.replaceWith(g);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
parentG.appendChild(g);
|
|
52
|
+
}
|
|
53
|
+
this.g = g;
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
this.destroy();
|
|
57
|
+
}
|
|
58
|
+
if (hasAfterDraw(this)) {
|
|
59
|
+
this.afterDraw(element);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
this.destroy();
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
destroy() {
|
|
67
|
+
if (this.g) {
|
|
68
|
+
this.g.remove();
|
|
69
|
+
this.g = undefined;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
function hasAfterDraw(value) {
|
|
74
|
+
if (value.afterDraw) {
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
class ActiveGenerator extends Generator {
|
|
81
|
+
constructor(board, options) {
|
|
82
|
+
super(board, options);
|
|
83
|
+
this.board = board;
|
|
84
|
+
this.options = options;
|
|
85
|
+
this.hasResizeHandle = false;
|
|
86
|
+
}
|
|
87
|
+
canDraw(element, data) {
|
|
88
|
+
if (data.selected) {
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
baseDraw(element, data) {
|
|
96
|
+
const activeG = createG();
|
|
97
|
+
const rectangle = this.options.getRectangle(element);
|
|
98
|
+
const delta = this.options.getStrokeWidth();
|
|
99
|
+
const activeRectangle = RectangleClient.inflate(rectangle, delta);
|
|
100
|
+
const strokeG = drawRectangle(this.board, activeRectangle, {
|
|
101
|
+
stroke: PRIMARY_COLOR,
|
|
102
|
+
strokeWidth: delta
|
|
103
|
+
});
|
|
104
|
+
activeG.append(strokeG);
|
|
105
|
+
strokeG.style.opacity = `${this.options.getStrokeOpacity()}`;
|
|
106
|
+
if (this.options.hasResizeHandle()) {
|
|
107
|
+
this.hasResizeHandle = true;
|
|
108
|
+
// resize handle
|
|
109
|
+
const options = { stroke: '#999999', strokeWidth: 1, fill: '#FFF', fillStyle: 'solid' };
|
|
110
|
+
const leftTopHandleG = drawCircle(PlaitBoard.getRoughSVG(this.board), [activeRectangle.x, activeRectangle.y], RESIZE_HANDLE_DIAMETER, options);
|
|
111
|
+
const rightTopHandleG = drawCircle(PlaitBoard.getRoughSVG(this.board), [activeRectangle.x + activeRectangle.width, activeRectangle.y], RESIZE_HANDLE_DIAMETER, options);
|
|
112
|
+
const rightBottomHandleG = drawCircle(PlaitBoard.getRoughSVG(this.board), [activeRectangle.x + activeRectangle.width, activeRectangle.y + activeRectangle.height], RESIZE_HANDLE_DIAMETER, options);
|
|
113
|
+
const leftBottomHandleG = drawCircle(PlaitBoard.getRoughSVG(this.board), [activeRectangle.x, activeRectangle.y + activeRectangle.height], RESIZE_HANDLE_DIAMETER, options);
|
|
114
|
+
activeG.append(...[leftTopHandleG, rightTopHandleG, rightBottomHandleG, leftBottomHandleG]);
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
this.hasResizeHandle = false;
|
|
118
|
+
}
|
|
119
|
+
return activeG;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
class ImageGenerator extends Generator {
|
|
124
|
+
constructor(board, options) {
|
|
125
|
+
super(board, options);
|
|
126
|
+
this.board = board;
|
|
127
|
+
this.options = options;
|
|
128
|
+
}
|
|
129
|
+
canDraw(element, data) {
|
|
130
|
+
return !!this.options.getImageItem(element);
|
|
131
|
+
}
|
|
132
|
+
baseDraw(element, viewContainerRef) {
|
|
133
|
+
const g = createG();
|
|
134
|
+
const foreignRectangle = this.options.getRectangle(element);
|
|
135
|
+
this.foreignObject = createForeignObject(foreignRectangle.x, foreignRectangle.y, foreignRectangle.width, foreignRectangle.height);
|
|
136
|
+
g.append(this.foreignObject);
|
|
137
|
+
const componentType = this.board.getPluginOptions(WithCommonPluginKey)
|
|
138
|
+
.imageComponentType;
|
|
139
|
+
if (!componentType) {
|
|
140
|
+
throw new Error('Not implement ImageBaseComponent error.');
|
|
141
|
+
}
|
|
142
|
+
this.componentRef = viewContainerRef.createComponent(componentType);
|
|
143
|
+
this.componentRef.instance.board = this.board;
|
|
144
|
+
this.componentRef.instance.imageItem = this.options.getImageItem(element);
|
|
145
|
+
this.componentRef.instance.element = element;
|
|
146
|
+
this.componentRef.instance.getRectangle = () => {
|
|
147
|
+
return this.options.getRectangle(element);
|
|
148
|
+
};
|
|
149
|
+
this.componentRef.instance.cdr.markForCheck();
|
|
150
|
+
this.foreignObject.append(this.componentRef.instance.nativeElement);
|
|
151
|
+
return g;
|
|
152
|
+
}
|
|
153
|
+
updateImage(nodeG, previous, current) {
|
|
154
|
+
if (previous !== current && this.componentRef) {
|
|
155
|
+
this.componentRef.instance.imageItem = this.options.getImageItem(current);
|
|
156
|
+
this.componentRef.instance.getRectangle = () => {
|
|
157
|
+
return this.options.getRectangle(current);
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
const currentForeignObject = this.options.getRectangle(current);
|
|
161
|
+
updateForeignObject(this.g, currentForeignObject.width, currentForeignObject.height, currentForeignObject.x, currentForeignObject.y);
|
|
162
|
+
// solve image lose on move node
|
|
163
|
+
if (this.foreignObject.children.length === 0) {
|
|
164
|
+
this.foreignObject.append(this.componentRef.instance.nativeElement);
|
|
165
|
+
}
|
|
166
|
+
this.componentRef?.instance.cdr.markForCheck();
|
|
167
|
+
}
|
|
168
|
+
destroy() {
|
|
169
|
+
super.destroy();
|
|
170
|
+
this.componentRef?.destroy();
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const setProperty = (board, options, callback) => {
|
|
175
|
+
const selectedElements = getSelectedElements(board);
|
|
176
|
+
selectedElements.forEach(element => {
|
|
177
|
+
const path = PlaitBoard.findPath(board, element);
|
|
178
|
+
if (callback) {
|
|
179
|
+
const component = PlaitElement.getComponent(element);
|
|
180
|
+
callback(component, path);
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
Transforms.setNode(board, options, path);
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
const setStrokeStyle = (board, strokeStyle) => {
|
|
189
|
+
setProperty(board, { strokeStyle });
|
|
190
|
+
};
|
|
191
|
+
const setFillColor = (board, fill) => {
|
|
192
|
+
setProperty(board, { fill });
|
|
193
|
+
};
|
|
194
|
+
const setStrokeColor = (board, strokeColor) => {
|
|
195
|
+
setProperty(board, { strokeColor });
|
|
196
|
+
};
|
|
197
|
+
const setStrokeWidth = (board, strokeWidth) => {
|
|
198
|
+
setProperty(board, { strokeWidth });
|
|
199
|
+
};
|
|
200
|
+
const PropertyTransforms = {
|
|
201
|
+
setFillColor,
|
|
202
|
+
setStrokeStyle,
|
|
203
|
+
setProperty,
|
|
204
|
+
setStrokeWidth,
|
|
205
|
+
setStrokeColor
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
const normalizeShapePoints = (points, shift = false) => {
|
|
209
|
+
let start = points[0];
|
|
210
|
+
let end = points[1];
|
|
211
|
+
if (shift) {
|
|
212
|
+
const width = Math.abs(start[0] - end[0]);
|
|
213
|
+
const height = Math.abs(start[1] - end[1]);
|
|
214
|
+
const edge = Math.max(height, width);
|
|
215
|
+
end = [start[0] + (end[0] > start[0] ? edge : -edge), start[1] + (end[1] > start[1] ? edge : -edge)];
|
|
216
|
+
}
|
|
217
|
+
const leftTopPoint = [Math.min(start[0], end[0]), Math.min(start[1], end[1])];
|
|
218
|
+
let rightBottomPoint = [Math.max(start[0], end[0]), Math.max(start[1], end[1])];
|
|
219
|
+
return [leftTopPoint, rightBottomPoint];
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
const getResizeHandleByIndex = (index) => {
|
|
223
|
+
switch (index) {
|
|
224
|
+
case 0:
|
|
225
|
+
return ResizeHandle.nw;
|
|
226
|
+
case 1:
|
|
227
|
+
return ResizeHandle.ne;
|
|
228
|
+
case 2:
|
|
229
|
+
return ResizeHandle.se;
|
|
230
|
+
case 3:
|
|
231
|
+
return ResizeHandle.sw;
|
|
232
|
+
default:
|
|
233
|
+
return null;
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
const getResizeCursorClassByIndex = (index) => {
|
|
237
|
+
switch (index) {
|
|
238
|
+
case 0:
|
|
239
|
+
return ResizeCursorClass.nwse;
|
|
240
|
+
case 1:
|
|
241
|
+
return ResizeCursorClass.nesw;
|
|
242
|
+
case 2:
|
|
243
|
+
return ResizeCursorClass.nwse;
|
|
244
|
+
case 3:
|
|
245
|
+
return ResizeCursorClass.nesw;
|
|
246
|
+
default:
|
|
247
|
+
return null;
|
|
248
|
+
}
|
|
249
|
+
};
|
|
250
|
+
const getRectangleResizeHandleRefs = (rectangle, diameter) => {
|
|
251
|
+
const centers = RectangleClient.getCornerPoints(rectangle);
|
|
252
|
+
return centers.map((center, index) => {
|
|
253
|
+
return {
|
|
254
|
+
rectangle: {
|
|
255
|
+
x: center[0] - diameter / 2,
|
|
256
|
+
y: center[1] - diameter / 2,
|
|
257
|
+
width: diameter,
|
|
258
|
+
height: diameter
|
|
259
|
+
},
|
|
260
|
+
handle: getResizeHandleByIndex(index),
|
|
261
|
+
cursorClass: getResizeCursorClassByIndex(index)
|
|
262
|
+
};
|
|
263
|
+
});
|
|
264
|
+
};
|
|
265
|
+
const IS_RESIZING = new WeakMap();
|
|
266
|
+
const isResizing = (board) => {
|
|
267
|
+
return !!IS_RESIZING.get(board);
|
|
268
|
+
};
|
|
269
|
+
const isResizingByCondition = (board, match) => {
|
|
270
|
+
return isResizing(board) && match(IS_RESIZING.get(board));
|
|
271
|
+
};
|
|
272
|
+
const addResizing = (board, resizeRef, key) => {
|
|
273
|
+
PlaitBoard.getBoardContainer(board).classList.add(`${key}-resizing`);
|
|
274
|
+
IS_RESIZING.set(board, resizeRef);
|
|
275
|
+
};
|
|
276
|
+
const removeResizing = (board, key) => {
|
|
277
|
+
PlaitBoard.getBoardContainer(board).classList.remove(`${key}-resizing`);
|
|
278
|
+
IS_RESIZING.delete(board);
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
const generalCanResize = (board, event) => {
|
|
282
|
+
return (PlaitBoard.isReadonly(board) ||
|
|
283
|
+
PlaitBoard.hasBeenTextEditing(board) ||
|
|
284
|
+
!PlaitBoard.isPointer(board, PlaitPointerType.hand) ||
|
|
285
|
+
!isMainPointer(event));
|
|
286
|
+
};
|
|
287
|
+
const withResize = (board, options) => {
|
|
288
|
+
const { pointerDown, pointerMove, globalPointerUp } = board;
|
|
289
|
+
let resizeDetectResult = null;
|
|
290
|
+
let resizeRef = null;
|
|
291
|
+
let startPoint = null;
|
|
292
|
+
let hoveDetectResult = null;
|
|
293
|
+
board.pointerDown = (event) => {
|
|
294
|
+
if (!options.canResize() || !generalCanResize(board, event)) {
|
|
295
|
+
pointerDown(event);
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
const point = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
|
|
299
|
+
resizeDetectResult = options.detect(point);
|
|
300
|
+
if (resizeDetectResult) {
|
|
301
|
+
if (resizeDetectResult.cursorClass) {
|
|
302
|
+
PlaitBoard.getBoardContainer(board).classList.add(`${resizeDetectResult.cursorClass}`);
|
|
303
|
+
}
|
|
304
|
+
startPoint = [event.x, event.y];
|
|
305
|
+
resizeRef = {
|
|
306
|
+
path: PlaitBoard.findPath(board, resizeDetectResult.element),
|
|
307
|
+
element: resizeDetectResult.element,
|
|
308
|
+
handle: resizeDetectResult.handle
|
|
309
|
+
};
|
|
310
|
+
preventTouchMove(board, event, true);
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
pointerDown(event);
|
|
314
|
+
};
|
|
315
|
+
board.pointerMove = (event) => {
|
|
316
|
+
if (!options.canResize() || !generalCanResize(board, event)) {
|
|
317
|
+
pointerMove(event);
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
if (startPoint && resizeDetectResult && !isResizing(board)) {
|
|
321
|
+
// prevent text from being selected
|
|
322
|
+
event.preventDefault();
|
|
323
|
+
const endPoint = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
|
|
324
|
+
const distance = distanceBetweenPointAndPoint(startPoint[0], startPoint[1], endPoint[0], endPoint[1]);
|
|
325
|
+
if (distance > PRESS_AND_MOVE_BUFFER) {
|
|
326
|
+
addResizing(board, resizeRef, options.key);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
if (isResizing(board) && startPoint) {
|
|
330
|
+
// prevent text from being selected
|
|
331
|
+
event.preventDefault();
|
|
332
|
+
const endTransformPoint = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
|
|
333
|
+
throttleRAF(() => {
|
|
334
|
+
const endPoint = [event.x, event.y];
|
|
335
|
+
if (startPoint && resizeRef) {
|
|
336
|
+
handleTouchTarget(board);
|
|
337
|
+
const offsetX = endPoint[0] - startPoint[0];
|
|
338
|
+
const offsetY = endPoint[1] - startPoint[1];
|
|
339
|
+
options.onResize(resizeRef, { offsetX, offsetY, endTransformPoint });
|
|
340
|
+
MERGING.set(board, true);
|
|
341
|
+
}
|
|
342
|
+
});
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
else {
|
|
346
|
+
const point = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
|
|
347
|
+
const resizeDetectResult = options.detect(point);
|
|
348
|
+
if (resizeDetectResult) {
|
|
349
|
+
hoveDetectResult = resizeDetectResult;
|
|
350
|
+
if (hoveDetectResult.cursorClass) {
|
|
351
|
+
PlaitBoard.getBoardContainer(board).classList.add(`${hoveDetectResult.cursorClass}`);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
else {
|
|
355
|
+
if (hoveDetectResult) {
|
|
356
|
+
if (hoveDetectResult.cursorClass) {
|
|
357
|
+
PlaitBoard.getBoardContainer(board).classList.remove(`${hoveDetectResult.cursorClass}`);
|
|
358
|
+
}
|
|
359
|
+
hoveDetectResult = null;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
pointerMove(event);
|
|
364
|
+
};
|
|
365
|
+
board.globalPointerUp = (event) => {
|
|
366
|
+
globalPointerUp(event);
|
|
367
|
+
if (isResizing(board) || resizeDetectResult) {
|
|
368
|
+
options.endResize && options.endResize(resizeRef);
|
|
369
|
+
removeResizing(board, options.key);
|
|
370
|
+
startPoint = null;
|
|
371
|
+
resizeDetectResult = null;
|
|
372
|
+
resizeRef = null;
|
|
373
|
+
MERGING.set(board, false);
|
|
374
|
+
preventTouchMove(board, event, false);
|
|
375
|
+
}
|
|
376
|
+
};
|
|
377
|
+
return board;
|
|
378
|
+
};
|
|
379
|
+
|
|
380
|
+
const handleDirectionFactors = {
|
|
381
|
+
[Direction.left]: { x: -1, y: 0 },
|
|
382
|
+
[Direction.right]: { x: 1, y: 0 },
|
|
383
|
+
[Direction.top]: { x: 0, y: -1 },
|
|
384
|
+
[Direction.bottom]: { x: 0, y: 1 }
|
|
385
|
+
};
|
|
386
|
+
function getDirectionByPointOfRectangle(point) {
|
|
387
|
+
if (point[0] === 0) {
|
|
388
|
+
return Direction.left;
|
|
389
|
+
}
|
|
390
|
+
if (point[0] === 1) {
|
|
391
|
+
return Direction.right;
|
|
392
|
+
}
|
|
393
|
+
if (point[1] === 0) {
|
|
394
|
+
return Direction.top;
|
|
395
|
+
}
|
|
396
|
+
if (point[1] === 1) {
|
|
397
|
+
return Direction.bottom;
|
|
398
|
+
}
|
|
399
|
+
return undefined;
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
402
|
+
* this function accepts vector parameter, the vector parameter vector is based on the screen coordinate system
|
|
403
|
+
* vector[0] and vector[1] are the x and y components of the vector respectively.
|
|
404
|
+
* if the vector has only one direction, the function returns a string in that direction, such as 'right', 'top', 'bottom' or 'left'.
|
|
405
|
+
* if the vector has two directions, the function will return the string in which direction it is closer.
|
|
406
|
+
*/
|
|
407
|
+
function getDirectionByVector(vector) {
|
|
408
|
+
const x = vector[0];
|
|
409
|
+
const y = vector[1];
|
|
410
|
+
if (x === 0 && y === 0) {
|
|
411
|
+
return null;
|
|
412
|
+
}
|
|
413
|
+
if (x === 0) {
|
|
414
|
+
return y > 0 ? Direction.bottom : Direction.top;
|
|
415
|
+
}
|
|
416
|
+
if (y === 0) {
|
|
417
|
+
return x > 0 ? Direction.right : Direction.left;
|
|
418
|
+
}
|
|
419
|
+
const angle = Math.atan2(y, x);
|
|
420
|
+
if (angle > -Math.PI / 4 && angle <= Math.PI / 4) {
|
|
421
|
+
return Direction.right;
|
|
422
|
+
}
|
|
423
|
+
else if (angle > Math.PI / 4 && angle <= (3 * Math.PI) / 4) {
|
|
424
|
+
return Direction.bottom;
|
|
425
|
+
}
|
|
426
|
+
else if (angle > (-3 * Math.PI) / 4 && angle <= -Math.PI / 4) {
|
|
427
|
+
return Direction.top;
|
|
428
|
+
}
|
|
429
|
+
else {
|
|
430
|
+
return Direction.left;
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
function getPointByVector(point, vector, offset) {
|
|
434
|
+
const distance = Math.hypot(vector[0], vector[1]);
|
|
435
|
+
return [point[0] + (vector[0] / distance) * offset, point[1] + (vector[1] / distance) * offset];
|
|
436
|
+
}
|
|
437
|
+
function rotateVectorAnti90(vector) {
|
|
438
|
+
const x = vector[0];
|
|
439
|
+
const y = vector[1];
|
|
440
|
+
const rotatedX = y;
|
|
441
|
+
const rotatedY = -x;
|
|
442
|
+
return [rotatedX, rotatedY];
|
|
443
|
+
}
|
|
444
|
+
function getDirectionBetweenPointAndPoint(source, target) {
|
|
445
|
+
if (source[0] === target[0]) {
|
|
446
|
+
if (source[1] >= target[1]) {
|
|
447
|
+
return Direction.top;
|
|
448
|
+
}
|
|
449
|
+
else {
|
|
450
|
+
return Direction.bottom;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
if (source[1] === target[1]) {
|
|
454
|
+
if (source[0] >= target[0]) {
|
|
455
|
+
return Direction.left;
|
|
456
|
+
}
|
|
457
|
+
else {
|
|
458
|
+
return Direction.right;
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
throw new Error('can not match direction');
|
|
462
|
+
}
|
|
463
|
+
function getDirectionFactor(direction) {
|
|
464
|
+
return handleDirectionFactors[direction];
|
|
465
|
+
}
|
|
466
|
+
function getFactorByPoints(source, target) {
|
|
467
|
+
const distance = distanceBetweenPointAndPoint(...source, ...target);
|
|
468
|
+
return {
|
|
469
|
+
x: (target[0] - source[0]) / distance,
|
|
470
|
+
y: (target[1] - source[1]) / distance
|
|
471
|
+
};
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
function getOppositeDirection(direction) {
|
|
475
|
+
switch (direction) {
|
|
476
|
+
case Direction.left:
|
|
477
|
+
return Direction.right;
|
|
478
|
+
case Direction.right:
|
|
479
|
+
return Direction.left;
|
|
480
|
+
case Direction.top:
|
|
481
|
+
return Direction.bottom;
|
|
482
|
+
case Direction.bottom:
|
|
483
|
+
return Direction.top;
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
const getPoints = (source, sourcePosition, target, targetPosition, offset) => {
|
|
487
|
+
const sourceDir = getDirectionFactor(sourcePosition);
|
|
488
|
+
const targetDir = getDirectionFactor(targetPosition);
|
|
489
|
+
const sourceGapped = [source[0] + sourceDir.x * offset, source[1] + sourceDir.y * offset];
|
|
490
|
+
const targetGapped = [target[0] + targetDir.x * offset, target[1] + targetDir.y * offset];
|
|
491
|
+
const dir = getDirection(sourceGapped, sourcePosition, targetGapped);
|
|
492
|
+
const dirAccessor = dir.x !== 0 ? 'x' : 'y';
|
|
493
|
+
const currDir = dir[dirAccessor];
|
|
494
|
+
let points = [];
|
|
495
|
+
let centerX, centerY;
|
|
496
|
+
const [defaultCenterX, defaultCenterY] = getEdgeCenter({
|
|
497
|
+
sourceX: source[0],
|
|
498
|
+
sourceY: source[1],
|
|
499
|
+
targetX: target[0],
|
|
500
|
+
targetY: target[1]
|
|
501
|
+
});
|
|
502
|
+
// opposite handle positions, default case
|
|
503
|
+
if (sourceDir[dirAccessor] * targetDir[dirAccessor] === -1) {
|
|
504
|
+
centerX = defaultCenterX;
|
|
505
|
+
centerY = defaultCenterY;
|
|
506
|
+
// --->
|
|
507
|
+
// |
|
|
508
|
+
// >---
|
|
509
|
+
const verticalSplit = [
|
|
510
|
+
[centerX, sourceGapped[1]],
|
|
511
|
+
[centerX, targetGapped[1]]
|
|
512
|
+
];
|
|
513
|
+
// |
|
|
514
|
+
// ---
|
|
515
|
+
// |
|
|
516
|
+
const horizontalSplit = [
|
|
517
|
+
[sourceGapped[0], centerY],
|
|
518
|
+
[targetGapped[0], centerY]
|
|
519
|
+
];
|
|
520
|
+
if (sourceDir[dirAccessor] === currDir) {
|
|
521
|
+
points = dirAccessor === 'x' ? verticalSplit : horizontalSplit;
|
|
522
|
+
}
|
|
523
|
+
else {
|
|
524
|
+
points = dirAccessor === 'x' ? horizontalSplit : verticalSplit;
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
else {
|
|
528
|
+
// sourceTarget means we take x from source and y from target, targetSource is the opposite
|
|
529
|
+
const sourceTarget = [[sourceGapped[0], targetGapped[1]]];
|
|
530
|
+
const targetSource = [[targetGapped[0], sourceGapped[1]]];
|
|
531
|
+
// this handles edges with same handle positions
|
|
532
|
+
if (dirAccessor === 'x') {
|
|
533
|
+
points = sourceDir.x === currDir ? targetSource : sourceTarget;
|
|
534
|
+
}
|
|
535
|
+
else {
|
|
536
|
+
points = sourceDir.y === currDir ? sourceTarget : targetSource;
|
|
537
|
+
}
|
|
538
|
+
// these are conditions for handling mixed handle positions like right -> bottom for example
|
|
539
|
+
let flipSourceTarget;
|
|
540
|
+
if (sourcePosition !== targetPosition) {
|
|
541
|
+
const dirAccessorOpposite = dirAccessor === 'x' ? 1 : 0;
|
|
542
|
+
const isSameDir = sourceDir[dirAccessor] === targetDir[dirAccessor === 'x' ? 'y' : 'x'];
|
|
543
|
+
const sourceGtTargetOppo = sourceGapped[dirAccessorOpposite] > targetGapped[dirAccessorOpposite];
|
|
544
|
+
const sourceLtTargetOppo = sourceGapped[dirAccessorOpposite] < targetGapped[dirAccessorOpposite];
|
|
545
|
+
flipSourceTarget =
|
|
546
|
+
(sourceDir[dirAccessor] === 1 && ((!isSameDir && sourceGtTargetOppo) || (isSameDir && sourceLtTargetOppo))) ||
|
|
547
|
+
(sourceDir[dirAccessor] !== 1 && ((!isSameDir && sourceLtTargetOppo) || (isSameDir && sourceGtTargetOppo)));
|
|
548
|
+
if (flipSourceTarget) {
|
|
549
|
+
points = dirAccessor === 'x' ? sourceTarget : targetSource;
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
return [source, sourceGapped, ...points, targetGapped, target];
|
|
554
|
+
};
|
|
555
|
+
const getDirection = (source, sourcePosition = Direction.bottom, target) => {
|
|
556
|
+
if (sourcePosition === Direction.left || sourcePosition === Direction.right) {
|
|
557
|
+
return source[0] < target[0] ? { x: 1, y: 0 } : { x: -1, y: 0 };
|
|
558
|
+
}
|
|
559
|
+
return source[1] < target[1] ? { x: 0, y: 1 } : { x: 0, y: -1 };
|
|
560
|
+
};
|
|
561
|
+
function getEdgeCenter({ sourceX, sourceY, targetX, targetY }) {
|
|
562
|
+
const xOffset = Math.abs(targetX - sourceX) / 2;
|
|
563
|
+
const centerX = targetX < sourceX ? targetX + xOffset : targetX - xOffset;
|
|
564
|
+
const yOffset = Math.abs(targetY - sourceY) / 2;
|
|
565
|
+
const centerY = targetY < sourceY ? targetY + yOffset : targetY - yOffset;
|
|
566
|
+
return [centerX, centerY, xOffset, yOffset];
|
|
567
|
+
}
|
|
568
|
+
function getPointOnPolyline(points, ratio) {
|
|
569
|
+
const totalLength = calculatePolylineLength(points);
|
|
570
|
+
const targetDistance = totalLength * ratio;
|
|
571
|
+
let accumulatedDistance = 0;
|
|
572
|
+
for (let i = 0; i < points.length - 1; i++) {
|
|
573
|
+
const [x1, y1] = points[i];
|
|
574
|
+
const [x2, y2] = points[i + 1];
|
|
575
|
+
const segmentLength = distanceBetweenPointAndPoint(x1, y1, x2, y2);
|
|
576
|
+
if (accumulatedDistance + segmentLength >= targetDistance) {
|
|
577
|
+
const remainingDistance = targetDistance - accumulatedDistance;
|
|
578
|
+
const ratioInSegment = remainingDistance / segmentLength;
|
|
579
|
+
const targetX = x1 + (x2 - x1) * ratioInSegment;
|
|
580
|
+
const targetY = y1 + (y2 - y1) * ratioInSegment;
|
|
581
|
+
return [targetX, targetY];
|
|
582
|
+
}
|
|
583
|
+
accumulatedDistance += segmentLength;
|
|
584
|
+
}
|
|
585
|
+
return points[points.length - 1];
|
|
586
|
+
}
|
|
587
|
+
function calculatePolylineLength(points) {
|
|
588
|
+
let length = 0;
|
|
589
|
+
for (let i = 0; i < points.length - 1; i++) {
|
|
590
|
+
const [x1, y1] = points[i];
|
|
591
|
+
const [x2, y2] = points[i + 1];
|
|
592
|
+
length += distanceBetweenPointAndPoint(x1, y1, x2, y2);
|
|
593
|
+
}
|
|
594
|
+
return length;
|
|
595
|
+
}
|
|
596
|
+
function getRatioByPoint(points, point) {
|
|
597
|
+
const totalLength = calculatePolylineLength(points);
|
|
598
|
+
let distance = 0;
|
|
599
|
+
for (let i = 0; i < points.length - 1; i++) {
|
|
600
|
+
const isOverlap = isPointOnLineSegment(point, points[i], points[i + 1]);
|
|
601
|
+
if (isOverlap) {
|
|
602
|
+
distance += distanceBetweenPointAndPoint(point[0], point[1], points[i][0], points[i][1]);
|
|
603
|
+
return distance / totalLength;
|
|
604
|
+
}
|
|
605
|
+
else {
|
|
606
|
+
distance += distanceBetweenPointAndPoint(points[i][0], points[i][1], points[i + 1][0], points[i + 1][1]);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
throw new Error('Cannot get ratio by point');
|
|
610
|
+
}
|
|
611
|
+
function isPointOnLineSegment(point, startPoint, endPoint) {
|
|
612
|
+
const distanceToStart = distanceBetweenPointAndPoint(point[0], point[1], startPoint[0], startPoint[1]);
|
|
613
|
+
const distanceToEnd = distanceBetweenPointAndPoint(point[0], point[1], endPoint[0], endPoint[1]);
|
|
614
|
+
const segmentLength = distanceBetweenPointAndPoint(startPoint[0], startPoint[1], endPoint[0], endPoint[1]);
|
|
615
|
+
return Math.abs(distanceToStart + distanceToEnd - segmentLength) < 0.1;
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
function isVirtualKey(e) {
|
|
619
|
+
const isMod = e.ctrlKey || e.metaKey;
|
|
620
|
+
const isAlt = isKeyHotkey('alt', e);
|
|
621
|
+
const isShift = isKeyHotkey('shift', e);
|
|
622
|
+
const isCapsLock = e.key.includes('CapsLock');
|
|
623
|
+
const isTab = e.key.includes('Tab');
|
|
624
|
+
const isEsc = e.key.includes('Escape');
|
|
625
|
+
const isF = e.key.startsWith('F');
|
|
626
|
+
const isArrow = e.key.includes('Arrow') ? true : false;
|
|
627
|
+
return isCapsLock || isMod || isAlt || isArrow || isShift || isTab || isEsc || isF;
|
|
628
|
+
}
|
|
629
|
+
const isExpandHotkey = (event) => {
|
|
630
|
+
return isKeyHotkey('mod+/', event);
|
|
631
|
+
};
|
|
632
|
+
const isTabHotkey = (event) => {
|
|
633
|
+
return event.key === 'Tab';
|
|
634
|
+
};
|
|
635
|
+
const isEnterHotkey = (event) => {
|
|
636
|
+
return event.key === 'Enter';
|
|
637
|
+
};
|
|
638
|
+
const isSpaceHotkey = (event) => {
|
|
639
|
+
return event.code === 'Space';
|
|
640
|
+
};
|
|
641
|
+
const isDelete = (event) => {
|
|
642
|
+
return hotkeys.isDeleteBackward(event) || hotkeys.isDeleteForward(event);
|
|
643
|
+
};
|
|
644
|
+
|
|
645
|
+
const getRectangleByPoints = (points) => {
|
|
646
|
+
let minX = Infinity, maxX = -Infinity, minY = Infinity, maxY = -Infinity;
|
|
647
|
+
points.forEach(point => {
|
|
648
|
+
minX = Math.min(point[0], minX);
|
|
649
|
+
maxX = Math.max(point[0], maxX);
|
|
650
|
+
minY = Math.min(point[1], minY);
|
|
651
|
+
maxY = Math.max(point[1], maxY);
|
|
652
|
+
});
|
|
653
|
+
return {
|
|
654
|
+
x: minX,
|
|
655
|
+
y: minY,
|
|
656
|
+
width: maxX - minX,
|
|
657
|
+
height: maxY - minY
|
|
658
|
+
};
|
|
659
|
+
};
|
|
660
|
+
|
|
661
|
+
var BoardCreationMode;
|
|
662
|
+
(function (BoardCreationMode) {
|
|
663
|
+
BoardCreationMode["dnd"] = "dnd";
|
|
664
|
+
BoardCreationMode["drawing"] = "drawing";
|
|
665
|
+
})(BoardCreationMode || (BoardCreationMode = {}));
|
|
666
|
+
const BOARD_TO_CREATION_MODE = new WeakMap();
|
|
667
|
+
const getCreationMode = (board) => {
|
|
668
|
+
return BOARD_TO_CREATION_MODE.get(board);
|
|
669
|
+
};
|
|
670
|
+
const setCreationMode = (board, mode) => {
|
|
671
|
+
BOARD_TO_CREATION_MODE.set(board, mode);
|
|
672
|
+
};
|
|
673
|
+
const isDndMode = (board) => {
|
|
674
|
+
return getCreationMode(board) === BoardCreationMode.dnd;
|
|
675
|
+
};
|
|
676
|
+
const isDrawingMode = (board) => {
|
|
677
|
+
return getCreationMode(board) === BoardCreationMode.drawing;
|
|
678
|
+
};
|
|
679
|
+
|
|
680
|
+
const getTextManages = (element) => {
|
|
681
|
+
const component = PlaitElement.getComponent(element);
|
|
682
|
+
return component.getTextManages();
|
|
683
|
+
};
|
|
684
|
+
const getTextEditors = (element) => {
|
|
685
|
+
return getTextManages(element).map(manage => {
|
|
686
|
+
return manage.componentRef.instance.editor;
|
|
687
|
+
});
|
|
688
|
+
};
|
|
689
|
+
|
|
690
|
+
const selectImage = (board, defaultImageWidth, handle, acceptImageTypes = ['png', 'jpeg', 'gif', 'bmp']) => {
|
|
691
|
+
const inputFile = document.createElement('input');
|
|
692
|
+
inputFile.setAttribute('type', 'file');
|
|
693
|
+
const acceptImageTypesString = '.' + acceptImageTypes.join(',.');
|
|
694
|
+
inputFile.setAttribute('accept', acceptImageTypesString);
|
|
695
|
+
inputFile.onchange = (event) => {
|
|
696
|
+
buildImage(board, event.target.files[0], defaultImageWidth, handle);
|
|
697
|
+
};
|
|
698
|
+
inputFile.click();
|
|
699
|
+
};
|
|
700
|
+
const buildImage = async (board, imageFile, defaultImageWidth, handle) => {
|
|
701
|
+
let width = 0, height = 0;
|
|
702
|
+
await getImageSize(imageFile, defaultImageWidth).then((value) => {
|
|
703
|
+
width = value.width;
|
|
704
|
+
height = value.height;
|
|
705
|
+
});
|
|
706
|
+
let imageItem = null;
|
|
707
|
+
const url = URL.createObjectURL(imageFile);
|
|
708
|
+
const context = PlaitBoard.getComponent(board).viewContainerRef.injector.get(PlaitContextService);
|
|
709
|
+
context.setUploadingFile({ url, file: imageFile });
|
|
710
|
+
imageItem = {
|
|
711
|
+
url,
|
|
712
|
+
width,
|
|
713
|
+
height
|
|
714
|
+
};
|
|
715
|
+
handle(imageItem);
|
|
716
|
+
};
|
|
717
|
+
function getImageSize(file, defaultImageWidth) {
|
|
718
|
+
return new Promise((resolve, reject) => {
|
|
719
|
+
const image = new Image();
|
|
720
|
+
image.src = URL.createObjectURL(file);
|
|
721
|
+
image.onload = function () {
|
|
722
|
+
const width = defaultImageWidth;
|
|
723
|
+
const height = (defaultImageWidth * image.naturalHeight) / image.naturalWidth;
|
|
724
|
+
resolve(image.naturalWidth > defaultImageWidth ? { width, height } : { width: image.naturalWidth, height: image.naturalHeight });
|
|
725
|
+
};
|
|
726
|
+
});
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
class CommonPluginElement extends PlaitPluginElementComponent {
|
|
730
|
+
constructor() {
|
|
731
|
+
super(...arguments);
|
|
732
|
+
this.textManages = [];
|
|
733
|
+
}
|
|
734
|
+
initializeTextManages(textManages) {
|
|
735
|
+
this.textManages = textManages;
|
|
736
|
+
}
|
|
737
|
+
getTextManages() {
|
|
738
|
+
return this.textManages;
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
class ImageBaseComponent {
|
|
743
|
+
set imageItem(value) {
|
|
744
|
+
this.afterImageItemChange(this._imageItem, value);
|
|
745
|
+
this._imageItem = value;
|
|
746
|
+
this.drawFocus();
|
|
747
|
+
}
|
|
748
|
+
get imageItem() {
|
|
749
|
+
return this._imageItem;
|
|
750
|
+
}
|
|
751
|
+
set isFocus(value) {
|
|
752
|
+
this._isFocus = value;
|
|
753
|
+
this.drawFocus();
|
|
754
|
+
}
|
|
755
|
+
get isFocus() {
|
|
756
|
+
return this._isFocus;
|
|
757
|
+
}
|
|
758
|
+
get nativeElement() {
|
|
759
|
+
return this.elementRef.nativeElement;
|
|
760
|
+
}
|
|
761
|
+
constructor(elementRef, cdr) {
|
|
762
|
+
this.elementRef = elementRef;
|
|
763
|
+
this.cdr = cdr;
|
|
764
|
+
this.initialized = false;
|
|
765
|
+
}
|
|
766
|
+
ngOnInit() {
|
|
767
|
+
this.activeGenerator = new ActiveGenerator(this.board, {
|
|
768
|
+
getStrokeWidth: () => {
|
|
769
|
+
const selectedElements = getSelectedElements(this.board);
|
|
770
|
+
if (!(selectedElements.length === 1 && !isSelectionMoving(this.board))) {
|
|
771
|
+
return ACTIVE_STROKE_WIDTH;
|
|
772
|
+
}
|
|
773
|
+
else {
|
|
774
|
+
return ACTIVE_STROKE_WIDTH;
|
|
775
|
+
}
|
|
776
|
+
},
|
|
777
|
+
getStrokeOpacity: () => {
|
|
778
|
+
const selectedElements = getSelectedElements(this.board);
|
|
779
|
+
if ((selectedElements.length === 1 && !isSelectionMoving(this.board)) || !selectedElements.length) {
|
|
780
|
+
return 1;
|
|
781
|
+
}
|
|
782
|
+
else {
|
|
783
|
+
return 0.5;
|
|
784
|
+
}
|
|
785
|
+
},
|
|
786
|
+
getRectangle: () => {
|
|
787
|
+
return this.getRectangle();
|
|
788
|
+
},
|
|
789
|
+
hasResizeHandle: () => {
|
|
790
|
+
const selectedElements = getSelectedElements(this.board);
|
|
791
|
+
return (selectedElements.length === 1 && !isSelectionMoving(this.board)) || !selectedElements.length;
|
|
792
|
+
}
|
|
793
|
+
});
|
|
794
|
+
this.initialized = true;
|
|
795
|
+
}
|
|
796
|
+
drawFocus() {
|
|
797
|
+
if (this.initialized) {
|
|
798
|
+
const activeG = PlaitBoard.getElementActiveHost(this.board);
|
|
799
|
+
this.activeGenerator.draw({}, activeG, { selected: this._isFocus });
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
ngOnDestroy() {
|
|
803
|
+
if (this.activeGenerator) {
|
|
804
|
+
this.activeGenerator.destroy();
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.3", ngImport: i0, type: ImageBaseComponent, deps: [{ token: i0.ElementRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
808
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.3", type: ImageBaseComponent, inputs: { element: "element", imageItem: "imageItem", board: "board", isFocus: "isFocus", getRectangle: "getRectangle", hasResizeHandle: "hasResizeHandle" }, host: { classAttribute: "plait-image-container" }, ngImport: i0 }); }
|
|
809
|
+
}
|
|
810
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.3", ngImport: i0, type: ImageBaseComponent, decorators: [{
|
|
811
|
+
type: Directive,
|
|
812
|
+
args: [{
|
|
813
|
+
host: {
|
|
814
|
+
class: 'plait-image-container'
|
|
815
|
+
}
|
|
816
|
+
}]
|
|
817
|
+
}], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { element: [{
|
|
818
|
+
type: Input
|
|
819
|
+
}], imageItem: [{
|
|
820
|
+
type: Input
|
|
821
|
+
}], board: [{
|
|
822
|
+
type: Input
|
|
823
|
+
}], isFocus: [{
|
|
824
|
+
type: Input
|
|
825
|
+
}], getRectangle: [{
|
|
826
|
+
type: Input
|
|
827
|
+
}], hasResizeHandle: [{
|
|
828
|
+
type: Input
|
|
829
|
+
}] } });
|
|
830
|
+
|
|
831
|
+
/*
|
|
832
|
+
* Public API Surface of utils
|
|
833
|
+
*/
|
|
834
|
+
|
|
835
|
+
/**
|
|
836
|
+
* Generated bundle index. Do not edit.
|
|
837
|
+
*/
|
|
838
|
+
|
|
839
|
+
export { ActiveGenerator, BASE, BoardCreationMode, CommonPluginElement, Generator, IS_RESIZING, ImageBaseComponent, ImageGenerator, MediaKeys, PICTURE_ACCEPTED_UPLOAD_SIZE, PRIMARY_COLOR, PropertyTransforms, RESIZE_HANDLE_DIAMETER, ResizeCursorClass, ResizeHandle, WithCommonPluginKey, WithTextPluginKey, acceptImageTypes, addResizing, buildImage, calculatePolylineLength, getCreationMode, getDirection, getDirectionBetweenPointAndPoint, getDirectionByPointOfRectangle, getDirectionByVector, getDirectionFactor, getEdgeCenter, getFactorByPoints, getOppositeDirection, getPointByVector, getPointOnPolyline, getPoints, getRatioByPoint, getRectangleByPoints, getRectangleResizeHandleRefs, getTextEditors, getTextManages, hasAfterDraw, isDelete, isDndMode, isDrawingMode, isEnterHotkey, isExpandHotkey, isPointOnLineSegment, isResizing, isResizingByCondition, isSpaceHotkey, isTabHotkey, isVirtualKey, normalizeShapePoints, removeResizing, rotateVectorAnti90, selectImage, setCreationMode, withResize };
|
|
840
|
+
//# sourceMappingURL=plait-common.mjs.map
|