@inditextech/weave-sdk 0.20.0 → 0.20.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/sdk.js CHANGED
@@ -1,4 +1,3 @@
1
- import "./node-extensions.d-Q3CaoYb8.d.ts";
2
1
  import Konva from "konva";
3
2
  import "konva/lib/types";
4
3
  import { WEAVE_AWARENESS_LAYER_ID, WEAVE_DEFAULT_TRANSFORM_PROPERTIES, WEAVE_EXPORT_BACKGROUND_COLOR, WEAVE_EXPORT_FILE_FORMAT, WEAVE_EXPORT_FORMATS, WEAVE_INSTANCE_STATUS, WEAVE_NODE_CUSTOM_EVENTS, WEAVE_NODE_LAYER_ID, WEAVE_NODE_POSITION, WEAVE_UTILITY_LAYER_ID } from "@inditextech/weave-types";
@@ -16463,6 +16462,7 @@ const setNodesDefaultConfiguration = (config) => {
16463
16462
  };
16464
16463
  };
16465
16464
  Konva.Node.prototype.updatePosition = function() {};
16465
+ Konva.Node.prototype.resetCrop = function() {};
16466
16466
  };
16467
16467
  var WeaveNode = class {
16468
16468
  register(instance) {
@@ -16510,6 +16510,10 @@ var WeaveNode = class {
16510
16510
  }
16511
16511
  node.width(Math.max(5, node.width() * node.scaleX()));
16512
16512
  node.height(Math.max(5, node.height() * node.scaleY()));
16513
+ if (node.getAttrs().nodeType === "image") node.setAttrs({ uncroppedImage: {
16514
+ width: node.getAttrs().uncroppedImage.width * node.scaleX(),
16515
+ height: node.getAttrs().uncroppedImage.height * node.scaleY()
16516
+ } });
16513
16517
  node.scaleX(1);
16514
16518
  node.scaleY(1);
16515
16519
  }
@@ -16524,7 +16528,9 @@ var WeaveNode = class {
16524
16528
  });
