@inditextech/weave-sdk 0.20.1 → 0.20.3

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