@plait/common 0.61.2 → 0.62.0-next.1
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/core/element-flavour.d.ts +1 -1
- package/core/index.d.ts +4 -0
- package/core/render-component.d.ts +4 -0
- package/esm2022/constants/default.mjs +2 -1
- package/esm2022/core/element-flavour.mjs +1 -1
- package/esm2022/core/group.component.mjs +3 -3
- package/esm2022/core/index.mjs +5 -0
- package/esm2022/core/render-component.mjs +2 -0
- package/esm2022/generators/generator.mjs +1 -1
- package/esm2022/generators/index.mjs +2 -2
- package/esm2022/image/image-base.component.mjs +28 -0
- package/esm2022/image/image.generator.mjs +99 -0
- package/esm2022/image/index.mjs +4 -0
- package/esm2022/image/with-image.mjs +8 -0
- package/esm2022/plugins/index.mjs +1 -2
- package/esm2022/public-api.mjs +5 -4
- package/esm2022/text/index.mjs +5 -0
- package/esm2022/text/text-manage.mjs +138 -0
- package/esm2022/text/text-measure.mjs +61 -0
- package/esm2022/text/types.mjs +7 -0
- package/esm2022/text/with-text.mjs +8 -0
- package/esm2022/transforms/index.mjs +1 -2
- package/esm2022/utils/image.mjs +3 -3
- package/esm2022/utils/text.mjs +22 -20
- package/fesm2022/plait-common.mjs +341 -214
- package/fesm2022/plait-common.mjs.map +1 -1
- package/generators/index.d.ts +1 -1
- package/image/image-base.component.d.ts +17 -0
- package/image/image.generator.d.ts +27 -0
- package/image/index.d.ts +3 -0
- package/image/with-image.d.ts +15 -0
- package/package.json +1 -3
- package/plugins/index.d.ts +0 -1
- package/public-api.d.ts +4 -3
- package/text/index.d.ts +4 -0
- package/text/text-manage.d.ts +41 -0
- package/text/text-measure.d.ts +8 -0
- package/text/types.d.ts +24 -0
- package/text/with-text.d.ts +25 -0
- package/transforms/index.d.ts +0 -1
- package/utils/image.d.ts +1 -5
- package/utils/text.d.ts +9 -6
- package/core/image-base.component.d.ts +0 -29
- package/esm2022/core/image-base.component.mjs +0 -95
- package/esm2022/generators/image.generator.mjs +0 -59
- package/esm2022/plugins/text-options.mjs +0 -2
- package/esm2022/transforms/text.mjs +0 -71
- package/generators/image.generator.d.ts +0 -24
- package/plugins/text-options.d.ts +0 -5
- package/transforms/text.d.ts +0 -9
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import { PlaitGroupElement, getSelectionAngle, getElementsInGroup, setAngleForG, RectangleClient, drawCircle, PlaitBoard, RESIZE_HANDLE_CLASS_NAME, createG, setStrokeLinecap, drawRectangle, SELECTION_RECTANGLE_CLASS_NAME,
|
|
1
|
+
import { PlaitGroupElement, getSelectionAngle, getElementsInGroup, setAngleForG, RectangleClient, drawCircle, PlaitBoard, RESIZE_HANDLE_CLASS_NAME, createG, setStrokeLinecap, drawRectangle, SELECTION_RECTANGLE_CLASS_NAME, ResizeCursorClass, RESIZE_CURSORS, setDragging, rotatePoints, isSelectionMoving, getSelectedElements, distanceBetweenPointAndPoint, Point, Direction, hotkeys, createDebugGenerator, createForeignObject, ACTIVE_STROKE_WIDTH, updateForeignObject, Transforms, getHighestSelectedElements, getRectangleByElements, MERGING, PlaitPointerType, isMainPointer, toViewBoxPoint, toHostPoint, preventTouchMove, PRESS_AND_MOVE_BUFFER, isDragging, throttleRAF, handleTouchTarget, getRectangleByGroup, ElementFlavour, isSelectedElementOrGroup, Selection, getHitElementsBySelection, createGroupRectangleG, getSelectedGroups, getHighestSelectedGroups, getSelectedIsolatedElements, idCreator, getSelectedIsolatedElementsCanAddToGroup, getGroupByElement, updateForeignObjectWidth, IS_TEXT_EDITABLE } from '@plait/core';
|
|
2
2
|
import { isKeyHotkey } from 'is-hotkey';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import * as i0 from '@angular/core';
|
|
6
|
-
import { Directive, Input } from '@angular/core';
|
|
3
|
+
import { Node, Operation, Transforms as Transforms$1, Range, Editor } from 'slate';
|
|
4
|
+
import { fromEvent, timer } from 'rxjs';
|
|
7
5
|
|
|
8
6
|
const BASE = 4;
|
|
9
7
|
const PRIMARY_COLOR = '#6698FF';
|
|
@@ -13,6 +11,7 @@ const DEFAULT_ROUTE_MARGIN = 30;
|
|
|
13
11
|
const TRANSPARENT = 'transparent';
|
|
14
12
|
const ROTATE_HANDLE_DISTANCE_TO_ELEMENT = 20;
|
|
15
13
|
const ROTATE_HANDLE_SIZE = 18;
|
|
14
|
+
const DEFAULT_FONT_FAMILY = 'PingFangSC-Regular, "PingFang SC"';
|
|
16
15
|
|
|
17
16
|
var MediaKeys;
|
|
18
17
|
(function (MediaKeys) {
|
|
@@ -183,62 +182,6 @@ class ActiveGenerator extends Generator {
|
|
|
183
182
|
}
|
|
184
183
|
}
|
|
185
184
|
|
|
186
|
-
class ImageGenerator extends Generator {
|
|
187
|
-
static { this.key = 'image-generator'; }
|
|
188
|
-
constructor(board, options) {
|
|
189
|
-
super(board, options);
|
|
190
|
-
this.board = board;
|
|
191
|
-
this.options = options;
|
|
192
|
-
}
|
|
193
|
-
canDraw(element, data) {
|
|
194
|
-
return !!this.options.getImageItem(element);
|
|
195
|
-
}
|
|
196
|
-
draw(element, viewContainerRef) {
|
|
197
|
-
const g = createG();
|
|
198
|
-
const foreignRectangle = this.options.getRectangle(element);
|
|
199
|
-
this.foreignObject = createForeignObject(foreignRectangle.x, foreignRectangle.y, foreignRectangle.width, foreignRectangle.height);
|
|
200
|
-
g.append(this.foreignObject);
|
|
201
|
-
const componentType = this.board.getPluginOptions(WithCommonPluginKey)
|
|
202
|
-
.imageComponentType;
|
|
203
|
-
if (!componentType) {
|
|
204
|
-
throw new Error('Not implement ImageBaseComponent error.');
|
|
205
|
-
}
|
|
206
|
-
this.componentRef = viewContainerRef.createComponent(componentType);
|
|
207
|
-
this.componentRef.instance.board = this.board;
|
|
208
|
-
this.componentRef.instance.imageItem = this.options.getImageItem(element);
|
|
209
|
-
this.componentRef.instance.element = element;
|
|
210
|
-
this.componentRef.instance.getRectangle = () => {
|
|
211
|
-
return this.options.getRectangle(element);
|
|
212
|
-
};
|
|
213
|
-
this.componentRef.instance.cdr.markForCheck();
|
|
214
|
-
this.foreignObject.append(this.componentRef.instance.nativeElement);
|
|
215
|
-
return g;
|
|
216
|
-
}
|
|
217
|
-
updateImage(nodeG, previous, current) {
|
|
218
|
-
if (previous !== current && this.componentRef) {
|
|
219
|
-
this.componentRef.instance.imageItem = this.options.getImageItem(current);
|
|
220
|
-
this.componentRef.instance.element = current;
|
|
221
|
-
this.componentRef.instance.getRectangle = () => {
|
|
222
|
-
return this.options.getRectangle(current);
|
|
223
|
-
};
|
|
224
|
-
}
|
|
225
|
-
const currentForeignObject = this.options.getRectangle(current);
|
|
226
|
-
updateForeignObject(this.g, currentForeignObject.width, currentForeignObject.height, currentForeignObject.x, currentForeignObject.y);
|
|
227
|
-
if (currentForeignObject && current.angle) {
|
|
228
|
-
setAngleForG(this.g, RectangleClient.getCenterPoint(currentForeignObject), current.angle);
|
|
229
|
-
}
|
|
230
|
-
// solve image lose on move node
|
|
231
|
-
if (this.foreignObject.children.length === 0) {
|
|
232
|
-
this.foreignObject.append(this.componentRef.instance.nativeElement);
|
|
233
|
-
}
|
|
234
|
-
this.componentRef?.instance.cdr.markForCheck();
|
|
235
|
-
}
|
|
236
|
-
destroy() {
|
|
237
|
-
super.destroy();
|
|
238
|
-
this.componentRef?.destroy();
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
|
|
242
185
|
const getResizeHandleByIndex = (index) => {
|
|
243
186
|
return `${index}`;
|
|
244
187
|
};
|
|
@@ -749,7 +692,7 @@ const getFirstTextManage = (element) => {
|
|
|
749
692
|
};
|
|
750
693
|
const getTextEditorsByElement = (element) => {
|
|
751
694
|
return getTextManages(element).map(manage => {
|
|
752
|
-
return manage.
|
|
695
|
+
return manage.editor;
|
|
753
696
|
});
|
|
754
697
|
};
|
|
755
698
|
const getFirstTextEditor = (element) => {
|
|
@@ -770,20 +713,6 @@ const findFirstTextEditor = (board) => {
|
|
|
770
713
|
});
|
|
771
714
|
return firstEditor;
|
|
772
715
|
};
|
|
773
|
-
const getTextMarksByElement = (element) => {
|
|
774
|
-
const editors = getTextEditorsByElement(element);
|
|
775
|
-
const editor = editors[0];
|
|
776
|
-
if (!editor) {
|
|
777
|
-
return {};
|
|
778
|
-
}
|
|
779
|
-
if (editor.children.length === 0) {
|
|
780
|
-
const textManage = getTextManages(element)[0];
|
|
781
|
-
const currentMarks = PlaitMarkEditor.getMarksByElement(textManage.componentRef.instance.children[0]);
|
|
782
|
-
return currentMarks;
|
|
783
|
-
}
|
|
784
|
-
const currentMarks = PlaitMarkEditor.getMarks(editor);
|
|
785
|
-
return currentMarks;
|
|
786
|
-
};
|
|
787
716
|
const getElementsText = (elements) => {
|
|
788
717
|
return elements
|
|
789
718
|
.map(item => {
|
|
@@ -815,10 +744,10 @@ const getTextEditors = (board, elements) => {
|
|
|
815
744
|
});
|
|
816
745
|
const editingTextManage = textManages.find(textManage => textManage.isEditing);
|
|
817
746
|
if (editingTextManage) {
|
|
818
|
-
return [editingTextManage.
|
|
747
|
+
return [editingTextManage.editor];
|
|
819
748
|
}
|
|
820
749
|
return textManages.map(item => {
|
|
821
|
-
return item.
|
|
750
|
+
return item.editor;
|
|
822
751
|
});
|
|
823
752
|
}
|
|
824
753
|
return undefined;
|
|
@@ -831,10 +760,27 @@ const getEditingTextEditor = (board, elements) => {
|
|
|
831
760
|
});
|
|
832
761
|
const editingTextManage = textManages.find(textManage => textManage.isEditing);
|
|
833
762
|
if (editingTextManage) {
|
|
834
|
-
return editingTextManage.
|
|
763
|
+
return editingTextManage.editor;
|
|
835
764
|
}
|
|
836
765
|
return undefined;
|
|
837
766
|
};
|
|
767
|
+
const buildText = (text, align, properties) => {
|
|
768
|
+
properties = properties || {};
|
|
769
|
+
const plaitText = typeof text === 'string' ? { children: [{ text, ...properties }] } : text;
|
|
770
|
+
if (align) {
|
|
771
|
+
plaitText.align = align;
|
|
772
|
+
}
|
|
773
|
+
return plaitText;
|
|
774
|
+
};
|
|
775
|
+
const getLineHeightByFontSize = (fontSize) => {
|
|
776
|
+
if (fontSize === 14) {
|
|
777
|
+
return 20;
|
|
778
|
+
}
|
|
779
|
+
if (fontSize === 18) {
|
|
780
|
+
return 25;
|
|
781
|
+
}
|
|
782
|
+
return fontSize * 1.5;
|
|
783
|
+
};
|
|
838
784
|
const ELEMENT_TO_TEXT_MANAGES = new WeakMap();
|
|
839
785
|
|
|
840
786
|
const selectImage = (board, defaultImageWidth, handle, acceptImageTypes = ['png', 'jpeg', 'gif', 'bmp']) => {
|
|
@@ -855,7 +801,7 @@ const buildImage = async (board, imageFile, defaultImageWidth, handle) => {
|
|
|
855
801
|
});
|
|
856
802
|
let imageItem = null;
|
|
857
803
|
const url = URL.createObjectURL(imageFile);
|
|
858
|
-
const context = PlaitBoard.
|
|
804
|
+
const context = PlaitBoard.getBoardContext(board);
|
|
859
805
|
context.setUploadingFile({ url, file: imageFile });
|
|
860
806
|
imageItem = {
|
|
861
807
|
url,
|
|
@@ -1280,6 +1226,101 @@ const removeRotating = (board) => {
|
|
|
1280
1226
|
setDragging(board, false);
|
|
1281
1227
|
};
|
|
1282
1228
|
|
|
1229
|
+
const FOREIGN_OBJECT_IMAGE_CLASS_NAME = 'foreign-object-image';
|
|
1230
|
+
const IMAGE_CONTAINER_CLASS_NAME = 'plait-image-container';
|
|
1231
|
+
class ImageGenerator extends Generator {
|
|
1232
|
+
static { this.key = 'image-generator'; }
|
|
1233
|
+
constructor(board, options) {
|
|
1234
|
+
super(board, options);
|
|
1235
|
+
this.board = board;
|
|
1236
|
+
this.options = options;
|
|
1237
|
+
this.isFocus = false;
|
|
1238
|
+
}
|
|
1239
|
+
canDraw(element) {
|
|
1240
|
+
return !!this.options.getImageItem(element);
|
|
1241
|
+
}
|
|
1242
|
+
draw(element) {
|
|
1243
|
+
this.element = element;
|
|
1244
|
+
const g = createG();
|
|
1245
|
+
const foreignRectangle = this.options.getRectangle(element);
|
|
1246
|
+
this.foreignObject = createForeignObject(foreignRectangle.x, foreignRectangle.y, foreignRectangle.width, foreignRectangle.height);
|
|
1247
|
+
this.foreignObject.classList.add(FOREIGN_OBJECT_IMAGE_CLASS_NAME);
|
|
1248
|
+
g.append(this.foreignObject);
|
|
1249
|
+
const props = {
|
|
1250
|
+
board: this.board,
|
|
1251
|
+
imageItem: this.options.getImageItem(element),
|
|
1252
|
+
element,
|
|
1253
|
+
getRectangle: () => {
|
|
1254
|
+
return this.options.getRectangle(element);
|
|
1255
|
+
}
|
|
1256
|
+
};
|
|
1257
|
+
this.imageComponentRef = this.board.renderImage(this.foreignObject, props);
|
|
1258
|
+
this.activeGenerator = new ActiveGenerator(this.board, {
|
|
1259
|
+
getStrokeWidth: () => {
|
|
1260
|
+
const selectedElements = getSelectedElements(this.board);
|
|
1261
|
+
if (!(selectedElements.length === 1 && !isSelectionMoving(this.board))) {
|
|
1262
|
+
return ACTIVE_STROKE_WIDTH;
|
|
1263
|
+
}
|
|
1264
|
+
else {
|
|
1265
|
+
return ACTIVE_STROKE_WIDTH;
|
|
1266
|
+
}
|
|
1267
|
+
},
|
|
1268
|
+
getStrokeOpacity: () => {
|
|
1269
|
+
const selectedElements = getSelectedElements(this.board);
|
|
1270
|
+
if ((selectedElements.length === 1 && !isSelectionMoving(this.board)) || !selectedElements.length) {
|
|
1271
|
+
return 1;
|
|
1272
|
+
}
|
|
1273
|
+
else {
|
|
1274
|
+
return 0.5;
|
|
1275
|
+
}
|
|
1276
|
+
},
|
|
1277
|
+
getRectangle: () => {
|
|
1278
|
+
return this.options.getRectangle(this.element);
|
|
1279
|
+
},
|
|
1280
|
+
hasResizeHandle: () => {
|
|
1281
|
+
const isSelectedImageElement = canResize(this.board, this.element);
|
|
1282
|
+
const isSelectedImage = !!getElementOfFocusedImage(this.board);
|
|
1283
|
+
return isSelectedImage || isSelectedImageElement;
|
|
1284
|
+
}
|
|
1285
|
+
});
|
|
1286
|
+
return g;
|
|
1287
|
+
}
|
|
1288
|
+
updateImage(nodeG, previous, current) {
|
|
1289
|
+
this.element = current;
|
|
1290
|
+
if (previous !== current && this.imageComponentRef) {
|
|
1291
|
+
const props = {
|
|
1292
|
+
imageItem: this.options.getImageItem(current),
|
|
1293
|
+
element: current,
|
|
1294
|
+
getRectangle: () => {
|
|
1295
|
+
return this.options.getRectangle(current);
|
|
1296
|
+
}
|
|
1297
|
+
};
|
|
1298
|
+
this.imageComponentRef.update(props);
|
|
1299
|
+
}
|
|
1300
|
+
const currentForeignObject = this.options.getRectangle(current);
|
|
1301
|
+
updateForeignObject(this.g, currentForeignObject.width, currentForeignObject.height, currentForeignObject.x, currentForeignObject.y);
|
|
1302
|
+
if (currentForeignObject && current.angle) {
|
|
1303
|
+
setAngleForG(this.g, RectangleClient.getCenterPoint(currentForeignObject), current.angle);
|
|
1304
|
+
}
|
|
1305
|
+
const activeG = PlaitBoard.getElementActiveHost(this.board);
|
|
1306
|
+
this.activeGenerator.processDrawing(current, activeG, { selected: this.isFocus });
|
|
1307
|
+
}
|
|
1308
|
+
setFocus(element, isFocus) {
|
|
1309
|
+
this.isFocus = isFocus;
|
|
1310
|
+
const activeG = PlaitBoard.getElementActiveHost(this.board);
|
|
1311
|
+
this.activeGenerator.processDrawing(element, activeG, { selected: isFocus });
|
|
1312
|
+
const props = {
|
|
1313
|
+
isFocus
|
|
1314
|
+
};
|
|
1315
|
+
this.imageComponentRef.update(props);
|
|
1316
|
+
}
|
|
1317
|
+
destroy() {
|
|
1318
|
+
super.destroy();
|
|
1319
|
+
this.imageComponentRef?.destroy();
|
|
1320
|
+
this.activeGenerator?.destroy();
|
|
1321
|
+
}
|
|
1322
|
+
}
|
|
1323
|
+
|
|
1283
1324
|
const setProperty = (board, properties, options) => {
|
|
1284
1325
|
const selectedElements = getSelectedElements(board);
|
|
1285
1326
|
selectedElements.forEach(element => {
|
|
@@ -1433,73 +1474,6 @@ const AlignTransform = {
|
|
|
1433
1474
|
distributeVertical
|
|
1434
1475
|
};
|
|
1435
1476
|
|
|
1436
|
-
const setTextMarks = (board, mark) => {
|
|
1437
|
-
const selectedElements = getSelectedElements(board);
|
|
1438
|
-
if (selectedElements.length) {
|
|
1439
|
-
const firstEditor = findFirstTextEditor(board);
|
|
1440
|
-
if (!firstEditor) {
|
|
1441
|
-
return;
|
|
1442
|
-
}
|
|
1443
|
-
const activeMarks = PlaitMarkEditor.getMarks(firstEditor);
|
|
1444
|
-
const elements = selectedElements.filter(element => {
|
|
1445
|
-
const editors = getTextEditorsByElement(element);
|
|
1446
|
-
return editors.some(editor => {
|
|
1447
|
-
const elementMarks = PlaitMarkEditor.getMarks(editor);
|
|
1448
|
-
return elementMarks[mark] === activeMarks[mark];
|
|
1449
|
-
});
|
|
1450
|
-
});
|
|
1451
|
-
const editors = getTextEditors(board, elements);
|
|
1452
|
-
if (editors && editors.length) {
|
|
1453
|
-
editors.forEach(editor => {
|
|
1454
|
-
PlaitMarkEditor.toggleMark(editor, mark);
|
|
1455
|
-
});
|
|
1456
|
-
}
|
|
1457
|
-
}
|
|
1458
|
-
};
|
|
1459
|
-
const setFontSize = (board, size, defaultFontSize) => {
|
|
1460
|
-
const editors = getTextEditors(board);
|
|
1461
|
-
if (editors && editors.length) {
|
|
1462
|
-
const selectedElements = getSelectedElements(board);
|
|
1463
|
-
editors.forEach(editor => {
|
|
1464
|
-
let finalDefaultFontSize;
|
|
1465
|
-
if (typeof defaultFontSize === 'function') {
|
|
1466
|
-
const element = selectedElements.find(element => {
|
|
1467
|
-
const textEditors = getTextEditorsByElement(element);
|
|
1468
|
-
return textEditors.includes(editor);
|
|
1469
|
-
});
|
|
1470
|
-
finalDefaultFontSize = defaultFontSize(element);
|
|
1471
|
-
}
|
|
1472
|
-
else {
|
|
1473
|
-
finalDefaultFontSize = defaultFontSize;
|
|
1474
|
-
}
|
|
1475
|
-
PlaitMarkEditor.setFontSizeMark(editor, size, finalDefaultFontSize);
|
|
1476
|
-
});
|
|
1477
|
-
}
|
|
1478
|
-
};
|
|
1479
|
-
const setTextColor = (board, color, textSelection) => {
|
|
1480
|
-
const editors = getTextEditors(board);
|
|
1481
|
-
if (editors && editors.length) {
|
|
1482
|
-
editors.forEach(editor => {
|
|
1483
|
-
if (textSelection) {
|
|
1484
|
-
Transforms$1.select(editor, textSelection);
|
|
1485
|
-
}
|
|
1486
|
-
if (color === 'transparent') {
|
|
1487
|
-
Editor.removeMark(editor, MarkTypes.color);
|
|
1488
|
-
}
|
|
1489
|
-
else {
|
|
1490
|
-
PlaitMarkEditor.setColorMark(editor, color);
|
|
1491
|
-
}
|
|
1492
|
-
});
|
|
1493
|
-
}
|
|
1494
|
-
};
|
|
1495
|
-
const setTextAlign = (board, align) => {
|
|
1496
|
-
const editors = getTextEditors(board);
|
|
1497
|
-
if (editors && editors.length) {
|
|
1498
|
-
editors.forEach(editor => AlignEditor.setAlign(editor, align));
|
|
1499
|
-
}
|
|
1500
|
-
};
|
|
1501
|
-
const TextTransforms = { setTextAlign, setTextColor, setFontSize, setTextMarks };
|
|
1502
|
-
|
|
1503
1477
|
const normalizeShapePoints = (points, shift = false) => {
|
|
1504
1478
|
let start = points[0];
|
|
1505
1479
|
let end = points[1];
|
|
@@ -1707,7 +1681,7 @@ class GroupComponent extends CommonElementFlavour {
|
|
|
1707
1681
|
initialize() {
|
|
1708
1682
|
super.initialize();
|
|
1709
1683
|
this.initializeGenerator();
|
|
1710
|
-
const contextService = PlaitBoard.
|
|
1684
|
+
const contextService = PlaitBoard.getBoardContext(this.board);
|
|
1711
1685
|
this.onStableSubscription = contextService.onStable().subscribe(() => {
|
|
1712
1686
|
const elementsInGroup = getElementsInGroup(this.board, this.element, false, true);
|
|
1713
1687
|
const isPartialSelectGroup = elementsInGroup.some(item => isSelectedElementOrGroup(this.board, item)) &&
|
|
@@ -1915,94 +1889,247 @@ const updateSiblingElementGroupId = (board, removeGroups) => {
|
|
|
1915
1889
|
};
|
|
1916
1890
|
|
|
1917
1891
|
class ImageBaseComponent {
|
|
1892
|
+
constructor() {
|
|
1893
|
+
this.initialized = false;
|
|
1894
|
+
}
|
|
1918
1895
|
set imageItem(value) {
|
|
1919
|
-
this.afterImageItemChange(this._imageItem, value);
|
|
1920
1896
|
this._imageItem = value;
|
|
1921
|
-
this.
|
|
1897
|
+
if (this.initialized) {
|
|
1898
|
+
this.afterImageItemChange(this._imageItem, value);
|
|
1899
|
+
}
|
|
1922
1900
|
}
|
|
1923
1901
|
get imageItem() {
|
|
1924
1902
|
return this._imageItem;
|
|
1925
1903
|
}
|
|
1926
1904
|
set isFocus(value) {
|
|
1927
1905
|
this._isFocus = value;
|
|
1928
|
-
this.drawFocus();
|
|
1929
1906
|
}
|
|
1930
1907
|
get isFocus() {
|
|
1931
1908
|
return this._isFocus;
|
|
1932
1909
|
}
|
|
1933
|
-
|
|
1934
|
-
|
|
1910
|
+
initialize() {
|
|
1911
|
+
this.initialized = true;
|
|
1912
|
+
this.nativeElement().classList.add(IMAGE_CONTAINER_CLASS_NAME);
|
|
1935
1913
|
}
|
|
1936
|
-
|
|
1937
|
-
this.elementRef = elementRef;
|
|
1938
|
-
this.cdr = cdr;
|
|
1939
|
-
this.initialized = false;
|
|
1914
|
+
destroy() {
|
|
1940
1915
|
}
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1916
|
+
}
|
|
1917
|
+
|
|
1918
|
+
function measureElement(element, options, containerMaxWidth = 10000) {
|
|
1919
|
+
const canvas = document.createElement('canvas');
|
|
1920
|
+
const ctx = canvas.getContext('2d');
|
|
1921
|
+
const textEntries = Node.texts(element);
|
|
1922
|
+
const lines = [[]];
|
|
1923
|
+
for (const textEntry of textEntries) {
|
|
1924
|
+
const [text] = textEntry;
|
|
1925
|
+
const textString = Node.string(text);
|
|
1926
|
+
const textArray = textString.split('\n');
|
|
1927
|
+
textArray.forEach((segmentTextString, index) => {
|
|
1928
|
+
const segmentText = { ...text, text: segmentTextString };
|
|
1929
|
+
if (index === 0) {
|
|
1930
|
+
const currentLine = lines[lines.length - 1];
|
|
1931
|
+
currentLine.push(segmentText);
|
|
1932
|
+
}
|
|
1933
|
+
else {
|
|
1934
|
+
const newLine = [];
|
|
1935
|
+
newLine.push(segmentText);
|
|
1936
|
+
lines.push(newLine);
|
|
1937
|
+
}
|
|
1938
|
+
});
|
|
1939
|
+
}
|
|
1940
|
+
let width = 0;
|
|
1941
|
+
let height = 0;
|
|
1942
|
+
lines.forEach((lineTexts, index) => {
|
|
1943
|
+
let lineWidth = 0;
|
|
1944
|
+
let maxLineHeight = getLineHeightByFontSize(options.fontSize);
|
|
1945
|
+
lineTexts.forEach((text, index) => {
|
|
1946
|
+
const font = getFont(text, { fontFamily: options.fontFamily, fontSize: options.fontSize });
|
|
1947
|
+
ctx.font = font;
|
|
1948
|
+
const textMetrics = ctx.measureText(text.text);
|
|
1949
|
+
lineWidth += textMetrics.width;
|
|
1950
|
+
const isLast = index === lineTexts.length - 1;
|
|
1951
|
+
// skip when text is empty and is not last text of line
|
|
1952
|
+
if (text['font-size'] && (isLast || text.text !== '')) {
|
|
1953
|
+
const lineHeight = getLineHeightByFontSize(parseFloat(text['font-size']));
|
|
1954
|
+
if (lineHeight > maxLineHeight) {
|
|
1955
|
+
maxLineHeight = lineHeight;
|
|
1956
1956
|
}
|
|
1957
|
-
|
|
1958
|
-
|
|
1957
|
+
}
|
|
1958
|
+
});
|
|
1959
|
+
if (lineWidth <= containerMaxWidth) {
|
|
1960
|
+
if (lineWidth > width) {
|
|
1961
|
+
width = lineWidth;
|
|
1962
|
+
}
|
|
1963
|
+
height += maxLineHeight;
|
|
1964
|
+
}
|
|
1965
|
+
else {
|
|
1966
|
+
width = containerMaxWidth;
|
|
1967
|
+
const lineWrapNumber = Math.ceil(lineWidth / containerMaxWidth);
|
|
1968
|
+
height += maxLineHeight * lineWrapNumber;
|
|
1969
|
+
}
|
|
1970
|
+
});
|
|
1971
|
+
return { width, height };
|
|
1972
|
+
}
|
|
1973
|
+
const getFont = (text, options) => {
|
|
1974
|
+
return `${text.italic ? 'italic ' : ''} ${text.bold ? 'bold ' : ''} ${text['font-size'] || options.fontSize}px ${options.fontFamily} `;
|
|
1975
|
+
};
|
|
1976
|
+
|
|
1977
|
+
class TextManage {
|
|
1978
|
+
constructor(board, options) {
|
|
1979
|
+
this.board = board;
|
|
1980
|
+
this.options = options;
|
|
1981
|
+
this.isEditing = false;
|
|
1982
|
+
this.getSize = (element) => {
|
|
1983
|
+
const computedStyle = window.getComputedStyle(this.foreignObject.children[0]);
|
|
1984
|
+
const fontFamily = computedStyle.fontFamily;
|
|
1985
|
+
const fontSize = parseFloat(computedStyle.fontSize);
|
|
1986
|
+
const target = element || this.editor.children[0];
|
|
1987
|
+
return measureElement(target, {
|
|
1988
|
+
fontSize: fontSize,
|
|
1989
|
+
fontFamily
|
|
1990
|
+
}, this.options.getMaxWidth());
|
|
1991
|
+
};
|
|
1992
|
+
this.getText = () => {
|
|
1993
|
+
return this.editor.children[0];
|
|
1994
|
+
};
|
|
1995
|
+
if (!this.options.getMaxWidth) {
|
|
1996
|
+
this.options.getMaxWidth = () => 999;
|
|
1997
|
+
}
|
|
1998
|
+
}
|
|
1999
|
+
draw(text) {
|
|
2000
|
+
const _rectangle = this.options.getRectangle();
|
|
2001
|
+
this.g = createG();
|
|
2002
|
+
this.foreignObject = createForeignObject(_rectangle.x, _rectangle.y, _rectangle.width, _rectangle.height);
|
|
2003
|
+
this.g.append(this.foreignObject);
|
|
2004
|
+
this.g.classList.add('text');
|
|
2005
|
+
const props = {
|
|
2006
|
+
board: this.board,
|
|
2007
|
+
text,
|
|
2008
|
+
textPlugins: this.options.textPlugins,
|
|
2009
|
+
onChange: (data) => {
|
|
2010
|
+
if (data.operations.some(op => !Operation.isSelectionOperation(op))) {
|
|
2011
|
+
const { width, height } = this.getSize();
|
|
2012
|
+
this.options.onChange && this.options.onChange({ ...data, width, height });
|
|
2013
|
+
MERGING.set(this.board, true);
|
|
1959
2014
|
}
|
|
1960
2015
|
},
|
|
1961
|
-
|
|
1962
|
-
|
|
2016
|
+
afterInit: (editor) => {
|
|
2017
|
+
this.editor = editor;
|
|
1963
2018
|
},
|
|
1964
|
-
|
|
1965
|
-
const
|
|
1966
|
-
|
|
1967
|
-
|
|
2019
|
+
onComposition: (event) => {
|
|
2020
|
+
const fakeRoot = buildCompositionData(this.editor, event.data);
|
|
2021
|
+
if (fakeRoot) {
|
|
2022
|
+
const sizeData = this.getSize(fakeRoot.children[0]);
|
|
2023
|
+
this.options.onChange && this.options.onChange(sizeData);
|
|
2024
|
+
MERGING.set(this.board, true);
|
|
2025
|
+
}
|
|
1968
2026
|
}
|
|
1969
|
-
}
|
|
1970
|
-
this.
|
|
2027
|
+
};
|
|
2028
|
+
this.textComponentRef = this.board.renderText(this.foreignObject, props);
|
|
1971
2029
|
}
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
const activeG = PlaitBoard.getElementActiveHost(this.board);
|
|
1975
|
-
this.activeGenerator.processDrawing(this.element, activeG, { selected: this._isFocus });
|
|
1976
|
-
}
|
|
2030
|
+
updateRectangleWidth(width) {
|
|
2031
|
+
updateForeignObjectWidth(this.g, width);
|
|
1977
2032
|
}
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
2033
|
+
updateAngle(centerPoint, angle = 0) {
|
|
2034
|
+
setAngleForG(this.g, centerPoint, angle);
|
|
2035
|
+
}
|
|
2036
|
+
updateRectangle(rectangle) {
|
|
2037
|
+
const { x, y, width, height } = rectangle || this.options.getRectangle();
|
|
2038
|
+
updateForeignObject(this.g, width, height, x, y);
|
|
2039
|
+
}
|
|
2040
|
+
updateText(newText) {
|
|
2041
|
+
const props = {
|
|
2042
|
+
text: newText
|
|
2043
|
+
};
|
|
2044
|
+
this.textComponentRef.update(props);
|
|
2045
|
+
}
|
|
2046
|
+
edit(callback) {
|
|
2047
|
+
this.isEditing = true;
|
|
2048
|
+
IS_TEXT_EDITABLE.set(this.board, true);
|
|
2049
|
+
const props = {
|
|
2050
|
+
readonly: false
|
|
2051
|
+
};
|
|
2052
|
+
this.textComponentRef.update(props);
|
|
2053
|
+
Transforms$1.select(this.editor, [0]);
|
|
2054
|
+
const mousedown$ = fromEvent(document, 'mousedown').subscribe((event) => {
|
|
2055
|
+
const point = toViewBoxPoint(this.board, toHostPoint(this.board, event.x, event.y));
|
|
2056
|
+
const textRec = this.options.getRenderRectangle ? this.options.getRenderRectangle() : this.options.getRectangle();
|
|
2057
|
+
const clickInText = RectangleClient.isHit(RectangleClient.getRectangleByPoints([point, point]), textRec);
|
|
2058
|
+
const isAttached = event.target.closest('.plait-board-attached');
|
|
2059
|
+
if (!clickInText && !isAttached) {
|
|
2060
|
+
// handle composition input state, like: Chinese IME Composition Input
|
|
2061
|
+
timer(0).subscribe(() => {
|
|
2062
|
+
exitCallback();
|
|
2063
|
+
});
|
|
2064
|
+
}
|
|
2065
|
+
});
|
|
2066
|
+
const keydown$ = fromEvent(document, 'keydown').subscribe((event) => {
|
|
2067
|
+
if (event.isComposing) {
|
|
2068
|
+
return;
|
|
2069
|
+
}
|
|
2070
|
+
if (event.key === 'Escape' || (event.key === 'Enter' && !event.shiftKey) || event.key === 'Tab') {
|
|
2071
|
+
event.preventDefault();
|
|
2072
|
+
event.stopPropagation();
|
|
2073
|
+
exitCallback();
|
|
2074
|
+
return;
|
|
2075
|
+
}
|
|
2076
|
+
});
|
|
2077
|
+
const exitCallback = () => {
|
|
2078
|
+
this.updateRectangle();
|
|
2079
|
+
mousedown$.unsubscribe();
|
|
2080
|
+
keydown$.unsubscribe();
|
|
2081
|
+
IS_TEXT_EDITABLE.set(this.board, false);
|
|
2082
|
+
MERGING.set(this.board, false);
|
|
2083
|
+
callback && callback();
|
|
2084
|
+
const props = {
|
|
2085
|
+
readonly: true
|
|
2086
|
+
};
|
|
2087
|
+
this.textComponentRef.update(props);
|
|
2088
|
+
this.isEditing = false;
|
|
2089
|
+
};
|
|
2090
|
+
return exitCallback;
|
|
2091
|
+
}
|
|
2092
|
+
destroy() {
|
|
2093
|
+
this.g?.remove();
|
|
2094
|
+
this.textComponentRef?.destroy();
|
|
1982
2095
|
}
|
|
1983
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: ImageBaseComponent, deps: [{ token: i0.ElementRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
1984
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.2.4", type: ImageBaseComponent, inputs: { element: "element", imageItem: "imageItem", board: "board", isFocus: "isFocus", getRectangle: "getRectangle", hasResizeHandle: "hasResizeHandle" }, host: { classAttribute: "plait-image-container" }, ngImport: i0 }); }
|
|
1985
2096
|
}
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2097
|
+
const buildCompositionData = (editor, data) => {
|
|
2098
|
+
if (editor.selection && Range.isCollapsed(editor.selection)) {
|
|
2099
|
+
const [textNode, textPath] = Editor.node(editor, editor.selection);
|
|
2100
|
+
const offset = editor.selection.anchor.offset;
|
|
2101
|
+
const clonedElement = JSON.parse(JSON.stringify(editor.children[0]));
|
|
2102
|
+
const root = { children: [clonedElement] };
|
|
2103
|
+
const newTextString = textNode.text.slice(0, offset + 1) + data + textNode.text.slice(offset + 1);
|
|
2104
|
+
const clonedTextNode = Node.get(root, textPath);
|
|
2105
|
+
clonedTextNode.text = newTextString;
|
|
2106
|
+
return root;
|
|
2107
|
+
}
|
|
2108
|
+
return null;
|
|
2109
|
+
};
|
|
2110
|
+
|
|
2111
|
+
const withText = (board) => {
|
|
2112
|
+
const newBoard = board;
|
|
2113
|
+
newBoard.renderText = (container, props) => {
|
|
2114
|
+
throw new Error('No implementation for renderText method.');
|
|
2115
|
+
};
|
|
2116
|
+
return newBoard;
|
|
2117
|
+
};
|
|
2118
|
+
|
|
2119
|
+
var Alignment;
|
|
2120
|
+
(function (Alignment) {
|
|
2121
|
+
Alignment["left"] = "left";
|
|
2122
|
+
Alignment["center"] = "center";
|
|
2123
|
+
Alignment["right"] = "right";
|
|
2124
|
+
})(Alignment || (Alignment = {}));
|
|
2125
|
+
|
|
2126
|
+
const withImage = (board) => {
|
|
2127
|
+
const newBoard = board;
|
|
2128
|
+
newBoard.renderImage = (container, props) => {
|
|
2129
|
+
throw new Error('No implementation for renderImage method.');
|
|
2130
|
+
};
|
|
2131
|
+
return newBoard;
|
|
2132
|
+
};
|
|
2006
2133
|
|
|
2007
2134
|
/*
|
|
2008
2135
|
* Public API Surface of utils
|
|
@@ -2012,5 +2139,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImpor
|
|
|
2012
2139
|
* Generated bundle index. Do not edit.
|
|
2013
2140
|
*/
|
|
2014
2141
|
|
|
2015
|
-
export { AStar, ActiveGenerator, AlignTransform, BASE, BoardCreationMode, CommonElementFlavour, DEFAULT_ROUTE_MARGIN, ELEMENT_TO_TEXT_MANAGES, Generator, IS_RESIZING, IS_ROTATING, ImageBaseComponent, ImageGenerator, MediaKeys, PICTURE_ACCEPTED_UPLOAD_SIZE, PRIMARY_COLOR, PlaitCommonElementRef, PointGraph, PointNode, PriorityQueue, PropertyTransforms, RESIZE_HANDLE_DIAMETER, ROTATE_HANDLE_DISTANCE_TO_ELEMENT, ROTATE_HANDLE_SIZE, ResizeHandle, TRANSPARENT,
|
|
2142
|
+
export { AStar, ActiveGenerator, AlignTransform, Alignment, BASE, BoardCreationMode, CommonElementFlavour, DEFAULT_FONT_FAMILY, DEFAULT_ROUTE_MARGIN, ELEMENT_TO_TEXT_MANAGES, FOREIGN_OBJECT_IMAGE_CLASS_NAME, Generator, GroupComponent, IMAGE_CONTAINER_CLASS_NAME, IS_RESIZING, IS_ROTATING, ImageBaseComponent, ImageGenerator, MediaKeys, PICTURE_ACCEPTED_UPLOAD_SIZE, PRIMARY_COLOR, PlaitCommonElementRef, PointGraph, PointNode, PriorityQueue, PropertyTransforms, RESIZE_HANDLE_DIAMETER, ROTATE_HANDLE_DISTANCE_TO_ELEMENT, ROTATE_HANDLE_SIZE, ResizeHandle, TRANSPARENT, TextManage, WithCommonPluginKey, WithTextPluginKey, acceptImageTypes, addElementOfFocusedImage, addResizing, addRotating, alignBottom, alignHorizontalCenter, alignLeft, alignRight, alignTop, alignVerticalCenter, buildCompositionData, buildImage, buildText, calculatePolylineLength, canResize, createGraph, distributeHorizontal, distributeVertical, drawFillPrimaryHandle, drawHandle, drawPrimaryHandle, drawRotateHandle, findFirstTextEditor, generateElbowLineRoute, getCreationMode, getCrossingPointsBetweenPointAndSegment, getDirectionBetweenPointAndPoint, getDirectionByPointOfRectangle, getDirectionByVector, getDirectionFactor, getDirectionFactorByDirectionComponent, getEditingTextEditor, getElementOfFocusedImage, getElementsText, getExtendPoint, getFirstTextEditor, getFirstTextManage, getGraphPoints, getIndexByResizeHandle, getLineHeightByFontSize, getMemorizedLatest, getNextPoint, getOppositeDirection, getPointByVectorComponent, getPointByVectorDirectionComponent, getPointOnPolyline, getPoints, getRatioByPoint, getRectangleResizeHandleRefs, getResizeHandleByIndex, getResizeHandlePointByIndex, getRotatedResizeCursorClassByAngle, getSourceAndTargetOuterRectangle, getSymmetricHandleIndex, getTextEditors, getTextEditorsByElement, getTextManages, getUnitVectorByPointAndPoint, hasAfterDraw, isCornerHandle, isDelete, isDndMode, isDrawingMode, isEdgeHandle, isEnterHotkey, isExpandHotkey, isPointOnSegment, isResizing, isResizingByCondition, isRotating, isSourceAndTargetIntersect, isSpaceHotkey, isTabHotkey, isVirtualKey, measureElement, memorizeLatest, normalizeShapePoints, reduceRouteMargin, removeDuplicatePoints, removeElementOfFocusedImage, removeResizing, removeRotating, resetPointsAfterResize, rotateVector, rotateVectorAnti90, routeAdjust, selectImage, setCreationMode, setProperty, simplifyOrthogonalPoints, withGroup, withImage, withResize, withText };
|
|
2016
2143
|
//# sourceMappingURL=plait-common.mjs.map
|