@plait/mind 0.16.0 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/base/image-base.component.d.ts +16 -0
  2. package/base/index.d.ts +1 -0
  3. package/constants/node-style.d.ts +9 -4
  4. package/drawer/node-image.drawer.d.ts +16 -0
  5. package/esm2020/base/image-base.component.mjs +28 -0
  6. package/esm2020/base/index.mjs +2 -1
  7. package/esm2020/constants/node-style.mjs +11 -6
  8. package/esm2020/drawer/node-active.drawer.mjs +10 -9
  9. package/esm2020/drawer/node-image.drawer.mjs +61 -0
  10. package/esm2020/interfaces/element-data.mjs +1 -1
  11. package/esm2020/interfaces/element.mjs +9 -1
  12. package/esm2020/interfaces/options.mjs +1 -1
  13. package/esm2020/node.component.mjs +12 -1
  14. package/esm2020/plugins/with-mind-image.mjs +49 -0
  15. package/esm2020/plugins/with-mind.mjs +4 -11
  16. package/esm2020/transforms/emoji.mjs +2 -2
  17. package/esm2020/transforms/image.mjs +10 -0
  18. package/esm2020/transforms/index.mjs +4 -2
  19. package/esm2020/transforms/node.mjs +2 -6
  20. package/esm2020/utils/draw/abstract-outline.mjs +44 -2
  21. package/esm2020/utils/draw/node-dnd.mjs +8 -1
  22. package/esm2020/utils/draw/node-link/logic-link.mjs +2 -2
  23. package/esm2020/utils/draw/node-shape.mjs +5 -5
  24. package/esm2020/utils/mind.mjs +2 -2
  25. package/esm2020/utils/node-style/shape.mjs +8 -4
  26. package/esm2020/utils/position/emoji.mjs +8 -8
  27. package/esm2020/utils/position/image.mjs +21 -0
  28. package/esm2020/utils/position/index.mjs +2 -1
  29. package/esm2020/utils/space/node-space.mjs +23 -5
  30. package/fesm2015/plait-mind.mjs +283 -42
  31. package/fesm2015/plait-mind.mjs.map +1 -1
  32. package/fesm2020/plait-mind.mjs +280 -42
  33. package/fesm2020/plait-mind.mjs.map +1 -1
  34. package/interfaces/element-data.d.ts +9 -0
  35. package/interfaces/element.d.ts +2 -1
  36. package/interfaces/options.d.ts +3 -1
  37. package/node.component.d.ts +3 -0
  38. package/package.json +1 -1
  39. package/plugins/with-mind-image.d.ts +2 -0
  40. package/transforms/image.d.ts +3 -0
  41. package/transforms/index.d.ts +1 -0
  42. package/utils/draw/abstract-outline.d.ts +2 -0
  43. package/utils/node-style/shape.d.ts +1 -0
  44. package/utils/position/emoji.d.ts +4 -4
  45. package/utils/position/image.d.ts +6 -0
  46. package/utils/position/index.d.ts +1 -0
  47. package/utils/space/node-space.d.ts +1 -0
@@ -1,7 +1,7 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Component, ChangeDetectionStrategy, NgModule, NgZone, Directive, Input, HostListener } from '@angular/core';
2
+ import { Directive, Input, Component, ChangeDetectionStrategy, NgModule, NgZone, HostListener } from '@angular/core';
3
3
  import * as i2 from '@plait/core';
4
- import { DefaultThemeColor, ColorfulThemeColor, SoftThemeColor, RetroThemeColor, DarkThemeColor, StarryThemeColor, RectangleClient, PlaitElement, idCreator, isNullOrUndefined, Transforms, clearSelectedElement, addSelectedElement, PlaitNode, Path, PlaitBoard, depthFirstRecursion, drawLinearPath, drawBezierPath, createG, updateForeignObject, drawRoundRectangle, getRectangleByElements, getSelectedElements, NODE_TO_PARENT, distanceBetweenPointAndRectangle, createForeignObject, drawAbstractRoundRectangle, createText, PlaitPointerType, PlaitPluginElementComponent, NODE_TO_INDEX, PlaitModule, transformPoint, toPoint, getHitElements, distanceBetweenPointAndPoint, CLIP_BOARD_FORMAT_KEY, isMainPointer, BOARD_TO_HOST, PlaitPluginKey, throttleRAF, BoardTransforms, removeSelectedElement, PlaitHistoryBoard, hotkeys } from '@plait/core';
4
+ import { DefaultThemeColor, ColorfulThemeColor, SoftThemeColor, RetroThemeColor, DarkThemeColor, StarryThemeColor, RectangleClient, PlaitElement, idCreator, isNullOrUndefined, Transforms, clearSelectedElement, addSelectedElement, PlaitNode, Path, PlaitBoard, depthFirstRecursion, drawLinearPath, drawBezierPath, createG, updateForeignObject, drawRoundRectangle, getRectangleByElements, getSelectedElements, NODE_TO_PARENT, distanceBetweenPointAndRectangle, createForeignObject, createText, PlaitPointerType, PlaitPluginElementComponent, NODE_TO_INDEX, PlaitModule, transformPoint, toPoint, getHitElements, distanceBetweenPointAndPoint, CLIP_BOARD_FORMAT_KEY, isMainPointer, BOARD_TO_HOST, PlaitPluginKey, throttleRAF, BoardTransforms, removeSelectedElement, PlaitHistoryBoard, hotkeys } from '@plait/core';
5
5
  import { MindLayoutType, isIndentedLayout, AbstractNode, getNonAbstractChildren, isStandardLayout, isLeftLayout, isRightLayout, isVerticalLogicLayout, isHorizontalLogicLayout, isTopLayout, isBottomLayout, isHorizontalLayout, getCorrectStartEnd, getAbstractLayout, ConnectingPosition, GlobalLayout } from '@plait/layouts';