16525
16529
  node.on("transform", (e) => {
16526
16530
  const node$1 = e.target;
16531
+ const nodesSelectionPlugin = this.instance.getPlugin("nodesSelection");
16527
16532
  const nodesSnappingPlugin = this.instance.getPlugin("nodesSnapping");
16533
+ if (nodesSelectionPlugin && this.isSelecting() && this.isNodeSelected(node$1)) nodesSelectionPlugin.getTransformer().forceUpdate();
16528
16534
  if (nodesSnappingPlugin && this.isSelecting() && this.isNodeSelected(node$1)) nodesSnappingPlugin.evaluateGuidelines(e);
16529
16535
  if (this.isSelecting() && this.isNodeSelected(node$1)) {
16530
16536
  this.scaleReset(node$1);
@@ -16535,8 +16541,10 @@ var WeaveNode = class {
16535
16541
  });
16536
16542
  node.on("transformend", (e) => {
16537
16543
  const node$1 = e.target;
16544
+ const nodesSelectionPlugin = this.instance.getPlugin("nodesSelection");
16538
16545
  const nodesSnappingPlugin = this.instance.getPlugin("nodesSnapping");
16539
16546
  if (nodesSnappingPlugin && this.isSelecting() && this.isNodeSelected(node$1)) nodesSnappingPlugin.cleanupEvaluateGuidelines();
16547
+ if (nodesSelectionPlugin && this.isSelecting() && this.isNodeSelected(node$1)) nodesSelectionPlugin.getTransformer().forceUpdate();
16540
16548
  });
16541
16549
  node.on("dragmove", (e) => {
16542
16550
  if (this.isSelecting() && this.isNodeSelected(node)) {
@@ -16549,6 +16557,8 @@ var WeaveNode = class {
16549
16557
  node.on("dragend", (e) => {
16550
16558
  if (this.isSelecting() && this.isNodeSelected(node)) {
16551
16559
  clearContainerTargets(this.instance);
16560
+ const nodesSnappingPlugin = this.instance.getPlugin("nodesSnapping");
16561
+ if (nodesSnappingPlugin && this.isSelecting() && this.isNodeSelected(node)) nodesSnappingPlugin.cleanupEvaluateGuidelines();
16552
16562
  const containerToMove = moveNodeToContainer(this.instance, e.target);
16553
16563
  if (containerToMove) return;
16554
16564
  this.instance.updateNode(this.serialize(node));
@@ -18025,7 +18035,7 @@ var WeaveRegisterManager = class {
18025
18035
 
18026
18036
  //#endregion
18027
18037
  //#region package.json
18028
- var version = "0.20.0";
18038
+ var version = "0.20.2";
18029
18039
 
18030
18040
  //#endregion
18031
18041
  //#region src/managers/setup.ts
@@ -18761,6 +18771,8 @@ var WeaveGroupNode = class extends WeaveNode {
18761
18771
  }
18762
18772
  onUpdate(nodeInstance, nextProps) {
18763
18773
  nodeInstance.setAttrs({ ...nextProps });
18774
+ const nodesSelectionPlugin = this.instance.getPlugin("nodesSelection");
18775
+ if (nodesSelectionPlugin) nodesSelectionPlugin.getTransformer().forceUpdate();
18764
18776
  }
18765
18777
  serialize(instance) {
18766
18778
  const attrs = instance.getAttrs();
@@ -18812,6 +18824,8 @@ var WeaveRectangleNode = class extends WeaveNode {
18812
18824
  }
18813
18825
  onUpdate(nodeInstance, nextProps) {
18814
18826
  nodeInstance.setAttrs({ ...nextProps });
18827
+ const nodesSelectionPlugin = this.instance.getPlugin("nodesSelection");
18828
+ if (nodesSelectionPlugin) nodesSelectionPlugin.getTransformer().forceUpdate();
18815
18829
  }
18816
18830
  };
18817
18831
 
@@ -18844,6 +18858,8 @@ var WeaveLineNode = class extends WeaveNode {
18844
18858
  }
18845
18859
  onUpdate(nodeInstance, nextProps) {
18846
18860
  nodeInstance.setAttrs({ ...nextProps });
18861
+ const nodesSelectionPlugin = this.instance.getPlugin("nodesSelection");
18862
+ if (nodesSelectionPlugin) nodesSelectionPlugin.getTransformer().forceUpdate();
18847
18863
  }
18848
18864
  };
18849
18865
 
@@ -19379,6 +19395,7 @@ var WeaveImageToolAction = class extends WeaveAction {
19379
19395
  width: 100 * aspectRatio,
19380
19396
  height: 100,
19381
19397
  opacity: 1,
19398
+ adding: true,
19382
19399
  imageURL: this.imageURL,
19383
19400
  stroke: "#000000ff",
19384
19401
  strokeWidth: 0,
@@ -19405,18 +19422,21 @@ var WeaveImageToolAction = class extends WeaveAction {
19405
19422
  x: this.clickPoint?.x ?? 0,
19406
19423
  y: this.clickPoint?.y ?? 0,
19407
19424
  opacity: 1,
19425
+ adding: false,
19408
19426
  imageURL: this.imageURL,
19409
19427
  stroke: "#000000ff",
19410
19428
  strokeWidth: 0,
19411
19429
  strokeScaleEnabled: false,
19430
+ imageWidth: this.preloadImgs[this.imageId].width,
19431
+ imageHeight: this.preloadImgs[this.imageId].height,
19412
19432
  imageInfo: {
19413
19433
  width: this.preloadImgs[this.imageId].width,
19414
19434
  height: this.preloadImgs[this.imageId].height
19415
19435
  }
19416
19436
  });
19417
19437
  this.instance.addNode(node, this.container?.getAttrs().id);
19418
- const rectangleNodeHandler = this.instance.getNodeHandler("rectangle");
19419
- this.instance.removeNode(rectangleNodeHandler.serialize(tempImage));
19438
+ const imageNodeHandler = this.instance.getNodeHandler("image");
19439
+ this.instance.removeNode(imageNodeHandler.serialize(tempImage));
19420
19440
  this.setState(IMAGE_TOOL_STATE.FINISHED);
19421
19441
  }
19422
19442
  this.cancelAction();
@@ -19460,20 +19480,17 @@ var WeaveImageToolAction = class extends WeaveAction {
19460
19480
  };
19461
19481
 
19462
19482
  //#endregion
19463
- //#region src/nodes/image/clip.ts
19464
- var WeaveImageClip = class {
19483
+ //#region src/nodes/image/crop.ts
19484
+ var WeaveImageCrop = class WeaveImageCrop {
19465
19485
  constructor(instance, node, image, internalImage, clipGroup) {
19466
19486
  this.instance = instance;
19467
19487
  this.node = node;
19468
19488
  this.image = image;
19469
19489
  this.internalImage = internalImage;
19470
- this.clipGroup = clipGroup;
19490
+ this.cropGroup = clipGroup;
19471
19491
  this.handleHide = this.hide.bind(this);
19472
- this.handleCrop = this.handleClipTransform.bind(this);
19473
- this.handleDrag = this.handleClipDrag.bind(this);
19474
19492
  }
19475
19493
  show() {
19476
- const originalImage = this.internalImage.getAttr("image");
19477
19494
  const nodeSnappingPlugin = this.instance.getPlugin("nodesSnapping");
19478
19495
  if (nodeSnappingPlugin) this.instance.disablePlugin("nodesSnapping");
19479
19496
  const selectionPlugin = this.instance.getPlugin("nodesSelection");
@@ -19482,74 +19499,153 @@ var WeaveImageClip = class {
19482
19499
  selectionPlugin.getTransformer().nodes([]);
19483
19500
  selectionPlugin.getTransformer().hide();
19484
19501
  }
19485
- const ratio = this.internalImage.cropWidth() === 0 ? this.image.width() / this.image.width() : this.image.width() / this.internalImage.cropWidth();
19486
- const originWidth = ratio * originalImage.width;
19487
- const originHeight = ratio * originalImage.height;
19488
- const cropX = this.internalImage.cropX() * ratio;
19489
- const cropY = this.internalImage.cropY() * ratio;
19502
+ this.image.setAttrs({ cropping: true });
19503
+ const imageAttrs = this.image.getAttrs();
19490
19504
  this.internalImage.hide();
19491
- const clipImage = this.internalImage.clone({
19492
- width: originWidth,
19493
- height: originHeight,
19494
- cropX: 0,
19495
- cropY: 0,
19496
- cropWidth: 0,
19497
- cropHeight: 0,
19505
+ this.cropGroup.destroyChildren();
19506
+ const actualScale = imageAttrs.uncroppedImage.width / imageAttrs.imageInfo.width;
19507
+ const cropScale = imageAttrs.cropInfo ? imageAttrs.cropInfo.scaleX : actualScale;
19508
+ const realScale = actualScale / cropScale;
19509
+ this.cropImage = new Konva.Image({
19510
+ x: imageAttrs.cropInfo ? -imageAttrs.cropInfo.x * realScale : 0,
19511
+ y: imageAttrs.cropInfo ? -imageAttrs.cropInfo.y * realScale : 0,
19512
+ width: imageAttrs.uncroppedImage.width,
19513
+ height: imageAttrs.uncroppedImage.height,
19514
+ scaleX: 1,
19515
+ scaleY: 1,
19516
+ image: this.internalImage.image(),
19517
+ crop: void 0,
19498
19518
  visible: true,
19499
- draggable: false,
19500
- rotation: 0
19519
+ listening: false,
19520
+ draggable: false
19501
19521
  });
19502
- this.clipRect = new Konva.Rect({
19503
- width: this.internalImage.width(),
19504
- height: this.internalImage.height(),
19505
- fill: "rgba(0,0,0,0.5)",
19522
+ this.imageOffsetX = imageAttrs.cropInfo ? imageAttrs.cropInfo.x * realScale : 0;
19523
+ this.imageOffsetY = imageAttrs.cropInfo ? imageAttrs.cropInfo.y * realScale : 0;
19524
+ this.cropRect = new Konva.Rect({
19506
19525
  x: 0,
19507
19526
  y: 0,
19527
+ width: imageAttrs.cropInfo ? imageAttrs.cropInfo.width * realScale : imageAttrs.uncroppedImage.width,
19528
+ height: imageAttrs.cropInfo ? imageAttrs.cropInfo.height * realScale : imageAttrs.uncroppedImage.height,
19529
+ fill: "rgba(0,0,0,0.2)",
19530
+ stroke: "#ff0000ff",
19531
+ strokeWidth: 0,
19532
+ strokeScaleEnabled: false,
19508
19533
  draggable: true,
19509
19534
  rotation: 0
19510
19535
  });
19511
19536
  this.transformer = new Konva.Transformer({
19537
+ id: `${this.image.getAttrs().id}_transformer`,
19538
+ x: 0,
19539
+ y: 0,
19512
19540
  flipEnabled: false,
19513
19541
  keepRatio: false,
19542
+ ignoreStroke: false,
19514
19543
  rotateEnabled: false,
19515
19544
  enabledAnchors: [
19516
19545
  "top-left",
19546
+ "top-center",
19517
19547
  "top-right",
19548
+ "middle-right",
19518
19549
  "bottom-left",
19519
- "bottom-right"
19550
+ "middle-left",
19551
+ "bottom-right",
19552
+ "bottom-center"
19520
19553
  ],
19554
+ anchorDragBoundFunc: (_, newPos) => {
19555
+ let closestSnap = newPos;
19556
+ let minDist = 10;
19557
+ const nodeRotation = this.image.getAbsoluteRotation();
19558
+ const stage = this.instance.getStage();
19559
+ const rotation = nodeRotation * (Math.PI / 180);
19560
+ const center = this.cropImage.getAbsolutePosition();
19561
+ const width = this.cropImage.width() * stage.scaleX();
19562
+ const height = this.cropImage.height() * stage.scaleY();
19563
+ const offset = this.cropImage.offset();
19564
+ const corners = [
19565
+ {
19566
+ x: -offset.x,
19567
+ y: -offset.y
19568
+ },
19569
+ {
19570
+ x: width - offset.x,
19571
+ y: -offset.y
19572
+ },
19573
+ {
19574
+ x: width - offset.x,
19575
+ y: height - offset.y
19576
+ },
19577
+ {
19578
+ x: -offset.x,
19579
+ y: height - offset.y
19580
+ }
19581
+ ].map((pt) => {
19582
+ const cos = Math.cos(rotation);
19583
+ const sin = Math.sin(rotation);
19584
+ return {
19585
+ x: center.x + pt.x * cos - pt.y * sin,
19586
+ y: center.y + pt.x * sin + pt.y * cos
19587
+ };
19588
+ });
19589
+ const edges = [
19590
+ [corners[0], corners[1]],
19591
+ [corners[1], corners[2]],
19592
+ [corners[2], corners[3]],
19593
+ [corners[3], corners[0]]
19594
+ ];
19595
+ for (const [a, b] of edges) {
19596
+ const candidate = this.closestPointOnLine(newPos, a, b);
19597
+ const dist = Math.hypot(newPos.x - candidate.x, newPos.y - candidate.y);
19598
+ if (dist < minDist) {
19599
+ closestSnap = candidate;
19600
+ minDist = dist;
19601
+ }
19602
+ }
19603
+ return closestSnap;
19604
+ },
19521
19605
  rotation: 0
19522
19606
  });
19523
19607
  this.grid = new Konva.Group();
19524
- this.transformer.on("dragmove", this.handleDrag);
19525
- this.transformer.on("transform", this.handleCrop);
19526
- this.transformer.nodes([this.clipRect]);
19527
- this.clipGroup.add(clipImage);
19528
- this.clipGroup.add(this.clipRect);
19529
- this.clipGroup.add(this.grid);
19530
- this.clipGroup.add(this.transformer);
19531
- this.clipGroup.setPosition({
19532
- x: -cropX,
19533
- y: -cropY
19608
+ const cropRect = this.cropRect.getClientRect({
19609
+ relativeTo: this.cropGroup,
19610
+ skipStroke: true
19611
+ });
19612
+ this.drawGridLines(0, 0, cropRect.width, cropRect.height);
19613
+ this.cropRect.on("dragmove", () => {
19614
+ const cropRect$1 = this.cropRect.getClientRect({
19615
+ relativeTo: this.cropGroup,
19616
+ skipStroke: true
19617
+ });
19618
+ this.drawGridLines(cropRect$1.x, cropRect$1.y, cropRect$1.width, cropRect$1.height);
19534
19619
  });
19535
- this.clipRect.position({
19536
- x: cropX,
19537
- y: cropY
19620
+ this.cropRect.on("transform", () => {
19621
+ const cropRect$1 = this.cropRect.getClientRect({
19622
+ relativeTo: this.cropGroup,
19623
+ skipStroke: true
19624
+ });
19625
+ this.drawGridLines(cropRect$1.x, cropRect$1.y, cropRect$1.width, cropRect$1.height);
19538
19626
  });
19539
- this.handleClipTransform();
19540
- this.clipGroup.show();
19627
+ this.transformer.nodes([this.cropRect]);
19628
+ this.cropGroup.add(this.cropImage);
19629
+ this.cropGroup.add(this.cropRect);
19630
+ this.cropGroup.add(this.grid);
19631
+ const utilityLayer = this.instance.getUtilityLayer();
19632
+ utilityLayer?.add(this.transformer);
19633
+ this.transformer.forceUpdate();
19634
+ this.cropGroup.show();
19541
19635
  this.instance.getStage().container().addEventListener("keydown", this.handleHide);
19542
19636
  }
19543
- hide() {
19544
- this.handleClipEnd();
19545
- this.node.cropping = false;
19637
+ hide(e) {
19638
+ if (!["Enter", "Escape"].includes(e.key)) return;
19639
+ this.image.setAttrs({ cropping: false });
19640
+ if (e.key === "Enter") this.handleClipEnd();
19641
+ const utilityLayer = this.instance.getUtilityLayer();
19642
+ utilityLayer?.destroyChildren();
19546
19643
  this.instance.getStage().container().removeEventListener("keydown", this.handleHide);
19547
- this.transformer.off("dragmove", this.handleDrag);
19548
- this.transformer.off("transform", this.handleCrop);
19549
- this.clipGroup.destroyChildren();
19550
- this.clipGroup.hide();
19644
+ this.cropGroup.destroyChildren();
19645
+ this.cropGroup.hide();
19551
19646
  const nodeSnappingPlugin = this.instance.getPlugin("nodesSnapping");
19552
19647
  if (nodeSnappingPlugin) this.instance.enablePlugin("nodesSnapping");
19648
+ this.internalImage.show();
19553
19649
  const selectionPlugin = this.instance.getPlugin("nodesSelection");
19554
19650
  if (selectionPlugin) {
19555
19651
  this.instance.enablePlugin("nodesSelection");
@@ -19557,126 +19653,145 @@ var WeaveImageClip = class {
19557
19653
  selectionTransformer.nodes([this.image]);
19558
19654
  selectionTransformer.show();
19559
19655
  setTimeout(() => {
19656
+ selectionPlugin.triggerSelectedNodesEvent();
19560
19657
  selectionTransformer.forceUpdate();
19561
19658
  }, 0);
19562
19659
  }
19563
- this.internalImage.show();
19564
- }
19565
- handleClipTransform() {
19566
- if (!this.node.cropping) return;
19567
- const originalImage = this.internalImage.getAttr("image");
19568
- let x = this.clipRect.x();
19569
- let y = this.clipRect.y();
19570
- let width = this.clipRect.width() * this.clipRect.scaleX();
19571
- let height = this.clipRect.height() * this.clipRect.scaleY();
19572
- if (x < 0) {
19573
- width += x;
19574
- x = 0;
19575
- }
19576
- if (x + width > originalImage.width) width = originalImage.width - x;
19577
- if (y < 0) {
19578
- height += y;
19579
- y = 0;
19580
- }
19581
- if (y + height > originalImage.height) height = originalImage.height - y;
19582
- this.clipRect.setAttrs({
19583
- x,
19584
- y,
19585
- width,
19586
- height,
19587
- scaleX: 1,
19588
- scaleY: 1
19589
- });
19590
- this.transformer.absolutePosition(this.clipRect.absolutePosition());
19591
- this.grid.position({
19592
- x,
19593
- y
19594
- });
19595
- this.drawGridLines(width, height);
19596
- }
19597
- handleClipDrag() {
19598
- if (!this.node.cropping) return;
19599
- const originalImage = this.internalImage.getAttr("image");
19600
- let x = this.clipRect.x();
19601
- let y = this.clipRect.y();
19602
- let width = this.clipRect.width();
19603
- let height = this.clipRect.height();
19604
- const originWidth = originalImage.width;
19605
- const originHeight = originalImage.height;
19606
- if (x < 0) x = 0;
19607
- if (x + width > originWidth) {
19608
- x = originWidth - width;
19609
- width = originWidth - x;
19610
- }
19611
- if (y < 0) y = 0;
19612
- if (y + height > originHeight) {
19613
- y = originHeight - height;
19614
- height = originHeight - y;
19615
- }
19616
- this.clipRect.setAttrs({
19617
- x,
19618
- y,
19619
- width,
19620
- height
19621
- });
19622
- this.grid.position({
19623
- x,
19624
- y
19625
- });
19626
- this.drawGridLines(width, height);
19627
19660
  }
19628
- drawGridLines(width, height) {
19629
- if (!this.node.cropping) return;
19661
+ drawGridLines(x, y, width, height) {
19662
+ if (!this.image.getAttrs().cropping) return;
19630
19663
  this.grid.destroyChildren();
19631
19664
  const stepX = width / 3;
19632
19665
  const stepY = height / 3;
19633
19666
  for (let i = 1; i <= 2; i++) {
19634
19667
  const vLine = new Konva.Line({
19635
19668
  points: [
19636
- stepX * i,
19637
- 0,
19638
- stepX * i,
19639
- height
19669
+ x + stepX * i,
19670
+ y,
19671
+ x + stepX * i,
19672
+ y + height
19640
19673
  ],
19641
- stroke: "#ffffff",
19642
- strokeWidth: 1
19674
+ stroke: "#0074ffcc",
19675
+ strokeWidth: 1,
19676
+ strokeScaleEnabled: false
19643
19677
  });
19644
19678
  const hLine = new Konva.Line({
19645
19679
  points: [
19646
- 0,
19647
- stepY * i,
19648
- width,
19649
- stepY * i
19680
+ x,
19681
+ y + stepY * i,
19682
+ x + width,
19683
+ y + stepY * i
19650
19684
  ],
19651
- stroke: "#ffffff",
19652
- strokeWidth: 1
19685
+ stroke: "#0074ffcc",
19686
+ strokeWidth: 1,
19687
+ strokeScaleEnabled: false
19653
19688
  });
19654
19689
  this.grid.add(vLine, hLine);
19655
19690
  }
19656
19691
  }
19692
+ unCrop() {
19693
+ const imageAttrs = this.image.getAttrs();
19694
+ this.cropGroup.destroyChildren();
19695
+ const actualScale = imageAttrs.uncroppedImage.width / imageAttrs.imageInfo.width;
19696
+ const cropScale = imageAttrs.cropInfo ? imageAttrs.cropInfo.scaleX : actualScale;
19697
+ const realScale = actualScale / cropScale;
19698
+ this.cropImage = new Konva.Image({
19699
+ x: imageAttrs.cropInfo ? -imageAttrs.cropInfo.x * realScale : 0,
19700
+ y: imageAttrs.cropInfo ? -imageAttrs.cropInfo.y * realScale : 0,
19701
+ width: imageAttrs.uncroppedImage.width,
19702
+ height: imageAttrs.uncroppedImage.height,
19703
+ scaleX: 1,
19704
+ scaleY: 1,
19705
+ image: this.internalImage.image(),
19706
+ crop: void 0,
19707
+ visible: false,
19708
+ listening: false,
19709
+ draggable: false
19710
+ });
19711
+ this.cropGroup.add(this.cropImage);
19712
+ const cropImageStage = this.cropImage.getAbsolutePosition();
19713
+ this.image.setAttrs({
19714
+ width: imageAttrs.uncroppedImage.width,
19715
+ height: imageAttrs.uncroppedImage.height
19716
+ });
19717
+ this.image.setAbsolutePosition(cropImageStage);
19718
+ this.image.attrs.cropInfo = void 0;
19719
+ this.instance.updateNode(this.node.serialize(this.image));
19720
+ }
19657
19721
  handleClipEnd() {
19658
- if (!this.node.cropping) return;
19659
- const cropX = this.clipRect.x();
19660
- const cropY = this.clipRect.y();
19661
- const width = this.clipRect.width();
19662
- const height = this.clipRect.height();
19663
- if (this.image) {
19722
+ const clipRect = this.cropRect.getClientRect({ relativeTo: this.cropGroup });
19723
+ const originalRotation = this.image.getAbsoluteRotation();
19724
+ this.cropImage.rotation(-originalRotation);
19725
+ this.cropRect.rotation(-originalRotation);
19726
+ const intersectionRect = this.getIntersectionRect(this.cropImage, this.cropRect);
19727
+ this.cropImage.rotation(0);
19728
+ this.cropRect.rotation(0);
19729
+ const clipRectGroup = this.cropRect.getClientRect({ relativeTo: this.cropGroup });
19730
+ if (!intersectionRect) return;
19731
+ const imageAttrs = this.internalImage.getAttrs();
19732
+ const actualScale = imageAttrs.uncroppedImage.width / imageAttrs.imageInfo.width;
19733
+ const realClipRect = {
19734
+ scaleX: actualScale,
19735
+ scaleY: actualScale,
19736
+ x: WeaveImageCrop.roundTo6Decimals(clipRectGroup.x + this.imageOffsetX),
19737
+ y: WeaveImageCrop.roundTo6Decimals(clipRectGroup.y + this.imageOffsetY),
19738
+ width: WeaveImageCrop.roundTo6Decimals(clipRectGroup.width),
19739
+ height: WeaveImageCrop.roundTo6Decimals(clipRectGroup.height)
19740
+ };
19741
+ if (this.image && clipRect) {
19742
+ const clipRectStage = this.cropRect.getAbsolutePosition();
19743
+ const clipRectGroup$1 = this.cropRect.getClientRect({ relativeTo: this.cropGroup });
19664
19744
  this.image.setAttrs({
19665
- width,
19666
- height,
19667
- cropX,
19668
- cropY,
19669
- cropWidth: width,
19670
- cropHeight: height
19671
- });
19672
- const clipRectPos = this.clipRect.getAbsolutePosition();
19673
- this.image.setPosition({
19674
- x: clipRectPos.x,
19675
- y: clipRectPos.y
19745
+ width: clipRectGroup$1.width,
19746
+ height: clipRectGroup$1.height,
19747
+ cropInfo: realClipRect,
19748
+ cropSize: clipRectGroup$1,
19749
+ uncroppedImage: {
19750
+ width: imageAttrs.uncroppedImage.width,
19751
+ height: imageAttrs.uncroppedImage.height
19752
+ }
19676
19753
  });
19754
+ this.image.setAbsolutePosition(clipRectStage);
19677
19755
  this.instance.updateNode(this.node.serialize(this.image));
19678
19756
  }
19679
19757
  }
19758
+ static roundTo6Decimals(value) {
19759
+ return parseFloat(value.toFixed(6));
19760
+ }
19761
+ getIntersectionRect(a, b) {
19762
+ const rectA = a.getClientRect({ skipStroke: true });
19763
+ const rectB = b.getClientRect({ skipStroke: true });
19764
+ const x1 = WeaveImageCrop.roundTo6Decimals(Math.max(rectA.x, rectB.x));
19765
+ const y1 = WeaveImageCrop.roundTo6Decimals(Math.max(rectA.y, rectB.y));
19766
+ const x2 = WeaveImageCrop.roundTo6Decimals(Math.min(rectA.x + rectA.width, rectB.x + rectB.width));
19767
+ const y2 = WeaveImageCrop.roundTo6Decimals(Math.min(rectA.y + rectA.height, rectB.y + rectB.height));
19768
+ const width = WeaveImageCrop.roundTo6Decimals(x2 - x1);
19769
+ const height = WeaveImageCrop.roundTo6Decimals(y2 - y1);
19770
+ if (width <= 0 || height <= 0) return null;
19771
+ return {
19772
+ x: x1,
19773
+ y: y1,
19774
+ width,
19775
+ height
19776
+ };
19777
+ }
19778
+ closestPointOnLine(p, a, b) {
19779
+ const ab = {
19780
+ x: b.x - a.x,
19781
+ y: b.y - a.y
19782
+ };
19783
+ const abLengthSquared = ab.x ** 2 + ab.y ** 2;
19784
+ if (abLengthSquared === 0) return a;
19785
+ const ap = {
19786
+ x: p.x - a.x,
19787
+ y: p.y - a.y
19788
+ };
19789
+ const t = Math.max(0, Math.min(1, (ap.x * ab.x + ap.y * ab.y) / abLengthSquared));
19790
+ return {
19791
+ x: a.x + t * ab.x,
19792
+ y: a.y + t * ab.y
19793
+ };
19794
+ }
19680
19795
  };
19681
19796
 
19682
19797
  //#endregion
@@ -19694,8 +19809,8 @@ var WeaveImageNode = class extends WeaveNode {
19694
19809
  ...WEAVE_DEFAULT_TRANSFORM_PROPERTIES,
19695
19810
  ...config?.transform
19696
19811
  } };
19812
+ this.cachedCropInfo = {};
19697
19813
  this.imageLoaded = false;
19698
- this.cropping = false;
19699
19814
  }
19700
19815
  onRender(props) {
19701
19816
  const imageProperties = props.imageProperties;
@@ -19711,9 +19826,18 @@ var WeaveImageNode = class extends WeaveNode {
19711
19826
  delete internalImageProps.zIndex;
19712
19827
  const image = new Konva.Group({
19713
19828
  ...groupImageProps,
19829
+ ...internalImageProps,
19714
19830
  id,
19715
19831
  name: "node"
19716
19832
  });
19833
+ image.resetCrop = () => {
19834
+ const stage = this.instance.getStage();
19835
+ const image$1 = stage.findOne(`#${id}`);
19836
+ if (!image$1) return;
19837
+ const imageCrop = new WeaveImageCrop(this.instance, this, image$1, internalImage, cropGroup);
19838
+ imageCrop.unCrop();
19839
+ this.cachedCropInfo[image$1.getAttrs().id ?? ""] = void 0;
19840
+ };
19717
19841
  image.getTransformerProperties = () => {
19718
19842
  return this.config.transform;
19719
19843
  };
@@ -19746,25 +19870,30 @@ var WeaveImageNode = class extends WeaveNode {
19746
19870
  rotation: 0,
19747
19871
  width: 0,
19748
19872
  height: 0,
19873
+ stroke: "#ff0000ff",
19874
+ strokeWidth: 0,
19875
+ strokeScaleEnabled: false,
19749
19876
  draggable: false,
19750
19877
  visible: false
19751
19878
  });
19752
19879
  image.add(internalImage);
19753
- const clipGroup = new Konva.Group({
19880
+ const cropGroup = new Konva.Group({
19881
+ id: `${id}-cropGroup`,
19754
19882
  x: 0,
19755
19883
  y: 0,
19884
+ scaleX: 1,
19885
+ scaleY: 1,
19756
19886
  visible: false
19757
19887
  });
19758
- image.add(clipGroup);
19888
+ image.add(cropGroup);
19759
19889
  this.setupDefaultNodeEvents(image);
19760
19890
  image.on("dblclick dbltap", (evt) => {
19761
19891
  evt.cancelBubble = true;
19762
- if (this.cropping) return;
19892
+ if (image.getAttrs().cropping ?? false) return;
19763
19893
  if (!internalImage.getAttr("image")) return;
19764
19894
  if (!(this.isSelecting() && this.isNodeSelected(image))) return;
19765
- this.cropping = true;
19766
- const imageClip = new WeaveImageClip(this.instance, this, image, internalImage, clipGroup);
19767
- imageClip.show();
19895
+ const imageCrop = new WeaveImageCrop(this.instance, this, image, internalImage, cropGroup);
19896
+ imageCrop.show();
19768
19897
  });
19769
19898
  const imageActionTool = this.getImageToolAction();
19770
19899
  const preloadImg = imageActionTool.getPreloadedImage(imageProps.id);
@@ -19783,6 +19912,12 @@ var WeaveImageNode = class extends WeaveNode {
19783
19912
  this.imageLoaded = true;
19784
19913
  image.setAttr("width", image.width() ? image.width() : preloadImg.width);
19785
19914
  image.setAttr("height", image.height() ? image.height() : preloadImg.height);
19915
+ const imageRect = image.getClientRect();
19916
+ image.setAttr("cropInfo", void 0);
19917
+ image.setAttr("uncroppedImage", {
19918
+ width: imageRect.width,
19919
+ height: imageRect.height
19920
+ });
19786
19921
  image.setAttr("imageInfo", {
19787
19922
  width: preloadImg.width,
19788
19923
  height: preloadImg.height
@@ -19838,25 +19973,33 @@ var WeaveImageNode = class extends WeaveNode {
19838
19973
  zIndex: 1
19839
19974
  });
19840
19975
  }
19841
- if (this.imageLoaded) internalImage?.setAttrs({
19842
- ...internalImageProps,
19843
- ...nodeAttrs.imageProperties ?? {},
19844
- name: void 0,
19845
- id: `${id}-image`,
19846
- nodeId: id,
19847
- x: 0,
19848
- y: 0,
19849
- scaleX: 1,
19850
- scaleY: 1,
19851
- rotation: 0,
19852
- visible: true,
19853
- draggable: false,
19854
- zIndex: 0
19855
- });
19976
+ if (this.imageLoaded) {
19977
+ internalImage?.setAttrs({
19978
+ ...internalImageProps,
19979
+ ...nodeAttrs.imageProperties ?? {},
19980
+ name: void 0,
19981
+ id: `${id}-image`,
19982
+ nodeId: id,
19983
+ x: 0,
19984
+ y: 0,
19985
+ scaleX: 1,
19986
+ scaleY: 1,
19987
+ rotation: 0,
19988
+ visible: true,
19989
+ draggable: false,
19990
+ zIndex: 0
19991
+ });
19992
+ this.updateCrop(nextProps);
19993
+ }
19994
+ try {
19995
+ const selectionPlugin = this.instance.getPlugin("nodesSelection");
19996
+ if (selectionPlugin) selectionPlugin.getTransformer().forceUpdate();
19997
+ } catch (error) {
19998
+ console.error("Error updating transformer", error);
19999
+ }
19856
20000
  }
19857
20001
  loadImage(params, image) {
19858
20002
  const imageProps = params;
19859
- const imageGroup = image.findOne(`#${imageProps.id}`);
19860
20003
  const imagePlaceholder = image.findOne(`#${imageProps.id}-placeholder`);
19861
20004
  const internalImage = image.findOne(`#${imageProps.id}-image`);
19862
20005
  const imageObj = new Image();
@@ -19866,29 +20009,71 @@ var WeaveImageNode = class extends WeaveNode {
19866
20009
  internalImage?.setAttrs({ visible: false });
19867
20010
  };
19868
20011
  imageObj.onload = () => {
19869
- imageGroup?.setAttrs({
19870
- width: imageProps.width ? imageProps.width : imageObj.width,
19871
- height: imageProps.height ? imageProps.height : imageObj.height
19872
- });
19873
- imagePlaceholder?.destroy();
19874
- internalImage?.setAttrs({
19875
- width: imageProps.width ? imageProps.width : imageObj.width,
19876
- height: imageProps.height ? imageProps.height : imageObj.height,
19877
- image: imageObj,
19878
- visible: true
19879
- });
19880
- internalImage?.zIndex(0);
19881
- this.imageLoaded = true;
19882
- image.setAttr("width", imageProps.width ? imageProps.width : imageObj.width);
19883
- image.setAttr("height", imageProps.height ? imageProps.height : imageObj.height);
19884
- image.setAttr("imageInfo", {
19885
- width: imageObj.width,
19886
- height: imageObj.height
19887
- });
19888
- this.instance.updateNode(this.serialize(image));
20012
+ if (image && imagePlaceholder && internalImage) {
20013
+ image.setAttrs({
20014
+ width: imageProps.width ? imageProps.width : imageObj.width,
20015
+ height: imageProps.height ? imageProps.height : imageObj.height
20016
+ });
20017
+ imagePlaceholder.destroy();
20018
+ internalImage.setAttrs({
20019
+ width: imageProps.width ? imageProps.width : imageObj.width,
20020
+ height: imageProps.height ? imageProps.height : imageObj.height,
20021
+ image: imageObj,
20022
+ visible: true
20023
+ });
20024
+ internalImage.setAttr("imageInfo", {
20025
+ width: imageObj.width,
20026
+ height: imageObj.height
20027
+ });
20028
+ internalImage.zIndex(0);
20029
+ this.imageLoaded = true;
20030
+ image.setAttrs({
20031
+ width: imageProps.width ? imageProps.width : imageObj.width,
20032
+ height: imageProps.height ? imageProps.height : imageObj.height
20033
+ });
20034
+ image.setAttr("imageInfo", {
20035
+ width: imageObj.width,
20036
+ height: imageObj.height
20037
+ });
20038
+ this.updateCrop(imageProps);
20039
+ }
19889
20040
  };
19890
20041
  if (imageProps.imageURL) imageObj.src = imageProps.imageURL;
19891
20042
  }
20043
+ updateCrop(nextProps) {
20044
+ const imageAttrs = nextProps;
20045
+ const stage = this.instance.getStage();
20046
+ const image = stage.findOne(`#${imageAttrs.id}`);
20047
+ const internalImage = image?.findOne(`#${imageAttrs.id}-image`);
20048
+ if (image && internalImage && !imageAttrs.adding && imageAttrs.cropInfo && !(0, import_lodash.isEqual)(imageAttrs.cropInfo, this.cachedCropInfo[imageAttrs.id ?? ""])) {
20049
+ const actualScale = imageAttrs.uncroppedImage.width / imageAttrs.imageInfo.width;
20050
+ internalImage.width(imageAttrs.uncroppedImage.width);
20051
+ internalImage.height(imageAttrs.uncroppedImage.height);
20052
+ internalImage.rotation(0);
20053
+ internalImage.scaleX(1);
20054
+ internalImage.scaleY(1);
20055
+ internalImage.crop({
20056
+ x: imageAttrs.cropInfo.x / actualScale,
20057
+ y: imageAttrs.cropInfo.y / actualScale,
20058
+ width: imageAttrs.cropInfo.width / actualScale,
20059
+ height: imageAttrs.cropInfo.height / actualScale
20060
+ });
20061
+ internalImage.width(imageAttrs.cropSize.width);
20062
+ internalImage.height(imageAttrs.cropSize.height);
20063
+ this.cachedCropInfo[imageAttrs.id ?? ""] = imageAttrs.cropInfo;
20064
+ }
20065
+ if (image && internalImage && !imageAttrs.adding && !imageAttrs.cropInfo && !(0, import_lodash.isEqual)(imageAttrs.cropInfo, this.cachedCropInfo[imageAttrs.id ?? ""])) {
20066
+ internalImage.width(imageAttrs.uncroppedImage.width);
20067
+ internalImage.height(imageAttrs.uncroppedImage.height);
20068
+ internalImage.rotation(0);
20069
+ internalImage.scaleX(1);
20070
+ internalImage.scaleY(1);
20071
+ internalImage.crop(void 0);
20072
+ internalImage.width(imageAttrs.uncroppedImage.width);
20073
+ internalImage.height(imageAttrs.uncroppedImage.height);
20074
+ this.cachedCropInfo[imageAttrs.id ?? ""] = void 0;
20075
+ }
20076
+ }
19892
20077
  getImageToolAction() {
19893
20078
  const imageToolAction = this.instance.getActionHandler("imageTool");
19894
20079
  if (!imageToolAction) throw new Error("Image Tool action not found");
@@ -20202,41 +20387,45 @@ var WeaveFrameNode = class extends WeaveNode {
20202
20387
  nodeInstance.setAttrs({ ...newProps });
20203
20388
  const selectorArea = frameNode.findOne(`#${id}-selector-area`);
20204
20389
  if (selectorArea) {
20390
+ const width = nextProps.width ? nextProps.width : nextProps.frameWidth;
20391
+ const height = nextProps.height ? nextProps.height : nextProps.frameHeight;
20205
20392
  selectorArea.setAttrs({
20206
20393
  x: 0,
20207
20394
  y: 0,
20208
- width: nextProps.width,
20209
- height: nextProps.height
20395
+ width,
20396
+ height
20210
20397
  });
20211
20398
  const frameInternalGroup = frameNode.findOne(`#${id}-selector`);
20212
20399
  if (frameInternalGroup) frameInternalGroup.setAttrs({
20213
20400
  x: 0,
20214
20401
  y: 0,
20215
- width: nextProps.width * selectorArea.scaleX(),
20216
- height: nextProps.height * selectorArea.scaleY()
20402
+ width: width * selectorArea.scaleX(),
20403
+ height: height * selectorArea.scaleY()
20217
20404
  });
20218
20405
  const background = frameNode.findOne(`#${id}-bg`);
20219
20406
  if (background) background.setAttrs({
20220
20407
  x: 0,
20221
20408
  y: 0,
20222
- width: nextProps.width * selectorArea.scaleX(),
20223
- height: nextProps.height * selectorArea.scaleY()
20409
+ width: width * selectorArea.scaleX(),
20410
+ height: height * selectorArea.scaleY()
20224
20411
  });
20225
20412
  const text = frameNode.findOne(`#${id}-title`);
20226
20413
  if (text) text.setAttrs({
20227
20414
  x: 0,
20228
20415
  y: -titleHeight,
20229
20416
  text: nextProps.title,
20230
- width: nextProps.width * selectorArea.scaleX()
20417
+ width: width * selectorArea.scaleX()
20231
20418
  });
20232
20419
  const frameInternal = frameNode.findOne(`#${id}-group-internal`);
20233
20420
  if (frameInternal) frameInternal.setAttrs({
20234
20421
  x: 0,
20235
20422
  y: titleHeight,
20236
- width: nextProps.width * selectorArea.scaleX(),
20237
- height: nextProps.height * selectorArea.scaleY()
20423
+ width: width * selectorArea.scaleX(),
20424
+ height: height * selectorArea.scaleY()
20238
20425
  });
20239
20426
  }
20427
+ const nodesSelectionPlugin = this.instance.getPlugin("nodesSelection");
20428
+ if (nodesSelectionPlugin) nodesSelectionPlugin.getTransformer().forceUpdate();
20240
20429
  }
20241
20430
  serialize(instance) {
20242
20431
  const stage = this.instance.getStage();
@@ -22195,6 +22384,7 @@ var WeaveConnectedUsersPlugin = class extends WeavePlugin {
22195
22384
  //#endregion
22196
22385
  //#region src/plugins/users-selection/users-selection.ts
22197
22386
  var WeaveUsersSelectionPlugin = class extends WeavePlugin {
22387
+ padding = 1;
22198
22388
  constructor(params) {
22199
22389
  super();
22200
22390
  const { config } = params;
@@ -22312,17 +22502,15 @@ var WeaveUsersSelectionPlugin = class extends WeavePlugin {
22312
22502
  id: `selector_${userSelector.actualNodes.user}`,
22313
22503
  x: selectionRect.x,
22314
22504
  y: selectionRect.y,
22315
- width: selectionRect.width / stage.scaleX(),
22316
- height: selectionRect.height / stage.scaleY(),
22317
22505
  listening: false
22318
22506
  });
22319
22507
  userSelectorNode.moveToBottom();
22320
22508
  const userSelectorRect = new Konva.Rect({
22321
- x: 0,
22322
- y: 0,
22509
+ x: -this.padding / stage.scaleX(),
22510
+ y: -this.padding / stage.scaleY(),
22323
22511
  id: `selector_${userSelector.actualNodes.user}_rect`,
22324
- width: selectionRect.width / stage.scaleX(),
22325
- height: selectionRect.height / stage.scaleY(),
22512
+ width: (selectionRect.width + 2 * this.padding) / stage.scaleX(),
22513
+ height: (selectionRect.height + 2 * this.padding) / stage.scaleY(),
22326
22514
  fill: "transparent",
22327
22515
  stroke: this.stringToColor(userSelector.actualNodes.user),
22328
22516
  strokeWidth: 3,