6
6
  import { TEXT_DEFAULT_HEIGHT, buildText, getTextSize, TextManage, ExitOrigin, TextModule, getTextFromClipboard } from '@plait/text';
7
7
  import { fromEvent, Subject } from 'rxjs';
@@ -186,7 +186,9 @@ const NodeDefaultSpace = {
186
186
  emojiAndText: BASE * 1.5
187
187
  },
188
188
  vertical: {
189
- nodeAndText: BASE * 1.5
189
+ nodeAndText: BASE * 1.5,
190
+ nodeAndImage: BASE,
191
+ imageAndText: BASE * 1.5
190
192
  }
191
193
  };
192
194
  const RootDefaultSpace = {
@@ -215,18 +217,27 @@ const getSpaceEmojiAndText = (element) => {
215
217
  };
216
218
  const NodeSpace = {
217
219
  getNodeWidth(board, element) {
220
+ var _a;
218
221
  const nodeAndText = getHorizontalSpaceBetweenNodeAndText(board, element);
222
+ const imageWidth = MindElement.hasImage(element) ? (_a = element.data.image) === null || _a === void 0 ? void 0 : _a.width : 0;
219
223
  if (MindElement.hasEmojis(element)) {
220
224
  return (NodeSpace.getEmojiLeftSpace(board, element) +
221
225
  getEmojisWidthHeight(board, element).width +
222
226
  getSpaceEmojiAndText(element) +
223
- element.width +
227
+ Math.max(element.width, imageWidth) +
224
228
  nodeAndText);
225
229
  }
226
- return nodeAndText + element.width + nodeAndText;
230
+ return nodeAndText + Math.max(element.width, imageWidth) + nodeAndText;
227
231
  },
228
232
  getNodeHeight(board, element) {
229
233
  const nodeAndText = getVerticalSpaceBetweenNodeAndText(element);
234
+ if (MindElement.hasImage(element)) {
235
+ return (NodeDefaultSpace.vertical.nodeAndImage +
236
+ element.data.image.height +
237
+ NodeDefaultSpace.vertical.imageAndText +
238
+ element.height +
239
+ nodeAndText);
240
+ }
230
241
  return nodeAndText + element.height + nodeAndText;
231
242
  },
232
243
  getTextLeftSpace(board, element) {
@@ -240,7 +251,15 @@ const NodeSpace = {
240
251
  },
241
252
  getTextTopSpace(element) {
242
253
  const nodeAndText = getVerticalSpaceBetweenNodeAndText(element);
243
- return nodeAndText;
254
+ if (MindElement.hasImage(element)) {
255
+ return element.data.image.height + NodeDefaultSpace.vertical.nodeAndImage + NodeDefaultSpace.vertical.imageAndText;
256
+ }
257
+ else {
258
+ return nodeAndText;
259
+ }
260
+ },
261
+ getImageTopSpace(element) {
262
+ return NodeDefaultSpace.vertical.nodeAndImage;
244
263
  },
245
264
  getEmojiLeftSpace(board, element) {
246
265
  const options = board.getPluginOptions(WithMindPluginKey);
@@ -267,12 +286,12 @@ function getEmojiRectangle(board, element) {
267
286
  function getEmojiForeignRectangle(board, element) {
268
287
  let { x, y } = getRectangleByNode(MindElement.getNode(element));
269
288
  x = x + NodeSpace.getEmojiLeftSpace(board, element);
270
- const { width, height } = getEmojisWidthHeight(board, element);
289
+ const { width } = getEmojisWidthHeight(board, element);
271
290
  return {
272
291
  x,
273
292
  y,
274
293
  width,
275
- height: height + NodeSpace.getEmojiTopSpace(element) * 2
294
+ height: NodeSpace.getNodeHeight(board, element)
276
295
  };
277
296
  }
278
297
  const isHitEmojis = (board, element, point) => {
@@ -294,6 +313,23 @@ function getTopicRectangleByElement(board, nodeRectangle, element) {
294
313
  return { height, width, x, y };
295
314
  }
296
315
 
316
+ function getImageForeignRectangle(board, element) {
317
+ let { x, y } = getRectangleByNode(MindElement.getNode(element));
318
+ x = x + NodeSpace.getTextLeftSpace(board, element);
319
+ y = NodeSpace.getImageTopSpace(element) + y;
320
+ const { width, height } = element.data.image;
321
+ return {
322
+ x,
323
+ y,
324
+ width,
325
+ height
326
+ };
327
+ }
328
+ const isHitImage = (board, element, range) => {
329
+ const client = getImageForeignRectangle(board, element);
330
+ return RectangleClient.isHit(RectangleClient.toRectangleClient([range.anchor, range.focus]), client);
331
+ };
332
+
297
333
  const NODE_MIN_WIDTH = 18;
298
334
 
299
335
  function editTopic(element) {
@@ -403,7 +439,7 @@ const copyNewNode = (node) => {
403
439
  const extractNodesText = (node) => {
404
440
  let str = '';
405
441
  if (node) {
406
- str += Node.string(node.data.topic.children[0]) + ' ';
442
+ str += Node.string(node.data.topic) + ' ';
407
443
  for (const childNode of node.children) {
408
444
  str += extractNodesText(childNode);
409
445
  }
@@ -590,15 +626,20 @@ const adjustNodeToRoot = (board, node) => {
590
626
  };
591
627
 
592
628
  const DefaultAbstractNodeStyle = {
593
- strokeColor: GRAY_COLOR,
594
- strokeWidth: 2,
595
629
  branchColor: GRAY_COLOR,
596
- branchWidth: 2
630
+ branchWidth: 2,
631
+ shape: {
632
+ strokeColor: GRAY_COLOR,
633
+ strokeWidth: 2
634
+ }
597
635
  };
598
636
  const DefaultNodeStyle = {
599
- strokeWidth: 3,
600
637
  branchWidth: 3,
601
- fill: 'none'
638
+ shape: {
639
+ rectangleRadius: 4,
640
+ strokeWidth: 3,
641
+ fill: 'none'
642
+ }
602
643
  };
603
644
 
604
645
  const getAvailableProperty = (board, element, propertyKey) => {
@@ -833,11 +874,15 @@ const getStrokeByMindElement = (board, element) => {
833
874
  return element.strokeColor || defaultRootStroke;
834
875
  }
835
876
  if (AbstractNode.isAbstract(element) || isChildOfAbstract(board, element)) {
836
- return element.strokeColor || DefaultAbstractNodeStyle.strokeColor;
837
- ;
877
+ return element.strokeColor || DefaultAbstractNodeStyle.shape.strokeColor;
838
878
  }
839
879
  return getAvailableProperty(board, element, 'strokeColor') || getDefaultBranchColor(board, element);
840
880
  };
881
+ const getStrokeWidthByElement = (board, element) => {
882
+ const strokeWidth = element.strokeWidth ||
883
+ (AbstractNode.isAbstract(element) ? DefaultAbstractNodeStyle.shape.strokeWidth : DefaultNodeStyle.shape.strokeWidth);
884
+ return strokeWidth;
885
+ };
841
886
  const getShapeByElement = (board, element) => {
842
887
  const shape = getAvailableProperty(board, element, 'shape');
843
888
  return shape || MindElementShape.roundRectangle;
@@ -1278,7 +1323,7 @@ function drawLogicLink(board, parent, node, isHorizontal, defaultStroke = null,
1278
1323
  const branchWidth = defaultStrokeWidth || getBranchWidthByMindElement(board, parent.origin);
1279
1324
  const hasStraightLine = branchShape === BranchShape.polyline ? true : !parent.origin.isRoot;
1280
1325
  const parentShape = getShapeByElement(board, parent.origin);
1281
- const shape = node.origin.shape ? node.origin.shape : parentShape;
1326
+ const shape = getShapeByElement(board, node.origin);
1282
1327
  const hasUnderlineShape = shape === MindElementShape.underline;
1283
1328
  const hasUnderlineShapeOfParent = parentShape === MindElementShape.underline;
1284
1329
  const nodeClient = getRectangleByNode(node);
@@ -1356,6 +1401,12 @@ const drawFakeDragNode = (board, element, offsetX, offsetY) => {
1356
1401
  updateForeignObject(fakeEmojisG, foreignRectangle.width, foreignRectangle.height, foreignRectangle.x + offsetX, foreignRectangle.y + offsetY);
1357
1402
  dragFakeNodeG === null || dragFakeNodeG === void 0 ? void 0 : dragFakeNodeG.append(fakeEmojisG);
1358
1403
  }
1404
+ if (MindElement.hasImage(element)) {
1405
+ const fakeImageG = activeComponent.imageDrawer.g.cloneNode(true);
1406
+ const foreignRectangle = getImageForeignRectangle(board, element);
1407
+ updateForeignObject(fakeImageG, foreignRectangle.width, foreignRectangle.height, foreignRectangle.x + offsetX, foreignRectangle.y + offsetY);
1408
+ dragFakeNodeG === null || dragFakeNodeG === void 0 ? void 0 : dragFakeNodeG.append(fakeImageG);
1409
+ }
1359
1410
  return dragFakeNodeG;
1360
1411
  };
1361
1412
  const drawFakeDropNode = (board, dropTarget, path) => {
@@ -1867,6 +1918,14 @@ const MindElement = {
1867
1918
  return false;
1868
1919
  }
1869
1920
  },
1921
+ hasImage(element) {
1922
+ if (element.data.image) {
1923
+ return true;
1924
+ }
1925
+ else {
1926
+ return false;
1927
+ }
1928
+ },
1870
1929
  getEmojis(element) {
1871
1930
  return element.data.emojis;
1872
1931
  },
@@ -1930,15 +1989,15 @@ function drawRoundRectangleByNode(board, node) {
1930
1989
  }
1931
1990
  function drawRoundRectangleByElement(board, nodeRectangle, element) {
1932
1991
  const defaultRootFill = getMindThemeColor(board).rootFill;
1933
- const fill = element.fill ? element.fill : element.isRoot ? defaultRootFill : DefaultNodeStyle.fill;
1992
+ const fill = element.fill ? element.fill : element.isRoot ? defaultRootFill : DefaultNodeStyle.shape.fill;
1934
1993
  const stroke = getStrokeByMindElement(board, element);
1935
- const strokeWidth = element.strokeWidth ? element.strokeWidth : DefaultNodeStyle.strokeWidth;
1994
+ const strokeWidth = getStrokeWidthByElement(board, element);
1936
1995
  const nodeG = drawRoundRectangle(PlaitBoard.getRoughSVG(board), nodeRectangle.x, nodeRectangle.y, nodeRectangle.x + nodeRectangle.width, nodeRectangle.y + nodeRectangle.height, {
1937
1996
  stroke,
1938
1997
  strokeWidth,
1939
1998
  fill,
1940
1999
  fillStyle: 'solid'
1941
- });
2000
+ }, false, DefaultNodeStyle.shape.rectangleRadius);
1942
2001
  return nodeG;
1943
2002
  }
1944
2003
 
@@ -2152,10 +2211,7 @@ const normalizeWidthAndHeight = (board, width, height) => {
2152
2211
  return { width: newWidth, height: newHeight };
2153
2212
  };
2154
2213
  const setTopic = (board, element, topic, width, height) => {
2155
- const newElement = Object.assign({ data: { topic } }, normalizeWidthAndHeight(board, width, height));
2156
- if (MindElement.hasEmojis(element)) {
2157
- newElement.data.emojis = element.data.emojis;
2158
- }
2214
+ const newElement = Object.assign({ data: Object.assign(Object.assign({}, element.data), { topic }) }, normalizeWidthAndHeight(board, width, height));
2159
2215
  const path = PlaitBoard.findPath(board, element);
2160
2216
  Transforms.setNode(board, newElement, path);
2161
2217
  };
@@ -2229,7 +2285,7 @@ const removeEmoji = (board, element, emojiItem) => {
2229
2285
  };
2230
2286
  const replaceEmoji = (board, element, oldEmoji, newEmoji) => {
2231
2287
  const newElement = {
2232
- data: { topic: element.data.topic }
2288
+ data: Object.assign({}, element.data)
2233
2289
  };
2234
2290
  const newEmojis = element.data.emojis.map(value => {
2235
2291
  if (value === oldEmoji) {
@@ -2242,6 +2298,15 @@ const replaceEmoji = (board, element, oldEmoji, newEmoji) => {
2242
2298
  Transforms.setNode(board, newElement, path);
2243
2299
  };
2244
2300
 
2301
+ const removeImage = (board, element) => {
2302
+ const newElement = {
2303
+ data: Object.assign({}, element.data)
2304
+ };
2305
+ delete newElement.data.image;
2306
+ const path = PlaitBoard.findPath(board, element);
2307
+ Transforms.setNode(board, newElement, path);
2308
+ };
2309
+
2245
2310
  const MindTransforms = {
2246
2311
  setLayout,
2247
2312
  setTopic,
@@ -2255,7 +2320,8 @@ const MindTransforms = {
2255
2320
  removeElements,
2256
2321
  insertNodes,
2257
2322
  insertAbstractNodes,
2258
- setRightNodeCountByRefs
2323
+ setRightNodeCountByRefs,
2324
+ removeImage
2259
2325
  };
2260
2326
 
2261
2327
  class BaseDrawer {
@@ -2443,6 +2509,48 @@ function handleBoardClass(board, activeHandlePosition, isHorizontal) {
2443
2509
  PlaitBoard.getBoardContainer(board).classList.remove('abstract-resizing-vertical');
2444
2510
  }
2445
2511
  }
2512
+ function drawAbstractRoundRectangle(rs, x1, y1, x2, y2, isHorizontal, options) {
2513
+ const width = Math.abs(x1 - x2);
2514
+ const height = Math.abs(y1 - y2);
2515
+ const radius = 5;
2516
+ const handleGap = 4;
2517
+ const handleLength = 10;
2518
+ const handleSpace = handleLength + handleGap * 2;
2519
+ if (isHorizontal) {
2520
+ const handleSideLine = (width - handleSpace - radius * 2) / 2;
2521
+ const sideLine = height - radius * 2;
2522
+ return rs.path(`M${x1 + radius},${y1}
2523
+ l${handleSideLine},0
2524
+ m${handleSpace},0
2525
+ l${handleSideLine},0
2526
+ a${radius},${radius},0,0,1,${radius},${radius}
2527
+ l0,${sideLine}
2528
+ a${radius},${radius},0,0,1,-${radius},${radius}
2529
+ l-${handleSideLine},0
2530
+ m-${handleSpace},0
2531
+ l-${handleSideLine},0
2532
+ a${radius},${radius},0,0,1,-${radius},-${radius}
2533
+ l0,-${sideLine}
2534
+ a${radius},${radius},0,0,1,${radius},-${radius}`, options);
2535
+ }
2536
+ else {
2537
+ const handleSideLine = (height - handleSpace - radius * 2) / 2;
2538
+ const sideLine = width - radius * 2;
2539
+ return rs.path(`M${x1 + radius},${y1}
2540
+ l${sideLine},0
2541
+ a${radius},${radius},0,0,1,${radius},${radius}
2542
+ l0,${handleSideLine}
2543
+ m0,${handleSpace}
2544
+ l0,${handleSideLine}
2545
+ a${radius},${radius},0,0,1,-${radius},${radius}
2546
+ l-${sideLine},0
2547
+ a${radius},${radius},0,0,1,-${radius},-${radius}
2548
+ l0,-${handleSideLine}
2549
+ m0,-${handleSpace}
2550
+ l0,-${handleSideLine}
2551
+ a${radius},${radius},0,0,1,${radius},-${radius}`, options);
2552
+ }
2553
+ }
2446
2554
 
2447
2555
  class NodeActiveDrawer extends BaseDrawer {
2448
2556
  canDraw(element, data) {
@@ -2461,14 +2569,13 @@ class NodeActiveDrawer extends BaseDrawer {
2461
2569
  activeG.append(this.abstractOutlineG);
2462
2570
  }
2463
2571
  const node = MindElement.getNode(element);
2464
- let { x, y, width, height } = getRectangleByNode(node);
2465
- const strokeG = drawRoundRectangle(PlaitBoard.getRoughSVG(this.board), x - 2, y - 2, x + width + 2, y + height + 2, { stroke: PRIMARY_COLOR, strokeWidth: 2, fill: '' }, true);
2572
+ const rectangle = getRectangleByNode(node);
2573
+ const activeStrokeWidth = 2;
2574
+ // add 0.1 to avoid white gap
2575
+ const offset = (getStrokeWidthByElement(this.board, element) + activeStrokeWidth) / 2 - 0.1;
2576
+ const activeRectangle = RectangleClient.getOutlineRectangle(rectangle, -offset);
2577
+ const strokeG = drawRoundRectangle(PlaitBoard.getRoughSVG(this.board), activeRectangle.x, activeRectangle.y, activeRectangle.x + activeRectangle.width, activeRectangle.y + activeRectangle.height, { stroke: PRIMARY_COLOR, strokeWidth: activeStrokeWidth, fill: '' }, true, DefaultNodeStyle.shape.rectangleRadius + offset);
2466
2578
  this.g.appendChild(strokeG);
2467
- if (!data.isEditing) {
2468
- const fillG = drawRoundRectangle(PlaitBoard.getRoughSVG(this.board), x - 2, y - 2, x + width + 2, y + height + 2, { stroke: PRIMARY_COLOR, fill: PRIMARY_COLOR, fillStyle: 'solid' }, true);
2469
- fillG.style.opacity = '0.15';
2470
- this.g.appendChild(fillG);
2471
- }
2472
2579
  return activeG;
2473
2580
  }
2474
2581
  updateAbstractOutline(element, activeHandlePosition, resizingLocation) {
@@ -2574,6 +2681,90 @@ class CollapseDrawer extends BaseDrawer {
2574
2681
  }
2575
2682
  }
2576
2683
 
2684
+ class MindImageBaseComponent {
2685
+ get nativeElement() {
2686
+ return this.elementRef.nativeElement;
2687
+ }
2688
+ constructor(elementRef) {
2689
+ this.elementRef = elementRef;
2690
+ }
2691
+ ngOnInit() { }
2692
+ }
2693
+ MindImageBaseComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: MindImageBaseComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
2694
+ MindImageBaseComponent.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.5", type: MindImageBaseComponent, inputs: { imageItem: "imageItem", board: "board", element: "element" }, host: { classAttribute: "mind-node-image" }, ngImport: i0 });
2695
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: MindImageBaseComponent, decorators: [{
2696
+ type: Directive,
2697
+ args: [{
2698
+ host: {
2699
+ class: 'mind-node-image'
2700
+ }
2701
+ }]
2702
+ }], ctorParameters: function () { return [{ type: i0.ElementRef }]; }, propDecorators: { imageItem: [{
2703
+ type: Input
2704
+ }], board: [{
2705
+ type: Input
2706
+ }], element: [{
2707
+ type: Input
2708
+ }] } });
2709
+
2710
+ class NodeImageDrawer {
2711
+ constructor(board, viewContainerRef) {
2712
+ this.board = board;
2713
+ this.viewContainerRef = viewContainerRef;
2714
+ this.componentRef = null;
2715
+ }
2716
+ drawImage(element) {
2717
+ this.destroy();
2718
+ if (MindElement.hasImage(element)) {
2719
+ this.g = createG();
2720
+ const foreignRectangle = getImageForeignRectangle(this.board, element);
2721
+ const foreignObject = createForeignObject(foreignRectangle.x, foreignRectangle.y, foreignRectangle.width, foreignRectangle.height);
2722
+ this.g.append(foreignObject);
2723
+ if (this.componentRef) {
2724
+ this.componentRef.destroy();
2725
+ this.componentRef = null;
2726
+ }
2727
+ const componentType = this.board.getPluginOptions(WithMindPluginKey).imageComponentType || MindImageBaseComponent;
2728
+ if (!componentType) {
2729
+ throw new Error('Not implement drawEmoji method error.');
2730
+ }
2731
+ this.componentRef = this.viewContainerRef.createComponent(componentType);
2732
+ this.componentRef.instance.board = this.board;
2733
+ this.componentRef.instance.element = element;
2734
+ this.componentRef.instance.imageItem = element.data.image;
2735
+ foreignObject.append(this.componentRef.instance.nativeElement);
2736
+ return this.g;
2737
+ }
2738
+ return undefined;
2739
+ }
2740
+ drawActive(element) {
2741
+ var _a;
2742
+ this.destroyActive();
2743
+ const imageRectangle = getImageForeignRectangle(this.board, element);
2744
+ const rectangle = RectangleClient.getOutlineRectangle(imageRectangle, -1);
2745
+ const roughSVG = PlaitBoard.getRoughSVG(this.board);
2746
+ this.activeG = roughSVG.rectangle(rectangle.x, rectangle.y, rectangle.width, rectangle.height, {
2747
+ stroke: PRIMARY_COLOR,
2748
+ fill: '',
2749
+ fillStyle: 'solid'
2750
+ });
2751
+ (_a = this.g) === null || _a === void 0 ? void 0 : _a.append(this.activeG);
2752
+ }
2753
+ destroyActive() {
2754
+ var _a;
2755
+ (_a = this.activeG) === null || _a === void 0 ? void 0 : _a.remove();
2756
+ }
2757
+ destroy() {
2758
+ if (this.g) {
2759
+ this.g.remove();
2760
+ }
2761
+ if (this.componentRef) {
2762
+ this.componentRef.destroy();
2763
+ this.componentRef = null;
2764
+ }
2765
+ }
2766
+ }
2767
+
2577
2768
  // 1. When the text at the end has an italic attribute, the text is partially covered
2578
2769
  // 2. There will be some differences in the width measured by different browsers
2579
2770
  const WIDTH_BUFFER = 4;
@@ -2593,6 +2784,7 @@ class MindNodeComponent extends PlaitPluginElementComponent {
2593
2784
  this.nodeInsertDrawer = new NodeInsertDrawer(this.board);
2594
2785
  this.activeDrawer = new NodeActiveDrawer(this.board);
2595
2786
  this.collapseDrawer = new CollapseDrawer(this.board);
2787
+ this.imageDrawer = new NodeImageDrawer(this.board, this.viewContainerRef);
2596
2788
  const plugins = this.board.getPluginOptions(WithMindPluginKey).textPlugins;
2597
2789
  this.textManage = new TextManage(this.board, this.viewContainerRef, () => {
2598
2790
  const rect = getTopicRectangleByNode(this.board, this.node);
@@ -2623,6 +2815,7 @@ class MindNodeComponent extends PlaitPluginElementComponent {
2623
2815
  this.activeDrawer.draw(this.element, this.g, { selected: this.selected, isEditing: this.textManage.isEditing });
2624
2816
  this.drawEmojis();
2625
2817
  this.drawExtend();
2818
+ this.drawImage();
2626
2819
  if (PlaitMind.isMind(this.context.parent)) {
2627
2820
  this.g.classList.add('branch');
2628
2821
  }
@@ -2645,6 +2838,7 @@ class MindNodeComponent extends PlaitPluginElementComponent {
2645
2838
  this.drawShape();
2646
2839
  this.drawLink();
2647
2840
  this.drawEmojis();
2841
+ this.drawImage();
2648
2842
  this.drawExtend();
2649
2843
  this.textManage.updateText(this.element.data.topic);
2650
2844
  this.textManage.updateRectangle();
@@ -2666,6 +2860,12 @@ class MindNodeComponent extends PlaitPluginElementComponent {
2666
2860
  this.g.append(g);
2667
2861
  }
2668
2862
  }
2863
+ drawImage() {
2864
+ const image = this.imageDrawer.drawImage(this.element);
2865
+ if (image) {
2866
+ this.g.append(image);
2867
+ }
2868
+ }
2669
2869
  drawShape() {
2670
2870
  this.destroyShape();
2671
2871
  const shape = getShapeByElement(this.board, this.node.origin);
@@ -2734,6 +2934,7 @@ class MindNodeComponent extends PlaitPluginElementComponent {
2734
2934
  super.ngOnDestroy();
2735
2935
  this.textManage.destroy();
2736
2936
  this.nodeEmojisDrawer.destroy();
2937
+ this.imageDrawer.destroy();
2737
2938
  this.destroy$.next();
2738
2939
  this.destroy$.complete();
2739
2940
  if (ELEMENT_TO_NODE.get(this.element) === this.node) {
@@ -3554,6 +3755,52 @@ const removeHovered = (element) => {
3554
3755
  }
3555
3756
  };
3556
3757
 
3758
+ const withMindImage = (board) => {
3759
+ let selectedImageElement = null;
3760
+ const { keydown, mousedown } = board;
3761
+ board.mousedown = (event) => {
3762
+ if (PlaitBoard.isReadonly(board) || !isMainPointer(event) || !PlaitBoard.isPointer(board, PlaitPointerType.selection)) {
3763
+ mousedown(event);
3764
+ return;
3765
+ }
3766
+ const point = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
3767
+ const range = { anchor: point, focus: point };
3768
+ const hitElements = getHitElements(board, { ranges: [range] });
3769
+ const hasImage = hitElements.length && MindElement.hasImage(hitElements[0]);
3770
+ const hitImage = hasImage && isHitImage(board, hitElements[0], range);
3771
+ if (hitImage) {
3772
+ const currentOptions = board.getPluginOptions(PlaitPluginKey.withSelection);
3773
+ board.setPluginOptions(PlaitPluginKey.withSelection, {
3774
+ isDisabledSelect: true
3775
+ });
3776
+ setTimeout(() => {
3777
+ board.setPluginOptions(PlaitPluginKey.withSelection, Object.assign({}, currentOptions));
3778
+ }, 0);
3779
+ selectedImageElement = hitElements[0];
3780
+ const component = PlaitElement.getComponent(selectedImageElement);
3781
+ component.imageDrawer.drawActive(selectedImageElement);
3782
+ clearSelectedElement(board);
3783
+ }
3784
+ else {
3785
+ if (selectedImageElement) {
3786
+ const component = PlaitElement.getComponent(selectedImageElement);
3787
+ component && component.imageDrawer.destroyActive();
3788
+ }
3789
+ selectedImageElement = null;
3790
+ }
3791
+ mousedown(event);
3792
+ };
3793
+ board.keydown = (event) => {
3794
+ if (!PlaitBoard.isReadonly(board) && selectedImageElement && (hotkeys.isDeleteBackward(event) || hotkeys.isDeleteForward(event))) {
3795
+ MindTransforms.removeImage(board, selectedImageElement);
3796
+ selectedImageElement = null;
3797
+ return;
3798
+ }
3799
+ keydown(event);
3800
+ };
3801
+ return board;
3802
+ };
3803
+
3557
3804
  const withMind = (board) => {
3558
3805
  const { drawElement, dblclick, keydown, insertFragment, setFragment, deleteFragment, isHitSelection, getRectangle, isMovable, isRecursion } = board;
3559
3806
  board.drawElement = (context) => {
@@ -3568,15 +3815,9 @@ const withMind = (board) => {
3568
3815
  board.applyTheme = (element) => {
3569
3816
  const mindElement = element;
3570
3817
  const shouldClearProperty = !PlaitBoard.isBoard(element) && ((mindElement === null || mindElement === void 0 ? void 0 : mindElement.branchColor) || (mindElement === null || mindElement === void 0 ? void 0 : mindElement.fill) || (mindElement === null || mindElement === void 0 ? void 0 : mindElement.strokeColor));
3571
- const isAbstract = AbstractNode.isAbstract(element);
3572
3818
  if (shouldClearProperty) {
3573
3819
  const path = PlaitBoard.findPath(board, element);
3574
- if (isAbstract) {
3575
- Transforms.setNode(board, { fill: null, strokeColor: DefaultAbstractNodeStyle.strokeColor, branchColor: DefaultAbstractNodeStyle.branchColor }, path);
3576
- }
3577
- else {
3578
- Transforms.setNode(board, { fill: null, strokeColor: null, branchColor: null }, path);
3579
- }
3820
+ Transforms.setNode(board, { fill: null, strokeColor: null, branchColor: null }, path);
3580
3821
  }
3581
3822
  };
3582
3823
  board.getRectangle = element => {
@@ -3671,7 +3912,7 @@ const withMind = (board) => {
3671
3912
  MindTransforms.removeElements(board, selectedElements);
3672
3913
  deleteFragment(data);
3673
3914
  };
3674
- return withNodeHover(withMindHotkey(withMindExtend(withCreateMind(withAbstract(withNodeDnd(board))))));
3915
+ return withMindImage(withNodeHover(withMindHotkey(withMindExtend(withCreateMind(withAbstract(withNodeDnd(board)))))));
3675
3916
  };
3676
3917
 
3677
3918
  class MindEmojiBaseComponent {
@@ -3725,5 +3966,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImpor
3725
3966
  * Generated bundle index. Do not edit.
3726
3967
  */
3727
3968
 
3728
- export { ABSTRACT_HANDLE_COLOR, ABSTRACT_HANDLE_LENGTH, ABSTRACT_HANDLE_MASK_WIDTH, ABSTRACT_INCLUDED_OUTLINE_OFFSET, AbstractHandlePosition, AbstractResizeState, BASE, BRANCH_FONT_FAMILY, BRANCH_WIDTH, BaseDrawer, BranchShape, DEFAULT_FONT_FAMILY, DefaultAbstractNodeStyle, DefaultNodeStyle, ELEMENT_TO_NODE, EXTEND_DIAMETER, EXTEND_OFFSET, GRAY_COLOR, INHERIT_ATTRIBUTE_KEYS, IS_DRAGGING, LayoutDirection, LayoutDirectionsMap, MindColorfulThemeColor, MindDarkThemeColor, MindDefaultThemeColor, MindElement, MindElementShape, MindEmojiBaseComponent, MindModule, MindNode, MindNodeComponent, MindPointerType, MindQueries, MindRetroThemeColor, MindSoftThemeColor, MindStarryThemeColor, MindThemeColor, MindThemeColors, MindTransforms, NODE_MIN_WIDTH, PRIMARY_COLOR, PlaitMind, PlaitMindComponent, QUICK_INSERT_CIRCLE_COLOR, QUICK_INSERT_CIRCLE_OFFSET, QUICK_INSERT_INNER_CROSS_COLOR, ROOT_TOPIC_FONT_SIZE, ROOT_TOPIC_HEIGHT, STROKE_WIDTH, TOPIC_COLOR, TOPIC_DEFAULT_MAX_WORD_COUNT, TOPIC_FONT_SIZE, TRANSPARENT, WithMindPluginKey, addActiveOnDragOrigin, adjustAbstractToNode, adjustNodeToRoot, adjustRootToNode, canSetAbstract, copyNewNode, correctLayoutByDirection, createDefaultMind, createEmptyMind, createMindElement, deleteElementHandleAbstract, deleteElementsHandleRightNodeCount, detectDropTarget, directionCorrector, directionDetector, divideElementByParent, drawFakeDragNode, drawFakeDropNode, editTopic, extractNodesText, findLastChild, findLocationLeftIndex, getAbstractBranchColor, getAbstractBranchWidth, getAbstractHandleRectangle, getAllowedDirection, getAvailableSubLayoutsByLayoutDirections, getBehindAbstracts, getBranchColorByMindElement, getBranchDirectionsByLayouts, getBranchShapeByMindElement, getBranchWidthByMindElement, getChildrenCount, getCorrespondingAbstract, getDefaultBranchColor, getDefaultBranchColorByIndex, getDefaultLayout, getEmojiForeignRectangle, getEmojiRectangle, getFirstLevelElement, getHitAbstractHandle, getInCorrectLayoutDirection, getLayoutDirection$1 as getLayoutDirection, getLayoutReverseDirection, getLocationScope, getMindThemeColor, getNextBranchColor, getOverallAbstracts, getPathByDropTarget, getRectangleByElement, getRectangleByNode, getRectangleByResizingLocation, getRelativeStartEndByAbstractRef, getRootLayout, getShapeByElement, getStrokeByMindElement, getTopicRectangleByElement, getTopicRectangleByNode, getValidAbstractRefs, handleTouchedAbstract, hasAfterDraw, hasPreviousOrNextOfDropPath, insertElementHandleAbstract, insertElementHandleRightNodeCount, insertMindElement, isChildElement, isChildOfAbstract, isChildRight, isChildUp, isCorrectLayout, isDragging, isDropStandardRight, isHitEmojis, isHitMindElement, isInRightBranchOfStandardLayout, isMixedLayout, isSetAbstract, isValidTarget, isVirtualKey, removeActiveOnDragOrigin, separateChildren, setIsDragging, withMind, withMindExtend };
3969
+ export { ABSTRACT_HANDLE_COLOR, ABSTRACT_HANDLE_LENGTH, ABSTRACT_HANDLE_MASK_WIDTH, ABSTRACT_INCLUDED_OUTLINE_OFFSET, AbstractHandlePosition, AbstractResizeState, BASE, BRANCH_FONT_FAMILY, BRANCH_WIDTH, BaseDrawer, BranchShape, DEFAULT_FONT_FAMILY, DefaultAbstractNodeStyle, DefaultNodeStyle, ELEMENT_TO_NODE, EXTEND_DIAMETER, EXTEND_OFFSET, GRAY_COLOR, INHERIT_ATTRIBUTE_KEYS, IS_DRAGGING, LayoutDirection, LayoutDirectionsMap, MindColorfulThemeColor, MindDarkThemeColor, MindDefaultThemeColor, MindElement, MindElementShape, MindEmojiBaseComponent, MindImageBaseComponent, MindModule, MindNode, MindNodeComponent, MindPointerType, MindQueries, MindRetroThemeColor, MindSoftThemeColor, MindStarryThemeColor, MindThemeColor, MindThemeColors, MindTransforms, NODE_MIN_WIDTH, PRIMARY_COLOR, PlaitMind, PlaitMindComponent, QUICK_INSERT_CIRCLE_COLOR, QUICK_INSERT_CIRCLE_OFFSET, QUICK_INSERT_INNER_CROSS_COLOR, ROOT_TOPIC_FONT_SIZE, ROOT_TOPIC_HEIGHT, STROKE_WIDTH, TOPIC_COLOR, TOPIC_DEFAULT_MAX_WORD_COUNT, TOPIC_FONT_SIZE, TRANSPARENT, WithMindPluginKey, addActiveOnDragOrigin, adjustAbstractToNode, adjustNodeToRoot, adjustRootToNode, canSetAbstract, copyNewNode, correctLayoutByDirection, createDefaultMind, createEmptyMind, createMindElement, deleteElementHandleAbstract, deleteElementsHandleRightNodeCount, detectDropTarget, directionCorrector, directionDetector, divideElementByParent, drawFakeDragNode, drawFakeDropNode, editTopic, extractNodesText, findLastChild, findLocationLeftIndex, getAbstractBranchColor, getAbstractBranchWidth, getAbstractHandleRectangle, getAllowedDirection, getAvailableSubLayoutsByLayoutDirections, getBehindAbstracts, getBranchColorByMindElement, getBranchDirectionsByLayouts, getBranchShapeByMindElement, getBranchWidthByMindElement, getChildrenCount, getCorrespondingAbstract, getDefaultBranchColor, getDefaultBranchColorByIndex, getDefaultLayout, getEmojiForeignRectangle, getEmojiRectangle, getFirstLevelElement, getHitAbstractHandle, getImageForeignRectangle, getInCorrectLayoutDirection, getLayoutDirection$1 as getLayoutDirection, getLayoutReverseDirection, getLocationScope, getMindThemeColor, getNextBranchColor, getOverallAbstracts, getPathByDropTarget, getRectangleByElement, getRectangleByNode, getRectangleByResizingLocation, getRelativeStartEndByAbstractRef, getRootLayout, getShapeByElement, getStrokeByMindElement, getStrokeWidthByElement, getTopicRectangleByElement, getTopicRectangleByNode, getValidAbstractRefs, handleTouchedAbstract, hasAfterDraw, hasPreviousOrNextOfDropPath, insertElementHandleAbstract, insertElementHandleRightNodeCount, insertMindElement, isChildElement, isChildOfAbstract, isChildRight, isChildUp, isCorrectLayout, isDragging, isDropStandardRight, isHitEmojis, isHitImage, isHitMindElement, isInRightBranchOfStandardLayout, isMixedLayout, isSetAbstract, isValidTarget, isVirtualKey, removeActiveOnDragOrigin, separateChildren, setIsDragging, withMind, withMindExtend };
3729
3970
  //# sourceMappingURL=plait-mind.mjs.map