@inditextech/weave-sdk 3.0.0 → 3.2.0-SNAPSHOT.100.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/sdk.js CHANGED
@@ -4,6 +4,7 @@ import { WEAVE_ASYNC_STATUS, WEAVE_AWARENESS_LAYER_ID, WEAVE_EXPORT_BACKGROUND_C
4
4
  import { getYjsDoc, getYjsValue, observeDeep, syncedStore } from "@syncedstore/core";
5
5
  import * as Y$1 from "yjs";
6
6
  import * as Y from "yjs";
7
+ import "konva/lib/types";
7
8
 
8
9
  //#region rolldown:runtime
9
10
  var __create = Object.create;
@@ -15151,6 +15152,7 @@ var WeaveStore = class {
15151
15152
  });
15152
15153
  }
15153
15154
  if (!this.isRoomLoaded && !(0, import_lodash.isEmpty)(this.state.weave)) {
15155
+ this.instance.checkForAsyncElements();
15154
15156
  this.instance.setupRenderer();
15155
15157
  this.isRoomLoaded = true;
15156
15158
  this.emitOnRoomLoadedEvent();
@@ -17604,7 +17606,7 @@ var require_mergeWith = __commonJS({ "../../node_modules/lodash/mergeWith.js"(ex
17604
17606
  var import_mergeWith = __toESM(require_mergeWith(), 1);
17605
17607
 
17606
17608
  //#endregion
17607
- //#region src/utils.ts
17609
+ //#region src/utils/utils.ts
17608
17610
  function resetScale(node) {
17609
17611
  node.width(Math.round((Math.max(1, node.width() * node.scaleX()) + Number.EPSILON) * 100) / 100);
17610
17612
  node.height(Math.round((Math.max(1, node.height() * node.scaleY()) + Number.EPSILON) * 100) / 100);
@@ -17817,7 +17819,7 @@ function getTargetAndSkipNodes(instance, e, forceTransformer = false) {
17817
17819
  };
17818
17820
  let skipNodes = [];
17819
17821
  let node = void 0;
17820
- if (e.type === "dragmove" && nodesSelectionPlugin && nodesSelectionPlugin.getTransformer().nodes().length === 1) {
17822
+ if (e.type === "dragmove" && nodesSelectionPlugin?.getTransformer().nodes().length === 1) {
17821
17823
  node = nodesSelectionPlugin.getTransformer().nodes()[0];
17822
17824
  skipNodes.push(node.getAttrs().id ?? "");
17823
17825
  if (node.getAttr("eventTarget")) {
@@ -17879,6 +17881,8 @@ function getTopmostShadowHost(el) {
17879
17881
  return current?.shadowRoot || null;
17880
17882
  }
17881
17883
  function getVisibleNodes({ instance, stage, nodeParent, skipNodes, referenceLayer }) {
17884
+ const nodesSelection = instance.getPlugin("nodesSelection");
17885
+ if (nodesSelection) nodesSelection.getTransformer().hide();
17882
17886
  const nodes = getVisibleNodesInViewport(stage, referenceLayer);
17883
17887
  const finalVisibleNodes = [];
17884
17888
  nodes.forEach((node) => {
@@ -17891,6 +17895,7 @@ function getVisibleNodes({ instance, stage, nodeParent, skipNodes, referenceLaye
17891
17895
  if (node.getParent() !== referenceLayer && !node.getParent()?.getAttrs().nodeId) return;
17892
17896
  finalVisibleNodes.push(node);
17893
17897
  });
17898
+ if (nodesSelection) nodesSelection.getTransformer().show();
17894
17899
  return finalVisibleNodes;
17895
17900
  }
17896
17901
  function memoize(fn) {
@@ -17920,7 +17925,7 @@ const getPositionRelativeToContainerOnPosition = (instance) => {
17920
17925
  };
17921
17926
  const canComposite = (node) => {
17922
17927
  const parent = node.getParent();
17923
- return parent && parent.getClassName() === "Group" && parent.getAttrs().nodeType !== "frame" && parent.getAttrs().nodeId === void 0;
17928
+ return parent?.getClassName() === "Group" && parent?.getAttrs().nodeType !== "frame" && parent?.getAttrs().nodeId === void 0;
17924
17929
  };
17925
17930
  function mergeExceptArrays(object, source) {
17926
17931
  return (0, import_mergeWith.default)({}, object, source, (objValue, srcValue) => {
@@ -18755,8 +18760,6 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
18755
18760
  tr.on("transformstart", () => {
18756
18761
  this.transformInProcess = true;
18757
18762
  this.triggerSelectedNodesEvent();
18758
- tr.visible(false);
18759
- tr.forceUpdate();
18760
18763
  const selectedNodes$1 = tr.nodes();
18761
18764
  for (const node of selectedNodes$1) {
18762
18765
  node.handleMouseout();
@@ -18790,7 +18793,11 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
18790
18793
  } else nodeHovered?.handleMouseout?.();
18791
18794
  });
18792
18795
  tr.on("mouseover", () => {
18793
- stage.container().style.cursor = "grab";
18796
+ const nodesSelected = tr.nodes();
18797
+ if (nodesSelected.length === 1) {
18798
+ const node = nodesSelected[0];
18799
+ stage.container().style.cursor = node.defineMousePointer() ?? "grab";
18800
+ } else stage.container().style.cursor = "grab";
18794
18801
  });
18795
18802
  tr.on("mouseout", () => {
18796
18803
  this.instance.getStage().handleMouseover?.();
@@ -18824,8 +18831,6 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
18824
18831
  tr.on("transform", (0, import_throttle.default)(handleTransform, DEFAULT_THROTTLE_MS));
18825
18832
  tr.on("transformend", () => {
18826
18833
  this.transformInProcess = false;
18827
- tr.visible(true);
18828
- tr.forceUpdate();
18829
18834
  if (this.getSelectedNodes().length > 1) this.instance.releaseMutexLock();
18830
18835
  const selectedNodes$1 = tr.nodes();
18831
18836
  for (const node of selectedNodes$1) {
@@ -18843,8 +18848,6 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
18843
18848
  let selectedNodes = [];
18844
18849
  tr.on("dragstart", (e) => {
18845
18850
  this.dragInProcess = true;
18846
- tr.visible(false);
18847
- tr.forceUpdate();
18848
18851
  const mainLayer = this.instance.getMainLayer();
18849
18852
  if (!mainLayer) return;
18850
18853
  initialPos = {
@@ -18919,8 +18922,6 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
18919
18922
  tr.on("dragmove", (0, import_throttle.default)(handleDragMove, DEFAULT_THROTTLE_MS));
18920
18923
  tr.on("dragend", (e) => {
18921
18924
  this.dragInProcess = false;
18922
- tr.visible(true);
18923
- tr.forceUpdate();
18924
18925
  const mainLayer = this.instance.getMainLayer();
18925
18926
  if (!mainLayer) return;
18926
18927
  this.instance.getSelectionLayer()?.hitGraphEnabled(true);
@@ -19225,7 +19226,7 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
19225
19226
  }
19226
19227
  });
19227
19228
  stage.container().addEventListener("keyup", (e) => {
19228
- if (e.ctrlKey || e.metaKey) this.isCtrlMetaPressed = false;
19229
+ if (!(e.ctrlKey || e.metaKey)) this.isCtrlMetaPressed = false;
19229
19230
  if (e.code === "Space") this.isSpaceKeyPressed = false;
19230
19231
  });
19231
19232
  stage.on("pointerdown", (e) => {
@@ -19402,8 +19403,8 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
19402
19403
  this.selecting = false;
19403
19404
  this.stopPanLoop();
19404
19405
  this.tr.nodes([...selectedNodes]);
19405
- this.handleBehaviors();
19406
19406
  this.handleMultipleSelectionBehavior();
19407
+ this.handleBehaviors();
19407
19408
  if (this.tr.nodes().length > 0) {
19408
19409
  stage.container().tabIndex = 1;
19409
19410
  stage.container().focus();
@@ -19514,12 +19515,12 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
19514
19515
  this.tr.nodes(nodes);
19515
19516
  areNodesSelected = true;
19516
19517
  }
19517
- this.handleBehaviors();
19518
19518
  this.handleMultipleSelectionBehavior();
19519
+ this.handleBehaviors();
19519
19520
  if (areNodesSelected) {
19520
19521
  stage.container().tabIndex = 1;
19521
19522
  stage.container().focus();
19522
- stage.container().style.cursor = "grab";
19523
+ stage.container().style.cursor = nodeTargeted.defineMousePointer() ?? "grab";
19523
19524
  }
19524
19525
  this.triggerSelectedNodesEvent();
19525
19526
  }
@@ -19551,11 +19552,12 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
19551
19552
  for (const node of nodes) anchorsArrays.push(node?.allowedAnchors() ?? []);
19552
19553
  const enabledAnchors = intersectArrays(anchorsArrays);
19553
19554
  transformerAttrs.enabledAnchors = enabledAnchors;
19554
- this.tr.enabledAnchors(transformerAttrs.enabledAnchors);
19555
19555
  }
19556
19556
  if (this.tr && this.tr.nodes().length > 0) {
19557
+ if (transformerAttrs.enabledAnchors?.length === 0) transformerAttrs.resizeEnabled = false;
19557
19558
  this.tr.setAttrs(transformerAttrs);
19558
19559
  this.tr.forceUpdate();
19560
+ this.tr.getLayer()?.batchDraw();
19559
19561
  }
19560
19562
  }
19561
19563
  setSelectedNodes(nodes) {
@@ -19792,32 +19794,25 @@ var WeaveCopyPasteNodesPlugin = class extends WeavePlugin {
19792
19794
  if (!this.enabled) return;
19793
19795
  }
19794
19796
  });
19795
- if (catcher) {
19796
- document.addEventListener("paste", async (e) => {
19797
- const dataList = e.clipboardData?.items;
19798
- if (!dataList) return;
19799
- if (dataList?.length > 0) this.sendExternalPasteEvent(dataList);
19800
- });
19801
- catcher.addEventListener("paste", async (e) => {
19802
- e.preventDefault();
19803
- let items = void 0;
19804
- let hasWeaveData = false;
19805
- if (!items) {
19806
- if (this.isClipboardAPIAvailable()) items = await navigator.clipboard.read();
19807
- }
19808
- if (!items || items.length === 0) return;
19809
- if (this.isClipboardAPIAvailable()) {
19810
- const readText = await navigator.clipboard.readText();
19811
- const continueToPaste = this.isWeaveData(readText);
19812
- if (continueToPaste) hasWeaveData = true;
19813
- }
19814
- if (hasWeaveData) {
19815
- this.handlePaste();
19816
- return;
19817
- }
19818
- this.sendExternalPasteEvent(void 0, items);
19819
- });
19820
- }
19797
+ if (catcher) catcher.addEventListener("paste", async (e) => {
19798
+ e.preventDefault();
19799
+ let items = void 0;
19800
+ let hasWeaveData = false;
19801
+ if (!items) {
19802
+ if (this.isClipboardAPIAvailable()) items = await navigator.clipboard.read();
19803
+ }
19804
+ if (!items || items.length === 0) return;
19805
+ if (this.isClipboardAPIAvailable()) {
19806
+ const readText = await navigator.clipboard.readText();
19807
+ const continueToPaste = this.isWeaveData(readText);
19808
+ if (continueToPaste) hasWeaveData = true;
19809
+ }
19810
+ if (hasWeaveData) {
19811
+ this.handlePaste();
19812
+ return;
19813
+ }
19814
+ this.sendExternalPasteEvent(void 0, items);
19815
+ });
19821
19816
  }
19822
19817
  sendExternalPasteEvent(dataList, items) {
19823
19818
  const stage = this.instance.getStage();
@@ -19872,8 +19867,9 @@ var WeaveCopyPasteNodesPlugin = class extends WeavePlugin {
19872
19867
  }
19873
19868
  }
19874
19869
  handlePaste(position, relativePosition) {
19875
- const stage = this.instance.getStage();
19876
- if (this.toPaste) {
19870
+ this.instance.stateTransactional(() => {
19871
+ const stage = this.instance.getStage();
19872
+ if (!this.toPaste) return;
19877
19873
  const nodesToSelect = [];
19878
19874
  const newElements = this.checkIfInternalElementsAreNew(JSON.stringify(this.toPaste));
19879
19875
  if (this.config.paddingOnPaste.enabled && newElements) {
@@ -19884,7 +19880,9 @@ var WeaveCopyPasteNodesPlugin = class extends WeavePlugin {
19884
19880
  for (const element of Object.keys(this.toPaste.weave)) {
19885
19881
  const node = this.toPaste.weave[element].element;
19886
19882
  const posRelativeToSelection = this.toPaste.weave[element].posRelativeToSelection;
19887
- let containerId = this.toPaste.weave[element].containerId;
19883
+ let containerId = this.toPaste.weave[element]?.containerId;
19884
+ const nodeHandler = this.instance.getNodeHandler(node.props.nodeType ?? "");
19885
+ if (!nodeHandler) continue;
19888
19886
  if (node.props.children) this.recursivelyUpdateKeys(node.props.children);
19889
19887
  const newNodeId = v4_default();
19890
19888
  delete node.props.containerId;
@@ -19906,24 +19904,24 @@ var WeaveCopyPasteNodesPlugin = class extends WeavePlugin {
19906
19904
  containerId = container.getAttrs().id ?? "";
19907
19905
  localPos = container.getAbsoluteTransform().copy().invert().point(position);
19908
19906
  }
19909
- const nodeHandler = this.instance.getNodeHandler(node.props.nodeType ?? "");
19910
- if (nodeHandler) {
19911
- const realOffset = nodeHandler.realOffset(node);
19912
- node.props.x = localPos.x + realOffset.x + posRelativeToSelection.x;
19913
- node.props.y = localPos.y + realOffset.y + posRelativeToSelection.y;
19914
- }
19915
- } else {
19916
- const nodeHandler = this.instance.getNodeHandler(node.props.nodeType ?? "");
19917
- if (nodeHandler) {
19918
- node.props.x = node.props.x + (this.config.paddingOnPaste.enabled ? this.actualInternalPaddingX : 0);
19919
- node.props.y = node.props.y + (this.config.paddingOnPaste.enabled ? this.actualInternalPaddingY : 0);
19920
- }
19907
+ const realOffset = nodeHandler.realOffset(node);
19908
+ node.props.x = localPos.x + realOffset.x + posRelativeToSelection.x;
19909
+ node.props.y = localPos.y + realOffset.y + posRelativeToSelection.y;
19910
+ }
19911
+ if (!position) {
19912
+ node.props.x = node.props.x + (this.config.paddingOnPaste.enabled ? this.actualInternalPaddingX : 0);
19913
+ node.props.y = node.props.y + (this.config.paddingOnPaste.enabled ? this.actualInternalPaddingY : 0);
19914
+ }
19915
+ let containerNode = this.instance.getStage().findOne(`#${containerId}`);
19916
+ if (!containerNode) {
19917
+ containerId = this.instance.getMainLayer()?.getAttrs().id ?? "";
19918
+ containerNode = this.instance.getMainLayer();
19919
+ }
19920
+ if (containerId) {
19921
+ this.instance.addNodeNT(node, containerId);
19922
+ const realNode = this.instance.getStage().findOne(`#${newNodeId}`);
19923
+ if (realNode) nodesToSelect.push(realNode);
19921
19924
  }
19922
- const containerNode = this.instance.getStage().findOne(`#${containerId}`);
19923
- if (!containerNode) containerId = this.instance.getMainLayer()?.getAttrs().id ?? "";
19924
- this.instance.addNode(node, containerId);
19925
- const realNode = this.instance.getStage().findOne(`#${newNodeId}`);
19926
- if (realNode) nodesToSelect.push(realNode);
19927
19925
  this.getStageGridPlugin()?.onRender();
19928
19926
  }
19929
19927
  this.instance.emitEvent("onPaste", {
@@ -19937,8 +19935,8 @@ var WeaveCopyPasteNodesPlugin = class extends WeavePlugin {
19937
19935
  smartZoom: true
19938
19936
  });
19939
19937
  this.toPaste = void 0;
19940
- }
19941
- this.cancel();
19938
+ this.cancel();
19939
+ });
19942
19940
  }
19943
19941
  async finishHandleCopy() {
19944
19942
  this.actualInternalPaddingX = 0;
@@ -19966,7 +19964,12 @@ var WeaveCopyPasteNodesPlugin = class extends WeavePlugin {
19966
19964
  y: 0
19967
19965
  }
19968
19966
  };
19969
- for (const node of selectedNodes) {
19967
+ const selectedNodesSortedByZIndexAsc = [...selectedNodes].sort((a, b) => {
19968
+ const aZ = a.getZIndex() ?? 0;
19969
+ const bZ = b.getZIndex() ?? 0;
19970
+ return aZ - bZ;
19971
+ });
19972
+ for (const node of selectedNodesSortedByZIndexAsc) {
19970
19973
  const nodeHandler = this.instance.getNodeHandler(node.getAttrs().nodeType);
19971
19974
  if (!nodeHandler) continue;
19972
19975
  const parentNode = node.getParent();
@@ -20194,6 +20197,11 @@ var WeaveNode = class {
20194
20197
  node.handleMouseout = function() {};
20195
20198
  node.handleSelectNode = function() {};
20196
20199
  node.handleDeselectNode = function() {};
20200
+ node.defineMousePointer = () => {
20201
+ const selectedNodes = this.getSelectionPlugin()?.getSelectedNodes() ?? [];
20202
+ if (this.isSelecting() && selectedNodes.includes(node)) return "grab";
20203
+ return "pointer";
20204
+ };
20197
20205
  node.canBeHovered = function() {
20198
20206
  return true;
20199
20207
  };
@@ -20328,7 +20336,8 @@ var WeaveNode = class {
20328
20336
  if (!selectionPlugin) return;
20329
20337
  selectionPlugin.getHoverTransformer().nodes([]);
20330
20338
  }
20331
- setupDefaultNodeEvents(node) {
20339
+ setupDefaultNodeEvents(node, options = { performScaleReset: true }) {
20340
+ const { performScaleReset } = mergeExceptArrays({ performScaleReset: true }, options);
20332
20341
  const handleNodesChange = () => {
20333
20342
  if (!this.isLocked(node) && this.isSelecting() && this.isNodeSelected(node)) {
20334
20343
  node.draggable(true);
@@ -20395,13 +20404,16 @@ var WeaveNode = class {
20395
20404
  const nodesSnappingPlugin = this.getNodesEdgeSnappingPlugin();
20396
20405
  if (nodesSnappingPlugin) nodesSnappingPlugin.cleanupGuidelines();
20397
20406
  if (nodesSelectionPlugin) nodesSelectionPlugin.getTransformer().forceUpdate();
20398
- this.scaleReset(node$1);
20407
+ if (performScaleReset) this.scaleReset(node$1);
20399
20408
  if (this.getSelectionPlugin()?.getSelectedNodes().length === 1) {
20400
20409
  this.getNodesSelectionFeedbackPlugin()?.showSelectionHalo(node$1);
20401
20410
  this.getNodesSelectionFeedbackPlugin()?.updateSelectionHalo(node$1);
20402
20411
  }
20403
20412
  const nodeHandler = this.instance.getNodeHandler(node$1.getAttrs().nodeType);
20404
- if (nodeHandler) this.instance.updateNode(nodeHandler.serialize(node$1));
20413
+ if (nodeHandler) {
20414
+ const shouldUpdateOnTransform = node$1.getAttrs().shouldUpdateOnTransform ?? true;
20415
+ if (shouldUpdateOnTransform) this.instance.updateNode(nodeHandler.serialize(node$1));
20416
+ }
20405
20417
  this.getNodesSelectionPlugin()?.getHoverTransformer().forceUpdate();
20406
20418
  });
20407
20419
  const stage = this.instance.getStage();
@@ -20637,7 +20649,9 @@ var WeaveNode = class {
20637
20649
  }
20638
20650
  });
20639
20651
  node.handleSelectNode = () => {
20640
- this.getNodesSelectionFeedbackPlugin()?.createSelectionHalo(node);
20652
+ const transformer = this.getNodesSelectionPlugin()?.getTransformer();
20653
+ if (!transformer) return;
20654
+ if (transformer.nodes().length > 1) this.getNodesSelectionFeedbackPlugin()?.createSelectionHalo(node);
20641
20655
  };
20642
20656
  node.handleDeselectNode = () => {
20643
20657
  this.getNodesSelectionFeedbackPlugin()?.destroySelectionHalo(node);
@@ -20674,12 +20688,12 @@ var WeaveNode = class {
20674
20688
  }
20675
20689
  if (isNodeSelectionEnabled && this.isSelecting() && !this.isNodeSelected(realNode) && !this.isPasting() && isTargetable && !(isLocked || isMutexLocked) && stage.mode() === WEAVE_STAGE_DEFAULT_MODE) {
20676
20690
  showHover = true;
20677
- stage.container().style.cursor = "pointer";
20691
+ stage.container().style.cursor = realNode?.defineMousePointer() ?? "pointer";
20678
20692
  cancelBubble = true;
20679
20693
  }
20680
20694
  if (isNodeSelectionEnabled && this.isSelecting() && this.isNodeSelected(realNode) && !this.isPasting() && isTargetable && !(isLocked || isMutexLocked) && stage.mode() === WEAVE_STAGE_DEFAULT_MODE) {
20681
20695
  showHover = true;
20682
- stage.container().style.cursor = "grab";
20696
+ stage.container().style.cursor = realNode?.defineMousePointer() ?? "grab";
20683
20697
  cancelBubble = true;
20684
20698
  }
20685
20699
  if (!isTargetable) cancelBubble = true;
@@ -20865,6 +20879,9 @@ var WeaveAction = class {
20865
20879
  hasAliases() {
20866
20880
  return false;
20867
20881
  }
20882
+ setForceExecution(forceExecution) {
20883
+ this.forceExecution = forceExecution;
20884
+ }
20868
20885
  getAliases() {
20869
20886
  return [];
20870
20887
  }
@@ -21342,8 +21359,10 @@ var WeaveTargetingManager = class {
21342
21359
  };
21343
21360
  let measureContainer = mainLayer;
21344
21361
  let container = mainLayer;
21362
+ const utilityLayer = this.instance.getUtilityLayer();
21363
+ if (utilityLayer) utilityLayer.visible(false);
21345
21364
  const nodesSelection = this.instance.getPlugin("nodesSelection");
21346
- if (nodesSelection) nodesSelection.disable();
21365
+ if (nodesSelection) nodesSelection.getTransformer().visible(false);
21347
21366
  const dummyRect = new Konva.Rect({
21348
21367
  width: 10,
21349
21368
  height: 10,
@@ -21364,7 +21383,8 @@ var WeaveTargetingManager = class {
21364
21383
  x: 0,
21365
21384
  y: 0
21366
21385
  };
21367
- if (nodesSelection) nodesSelection.enable();
21386
+ if (utilityLayer) utilityLayer.visible(true);
21387
+ if (nodesSelection) nodesSelection.getTransformer().visible(true);
21368
21388
  dummyRect.destroy();
21369
21389
  return {
21370
21390
  mousePoint: relativeMousePointer,
@@ -21768,13 +21788,13 @@ var WeaveStateManager = class {
21768
21788
  updateNodes(nodes) {
21769
21789
  for (const node of nodes) this.updateNode(node);
21770
21790
  }
21771
- stateTransactional(callback) {
21791
+ stateTransactional(callback, origin) {
21772
21792
  const state = this.instance.getStore().getState();
21773
21793
  const doc = getYjsDoc(state);
21774
- const userId = this.instance.getStore().getUser().id;
21794
+ const transactionOrigin = origin ?? this.instance.getStore().getUser().id;
21775
21795
  doc.transact(() => {
21776
21796
  callback();
21777
- }, userId);
21797
+ }, transactionOrigin);
21778
21798
  }
21779
21799
  removeNode(node) {
21780
21800
  const state = this.instance.getStore().getState();
@@ -21909,7 +21929,6 @@ var WeaveRegisterManager = class {
21909
21929
  registerActionsHandlers() {
21910
21930
  const config = this.instance.getConfiguration();
21911
21931
  if (config.actions) for (const action of config.actions) this.registerActionHandler(action);
21912
- this.logger.info(`Actions handlers registered`);
21913
21932
  }
21914
21933
  registerActionHandler(action) {
21915
21934
  const actionName = action.getName();
@@ -21936,7 +21955,7 @@ var WeaveRegisterManager = class {
21936
21955
 
21937
21956
  //#endregion
21938
21957
  //#region package.json
21939
- var version = "3.0.0";
21958
+ var version = "3.2.0-SNAPSHOT.100.1";
21940
21959
 
21941
21960
  //#endregion
21942
21961
  //#region src/managers/setup.ts
@@ -22076,14 +22095,15 @@ var WeaveActionsManager = class {
22076
22095
  getActiveAction() {
22077
22096
  return this.activeAction;
22078
22097
  }
22079
- triggerAction(actionName, params) {
22098
+ triggerAction(actionName, params, forceExecution = false) {
22080
22099
  const actionsHandlers = this.instance.getActionsHandlers();
22081
22100
  if (typeof actionName === "undefined") throw new Error("Action name is required");
22082
22101
  if (actionName && !actionsHandlers[actionName]) throw new Error(`Action handler with name [${actionName}] not registered`);
22083
- if (typeof this.activeAction !== "undefined") this.cancelAction(this.activeAction);
22084
- this.activeAction = actionName;
22102
+ if (this.activeAction !== void 0 && !forceExecution) this.cancelAction(this.activeAction);
22103
+ if (!forceExecution) this.activeAction = actionName;
22104
+ actionsHandlers[actionName].setForceExecution(forceExecution);
22085
22105
  const payload = actionsHandlers[actionName].trigger(this.cancelActionCallback(actionName), params);
22086
- this.instance.emitEvent("onActiveActionChange", this.activeAction);
22106
+ if (!forceExecution) this.instance.emitEvent("onActiveActionChange", this.activeAction);
22087
22107
  return payload;
22088
22108
  }
22089
22109
  updatePropsAction(actionName, props) {
@@ -22583,7 +22603,7 @@ var WeaveMutexManager = class {
22583
22603
  };
22584
22604
 
22585
22605
  //#endregion
22586
- //#region src/utils/watch-map.ts
22606
+ //#region src/internal-utils/watch-map.ts
22587
22607
  function watchMap(onChange, map = new Map()) {
22588
22608
  const handler = { get(target, prop, receiver) {
22589
22609
  if (prop === "set") return (key, value$1) => {
@@ -22638,14 +22658,13 @@ var WeaveAsyncManager = class {
22638
22658
  this.asyncElements = watchMap(() => {
22639
22659
  this.instance.emitEvent("onAsyncElementChange");
22640
22660
  }, new Map());
22641
- this.instance.addEventListener("onRoomLoaded", (isRoomLoaded) => {
22642
- if (!isRoomLoaded) return;
22643
- const roomHasResourcesToLoad = this.roomHasResourcesToLoad();
22644
- if (!roomHasResourcesToLoad && !this.asyncElementsLoadedEventEmitted) {
22645
- this.instance.emitEvent("onAsyncElementsLoaded");
22646
- this.asyncElementsLoadedEventEmitted = true;
22647
- }
22648
- });
22661
+ }
22662
+ checkForAsyncElements(elements) {
22663
+ const amountAsyncResourcesExtracted = this.extractAsyncResources(elements);
22664
+ if (amountAsyncResourcesExtracted === 0 && !this.asyncElementsLoadedEventEmitted) {
22665
+ this.instance.emitEvent("onAsyncElementsLoaded");
22666
+ this.asyncElementsLoadedEventEmitted = true;
22667
+ }
22649
22668
  }
22650
22669
  extractAsyncElements(state) {
22651
22670
  const asyncElements = [];
@@ -22661,11 +22680,20 @@ var WeaveAsyncManager = class {
22661
22680
  } else for (const element of Object.values(state.weave)) traverse(element);
22662
22681
  return asyncElements;
22663
22682
  }
22664
- roomHasResourcesToLoad() {
22683
+ extractAsyncResources(elements) {
22665
22684
  const roomData = this.instance.getStore().getState();
22666
- const jsonRoomData = JSON.parse(JSON.stringify(roomData));
22685
+ let jsonRoomData = JSON.parse(JSON.stringify(roomData));
22686
+ if (elements) jsonRoomData = elements;
22667
22687
  const asyncElements = this.extractAsyncElements(jsonRoomData);
22668
- return asyncElements.length > 0;
22688
+ for (const element of asyncElements) {
22689
+ const elementId = element.props?.id;
22690
+ if (!elementId) continue;
22691
+ if (!this.asyncElements.has(elementId)) this.asyncElements.set(elementId, {
22692
+ type: element.type,
22693
+ status: WEAVE_ASYNC_STATUS.NOT_LOADED
22694
+ });
22695
+ }
22696
+ return asyncElements.length;
22669
22697
  }
22670
22698
  asyncElementsLoaded() {
22671
22699
  return [...this.asyncElements.values()].every((el) => el.status === WEAVE_ASYNC_STATUS.LOADED);
@@ -23111,8 +23139,8 @@ var Weave = class {
23111
23139
  getActiveAction() {
23112
23140
  return this.actionsManager.getActiveAction();
23113
23141
  }
23114
- triggerAction(actionName, params) {
23115
- return this.actionsManager.triggerAction(actionName, params);
23142
+ triggerAction(actionName, params, forceExecution = false) {
23143
+ return this.actionsManager.triggerAction(actionName, params, forceExecution);
23116
23144
  }
23117
23145
  getPropsAction(actionName) {
23118
23146
  return this.actionsManager.getPropsAction(actionName);
@@ -23144,9 +23172,10 @@ var Weave = class {
23144
23172
  return this.stateManager.getNode(nodeKey);
23145
23173
  }
23146
23174
  addNode(node, parentId = "mainLayer", options = DEFAULT_ADD_NODE_OPTIONS) {
23175
+ const { origin,...restOptions } = options;
23147
23176
  this.stateTransactional(() => {
23148
- this.addNodeNT(node, parentId, options);
23149
- });
23177
+ this.addNodeNT(node, parentId, restOptions);
23178
+ }, origin);
23150
23179
  }
23151
23180
  addNodeNT(node, parentId = "mainLayer", options = DEFAULT_ADD_NODE_OPTIONS) {
23152
23181
  const { index, emitUserChangeEvent, overrideUserChangeType } = mergeExceptArrays(DEFAULT_ADD_NODE_OPTIONS, options);
@@ -23167,9 +23196,10 @@ var Weave = class {
23167
23196
  }
23168
23197
  }
23169
23198
  updateNode(node, options = DEFAULT_UPDATE_NODE_OPTIONS) {
23199
+ const { origin,...restOptions } = options;
23170
23200
  this.stateTransactional(() => {
23171
- this.updateNodeNT(node, options);
23172
- });
23201
+ this.updateNodeNT(node, restOptions);
23202
+ }, origin);
23173
23203
  }
23174
23204
  updateNodeNT(node, options = DEFAULT_UPDATE_NODE_OPTIONS) {
23175
23205
  const { emitUserChangeEvent } = mergeExceptArrays(DEFAULT_UPDATE_NODE_OPTIONS, options);
@@ -23187,9 +23217,10 @@ var Weave = class {
23187
23217
  }
23188
23218
  }
23189
23219
  updateNodes(nodes, options = DEFAULT_UPDATE_NODE_OPTIONS) {
23220
+ const { origin,...restOptions } = options;
23190
23221
  this.stateTransactional(() => {
23191
- this.updateNodesNT(nodes, options);
23192
- });
23222
+ this.updateNodesNT(nodes, restOptions);
23223
+ }, origin);
23193
23224
  }
23194
23225
  updateNodesNT(nodes, options = DEFAULT_UPDATE_NODE_OPTIONS) {
23195
23226
  const { emitUserChangeEvent } = mergeExceptArrays(DEFAULT_UPDATE_NODE_OPTIONS, options);
@@ -23213,9 +23244,10 @@ var Weave = class {
23213
23244
  }
23214
23245
  }
23215
23246
  removeNode(node, options = DEFAULT_REMOVE_NODE_OPTIONS) {
23247
+ const { origin,...restOptions } = options;
23216
23248
  this.stateTransactional(() => {
23217
- this.removeNodeNT(node, options);
23218
- });
23249
+ this.removeNodeNT(node, restOptions);
23250
+ }, origin);
23219
23251
  }
23220
23252
  removeNodeNT(node, options = DEFAULT_REMOVE_NODE_OPTIONS) {
23221
23253
  const { emitUserChangeEvent } = mergeExceptArrays(DEFAULT_REMOVE_NODE_OPTIONS, options);
@@ -23247,9 +23279,10 @@ var Weave = class {
23247
23279
  if (selectionPlugin) selectionPlugin.setSelectedNodes([]);
23248
23280
  }
23249
23281
  removeNodes(nodes, options = DEFAULT_REMOVE_NODE_OPTIONS) {
23282
+ const { origin,...restOptions } = options;
23250
23283
  this.stateTransactional(() => {
23251
- this.removeNodesNT(nodes, options);
23252
- });
23284
+ this.removeNodesNT(nodes, restOptions);
23285
+ }, origin);
23253
23286
  }
23254
23287
  removeNodesNT(nodes, options = DEFAULT_REMOVE_NODE_OPTIONS) {
23255
23288
  for (const node of nodes) this.removeNodeNT(node, options);
@@ -23257,9 +23290,10 @@ var Weave = class {
23257
23290
  if (selectionPlugin) selectionPlugin.setSelectedNodes([]);
23258
23291
  }
23259
23292
  zMoveNode(node, position, options = DEFAULT_MOVE_NODE_OPTIONS) {
23293
+ const { origin,...restOptions } = options;
23260
23294
  this.stateTransactional(() => {
23261
- this.zMoveNodeNT(node, position, options);
23262
- });
23295
+ this.zMoveNodeNT(node, position, restOptions);
23296
+ }, origin);
23263
23297
  }
23264
23298
  zMoveNodeNT(node, position, options = DEFAULT_MOVE_NODE_OPTIONS) {
23265
23299
  const { emitUserChangeEvent } = mergeExceptArrays(DEFAULT_MOVE_NODE_OPTIONS, options);
@@ -23313,8 +23347,8 @@ var Weave = class {
23313
23347
  getBoundingBox(nodes, config) {
23314
23348
  return getBoundingBox(nodes, config);
23315
23349
  }
23316
- stateTransactional(callback) {
23317
- this.stateManager.stateTransactional(callback);
23350
+ stateTransactional(callback, origin) {
23351
+ this.stateManager.stateTransactional(callback, origin);
23318
23352
  }
23319
23353
  moveUp(node) {
23320
23354
  this.zIndexManager.moveUp(node);
@@ -23478,6 +23512,9 @@ var Weave = class {
23478
23512
  nodeHandler.show(node);
23479
23513
  }
23480
23514
  }
23515
+ checkForAsyncElements(elements) {
23516
+ this.asyncManager.checkForAsyncElements(elements);
23517
+ }
23481
23518
  asyncElementsLoaded() {
23482
23519
  return this.asyncManager.asyncElementsLoaded();
23483
23520
  }
@@ -23548,7 +23585,93 @@ var Weave = class {
23548
23585
  };
23549
23586
 
23550
23587
  //#endregion
23551
- //#region src/utils/upscale.ts
23588
+ //#region src/utils/image.ts
23589
+ function loadImageSource(image, options) {
23590
+ return new Promise((resolve, reject) => {
23591
+ const { crossOrigin } = mergeExceptArrays({ crossOrigin: "anonymous" }, options);
23592
+ const reader = new FileReader();
23593
+ reader.onloadend = () => {
23594
+ const imageSource = Konva.Util.createImageElement();
23595
+ imageSource.crossOrigin = crossOrigin;
23596
+ imageSource.onerror = () => {
23597
+ reject();
23598
+ };
23599
+ imageSource.onload = async () => {
23600
+ resolve(imageSource);
23601
+ };
23602
+ imageSource.src = reader.result;
23603
+ };
23604
+ reader.onerror = () => {
23605
+ reject(new Error("Failed to read image file"));
23606
+ };
23607
+ reader.readAsDataURL(image);
23608
+ });
23609
+ }
23610
+ async function downscaleImageFile(file, ratio) {
23611
+ const bitmap = await createImageBitmap(file);
23612
+ const width = Math.round(bitmap.width * ratio);
23613
+ const height = Math.round(bitmap.height * ratio);
23614
+ const canvas = document.createElement("canvas");
23615
+ canvas.width = width;
23616
+ canvas.height = height;
23617
+ const ctx = canvas.getContext("2d");
23618
+ ctx.drawImage(bitmap, 0, 0, width, height);
23619
+ return new Promise((resolve) => {
23620
+ canvas.toBlob((blob) => resolve(blob), file.type, .9);
23621
+ });
23622
+ }
23623
+ function getImageSizeFromFile(file) {
23624
+ return new Promise((resolve, reject) => {
23625
+ const img = new Image();
23626
+ const url = URL.createObjectURL(file);
23627
+ img.onload = () => {
23628
+ resolve({
23629
+ width: img.naturalWidth,
23630
+ height: img.naturalHeight
23631
+ });
23632
+ URL.revokeObjectURL(url);
23633
+ };
23634
+ img.onerror = reject;
23635
+ img.src = url;
23636
+ });
23637
+ }
23638
+ function getDownscaleRatio(width, height, options) {
23639
+ const { maxWidth, maxHeight } = mergeExceptArrays({
23640
+ maxWidth: 200,
23641
+ maxHeight: 200
23642
+ }, options);
23643
+ const widthRatio = maxWidth / width;
23644
+ const heightRatio = maxHeight / height;
23645
+ return Math.min(widthRatio, heightRatio, 1);
23646
+ }
23647
+ const downscaleImageFromURL = (url, options) => {
23648
+ return new Promise((resolve, reject) => {
23649
+ const { type, crossOrigin, maxWidth, maxHeight } = mergeExceptArrays({
23650
+ type: "image/png",
23651
+ crossOrigin: "anonymous",
23652
+ maxWidth: 200,
23653
+ maxHeight: 200
23654
+ }, options);
23655
+ const img = new Image();
23656
+ img.crossOrigin = crossOrigin;
23657
+ img.onload = () => {
23658
+ const ratio = Math.min(maxWidth / img.width, maxHeight / img.height, 1);
23659
+ const width = Math.round(img.width * ratio);
23660
+ const height = Math.round(img.height * ratio);
23661
+ const canvas = document.createElement("canvas");
23662
+ canvas.width = width;
23663
+ canvas.height = height;
23664
+ const ctx = canvas.getContext("2d");
23665
+ ctx.drawImage(img, 0, 0, width, height);
23666
+ resolve(canvas.toDataURL(type));
23667
+ };
23668
+ img.onerror = reject;
23669
+ img.src = url;
23670
+ });
23671
+ };
23672
+
23673
+ //#endregion
23674
+ //#region src/internal-utils/upscale.ts
23552
23675
  const setupUpscaleStage = (instance, stage) => {
23553
23676
  const config = instance.getConfiguration();
23554
23677
  const doUpscale = config.performance?.upscale?.enabled ?? false;
@@ -23685,7 +23808,7 @@ var WeaveStageNode = class extends WeaveNode {
23685
23808
  }
23686
23809
  });
23687
23810
  window.addEventListener("keyup", (e) => {
23688
- if (!e.ctrlKey && !e.metaKey) {
23811
+ if (!(e.ctrlKey || e.metaKey)) {
23689
23812
  this.isCmdCtrlPressed = false;
23690
23813
  this.instance.getStage().container().style.cursor = "default";
23691
23814
  const transformer = this.getSelectionPlugin()?.getTransformer();
@@ -23982,7 +24105,7 @@ const WEAVE_LINE_NODE_DEFAULT_CONFIG = { snapAngles: {
23982
24105
  } };
23983
24106
 
23984
24107
  //#endregion
23985
- //#region src/utils/greedy-snapper.ts
24108
+ //#region src/internal-utils/greedy-snapper.ts
23986
24109
  var GreedySnapper = class {
23987
24110
  snappedAngle = null;
23988
24111
  constructor(config) {
@@ -24328,16 +24451,8 @@ const WEAVE_TEXT_NODE_DEFAULT_CONFIG = {
24328
24451
  transform: { ...WEAVE_NODES_SELECTION_DEFAULT_CONFIG.selection },
24329
24452
  outline: { enabled: false }
24330
24453
  };
24331
-
24332
- //#endregion
24333
- //#region src/actions/text-tool/constants.ts
24334
- const TEXT_TOOL_ACTION_NAME = "textTool";
24335
- const TEXT_TOOL_STATE = {
24336
- ["IDLE"]: "idle",
24337
- ["ADDING"]: "adding",
24338
- ["FINISHED"]: "finished"
24339
- };
24340
24454
  const TEXT_LAYOUT = {
24455
+ ["SMART"]: "smart",
24341
24456
  ["AUTO_ALL"]: "auto-all",
24342
24457
  ["AUTO_HEIGHT"]: "auto-height",
24343
24458
  ["FIXED"]: "fixed"
@@ -24351,6 +24466,8 @@ var WeaveTextNode = class extends WeaveNode {
24351
24466
  textAreaSuperContainer = null;
24352
24467
  textAreaContainer = null;
24353
24468
  textArea = null;
24469
+ eventsInitialized = false;
24470
+ isCtrlMetaPressed = false;
24354
24471
  constructor(params) {
24355
24472
  super();
24356
24473
  const { config } = params ?? {};
@@ -24359,6 +24476,17 @@ var WeaveTextNode = class extends WeaveNode {
24359
24476
  this.editing = false;
24360
24477
  this.textArea = null;
24361
24478
  }
24479
+ initEvents() {
24480
+ if (!this.eventsInitialized && !globalThis._weave_isServerSide) {
24481
+ window.addEventListener("keydown", (e) => {
24482
+ if (e.ctrlKey || e.metaKey) this.isCtrlMetaPressed = true;
24483
+ });
24484
+ window.addEventListener("keyup", (e) => {
24485
+ if (!(e.ctrlKey || e.metaKey)) this.isCtrlMetaPressed = false;
24486
+ });
24487
+ this.eventsInitialized = true;
24488
+ }
24489
+ }
24362
24490
  updateNode(nodeInstance) {
24363
24491
  const actNode = this.instance.getStage().findOne(`#${nodeInstance.id()}`);
24364
24492
  if (actNode) {
@@ -24387,6 +24515,7 @@ var WeaveTextNode = class extends WeaveNode {
24387
24515
  }
24388
24516
  }
24389
24517
  onRender(props) {
24518
+ this.initEvents();
24390
24519
  const text = new Konva.Text({
24391
24520
  ...props,
24392
24521
  name: "node",
@@ -24402,6 +24531,12 @@ var WeaveTextNode = class extends WeaveNode {
24402
24531
  const defaultTransformerProperties = this.defaultGetTransformerProperties(this.config.transform);
24403
24532
  text.getTransformerProperties = function() {
24404
24533
  const actualAttrs = this.getAttrs();
24534
+ if (actualAttrs.layout === TEXT_LAYOUT.SMART) return {
24535
+ ...defaultTransformerProperties,
24536
+ resizeEnabled: true,
24537
+ keepRatio: false,
24538
+ enabledAnchors: []
24539
+ };
24405
24540
  if (actualAttrs.layout === TEXT_LAYOUT.AUTO_ALL) return {
24406
24541
  ...defaultTransformerProperties,
24407
24542
  resizeEnabled: false,
@@ -24416,6 +24551,14 @@ var WeaveTextNode = class extends WeaveNode {
24416
24551
  };
24417
24552
  text.allowedAnchors = function() {
24418
24553
  const actualAttrs = this.getAttrs();
24554
+ if (actualAttrs.layout === TEXT_LAYOUT.SMART) return [
24555
+ "top-left",
24556
+ "top-right",
24557
+ "middle-right",
24558
+ "middle-left",
24559
+ "bottom-left",
24560
+ "bottom-right"
24561
+ ];
24419
24562
  if (actualAttrs.layout === TEXT_LAYOUT.AUTO_ALL) return [];
24420
24563
  if (actualAttrs.layout === TEXT_LAYOUT.AUTO_HEIGHT) return ["middle-right", "middle-left"];
24421
24564
  return [
@@ -24430,35 +24573,93 @@ var WeaveTextNode = class extends WeaveNode {
24430
24573
  ];
24431
24574
  };
24432
24575
  text.setAttrs({ measureMultilineText: this.measureMultilineText(text) });
24433
- this.setupDefaultNodeEvents(text);
24434
- const handleTextTransform = (e) => {
24435
- const node = e.target;
24436
- if (this.isSelecting() && this.isNodeSelected(node)) e.cancelBubble = true;
24437
- };
24438
- text.on("transformstart", (e) => {
24439
- this.instance.emitEvent("onTransform", e.target);
24440
- });
24441
- text.on("transform", (0, import_lodash.throttle)(handleTextTransform, DEFAULT_THROTTLE_MS));
24442
- text.on("transformend", () => {
24443
- this.instance.emitEvent("onTransform", null);
24444
- });
24576
+ this.setupDefaultNodeEvents(text, { performScaleReset: false });
24445
24577
  text.dblClick = () => {
24446
24578
  if (this.editing) return;
24447
24579
  if (!(this.isSelecting() && this.isNodeSelected(text))) return;
24448
24580
  this.triggerEditMode(text);
24449
24581
  };
24450
- text.on("transform", (e) => {
24451
- if (this.isSelecting() && this.isNodeSelected(text)) {
24452
- text.setAttrs({
24453
- width: text.width() * text.scaleX(),
24454
- scaleX: 1
24455
- });
24582
+ text.setAttr("triggerEditMode", this.triggerEditMode.bind(this));
24583
+ let actualAnchor = void 0;
24584
+ text.on("transformstart", (e) => {
24585
+ this.instance.emitEvent("onTransform", e.target);
24586
+ actualAnchor = this.getNodesSelectionPlugin()?.getTransformer()?.getActiveAnchor();
24587
+ if (text.getAttrs().layout === TEXT_LAYOUT.SMART && [
24588
+ "top-left",
24589
+ "top-right",
24590
+ "bottom-left",
24591
+ "bottom-right"
24592
+ ].includes(actualAnchor ?? "") || text.getAttrs().layout === TEXT_LAYOUT.FIXED && this.isCtrlMetaPressed) this.getNodesSelectionPlugin()?.getTransformer()?.keepRatio(true);
24593
+ else this.getNodesSelectionPlugin()?.getTransformer()?.keepRatio(false);
24594
+ if ([TEXT_LAYOUT.AUTO_HEIGHT, TEXT_LAYOUT.SMART].includes(text.getAttrs().layout) && ["middle-right", "middle-left"].includes(actualAnchor ?? "")) {
24595
+ text.wrap("word");
24596
+ text.height(void 0);
24597
+ }
24598
+ e.cancelBubble = true;
24599
+ });
24600
+ const handleTextTransform = () => {
24601
+ if ([TEXT_LAYOUT.AUTO_HEIGHT, TEXT_LAYOUT.SMART].includes(text.getAttrs().layout) && ["middle-right", "middle-left"].includes(actualAnchor ?? "")) {
24602
+ text.width(text.width() * text.scaleX());
24603
+ text.scaleX(1);
24604
+ text.scaleY(1);
24605
+ text.height(void 0);
24606
+ text.getLayer()?.batchDraw();
24607
+ }
24608
+ if (this.isSelecting() && this.isNodeSelected(text) && ![TEXT_LAYOUT.SMART].includes(text.getAttrs().layout) || this.isSelecting() && this.isNodeSelected(text) && [TEXT_LAYOUT.SMART].includes(text.getAttrs().layout) && ![
24609
+ "top-left",
24610
+ "top-right",
24611
+ "bottom-left",
24612
+ "bottom-right"
24613
+ ].includes(actualAnchor ?? "")) {
24614
+ text.width(text.width() * text.scaleX());
24456
24615
  resetScale(text);
24457
24616
  text.fontSize(text.fontSize() * text.scaleY());
24458
- e.cancelBubble = true;
24459
24617
  }
24618
+ text.setAttr("shouldUpdateOnTransform", false);
24619
+ text.getLayer()?.batchDraw();
24620
+ };
24621
+ text.on("transform", (0, import_lodash.throttle)(handleTextTransform, DEFAULT_THROTTLE_MS));
24622
+ const handleTransformEnd = () => {
24623
+ this.instance.emitEvent("onTransform", null);
24624
+ let definedSmartWidth = false;
24625
+ let smartFixedWidth = text.getAttr("smartFixedWidth") ?? false;
24626
+ if (![TEXT_LAYOUT.SMART].includes(text.getAttrs().layout) && ![
24627
+ "top-left",
24628
+ "top-right",
24629
+ "bottom-left",
24630
+ "bottom-right"
24631
+ ].includes(actualAnchor ?? "")) this.scaleReset(text);
24632
+ if ([TEXT_LAYOUT.SMART].includes(text.getAttrs().layout) && [
24633
+ "top-left",
24634
+ "top-right",
24635
+ "bottom-left",
24636
+ "bottom-right"
24637
+ ].includes(actualAnchor ?? "")) text.setAttrs({
24638
+ width: Math.ceil(text.width() * text.scaleX()),
24639
+ height: Math.ceil(text.height() * text.scaleY()),
24640
+ fontSize: text.fontSize() * text.scaleY(),
24641
+ scaleX: 1,
24642
+ scaleY: 1
24643
+ });
24644
+ if ([TEXT_LAYOUT.AUTO_HEIGHT, TEXT_LAYOUT.SMART].includes(text.getAttrs().layout) && ["middle-right", "middle-left"].includes(actualAnchor ?? "") && !smartFixedWidth && !definedSmartWidth) {
24645
+ text.setAttr("smartFixedWidth", true);
24646
+ smartFixedWidth = true;
24647
+ definedSmartWidth = true;
24648
+ text.width(Math.ceil(text.width() * text.scaleX()));
24649
+ text.scaleX(1);
24650
+ text.height(void 0);
24651
+ text.getLayer()?.batchDraw();
24652
+ text.height(Math.ceil(text.height()));
24653
+ }
24654
+ if ([TEXT_LAYOUT.SMART].includes(text.getAttrs().layout) && ["middle-right", "middle-left"].includes(actualAnchor ?? "") && smartFixedWidth && !definedSmartWidth) {
24655
+ text.width(Math.ceil(text.width() * text.scaleX()));
24656
+ text.scaleX(1);
24657
+ }
24658
+ this.instance.updateNode(this.serialize(text));
24659
+ };
24660
+ text.on("transformend", () => {
24661
+ handleTransformEnd();
24460
24662
  });
24461
- text.setAttr("triggerEditMode", this.triggerEditMode.bind(this));
24462
24663
  this.instance.addEventListener("onNodeRenderedAdded", (node) => {
24463
24664
  if (node.id() === text.id() && node.getParent() !== text.getParent()) text.getAttr("cancelEditMode")?.();
24464
24665
  });
@@ -24494,10 +24695,13 @@ var WeaveTextNode = class extends WeaveNode {
24494
24695
  width = textAreaWidth;
24495
24696
  height = textAreaHeight;
24496
24697
  }
24497
- if (nextProps.layout === TEXT_LAYOUT.AUTO_HEIGHT) {
24498
- const { height: textAreaHeight } = this.textRenderedSize(nextProps.text, nodeInstance);
24499
- height = textAreaHeight;
24698
+ if (nextProps.layout === TEXT_LAYOUT.SMART && !nextProps.smartFixedWidth) {
24699
+ const { width: textAreaWidth } = this.textRenderedSize(nextProps.text, nodeInstance);
24700
+ width = textAreaWidth;
24701
+ height = void 0;
24500
24702
  }
24703
+ if (nextProps.layout === TEXT_LAYOUT.SMART && nextProps.smartFixedWidth) height = void 0;
24704
+ if (nextProps.layout === TEXT_LAYOUT.AUTO_HEIGHT) height = void 0;
24501
24705
  if (nextProps.layout === TEXT_LAYOUT.FIXED) updateNeeded = false;
24502
24706
  nodeInstance.setAttrs({
24503
24707
  width,
@@ -24523,6 +24727,7 @@ var WeaveTextNode = class extends WeaveNode {
24523
24727
  delete cleanedAttrs.cancelEditMode;
24524
24728
  delete cleanedAttrs.measureMultilineText;
24525
24729
  delete cleanedAttrs.overridesMouseControl;
24730
+ delete cleanedAttrs.shouldUpdateOnTransform;
24526
24731
  delete cleanedAttrs.dragBoundFunc;
24527
24732
  return {
24528
24733
  key: attrs.id ?? "",
@@ -24547,12 +24752,11 @@ var WeaveTextNode = class extends WeaveNode {
24547
24752
  };
24548
24753
  textAreaDomResize(textNode) {
24549
24754
  if (!this.textArea || !this.textAreaContainer) return;
24550
- if (!textNode.getAttrs().layout || textNode.getAttrs().layout === TEXT_LAYOUT.AUTO_ALL) {
24755
+ if (!textNode.getAttrs().layout || textNode.getAttrs().layout === TEXT_LAYOUT.AUTO_ALL || textNode.getAttrs().layout === TEXT_LAYOUT.SMART && !textNode.getAttrs().smartFixedWidth) {
24551
24756
  const { width: textAreaWidth } = this.textRenderedSize(this.textArea.value, textNode);
24552
- this.textAreaContainer.style.width = textAreaWidth * textNode.getAbsoluteScale().x + 2 + "px";
24757
+ this.textAreaContainer.style.width = textAreaWidth * textNode.getAbsoluteScale().x + 1 + "px";
24553
24758
  }
24554
- if (!textNode.getAttrs().layout || textNode.getAttrs().layout === TEXT_LAYOUT.AUTO_HEIGHT) this.textAreaContainer.style.height = "auto";
24555
- if (!textNode.getAttrs().layout || textNode.getAttrs().layout === TEXT_LAYOUT.AUTO_ALL || textNode.getAttrs().layout === TEXT_LAYOUT.AUTO_HEIGHT) {
24759
+ if (!textNode.getAttrs().layout || textNode.getAttrs().layout === TEXT_LAYOUT.AUTO_ALL || textNode.getAttrs().layout === TEXT_LAYOUT.AUTO_HEIGHT || textNode.getAttrs().layout === TEXT_LAYOUT.SMART) {
24556
24760
  this.textAreaContainer.style.height = "auto";
24557
24761
  this.textAreaContainer.style.height = this.textArea.scrollHeight + textNode.getAbsoluteScale().y + "px";
24558
24762
  }
@@ -24638,15 +24842,21 @@ var WeaveTextNode = class extends WeaveNode {
24638
24842
  this.textAreaContainer.style.position = "absolute";
24639
24843
  this.textAreaContainer.style.top = position.y * upscaleScale + "px";
24640
24844
  this.textAreaContainer.style.left = position.x * upscaleScale + "px";
24845
+ if (textNode.getAttrs().layout === TEXT_LAYOUT.SMART && !textNode.getAttrs().smartFixedWidth) {
24846
+ const rect = textNode.getClientRect({ relativeTo: stage });
24847
+ this.textAreaContainer.style.width = (rect.width + 2) * stage.scaleX() + "px";
24848
+ this.textAreaContainer.style.height = (textNode.height() - textNode.padding() * 2 + 1) * textNode.getAbsoluteScale().x + "px";
24849
+ }
24641
24850
  if (!textNode.getAttrs().layout || textNode.getAttrs().layout === TEXT_LAYOUT.AUTO_ALL) {
24642
24851
  const rect = textNode.getClientRect({ relativeTo: stage });
24643
- this.textAreaContainer.style.width = (rect.width + 1) * stage.scaleX() + "px";
24644
- this.textAreaContainer.style.height = (textNode.height() - textNode.padding() * 2) * textNode.getAbsoluteScale().x + "px";
24852
+ this.textAreaContainer.style.width = (rect.width + 2) * stage.scaleX() + "px";
24853
+ this.textAreaContainer.style.height = (textNode.height() - textNode.padding() * 2 + 1) * textNode.getAbsoluteScale().x + "px";
24645
24854
  }
24646
- if (textNode.getAttrs().layout === TEXT_LAYOUT.AUTO_HEIGHT) {
24855
+ if (textNode.getAttrs().layout === TEXT_LAYOUT.AUTO_HEIGHT || textNode.getAttrs().layout === TEXT_LAYOUT.SMART && textNode.getAttrs().smartFixedWidth) {
24647
24856
  const rect = textNode.getClientRect({ relativeTo: stage });
24648
- this.textAreaContainer.style.width = (rect.width + 1) * stage.scaleX() + "px";
24649
- this.textAreaContainer.style.height = (textNode.height() - textNode.padding() * 2) * textNode.getAbsoluteScale().x + "px";
24857
+ this.textAreaContainer.style.width = (rect.width + 10) * stage.scaleX() + "px";
24858
+ if (textNode.getAttrs().smartFixedWidth) this.textAreaContainer.style.width = (textNode.width() - textNode.padding() * 2 + 1) * textNode.getAbsoluteScale().x + "px";
24859
+ this.textAreaContainer.style.height = (textNode.height() - textNode.padding() * 2 + 1) * textNode.getAbsoluteScale().x + "px";
24650
24860
  }
24651
24861
  if (textNode.getAttrs().layout === TEXT_LAYOUT.FIXED) {
24652
24862
  this.textAreaContainer.style.width = (textNode.width() - textNode.padding() * 2) * textNode.getAbsoluteScale().x + "px";
@@ -24731,11 +24941,11 @@ var WeaveTextNode = class extends WeaveNode {
24731
24941
  }
24732
24942
  const updateTextNodeSize = () => {
24733
24943
  if (!this.textArea) return;
24734
- if (!textNode.getAttrs().layout || textNode.getAttrs().layout === TEXT_LAYOUT.AUTO_ALL) {
24944
+ if (!textNode.getAttrs().layout || textNode.getAttrs().layout === TEXT_LAYOUT.AUTO_ALL || textNode.getAttrs().layout === TEXT_LAYOUT.SMART && !textNode.getAttrs().smartFixedWidth) {
24735
24945
  const { width: textAreaWidth } = this.textRenderedSize(this.textArea.value, textNode);
24736
24946
  textNode.width(textAreaWidth);
24737
24947
  }
24738
- if (!textNode.getAttrs().layout || textNode.getAttrs().layout === TEXT_LAYOUT.AUTO_HEIGHT || textNode.getAttrs().layout === TEXT_LAYOUT.AUTO_ALL) textNode.height(this.textArea.scrollHeight * (1 / textNode.getAbsoluteScale().x));
24948
+ if (!textNode.getAttrs().layout || textNode.getAttrs().layout === TEXT_LAYOUT.AUTO_HEIGHT || textNode.getAttrs().layout === TEXT_LAYOUT.AUTO_ALL || textNode.getAttrs().layout === TEXT_LAYOUT.SMART) textNode.height(this.textArea.scrollHeight * (1 / textNode.getAbsoluteScale().x));
24739
24949
  };
24740
24950
  const handleKeyDown = (e) => {
24741
24951
  if (this.textArea && textNode && e.code === "Escape") {
@@ -24806,13 +25016,15 @@ var WeaveTextNode = class extends WeaveNode {
24806
25016
  }
24807
25017
  updateTextAreaDOM(textNode) {
24808
25018
  if (!this.textAreaContainer || !this.textArea) return;
24809
- const textPosition = textNode.getClientRect();
25019
+ const stage = this.instance.getStage();
25020
+ const upscaleScale = stage.getAttr("upscaleScale");
25021
+ const textPosition = textNode.absolutePosition();
24810
25022
  const position = {
24811
25023
  x: textPosition.x,
24812
25024
  y: textPosition.y
24813
25025
  };
24814
- this.textAreaContainer.style.top = position.y + "px";
24815
- this.textAreaContainer.style.left = position.x + "px";
25026
+ this.textAreaContainer.style.top = position.y * upscaleScale + "px";
25027
+ this.textAreaContainer.style.left = position.x * upscaleScale + "px";
24816
25028
  if (textNode.getAttrs().verticalAlign === "top") this.textAreaContainer.style.alignItems = "start";
24817
25029
  if (textNode.getAttrs().verticalAlign === "middle") this.textAreaContainer.style.alignItems = "center";
24818
25030
  if (textNode.getAttrs().verticalAlign === "bottom") this.textAreaContainer.style.alignItems = "end";
@@ -24881,6 +25093,12 @@ var WeaveTextNode = class extends WeaveNode {
24881
25093
  this.keyPressHandler = void 0;
24882
25094
  }
24883
25095
  }
25096
+ resetSmartLayout(textNode) {
25097
+ textNode.setAttr("smartFixedWidth", void 0);
25098
+ const { width: textAreaWidth } = this.textRenderedSize(textNode.text(), textNode);
25099
+ textNode.width(textAreaWidth);
25100
+ this.instance.updateNode(this.serialize(textNode));
25101
+ }
24884
25102
  };
24885
25103
 
24886
25104
  //#endregion
@@ -24904,7 +25122,12 @@ const WEAVE_IMAGE_CROP_ANCHOR_POSITION = {
24904
25122
  const WEAVE_IMAGE_DEFAULT_CONFIG = {
24905
25123
  performance: { cache: { enabled: false } },
24906
25124
  style: { placeholder: { fill: "#aaaaaa" } },
25125
+ imageLoading: {
25126
+ maxRetryAttempts: 15,
25127
+ retryDelayMs: 2e3
25128
+ },
24907
25129
  crossOrigin: "anonymous",
25130
+ useFallbackImage: true,
24908
25131
  cropMode: {
24909
25132
  gridLines: { enabled: true },
24910
25133
  overlay: { fill: "rgba(0,0,0,0.2)" },
@@ -25474,8 +25697,10 @@ var WeaveImageCrop = class WeaveImageCrop {
25474
25697
  var WeaveImageNode = class extends WeaveNode {
25475
25698
  imageBitmapCache = {};
25476
25699
  imageSource = {};
25700
+ imageFallback = {};
25477
25701
  imageState = {};
25478
- imageIconSource = null;
25702
+ imageTryoutAttempts = {};
25703
+ imageTryoutIds = {};
25479
25704
  nodeType = WEAVE_IMAGE_NODE_TYPE;
25480
25705
  constructor(params) {
25481
25706
  super();
@@ -25485,9 +25710,14 @@ var WeaveImageNode = class extends WeaveNode {
25485
25710
  y: 0,
25486
25711
  time: 0
25487
25712
  };
25488
- this.lastTapTime = 0;
25489
25713
  this.config = mergeExceptArrays(WEAVE_IMAGE_DEFAULT_CONFIG, config);
25490
25714
  this.imageCrop = null;
25715
+ this.imageBitmapCache = {};
25716
+ this.imageSource = {};
25717
+ this.imageState = {};
25718
+ this.imageTryoutIds = {};
25719
+ this.imageTryoutAttempts = {};
25720
+ this.imageFallback = {};
25491
25721
  }
25492
25722
  getConfiguration() {
25493
25723
  return this.config;
@@ -25568,6 +25798,12 @@ var WeaveImageNode = class extends WeaveNode {
25568
25798
  cropping: false
25569
25799
  });
25570
25800
  this.setupDefaultNodeAugmentation(image);
25801
+ image.defineMousePointer = () => {
25802
+ if (this.imageState[id]?.status === "loading") return "wait";
25803
+ const selectedNodes = this.getSelectionPlugin()?.getSelectedNodes() ?? [];
25804
+ if (this.isSelecting() && selectedNodes.includes(image)) return "grab";
25805
+ return "pointer";
25806
+ };
25571
25807
  image.movedToContainer = () => {
25572
25808
  const stage = this.instance.getStage();
25573
25809
  const image$1 = stage.findOne(`#${id}`);
@@ -25646,8 +25882,8 @@ var WeaveImageNode = class extends WeaveNode {
25646
25882
  image.dblClick = () => {
25647
25883
  if (this.imageState[id]?.loaded && !this.imageState[id]?.error) this.config.onDblClick?.(this, image);
25648
25884
  };
25649
- if (this.imageSource[id]) {
25650
- imagePlaceholder.destroy();
25885
+ if (this.imageSource[id] && imageProps.imageURL) {
25886
+ imagePlaceholder?.destroy();
25651
25887
  const imageSource = this.imageSource[id];
25652
25888
  internalImage.setAttrs({
25653
25889
  image: imageSource,
@@ -25672,13 +25908,14 @@ var WeaveImageNode = class extends WeaveNode {
25672
25908
  height: sourceImageHeight
25673
25909
  });
25674
25910
  this.imageState[id] = {
25911
+ status: "loaded",
25675
25912
  loaded: true,
25676
25913
  error: false
25677
25914
  };
25678
25915
  this.updateImageCrop(image);
25679
25916
  } else {
25680
25917
  this.updatePlaceholderSize(image, imagePlaceholder);
25681
- this.loadImage(imageProps, image);
25918
+ this.loadImage(imageProps, image, true);
25682
25919
  }
25683
25920
  if (this.config.performance.cache.enabled) image.on("transformend", () => {
25684
25921
  this.cacheNode(image);
@@ -25909,7 +26146,7 @@ var WeaveImageNode = class extends WeaveNode {
25909
26146
  scaleY: 1,
25910
26147
  rotation: 0,
25911
26148
  visible: true,
25912
- fill: "#ccccccff",
26149
+ fill: this.config.style.placeholder.fill,
25913
26150
  strokeWidth: 0,
25914
26151
  draggable: false,
25915
26152
  zIndex: 0
@@ -25943,7 +26180,7 @@ var WeaveImageNode = class extends WeaveNode {
25943
26180
  scaleY: 1,
25944
26181
  rotation: 0,
25945
26182
  visible: true,
25946
- fill: "#ccccccff",
26183
+ fill: this.config.style.placeholder.fill,
25947
26184
  strokeWidth: 0,
25948
26185
  draggable: false,
25949
26186
  zIndex: 0
@@ -25985,59 +26222,111 @@ var WeaveImageNode = class extends WeaveNode {
25985
26222
  }
25986
26223
  this.cacheNode(nodeInstance);
25987
26224
  }
25988
- preloadImage(imageId, imageURL, { onLoad, onError }) {
26225
+ preloadFallbackImage(imageId, imageURL, { onLoad, onError }) {
26226
+ const imageURLToLoad = imageURL ?? "http://localhost/false-image";
26227
+ this.imageFallback[imageId] = Konva.Util.createImageElement();
26228
+ this.imageFallback[imageId].crossOrigin = this.config.crossOrigin;
26229
+ this.imageFallback[imageId].onerror = (error) => {
26230
+ this.imageState[imageId] = {
26231
+ status: "error-fallback",
26232
+ loaded: false,
26233
+ error: true
26234
+ };
26235
+ onError(error);
26236
+ };
26237
+ this.imageFallback[imageId].onload = async () => {
26238
+ this.imageState[imageId] = {
26239
+ status: "loading",
26240
+ loaded: true,
26241
+ error: false
26242
+ };
26243
+ onLoad();
26244
+ };
26245
+ this.imageState[imageId] = {
26246
+ status: "loading",
26247
+ loaded: false,
26248
+ error: false
26249
+ };
26250
+ try {
26251
+ this.imageFallback[imageId].src = imageURLToLoad;
26252
+ } catch (ex) {
26253
+ console.error(ex);
26254
+ }
26255
+ }
26256
+ preloadImage(imageId, imageURL, { onLoad, onError }, loadingTryout = false) {
26257
+ const imageURLToLoad = imageURL ?? "http://localhost/false-image";
25989
26258
  this.imageSource[imageId] = Konva.Util.createImageElement();
25990
26259
  this.imageSource[imageId].crossOrigin = this.config.crossOrigin;
25991
26260
  this.imageSource[imageId].onerror = (error) => {
25992
- this.imageState[imageId] = {
26261
+ if (!loadingTryout) this.imageState[imageId] = {
26262
+ status: "error",
25993
26263
  loaded: false,
25994
26264
  error: true
25995
26265
  };
25996
26266
  delete this.imageSource[imageId];
25997
- delete this.imageState[imageId];
25998
26267
  onError(error);
25999
26268
  };
26000
26269
  this.imageSource[imageId].onload = async () => {
26001
26270
  this.imageState[imageId] = {
26271
+ status: "loaded",
26002
26272
  loaded: true,
26003
26273
  error: false
26004
26274
  };
26005
26275
  onLoad();
26006
26276
  };
26007
- this.imageState[imageId] = {
26277
+ if (this.imageState[imageId]) this.imageState[imageId].status = "loading";
26278
+ else this.imageState[imageId] = {
26279
+ status: "loading",
26008
26280
  loaded: false,
26009
26281
  error: false
26010
26282
  };
26011
26283
  try {
26012
- if (imageURL) this.imageSource[imageId].src = imageURL;
26284
+ this.imageSource[imageId].src = imageURLToLoad;
26013
26285
  } catch (ex) {
26014
26286
  console.error(ex);
26015
26287
  }
26016
26288
  }
26017
- loadImage(params, image) {
26289
+ loadImage(params, image, useFallback = false, loadTryout = false) {
26018
26290
  const imageProps = params;
26019
26291
  const { id } = imageProps;
26020
26292
  const imagePlaceholder = image.findOne(`#${id}-placeholder`);
26021
26293
  const internalImage = image.findOne(`#${id}-image`);
26022
- const realImageURL = this.config.urlTransformer?.(imageProps.imageURL ?? "", image) ?? imageProps.imageURL;
26294
+ let realImageURL = this.config.urlTransformer?.(imageProps.imageURL ?? "", image) ?? imageProps.imageURL;
26295
+ let preloadFunction = this.preloadImage.bind(this);
26296
+ const loadFallback = useFallback && imageProps.imageFallback && this.config.useFallbackImage;
26297
+ if (loadFallback) {
26298
+ preloadFunction = this.preloadFallbackImage.bind(this);
26299
+ realImageURL = imageProps.imageFallback;
26300
+ }
26023
26301
  this.loadAsyncElement(id);
26024
- this.preloadImage(id, realImageURL ?? "", {
26302
+ preloadFunction(id, realImageURL ?? "", {
26025
26303
  onLoad: () => {
26026
- if (image && imagePlaceholder && internalImage) {
26304
+ if (useFallback) this.imageTryoutIds[id] = setTimeout(() => {
26305
+ const node = this.instance.getStage().findOne(`#${id}`);
26306
+ if (node) {
26307
+ this.imageTryoutAttempts[id] = (this.imageTryoutAttempts[id] ?? 0) + 1;
26308
+ this.loadImage(node.getAttrs(), node, false, true);
26309
+ }
26310
+ }, this.config.imageLoading.retryDelayMs);
26311
+ if (useFallback && loadTryout && this.imageTryoutIds[id]) {
26312
+ clearTimeout(this.imageTryoutIds[id]);
26313
+ delete this.imageTryoutIds[id];
26314
+ }
26315
+ if (image && internalImage) {
26027
26316
  image.setAttrs({
26028
26317
  width: imageProps.width ? imageProps.width : this.imageSource[id].width,
26029
26318
  height: imageProps.height ? imageProps.height : this.imageSource[id].height
26030
26319
  });
26031
- imagePlaceholder.destroy();
26032
- const imageSource = this.imageSource[id];
26320
+ imagePlaceholder?.destroy();
26321
+ const imageSource = loadFallback ? this.imageFallback[id] : this.imageSource[id];
26033
26322
  internalImage.setAttrs({
26034
26323
  width: imageProps.width ? imageProps.width : this.imageSource[id].width,
26035
26324
  height: imageProps.height ? imageProps.height : this.imageSource[id].height,
26036
26325
  image: imageSource,
26037
26326
  visible: true
26038
26327
  });
26039
- let sourceImageWidth = this.imageSource[id].width;
26040
- let sourceImageHeight = this.imageSource[id].height;
26328
+ let sourceImageWidth = imageProps.width ? imageProps.width : this.imageSource[id].width;
26329
+ let sourceImageHeight = imageProps.height ? imageProps.height : this.imageSource[id].height;
26041
26330
  if (image.getAttrs().imageInfo) {
26042
26331
  sourceImageWidth = image.getAttrs().imageInfo.width;
26043
26332
  sourceImageHeight = image.getAttrs().imageInfo.height;
@@ -26056,40 +26345,56 @@ var WeaveImageNode = class extends WeaveNode {
26056
26345
  width: imageRect.width,
26057
26346
  height: imageRect.height
26058
26347
  });
26059
- this.imageState[id] = {
26060
- loaded: true,
26061
- error: false
26062
- };
26348
+ const stage = this.instance.getStage();
26349
+ if (!loadFallback) {
26350
+ if (!this.instance.isServerSide() && stage.container().style.cursor === "wait") stage.container().style.cursor = "pointer";
26351
+ this.imageState[id] = {
26352
+ status: "loaded",
26353
+ loaded: true,
26354
+ error: false
26355
+ };
26356
+ }
26063
26357
  this.updateImageCrop(image);
26064
26358
  this.resolveAsyncElement(id);
26065
26359
  this.cacheNode(image);
26066
26360
  }
26067
26361
  },
26068
26362
  onError: (error) => {
26363
+ if (!this.config.useFallbackImage) this.imageTryoutIds[id] = setTimeout(() => {
26364
+ const node = this.instance.getStage().findOne(`#${id}`);
26365
+ if (node) {
26366
+ this.imageTryoutAttempts[id] = (this.imageTryoutAttempts[id] ?? 0) + 1;
26367
+ this.loadImage(node.getAttrs(), node, false, true);
26368
+ }
26369
+ }, this.config.imageLoading.retryDelayMs);
26370
+ if (loadTryout) {
26371
+ const tryoutAttempts = this.imageTryoutAttempts[id] ?? 0;
26372
+ if (tryoutAttempts < this.config.imageLoading.maxRetryAttempts) this.imageTryoutIds[id] = setTimeout(() => {
26373
+ const node = this.instance.getStage().findOne(`#${id}`);
26374
+ if (node) {
26375
+ this.imageTryoutAttempts[id] = tryoutAttempts + 1;
26376
+ this.loadImage(node.getAttrs(), node, false, true);
26377
+ }
26378
+ }, this.config.imageLoading.retryDelayMs);
26379
+ return;
26380
+ }
26381
+ if (this.config.useFallbackImage && !useFallback && !loadTryout && imageProps.imageFallback) {
26382
+ this.loadImage({ ...params }, image, true);
26383
+ return;
26384
+ }
26069
26385
  this.imageState[id] = {
26386
+ status: "error",
26070
26387
  loaded: false,
26071
26388
  error: true
26072
26389
  };
26073
- image.setAttrs({
26074
- image: void 0,
26075
- width: 100,
26076
- height: 100,
26077
- imageInfo: {
26078
- width: 100,
26079
- height: 100
26080
- },
26081
- uncroppedImage: {
26082
- width: 100,
26083
- height: 100
26084
- }
26085
- });
26390
+ image.setAttrs({ image: void 0 });
26086
26391
  this.resolveAsyncElement(id);
26087
26392
  console.error("Error loading image", realImageURL, error);
26088
26393
  imagePlaceholder?.setAttrs({ visible: true });
26089
26394
  internalImage?.setAttrs({ visible: false });
26090
26395
  this.cacheNode(image);
26091
26396
  }
26092
- });
26397
+ }, loadTryout);
26093
26398
  }
26094
26399
  updatePlaceholderSize(image, imagePlaceholder) {
26095
26400
  const imageAttrs = image.getAttrs();
@@ -26110,8 +26415,16 @@ var WeaveImageNode = class extends WeaveNode {
26110
26415
  const internalImage = image?.findOne(`#${imageAttrs.id}-image`);
26111
26416
  if (!this.imageState[imageAttrs.id ?? ""]?.loaded) return;
26112
26417
  if (image && internalImage && !imageAttrs.adding && imageAttrs.cropInfo && imageAttrs.uncroppedImage) {
26418
+ const imageId = imageAttrs.id ?? "";
26113
26419
  const originalImageInfo = imageAttrs.imageInfo;
26114
- const actualImageInfo = this.imageSource[imageAttrs.id ?? ""];
26420
+ let actualImageInfo = {
26421
+ width: this.imageSource[imageId]?.width ?? 0,
26422
+ height: this.imageSource[imageId]?.height ?? 0
26423
+ };
26424
+ if (actualImageInfo.width === 0 && actualImageInfo.height === 0 && this.imageFallback[imageId]) actualImageInfo = {
26425
+ width: this.imageFallback[imageId].width,
26426
+ height: this.imageFallback[imageId].height
26427
+ };
26115
26428
  const originalActualDiffScale = originalImageInfo ? actualImageInfo.width / originalImageInfo.width : 1;
26116
26429
  const actualScale = imageAttrs.uncroppedImage.width / imageAttrs.imageInfo.width;
26117
26430
  const cropScale = imageAttrs.cropInfo ? imageAttrs.cropInfo.scaleX : actualScale;
@@ -26140,6 +26453,9 @@ var WeaveImageNode = class extends WeaveNode {
26140
26453
  internalImage.height(imageAttrs.uncroppedImage.height);
26141
26454
  }
26142
26455
  }
26456
+ getFallbackImageSource(imageId) {
26457
+ return this.imageFallback[imageId];
26458
+ }
26143
26459
  getImageSource(imageId) {
26144
26460
  return this.imageSource[imageId];
26145
26461
  }
@@ -26191,6 +26507,23 @@ var WeaveImageNode = class extends WeaveNode {
26191
26507
  getIsAsync() {
26192
26508
  return true;
26193
26509
  }
26510
+ forceLoadImage(nodeInstance) {
26511
+ const nodeId = nodeInstance.getAttrs().id ?? "";
26512
+ const node = this.instance.getStage().findOne(`#${nodeId}`);
26513
+ if (this.imageTryoutIds[nodeId]) {
26514
+ clearTimeout(this.imageTryoutIds[nodeId]);
26515
+ delete this.imageTryoutIds[nodeId];
26516
+ }
26517
+ if (node) this.loadImage(node.getAttrs(), node, false, false);
26518
+ }
26519
+ onDestroy(nodeInstance) {
26520
+ const nodeId = nodeInstance.getAttrs().id ?? "";
26521
+ delete this.imageSource[nodeId];
26522
+ delete this.imageState[nodeId];
26523
+ delete this.imageTryoutAttempts[nodeId];
26524
+ delete this.imageFallback[nodeId];
26525
+ nodeInstance.destroy();
26526
+ }
26194
26527
  };
26195
26528
 
26196
26529
  //#endregion
@@ -32914,14 +33247,19 @@ var WeaveBrushToolAction = class extends WeaveAction {
32914
33247
  });
32915
33248
  window.addEventListener("keydown", (e) => {
32916
33249
  if (e.code === "Enter" && this.instance.getActiveAction() === BRUSH_TOOL_ACTION_NAME) {
33250
+ e.stopPropagation();
32917
33251
  this.cancelAction();
32918
33252
  return;
32919
33253
  }
32920
33254
  if (e.code === "Space" && this.instance.getActiveAction() === BRUSH_TOOL_ACTION_NAME) {
33255
+ e.stopPropagation();
32921
33256
  this.isSpacePressed = true;
32922
33257
  return;
32923
33258
  }
32924
- if (e.code === "Escape" && this.instance.getActiveAction() === BRUSH_TOOL_ACTION_NAME) this.cancelAction();
33259
+ if (e.code === "Escape" && this.instance.getActiveAction() === BRUSH_TOOL_ACTION_NAME) {
33260
+ e.stopPropagation();
33261
+ this.cancelAction();
33262
+ }
32925
33263
  });
32926
33264
  const handlePointerDown = (e) => {
32927
33265
  if (this.state === BRUSH_TOOL_STATE.INACTIVE) return;
@@ -33113,6 +33451,15 @@ var WeaveBrushToolAction = class extends WeaveAction {
33113
33451
  }
33114
33452
  };
33115
33453
 
33454
+ //#endregion
33455
+ //#region src/actions/text-tool/constants.ts
33456
+ const TEXT_TOOL_ACTION_NAME = "textTool";
33457
+ const TEXT_TOOL_STATE = {
33458
+ ["IDLE"]: "idle",
33459
+ ["ADDING"]: "adding",
33460
+ ["FINISHED"]: "finished"
33461
+ };
33462
+
33116
33463
  //#endregion
33117
33464
  //#region src/actions/text-tool/text-tool.ts
33118
33465
  var WeaveTextToolAction = class extends WeaveAction {
@@ -33135,7 +33482,7 @@ var WeaveTextToolAction = class extends WeaveAction {
33135
33482
  initProps() {
33136
33483
  return {
33137
33484
  text: "",
33138
- layout: TEXT_LAYOUT.AUTO_ALL,
33485
+ layout: TEXT_LAYOUT.SMART,
33139
33486
  fontSize: 20,
33140
33487
  fontFamily: "Arial, sans-serif",
33141
33488
  fill: "#000000",
@@ -33239,42 +33586,62 @@ var WeaveTextToolAction = class extends WeaveAction {
33239
33586
 
33240
33587
  //#endregion
33241
33588
  //#region src/actions/image-tool/constants.ts
33242
- const IMAGE_TOOL_ACTION_NAME = "imageTool";
33243
- const IMAGE_TOOL_STATE = {
33589
+ const WEAVE_IMAGE_TOOL_ACTION_NAME = "imageTool";
33590
+ const WEAVE_IMAGE_TOOL_UPLOAD_TYPE = {
33591
+ ["FILE"]: "file",
33592
+ ["IMAGE_URL"]: "imageURL"
33593
+ };
33594
+ const WEAVE_IMAGE_TOOL_STATE = {
33244
33595
  ["IDLE"]: "idle",
33245
33596
  ["DEFINING_POSITION"]: "definingPosition",
33246
33597
  ["SELECTED_POSITION"]: "selectedPosition",
33247
33598
  ["ADDING"]: "adding",
33248
33599
  ["FINISHED"]: "finished"
33249
33600
  };
33250
- const IMAGE_TOOL_LOAD_FROM = {
33251
- ["DATAURL"]: "dataURL",
33252
- ["URL"]: "url"
33253
- };
33601
+ const WEAVE_IMAGE_TOOL_CONFIG_DEFAULT = { style: { cursor: {
33602
+ padding: 5,
33603
+ imageThumbnail: {
33604
+ width: 250,
33605
+ height: 250,
33606
+ shadowColor: "#aaaaaa",
33607
+ shadowBlur: 10,
33608
+ shadowOffset: {
33609
+ x: 2,
33610
+ y: 2
33611
+ },
33612
+ shadowOpacity: .5
33613
+ }
33614
+ } } };
33254
33615
 
33255
33616
  //#endregion
33256
33617
  //#region src/actions/image-tool/image-tool.ts
33257
33618
  var WeaveImageToolAction = class extends WeaveAction {
33258
33619
  initialized = false;
33259
33620
  initialCursor = null;
33260
- cursorPadding = 5;
33621
+ imageFile = null;
33622
+ imageURL = null;
33261
33623
  forceMainContainer = false;
33624
+ ignoreKeyboardEvents = false;
33625
+ ignorePointerEvents = false;
33626
+ uploadType = null;
33262
33627
  onPropsChange = void 0;
33263
33628
  update = void 0;
33264
- constructor() {
33629
+ constructor(params) {
33265
33630
  super();
33631
+ this.config = mergeExceptArrays(WEAVE_IMAGE_TOOL_CONFIG_DEFAULT, params?.config ?? {});
33266
33632
  this.pointers = new Map();
33267
33633
  this.initialized = false;
33268
- this.state = IMAGE_TOOL_STATE.IDLE;
33634
+ this.state = WEAVE_IMAGE_TOOL_STATE.IDLE;
33269
33635
  this.imageId = null;
33270
33636
  this.tempImageId = null;
33271
33637
  this.tempImageNode = null;
33272
33638
  this.container = void 0;
33273
33639
  this.imageURL = null;
33640
+ this.uploadType = null;
33274
33641
  this.clickPoint = null;
33275
33642
  }
33276
33643
  getName() {
33277
- return IMAGE_TOOL_ACTION_NAME;
33644
+ return WEAVE_IMAGE_TOOL_ACTION_NAME;
33278
33645
  }
33279
33646
  initProps() {
33280
33647
  return {
@@ -33288,14 +33655,15 @@ var WeaveImageToolAction = class extends WeaveAction {
33288
33655
  this.instance.addEventListener("onStageDrop", (e) => {
33289
33656
  const dragId = this.instance.getDragStartedId();
33290
33657
  const dragProperties = this.instance.getDragProperties();
33291
- if (dragProperties && dragId === IMAGE_TOOL_ACTION_NAME) {
33658
+ if (dragProperties && dragId === WEAVE_IMAGE_TOOL_ACTION_NAME) {
33292
33659
  this.instance.getStage().setPointersPositions(e);
33293
33660
  const position = getPositionRelativeToContainerOnPosition(this.instance);
33294
- this.instance.triggerAction(IMAGE_TOOL_ACTION_NAME, {
33295
- imageURL: dragProperties.imageURL,
33296
- ...dragProperties.imageId && { imageId: dragProperties.imageId },
33297
- ...dragProperties.imageWidth && { imageWidth: dragProperties.imageWidth },
33298
- ...dragProperties.imageHeight && { imageHeight: dragProperties.imageHeight },
33661
+ if (!position) return;
33662
+ this.instance.triggerAction(WEAVE_IMAGE_TOOL_ACTION_NAME, {
33663
+ type: WEAVE_IMAGE_TOOL_UPLOAD_TYPE.IMAGE_URL,
33664
+ image: dragProperties.imageURL,
33665
+ ...dragProperties.imageId ? { imageId: dragProperties.imageId } : {},
33666
+ ...dragProperties.forceMainContainer && { forceMainContainer: dragProperties.forceMainContainer },
33299
33667
  position
33300
33668
  });
33301
33669
  }
@@ -33304,87 +33672,93 @@ var WeaveImageToolAction = class extends WeaveAction {
33304
33672
  setupEvents() {
33305
33673
  const stage = this.instance.getStage();
33306
33674
  window.addEventListener("keydown", (e) => {
33307
- if (e.code === "Escape" && this.instance.getActiveAction() === IMAGE_TOOL_ACTION_NAME) {
33675
+ if (e.code === "Escape" && this.instance.getActiveAction() === WEAVE_IMAGE_TOOL_ACTION_NAME && !this.ignoreKeyboardEvents) {
33308
33676
  this.cancelAction();
33309
33677
  return;
33310
33678
  }
33311
33679
  });
33312
33680
  stage.on("pointerdown", (e) => {
33313
33681
  this.setTapStart(e);
33682
+ if (this.ignorePointerEvents) return;
33314
33683
  this.pointers.set(e.evt.pointerId, {
33315
33684
  x: e.evt.clientX,
33316
33685
  y: e.evt.clientY
33317
33686
  });
33318
- if (this.pointers.size === 2 && this.instance.getActiveAction() === IMAGE_TOOL_ACTION_NAME) {
33319
- this.state = IMAGE_TOOL_STATE.DEFINING_POSITION;
33687
+ if (this.pointers.size === 2 && this.instance.getActiveAction() === WEAVE_IMAGE_TOOL_ACTION_NAME) {
33688
+ this.state = WEAVE_IMAGE_TOOL_STATE.DEFINING_POSITION;
33320
33689
  return;
33321
33690
  }
33322
- if (this.state === IMAGE_TOOL_STATE.DEFINING_POSITION) this.state = IMAGE_TOOL_STATE.SELECTED_POSITION;
33691
+ if (this.state === WEAVE_IMAGE_TOOL_STATE.DEFINING_POSITION) this.state = WEAVE_IMAGE_TOOL_STATE.SELECTED_POSITION;
33323
33692
  });
33324
33693
  stage.on("pointermove", (e) => {
33325
- if (this.state === IMAGE_TOOL_STATE.IDLE) return;
33694
+ if (this.ignorePointerEvents) return;
33695
+ if (this.state === WEAVE_IMAGE_TOOL_STATE.IDLE) return;
33326
33696
  this.setCursor();
33327
- if (this.pointers.size === 2 && this.instance.getActiveAction() === IMAGE_TOOL_ACTION_NAME) {
33328
- this.state = IMAGE_TOOL_STATE.DEFINING_POSITION;
33697
+ if (this.pointers.size === 2 && this.instance.getActiveAction() === WEAVE_IMAGE_TOOL_ACTION_NAME) {
33698
+ this.state = WEAVE_IMAGE_TOOL_STATE.DEFINING_POSITION;
33329
33699
  return;
33330
33700
  }
33331
- if ([IMAGE_TOOL_STATE.DEFINING_POSITION, IMAGE_TOOL_STATE.SELECTED_POSITION].includes(this.state) && this.tempImageNode && this.instance.getActiveAction() === IMAGE_TOOL_ACTION_NAME && e.evt.pointerType === "mouse") {
33701
+ if ([WEAVE_IMAGE_TOOL_STATE.DEFINING_POSITION, WEAVE_IMAGE_TOOL_STATE.SELECTED_POSITION].includes(this.state) && this.tempImageNode && this.instance.getActiveAction() === WEAVE_IMAGE_TOOL_ACTION_NAME && e.evt.pointerType === "mouse") {
33332
33702
  const mousePos = stage.getRelativePointerPosition();
33703
+ const cursorPadding = this.config.style.cursor.padding;
33333
33704
  this.tempImageNode.setAttrs({
33334
- x: (mousePos?.x ?? 0) + this.cursorPadding,
33335
- y: (mousePos?.y ?? 0) + this.cursorPadding
33705
+ x: (mousePos?.x ?? 0) + cursorPadding / stage.scaleX(),
33706
+ y: (mousePos?.y ?? 0) + cursorPadding / stage.scaleX()
33336
33707
  });
33337
33708
  }
33338
33709
  });
33339
33710
  stage.on("pointerup", (e) => {
33711
+ if (this.ignorePointerEvents) return;
33340
33712
  this.pointers.delete(e.evt.pointerId);
33341
- if (this.state === IMAGE_TOOL_STATE.SELECTED_POSITION) this.handleAdding();
33713
+ if (this.state === WEAVE_IMAGE_TOOL_STATE.SELECTED_POSITION) this.handleAdding();
33342
33714
  });
33343
33715
  this.initialized = true;
33344
33716
  }
33345
33717
  setState(state) {
33346
33718
  this.state = state;
33347
33719
  }
33348
- loadImage(imageData, kind, position) {
33720
+ async loadImage(params) {
33349
33721
  this.setCursor();
33350
33722
  this.setFocusStage();
33351
33723
  if (!this.imageId) {
33352
33724
  this.cancelAction();
33353
33725
  return;
33354
33726
  }
33355
- this.imageURL = kind === IMAGE_TOOL_LOAD_FROM.DATAURL ? "not-defined" : imageData;
33356
33727
  const imageNodeHandler = this.getImageNodeHandler();
33357
- if (!imageNodeHandler) {
33358
- this.cancelAction();
33359
- return;
33360
- }
33361
- if (IMAGE_TOOL_LOAD_FROM.URL === kind) {
33362
- this.props = {
33363
- ...this.props,
33364
- imageURL: this.imageURL,
33365
- width: this.props.loadImageWidth,
33366
- height: this.props.loadImageHeight
33728
+ if (!imageNodeHandler) return;
33729
+ const actualImageId = this.imageId;
33730
+ if (params.type === WEAVE_IMAGE_TOOL_UPLOAD_TYPE.FILE) {
33731
+ const image = params.image;
33732
+ const realImageSize = await getImageSizeFromFile(image.file);
33733
+ const downscaledImage = await downscaleImageFile(image.file, image.downscaleRatio);
33734
+ const reader = new FileReader();
33735
+ reader.onloadend = () => {
33736
+ imageNodeHandler.preloadFallbackImage(actualImageId, reader.result, {
33737
+ onLoad: () => {
33738
+ this.props = {
33739
+ ...this.props,
33740
+ imageFallback: reader.result,
33741
+ imageURL: void 0,
33742
+ width: realImageSize.width,
33743
+ height: realImageSize.height
33744
+ };
33745
+ this.addImageNode(params?.position);
33746
+ },
33747
+ onError: () => {
33748
+ this.cancelAction();
33749
+ }
33750
+ });
33367
33751
  };
33368
- this.addImageNode(position);
33752
+ reader.onerror = () => {};
33753
+ reader.readAsDataURL(downscaledImage);
33754
+ }
33755
+ if (params.type === WEAVE_IMAGE_TOOL_UPLOAD_TYPE.IMAGE_URL) {
33756
+ const image = params.image;
33757
+ setTimeout(() => {
33758
+ this.saveImageUrl(actualImageId, image.url);
33759
+ }, 0);
33760
+ this.addImageNode(params?.position);
33369
33761
  }
33370
- imageNodeHandler.preloadImage(this.imageId, imageData, {
33371
- onLoad: () => {
33372
- this.instance.emitEvent("onImageLoadEnd", void 0);
33373
- const imageSource = imageNodeHandler.getImageSource(this.imageId);
33374
- if (imageSource && this.imageId) this.props = {
33375
- ...this.props,
33376
- imageURL: this.imageURL,
33377
- width: imageSource.width,
33378
- height: imageSource.height
33379
- };
33380
- this.addImageNode(position);
33381
- },
33382
- onError: () => {
33383
- this.instance.emitEvent("onImageLoadEnd", new Error("Error loading image"));
33384
- this.cancelAction();
33385
- }
33386
- });
33387
- this.instance.emitEvent("onImageLoadStart");
33388
33762
  }
33389
33763
  isTouchDevice() {
33390
33764
  return window.matchMedia("(pointer: coarse)").matches;
@@ -33394,54 +33768,67 @@ var WeaveImageToolAction = class extends WeaveAction {
33394
33768
  this.setCursor();
33395
33769
  this.setFocusStage();
33396
33770
  if (position) {
33397
- this.setState(IMAGE_TOOL_STATE.SELECTED_POSITION);
33771
+ this.setState(WEAVE_IMAGE_TOOL_STATE.SELECTED_POSITION);
33398
33772
  this.handleAdding(position);
33399
33773
  return;
33400
33774
  }
33775
+ const imageNodeHandler = this.getImageNodeHandler();
33776
+ if (!imageNodeHandler) {
33777
+ this.cancelAction();
33778
+ return;
33779
+ }
33401
33780
  if (this.imageId) {
33402
33781
  const mousePos = stage.getRelativePointerPosition();
33403
33782
  this.tempImageId = v4_default();
33404
- const imageNodeHandler = this.getImageNodeHandler();
33405
- if (!imageNodeHandler) {
33406
- this.cancelAction();
33407
- return;
33408
- }
33409
- const imageSource = imageNodeHandler.getImageSource(this.imageId);
33783
+ let imageSource = imageNodeHandler.getImageSource(this.imageId);
33784
+ if (this.uploadType === "file") imageSource = imageNodeHandler.getFallbackImageSource(this.imageId);
33410
33785
  if (!imageSource) {
33411
33786
  this.cancelAction();
33412
33787
  return;
33413
33788
  }
33414
33789
  const aspectRatio = imageSource.width / imageSource.height;
33415
33790
  if (!this.tempImageNode && this.tempImageId && !this.isTouchDevice()) {
33791
+ const cursorPadding = this.config.style.cursor.padding;
33792
+ const imageThumbnailWidth = this.config.style.cursor.imageThumbnail.width;
33793
+ const imageThumbnailHeight = this.config.style.cursor.imageThumbnail.height;
33794
+ const shadowColor = this.config.style.cursor.imageThumbnail.shadowColor;
33795
+ const shadowBlur = this.config.style.cursor.imageThumbnail.shadowBlur;
33796
+ const shadowOffset = this.config.style.cursor.imageThumbnail.shadowOffset;
33797
+ const shadowOpacity = this.config.style.cursor.imageThumbnail.shadowOpacity;
33416
33798
  this.tempImageNode = new Konva.Image({
33417
33799
  id: this.tempImageId,
33418
- x: (mousePos?.x ?? 0) + this.cursorPadding,
33419
- y: (mousePos?.y ?? 0) + this.cursorPadding,
33420
- width: 240 * aspectRatio * (1 / stage.scaleX()),
33421
- height: 240 * (1 / stage.scaleY()),
33800
+ x: (mousePos?.x ?? 0) + cursorPadding / stage.scaleX(),
33801
+ y: (mousePos?.y ?? 0) + cursorPadding / stage.scaleY(),
33802
+ width: imageThumbnailWidth * aspectRatio * (1 / stage.scaleX()),
33803
+ height: imageThumbnailHeight * (1 / stage.scaleY()),
33422
33804
  opacity: 1,
33423
33805
  adding: true,
33424
33806
  image: imageSource,
33425
33807
  stroke: "#000000ff",
33426
33808
  strokeWidth: 0,
33427
33809
  strokeScaleEnabled: true,
33428
- listening: false
33810
+ listening: false,
33811
+ shadowColor,
33812
+ shadowBlur,
33813
+ shadowOffset,
33814
+ shadowOpacity
33429
33815
  });
33430
33816
  this.instance.getMainLayer()?.add(this.tempImageNode);
33431
33817
  }
33432
33818
  this.instance.emitEvent("onAddingImage", { imageURL: this.props.imageURL });
33433
33819
  }
33434
33820
  this.clickPoint = null;
33435
- this.setState(IMAGE_TOOL_STATE.DEFINING_POSITION);
33821
+ this.setState(WEAVE_IMAGE_TOOL_STATE.DEFINING_POSITION);
33436
33822
  }
33437
33823
  handleAdding(position) {
33824
+ const imageNodeHandler = this.getImageNodeHandler();
33825
+ if (!imageNodeHandler) {
33826
+ this.cancelAction();
33827
+ return;
33828
+ }
33438
33829
  if (this.imageId) {
33439
- const imageNodeHandler = this.getImageNodeHandler();
33440
- if (!imageNodeHandler) {
33441
- this.cancelAction();
33442
- return;
33443
- }
33444
- const imageSource = imageNodeHandler.getImageSource(this.imageId);
33830
+ let imageSource = imageNodeHandler.getImageSource(this.imageId);
33831
+ if (this.uploadType === WEAVE_IMAGE_TOOL_UPLOAD_TYPE.FILE) imageSource = imageNodeHandler.getFallbackImageSource(this.imageId);
33445
33832
  if (!imageSource && !position) {
33446
33833
  this.cancelAction();
33447
33834
  return;
@@ -33450,8 +33837,10 @@ var WeaveImageToolAction = class extends WeaveAction {
33450
33837
  this.clickPoint = mousePoint;
33451
33838
  this.container = container;
33452
33839
  const nodeHandler = this.instance.getNodeHandler("image");
33453
- const imageWidth = this.props.loadImageWidth ? this.props.loadImageWidth : imageSource?.width;
33454
- const imageHeight = this.props.loadImageHeight ? this.props.loadImageHeight : imageSource?.height;
33840
+ const imageWidth = this.props.width ? this.props.width : imageSource?.width;
33841
+ const imageHeight = this.props.height ? this.props.height : imageSource?.height;
33842
+ let realImageURL = void 0;
33843
+ if (this.uploadType === WEAVE_IMAGE_TOOL_UPLOAD_TYPE.IMAGE_URL && this.imageURL) realImageURL = this.imageURL?.url;
33455
33844
  if (nodeHandler) {
33456
33845
  const node = nodeHandler.create(this.imageId, {
33457
33846
  ...this.props,
@@ -33459,7 +33848,7 @@ var WeaveImageToolAction = class extends WeaveAction {
33459
33848
  y: this.clickPoint?.y ?? 0,
33460
33849
  opacity: 1,
33461
33850
  adding: false,
33462
- imageURL: this.imageURL,
33851
+ imageURL: realImageURL,
33463
33852
  stroke: "#000000ff",
33464
33853
  strokeWidth: 0,
33465
33854
  strokeScaleEnabled: true,
@@ -33468,15 +33857,32 @@ var WeaveImageToolAction = class extends WeaveAction {
33468
33857
  imageInfo: {
33469
33858
  width: imageWidth,
33470
33859
  height: imageHeight
33860
+ },
33861
+ uncroppedImage: {
33862
+ width: imageWidth,
33863
+ height: imageHeight
33471
33864
  }
33472
33865
  });
33473
33866
  this.instance.addNode(node, this.forceMainContainer ? this.instance.getMainLayer()?.getAttrs().id : this.container?.getAttrs().id);
33474
- this.instance.emitEvent("onAddedImage", {
33475
- imageURL: this.props.imageURL,
33476
- nodeId: this.imageId
33477
- });
33867
+ this.instance.emitEvent("onAddedImage", { nodeId: this.imageId });
33868
+ if (this.uploadType === WEAVE_IMAGE_TOOL_UPLOAD_TYPE.FILE) {
33869
+ const uploadImageFunctionInternal = async () => {
33870
+ const nodeId = this.imageId ?? "";
33871
+ try {
33872
+ const imageURL = await this.uploadImageFunction(this.imageFile.file);
33873
+ this.saveImageUrl(nodeId, imageURL);
33874
+ this.instance.emitEvent("onImageUploaded", {
33875
+ imageURL,
33876
+ nodeId
33877
+ });
33878
+ } catch (error) {
33879
+ this.instance.emitEvent("onImageUploadedError", { error });
33880
+ }
33881
+ };
33882
+ uploadImageFunctionInternal();
33883
+ }
33478
33884
  }
33479
- this.setState(IMAGE_TOOL_STATE.FINISHED);
33885
+ this.setState(WEAVE_IMAGE_TOOL_STATE.FINISHED);
33480
33886
  }
33481
33887
  this.cancelAction();
33482
33888
  }
@@ -33486,55 +33892,507 @@ var WeaveImageToolAction = class extends WeaveAction {
33486
33892
  this.cancelAction = cancelAction;
33487
33893
  const selectionPlugin = this.instance.getPlugin("nodesSelection");
33488
33894
  if (selectionPlugin) selectionPlugin.setSelectedNodes([]);
33895
+ this.ignorePointerEvents = false;
33896
+ this.ignoreKeyboardEvents = false;
33489
33897
  this.forceMainContainer = params?.forceMainContainer ?? false;
33898
+ this.imageFile = null;
33899
+ this.imageURL = null;
33490
33900
  this.imageId = v4_default();
33491
33901
  this.props = this.initProps();
33492
33902
  if (params?.imageId) this.updateProps({ imageId: params.imageId });
33493
- if (params?.imageId) this.updateProps({ loadImageWidth: params.imageWidth });
33494
- if (params?.imageId) this.updateProps({ loadImageHeight: params.imageHeight });
33495
- if (params.imageData) this.loadImage(params.imageData, IMAGE_TOOL_LOAD_FROM.DATAURL, params?.position ?? void 0);
33496
- if (params.imageURL) this.loadImage(params.imageURL, IMAGE_TOOL_LOAD_FROM.URL, params?.position ?? void 0);
33497
- return {
33498
- nodeId: this.imageId,
33499
- finishUploadCallback: (nodeId, imageURL) => {
33500
- return this.saveImageUrl.bind(this)(nodeId, imageURL);
33903
+ if (this.forceExecution) {
33904
+ this.ignorePointerEvents = true;
33905
+ this.ignoreKeyboardEvents = true;
33906
+ }
33907
+ if (params?.position) this.setState(WEAVE_IMAGE_TOOL_STATE.SELECTED_POSITION);
33908
+ if (params.type === WEAVE_IMAGE_TOOL_UPLOAD_TYPE.FILE && params.image) {
33909
+ this.uploadType = WEAVE_IMAGE_TOOL_UPLOAD_TYPE.FILE;
33910
+ this.imageFile = params.image;
33911
+ this.uploadImageFunction = params.uploadImageFunction;
33912
+ this.loadImage({
33913
+ type: WEAVE_IMAGE_TOOL_UPLOAD_TYPE.FILE,
33914
+ image: params.image,
33915
+ position: params?.position
33916
+ });
33917
+ }
33918
+ if (params.type === WEAVE_IMAGE_TOOL_UPLOAD_TYPE.IMAGE_URL && params.image) {
33919
+ this.uploadType = WEAVE_IMAGE_TOOL_UPLOAD_TYPE.IMAGE_URL;
33920
+ this.imageURL = params.image;
33921
+ this.updateProps({
33922
+ imageFallback: params.image.fallback,
33923
+ width: params.image.width,
33924
+ height: params.image.height
33925
+ });
33926
+ this.loadImage({
33927
+ type: WEAVE_IMAGE_TOOL_UPLOAD_TYPE.IMAGE_URL,
33928
+ image: params.image,
33929
+ position: params?.position
33930
+ });
33931
+ }
33932
+ return { nodeId: this.imageId };
33933
+ }
33934
+ saveImageUrl(nodeId, imageURL) {
33935
+ const stage = this.instance.getStage();
33936
+ const nodeHandler = this.instance.getNodeHandler("image");
33937
+ const node = stage.findOne(`#${nodeId}`);
33938
+ if (nodeHandler && node) {
33939
+ node.setAttr("imageURL", imageURL);
33940
+ nodeHandler.forceLoadImage(node);
33941
+ this.instance.updateNode(nodeHandler.serialize(node), { origin: "system" });
33942
+ }
33943
+ }
33944
+ cleanup() {
33945
+ const stage = this.instance.getStage();
33946
+ if (this.tempImageNode) this.tempImageNode.destroy();
33947
+ if (!this.forceExecution) {
33948
+ const selectionPlugin = this.instance.getPlugin("nodesSelection");
33949
+ if (selectionPlugin) {
33950
+ const node = stage.findOne(`#${this.imageId}`);
33951
+ if (node) selectionPlugin.setSelectedNodes([node]);
33952
+ this.instance.triggerAction(SELECTION_TOOL_ACTION_NAME);
33501
33953
  }
33954
+ stage.container().style.cursor = "default";
33955
+ this.instance.endDrag(WEAVE_IMAGE_TOOL_ACTION_NAME);
33956
+ }
33957
+ this.initialCursor = null;
33958
+ this.forceMainContainer = false;
33959
+ this.container = void 0;
33960
+ this.tempImageNode = null;
33961
+ this.imageURL = null;
33962
+ this.clickPoint = null;
33963
+ this.setState(WEAVE_IMAGE_TOOL_STATE.IDLE);
33964
+ }
33965
+ getImageNodeHandler() {
33966
+ return this.instance.getNodeHandler("image");
33967
+ }
33968
+ setCursor() {
33969
+ const stage = this.instance.getStage();
33970
+ stage.container().style.cursor = "crosshair";
33971
+ }
33972
+ setFocusStage() {
33973
+ const stage = this.instance.getStage();
33974
+ stage.container().tabIndex = 1;
33975
+ stage.container().blur();
33976
+ stage.container().focus();
33977
+ }
33978
+ setDragAndDropProperties(properties) {
33979
+ this.instance.startDrag(WEAVE_IMAGE_TOOL_ACTION_NAME);
33980
+ this.instance.setDragProperties(properties);
33981
+ }
33982
+ getActualState() {
33983
+ return this.state;
33984
+ }
33985
+ };
33986
+
33987
+ //#endregion
33988
+ //#region src/actions/images-tool/constants.ts
33989
+ const WEAVE_IMAGES_TOOL_ACTION_NAME = "imagesTool";
33990
+ const WEAVE_IMAGES_TOOL_UPLOAD_TYPE = {
33991
+ ["FILE"]: "file",
33992
+ ["IMAGE_URL"]: "imageURL"
33993
+ };
33994
+ const WEAVE_IMAGES_TOOL_STATE = {
33995
+ ["IDLE"]: "idle",
33996
+ ["UPLOADING"]: "uploading",
33997
+ ["DEFINING_POSITION"]: "definingPosition",
33998
+ ["SELECTED_POSITION"]: "selectedPosition",
33999
+ ["ADDING"]: "adding",
34000
+ ["FINISHED"]: "finished"
34001
+ };
34002
+ const WEAVE_IMAGES_TOOL_DEFAULT_CONFIG = {
34003
+ style: {
34004
+ cursor: {
34005
+ padding: 5,
34006
+ imageThumbnails: {
34007
+ padding: 15,
34008
+ width: 250,
34009
+ height: 250,
34010
+ shadowColor: "#aaaaaa",
34011
+ shadowBlur: 10,
34012
+ shadowOffset: {
34013
+ x: 2,
34014
+ y: 2
34015
+ },
34016
+ shadowOpacity: .5
34017
+ }
34018
+ },
34019
+ moreImages: {
34020
+ paddingX: 12,
34021
+ paddingY: 8,
34022
+ fontSize: 16,
34023
+ fontFamily: "Arial",
34024
+ textColor: "#000000",
34025
+ backgroundColor: "#FFFFFF",
34026
+ backgroundOpacity: 1
34027
+ },
34028
+ images: { padding: 20 }
34029
+ },
34030
+ layout: { columns: 4 }
34031
+ };
34032
+
34033
+ //#endregion
34034
+ //#region src/internal-utils/generic.ts
34035
+ function sleep(ms) {
34036
+ return new Promise((resolve) => setTimeout(resolve, ms));
34037
+ }
34038
+
34039
+ //#endregion
34040
+ //#region src/actions/images-tool/images-tool.ts
34041
+ var WeaveImagesToolAction = class extends WeaveAction {
34042
+ initialized = false;
34043
+ initialCursor = null;
34044
+ nodesIds = [];
34045
+ imagesFile = [];
34046
+ imagesURL = [];
34047
+ forceMainContainer = false;
34048
+ uploadType = null;
34049
+ onPropsChange = void 0;
34050
+ update = void 0;
34051
+ constructor(params) {
34052
+ super();
34053
+ this.config = mergeExceptArrays(WEAVE_IMAGES_TOOL_DEFAULT_CONFIG, params ?? {});
34054
+ this.pointers = new Map();
34055
+ this.initialized = false;
34056
+ this.tempPointerFeedbackNode = null;
34057
+ this.state = WEAVE_IMAGES_TOOL_STATE.IDLE;
34058
+ this.imagesFile = [];
34059
+ this.imagesURL = [];
34060
+ this.container = void 0;
34061
+ this.preloadImgs = {};
34062
+ this.uploadType = null;
34063
+ this.clickPoint = null;
34064
+ }
34065
+ getName() {
34066
+ return WEAVE_IMAGES_TOOL_ACTION_NAME;
34067
+ }
34068
+ getPreloadedImage(imageId) {
34069
+ return this.preloadImgs?.[imageId];
34070
+ }
34071
+ initProps() {
34072
+ return {
34073
+ width: 100,
34074
+ height: 100,
34075
+ scaleX: 1,
34076
+ scaleY: 1
33502
34077
  };
33503
34078
  }
34079
+ onInit() {
34080
+ this.instance.addEventListener("onStageDrop", (e) => {
34081
+ const dragId = this.instance.getDragStartedId();
34082
+ const dragProperties = this.instance.getDragProperties();
34083
+ if (dragProperties && dragId === WEAVE_IMAGES_TOOL_ACTION_NAME) {
34084
+ this.instance.getStage().setPointersPositions(e);
34085
+ const position = getPositionRelativeToContainerOnPosition(this.instance);
34086
+ if (!position) return;
34087
+ this.instance.triggerAction(WEAVE_IMAGES_TOOL_ACTION_NAME, {
34088
+ type: WEAVE_IMAGES_TOOL_UPLOAD_TYPE.IMAGE_URL,
34089
+ images: dragProperties.imagesURL,
34090
+ position,
34091
+ ...dragProperties.forceMainContainer && { forceMainContainer: dragProperties.forceMainContainer }
34092
+ });
34093
+ }
34094
+ });
34095
+ }
34096
+ setupEvents() {
34097
+ const stage = this.instance.getStage();
34098
+ stage.container().addEventListener("keydown", (e) => {
34099
+ if (e.key === "Escape" && this.instance.getActiveAction() === WEAVE_IMAGES_TOOL_ACTION_NAME) this.cancelAction();
34100
+ });
34101
+ stage.on("pointerdown", (e) => {
34102
+ this.setTapStart(e);
34103
+ this.pointers.set(e.evt.pointerId, {
34104
+ x: e.evt.clientX,
34105
+ y: e.evt.clientY
34106
+ });
34107
+ if (this.pointers.size === 2 && this.instance.getActiveAction() === WEAVE_IMAGES_TOOL_ACTION_NAME) {
34108
+ this.state = WEAVE_IMAGES_TOOL_STATE.DEFINING_POSITION;
34109
+ return;
34110
+ }
34111
+ if (this.state === WEAVE_IMAGES_TOOL_STATE.DEFINING_POSITION) this.state = WEAVE_IMAGES_TOOL_STATE.SELECTED_POSITION;
34112
+ });
34113
+ stage.on("pointermove", (e) => {
34114
+ if (this.state === WEAVE_IMAGES_TOOL_STATE.IDLE) return;
34115
+ this.setCursor();
34116
+ this.setFocusStage();
34117
+ if (this.pointers.size === 2 && this.instance.getActiveAction() === WEAVE_IMAGES_TOOL_ACTION_NAME) {
34118
+ this.state = WEAVE_IMAGES_TOOL_STATE.DEFINING_POSITION;
34119
+ return;
34120
+ }
34121
+ if ([WEAVE_IMAGES_TOOL_STATE.DEFINING_POSITION, WEAVE_IMAGES_TOOL_STATE.SELECTED_POSITION].includes(this.state) && this.tempPointerFeedbackNode && this.instance.getActiveAction() === WEAVE_IMAGES_TOOL_ACTION_NAME && e.evt.pointerType === "mouse") {
34122
+ const mousePos = stage.getRelativePointerPosition();
34123
+ const cursorPadding = this.config.style.cursor.padding;
34124
+ this.tempPointerFeedbackNode.setAttrs({
34125
+ x: (mousePos?.x ?? 0) + cursorPadding / stage.scaleX(),
34126
+ y: (mousePos?.y ?? 0) + cursorPadding / stage.scaleY()
34127
+ });
34128
+ }
34129
+ });
34130
+ stage.on("pointerup", (e) => {
34131
+ this.pointers.delete(e.evt.pointerId);
34132
+ if (this.state === WEAVE_IMAGES_TOOL_STATE.SELECTED_POSITION) this.handleAdding();
34133
+ });
34134
+ this.initialized = true;
34135
+ }
34136
+ setState(state) {
34137
+ this.state = state;
34138
+ }
34139
+ async addImages(position) {
34140
+ const stage = this.instance.getStage();
34141
+ this.setCursor();
34142
+ this.setFocusStage();
34143
+ if (position) {
34144
+ this.setState(WEAVE_IMAGES_TOOL_STATE.SELECTED_POSITION);
34145
+ this.handleAdding(position);
34146
+ return;
34147
+ }
34148
+ if (!this.tempPointerFeedbackNode && !this.isTouchDevice() && this.imagesFile && this.uploadType === WEAVE_IMAGES_TOOL_UPLOAD_TYPE.FILE) {
34149
+ const mousePos = stage.getRelativePointerPosition();
34150
+ const cursorPadding = this.config.style.cursor.padding;
34151
+ const imageThumbnailsPadding = this.config.style.cursor.imageThumbnails.padding;
34152
+ this.tempPointerFeedbackNode = new Konva.Group({
34153
+ x: (mousePos?.x ?? 0) + cursorPadding / stage.scaleX(),
34154
+ y: (mousePos?.y ?? 0) + cursorPadding / stage.scaleY(),
34155
+ listening: false
34156
+ });
34157
+ const imagesTop3 = this.imagesFile.slice(0, 3) ?? [];
34158
+ let maxWidth = 0;
34159
+ let maxHeight = 0;
34160
+ let position$1 = {
34161
+ x: 0,
34162
+ y: 0
34163
+ };
34164
+ for (const image of imagesTop3) {
34165
+ const imageSource = await loadImageSource(image.file);
34166
+ const maxImageWidth = this.config.style.cursor.imageThumbnails.width;
34167
+ const maxImageHeight = this.config.style.cursor.imageThumbnails.height;
34168
+ const shadowColor = this.config.style.cursor.imageThumbnails.shadowColor;
34169
+ const shadowBlur = this.config.style.cursor.imageThumbnails.shadowBlur;
34170
+ const shadowOffset = this.config.style.cursor.imageThumbnails.shadowOffset;
34171
+ const shadowOpacity = this.config.style.cursor.imageThumbnails.shadowOpacity;
34172
+ const aspectRatio = imageSource.width / imageSource.height || 1;
34173
+ const imageWidth = maxImageWidth * aspectRatio * (1 / stage.scaleX());
34174
+ const imageHeight = maxImageHeight * (1 / stage.scaleY());
34175
+ const imageNode = new Konva.Image({
34176
+ x: position$1.x,
34177
+ y: position$1.y,
34178
+ width: imageWidth,
34179
+ height: imageHeight,
34180
+ opacity: 1,
34181
+ adding: true,
34182
+ image: imageSource,
34183
+ stroke: "#000000ff",
34184
+ strokeWidth: 0,
34185
+ strokeScaleEnabled: true,
34186
+ listening: false,
34187
+ shadowColor,
34188
+ shadowBlur,
34189
+ shadowOffset,
34190
+ shadowOpacity
34191
+ });
34192
+ maxWidth = position$1.x + imageWidth;
34193
+ maxHeight = Math.max(maxHeight, position$1.y + imageHeight);
34194
+ position$1 = {
34195
+ x: position$1.x + imageThumbnailsPadding / stage.scaleX(),
34196
+ y: position$1.y + imageThumbnailsPadding / stage.scaleY()
34197
+ };
34198
+ this.tempPointerFeedbackNode.add(imageNode);
34199
+ imageNode.moveToBottom();
34200
+ }
34201
+ if (this.imagesFile.length > 3) {
34202
+ const paddingX = this.config.style.moreImages.paddingX;
34203
+ const paddingY = this.config.style.moreImages.paddingY;
34204
+ const fontSize = this.config.style.moreImages.fontSize;
34205
+ const fontFamily = this.config.style.moreImages.fontFamily;
34206
+ const textColor = this.config.style.moreImages.textColor;
34207
+ const backgroundColor = this.config.style.moreImages.backgroundColor;
34208
+ const backgroundOpacity = this.config.style.moreImages.backgroundOpacity;
34209
+ const text = `and ${this.imagesFile.length - 3} more image(s)`;
34210
+ const textNode = new Konva.Text({
34211
+ x: maxWidth + paddingX / stage.scaleX() + cursorPadding / stage.scaleX(),
34212
+ y: position$1.y,
34213
+ fontFamily,
34214
+ fontSize: fontSize / stage.scaleX(),
34215
+ text,
34216
+ fill: textColor,
34217
+ listening: false
34218
+ });
34219
+ const textSize = textNode.measureSize(text);
34220
+ textNode.y((maxHeight - textSize.height) / 2);
34221
+ this.tempPointerFeedbackNode.add(textNode);
34222
+ const textBg = new Konva.Rect({
34223
+ x: textNode.x() - paddingX / stage.scaleX(),
34224
+ y: textNode.y() - paddingY / stage.scaleY(),
34225
+ width: textNode.width() + 2 * paddingX / stage.scaleX(),
34226
+ height: textNode.height() + 2 * paddingY / stage.scaleY(),
34227
+ fill: backgroundColor,
34228
+ opacity: backgroundOpacity
34229
+ });
34230
+ this.tempPointerFeedbackNode.add(textBg);
34231
+ textBg.moveToBottom();
34232
+ textNode.moveToTop();
34233
+ }
34234
+ this.instance.getUtilityLayer()?.add(this.tempPointerFeedbackNode);
34235
+ this.instance.emitEvent("onAddingImages");
34236
+ }
34237
+ this.clickPoint = null;
34238
+ this.setState(WEAVE_IMAGES_TOOL_STATE.DEFINING_POSITION);
34239
+ }
34240
+ async handleAdding(position) {
34241
+ const stage = this.instance.getStage();
34242
+ this.tempPointerFeedbackNode?.destroy();
34243
+ this.tempPointerFeedbackNode = null;
34244
+ this.instance.getUtilityLayer()?.batchDraw();
34245
+ stage.container().style.cursor = "default";
34246
+ const { mousePoint, container } = this.instance.getMousePointer(position);
34247
+ this.clickPoint = mousePoint;
34248
+ this.container = container;
34249
+ const originPoint = {
34250
+ x: this.clickPoint?.x ?? 0,
34251
+ y: this.clickPoint?.y ?? 0
34252
+ };
34253
+ if (!this.imagesFile && !this.imagesURL) return;
34254
+ const imageToolActionHandler = this.instance.getActionHandler(WEAVE_IMAGE_TOOL_ACTION_NAME);
34255
+ if (!imageToolActionHandler) return;
34256
+ const imagesPadding = this.config.style.images.padding;
34257
+ const layoutColumns = this.config.layout.columns;
34258
+ let imagePositionX = originPoint.x;
34259
+ let imagePositionY = originPoint.y;
34260
+ let maxHeight = 0;
34261
+ if (this.uploadType === WEAVE_IMAGES_TOOL_UPLOAD_TYPE.FILE && this.imagesFile) {
34262
+ const imagesToUpload = this.imagesFile.length;
34263
+ let imagesUploaded = 0;
34264
+ await this.onStartUploading();
34265
+ const handleUploadImage = async () => {
34266
+ imagesUploaded++;
34267
+ if (imagesUploaded >= imagesToUpload) {
34268
+ await this.onFinishedUploading();
34269
+ this.instance.removeEventListener("onImageUploaded", handleUploadImage);
34270
+ }
34271
+ };
34272
+ this.instance.addEventListener("onImageUploaded", handleUploadImage);
34273
+ for (let i = 0; i < this.imagesFile.length; i++) {
34274
+ const imageFile = this.imagesFile[i];
34275
+ const { imageId, width, height,...restImageFile } = imageFile;
34276
+ const uploadImageFunctionInternal = async () => {
34277
+ const imageURL = await this.uploadImageFunction(imageFile.file);
34278
+ return imageURL;
34279
+ };
34280
+ const { nodeId } = this.instance.triggerAction(WEAVE_IMAGE_TOOL_ACTION_NAME, {
34281
+ type: WEAVE_IMAGE_TOOL_UPLOAD_TYPE.FILE,
34282
+ image: restImageFile,
34283
+ uploadImageFunction: uploadImageFunctionInternal,
34284
+ ...imageId && { imageId },
34285
+ position: {
34286
+ x: imagePositionX,
34287
+ y: imagePositionY
34288
+ },
34289
+ forceMainContainer: this.forceMainContainer
34290
+ }, true);
34291
+ this.nodesIds.push(nodeId);
34292
+ maxHeight = Math.max(maxHeight, height);
34293
+ imagePositionX += imagesPadding + width;
34294
+ if ((i + 1) % layoutColumns === 0) {
34295
+ imagePositionX = originPoint.x;
34296
+ imagePositionY = imagePositionY + maxHeight + imagesPadding;
34297
+ maxHeight = 0;
34298
+ }
34299
+ while (imageToolActionHandler.getActualState() !== WEAVE_IMAGES_TOOL_STATE.IDLE) await sleep(10);
34300
+ }
34301
+ this.instance.emitEvent("onAddedImages", { nodesIds: this.nodesIds });
34302
+ }
34303
+ if (this.uploadType === WEAVE_IMAGES_TOOL_UPLOAD_TYPE.IMAGE_URL && this.imagesURL) {
34304
+ for (let i = 0; i < this.imagesURL.length; i++) {
34305
+ const imageURL = this.imagesURL[i];
34306
+ const { imageId, options,...restImageURL } = imageURL;
34307
+ const imageURLElement = restImageURL;
34308
+ const { nodeId } = this.instance.triggerAction(WEAVE_IMAGE_TOOL_ACTION_NAME, {
34309
+ type: WEAVE_IMAGE_TOOL_UPLOAD_TYPE.IMAGE_URL,
34310
+ image: imageURLElement,
34311
+ ...imageId && { imageId },
34312
+ ...options && { options },
34313
+ position: {
34314
+ x: imagePositionX,
34315
+ y: imagePositionY
34316
+ },
34317
+ forceMainContainer: this.forceMainContainer
34318
+ }, true);
34319
+ this.nodesIds.push(nodeId);
34320
+ maxHeight = Math.max(maxHeight, imageURL.height);
34321
+ imagePositionX += imagesPadding + imageURL.width;
34322
+ if ((i + 1) % layoutColumns === 0) {
34323
+ imagePositionX = originPoint.x;
34324
+ imagePositionY = imagePositionY + maxHeight + imagesPadding;
34325
+ maxHeight = 0;
34326
+ }
34327
+ while (imageToolActionHandler.getActualState() !== WEAVE_IMAGES_TOOL_STATE.IDLE) await sleep(10);
34328
+ }
34329
+ this.instance.emitEvent("onAddedImages", { nodesIds: this.nodesIds });
34330
+ }
34331
+ this.setState(WEAVE_IMAGES_TOOL_STATE.FINISHED);
34332
+ this.cancelAction();
34333
+ }
34334
+ trigger(cancelAction, params) {
34335
+ if (!this.instance) throw new Error("Instance not defined");
34336
+ if (!this.initialized) this.setupEvents();
34337
+ this.cancelAction = cancelAction;
34338
+ const selectionPlugin = this.instance.getPlugin("nodesSelection");
34339
+ if (selectionPlugin) selectionPlugin.setSelectedNodes([]);
34340
+ if (params?.position) this.setState(WEAVE_IMAGES_TOOL_STATE.SELECTED_POSITION);
34341
+ this.forceMainContainer = params.forceMainContainer ?? false;
34342
+ if (params.type === WEAVE_IMAGES_TOOL_UPLOAD_TYPE.FILE) {
34343
+ this.uploadType = WEAVE_IMAGES_TOOL_UPLOAD_TYPE.FILE;
34344
+ this.onStartUploading = params.onStartUploading;
34345
+ this.onFinishedUploading = params.onFinishedUploading;
34346
+ this.uploadImageFunction = params.uploadImageFunction;
34347
+ this.nodesIds = [];
34348
+ this.imagesFile = params.images;
34349
+ }
34350
+ if (params.type === WEAVE_IMAGES_TOOL_UPLOAD_TYPE.IMAGE_URL) {
34351
+ this.uploadType = WEAVE_IMAGES_TOOL_UPLOAD_TYPE.IMAGE_URL;
34352
+ this.nodesIds = [];
34353
+ this.imagesURL = params.images;
34354
+ }
34355
+ if (![WEAVE_IMAGES_TOOL_UPLOAD_TYPE.FILE, WEAVE_IMAGES_TOOL_UPLOAD_TYPE.IMAGE_URL].includes(params.type)) {
34356
+ this.cancelAction();
34357
+ return;
34358
+ }
34359
+ this.addImages(params?.position);
34360
+ }
33504
34361
  saveImageUrl(nodeId, imageURL) {
33505
- this.imageURL = imageURL;
33506
- if (this.state !== IMAGE_TOOL_STATE.DEFINING_POSITION) {
34362
+ if (this.state !== WEAVE_IMAGES_TOOL_STATE.DEFINING_POSITION) {
33507
34363
  const stage = this.instance.getStage();
33508
34364
  const nodeHandler = this.instance.getNodeHandler("image");
33509
34365
  const node = stage.findOne(`#${nodeId}`);
33510
34366
  if (nodeHandler && node) {
33511
34367
  node.setAttr("imageURL", imageURL);
33512
- this.instance.updateNode(nodeHandler.serialize(node));
34368
+ nodeHandler.forceLoadImage(node);
34369
+ this.instance.updateNode(nodeHandler.serialize(node), { origin: "system" });
33513
34370
  }
33514
34371
  }
33515
34372
  }
33516
34373
  cleanup() {
33517
34374
  const stage = this.instance.getStage();
33518
- if (this.tempImageNode) this.tempImageNode.destroy();
34375
+ this.tempPointerFeedbackNode?.destroy();
34376
+ this.tempPointerFeedbackNode = null;
34377
+ this.instance.getUtilityLayer()?.batchDraw();
33519
34378
  const selectionPlugin = this.instance.getPlugin("nodesSelection");
33520
34379
  if (selectionPlugin) {
33521
- const node = stage.findOne(`#${this.imageId}`);
33522
- if (node) selectionPlugin.setSelectedNodes([node]);
34380
+ const addedNodes = [];
34381
+ for (const nodeId of this.nodesIds) {
34382
+ const node = stage.findOne(`#${nodeId}`);
34383
+ if (node) addedNodes.push(node);
34384
+ }
34385
+ selectionPlugin.setSelectedNodes(addedNodes);
33523
34386
  this.instance.triggerAction(SELECTION_TOOL_ACTION_NAME);
33524
34387
  }
34388
+ this.instance.endDrag(WEAVE_IMAGES_TOOL_ACTION_NAME);
33525
34389
  stage.container().style.cursor = "default";
33526
- this.instance.endDrag(IMAGE_TOOL_ACTION_NAME);
33527
- this.initialCursor = null;
33528
- this.imageId = null;
34390
+ this.uploadType = null;
33529
34391
  this.forceMainContainer = false;
34392
+ this.initialCursor = null;
33530
34393
  this.container = void 0;
33531
- this.tempImageNode = null;
33532
- this.imageURL = null;
33533
34394
  this.clickPoint = null;
33534
- this.setState(IMAGE_TOOL_STATE.IDLE);
33535
- }
33536
- getImageNodeHandler() {
33537
- return this.instance.getNodeHandler("image");
34395
+ this.setState(WEAVE_IMAGES_TOOL_STATE.IDLE);
33538
34396
  }
33539
34397
  setCursor() {
33540
34398
  const stage = this.instance.getStage();
@@ -33546,8 +34404,11 @@ var WeaveImageToolAction = class extends WeaveAction {
33546
34404
  stage.container().blur();
33547
34405
  stage.container().focus();
33548
34406
  }
34407
+ isTouchDevice() {
34408
+ return window.matchMedia("(pointer: coarse)").matches;
34409
+ }
33549
34410
  setDragAndDropProperties(properties) {
33550
- this.instance.startDrag(IMAGE_TOOL_ACTION_NAME);
34411
+ this.instance.startDrag(WEAVE_IMAGES_TOOL_ACTION_NAME);
33551
34412
  this.instance.setDragProperties(properties);
33552
34413
  }
33553
34414
  };
@@ -36109,6 +36970,7 @@ var WeaveStageGridPlugin = class extends WeavePlugin {
36109
36970
  gridDotMaxDotsPerAxis: WEAVE_GRID_DEFAULT_DOT_MAX_DOTS_PER_AXIS,
36110
36971
  ...config
36111
36972
  };
36973
+ this.forceStageChange = false;
36112
36974
  }
36113
36975
  getName() {
36114
36976
  return WEAVE_STAGE_GRID_PLUGIN_KEY;
@@ -36316,6 +37178,10 @@ var WeaveStageGridPlugin = class extends WeavePlugin {
36316
37178
  gridLayer.add(originShape);
36317
37179
  }
36318
37180
  hasStageChanged() {
37181
+ if (this.forceStageChange) {
37182
+ this.forceStageChange = false;
37183
+ return true;
37184
+ }
36319
37185
  const stage = this.instance.getStage();
36320
37186
  const actualScaleX = stage.scaleX();
36321
37187
  const actualScaleY = stage.scaleY();
@@ -36358,6 +37224,7 @@ var WeaveStageGridPlugin = class extends WeavePlugin {
36358
37224
  }
36359
37225
  setType(type) {
36360
37226
  this.config.type = type;
37227
+ this.forceStageChange = true;
36361
37228
  this.onRender();
36362
37229
  }
36363
37230
  };
@@ -38764,7 +39631,7 @@ var WeaveStageKeyboardMovePlugin = class extends WeavePlugin {
38764
39631
  };
38765
39632
 
38766
39633
  //#endregion
38767
- //#region src/utils/mapping.ts
39634
+ //#region src/internal-utils/mapping.ts
38768
39635
  const isArray = (val) => {
38769
39636
  return Array.isArray(val);
38770
39637
  };
@@ -38810,4 +39677,4 @@ function getJSONFromYjsBinary(actualState) {
38810
39677
  }
38811
39678
 
38812
39679
  //#endregion
38813
- export { ALIGN_NODES_ALIGN_TO, ALIGN_NODES_TOOL_ACTION_NAME, ALIGN_NODES_TOOL_STATE, ARROW_TOOL_ACTION_NAME, ARROW_TOOL_STATE, BRUSH_TOOL_ACTION_NAME, BRUSH_TOOL_DEFAULT_CONFIG, BRUSH_TOOL_STATE, CONNECTOR_TOOL_ACTION_NAME, CONNECTOR_TOOL_DEFAULT_CONFIG, CONNECTOR_TOOL_STATE, COPY_PASTE_NODES_PLUGIN_STATE, ELLIPSE_TOOL_ACTION_NAME, ELLIPSE_TOOL_STATE, ERASER_TOOL_ACTION_NAME, ERASER_TOOL_STATE, FRAME_TOOL_ACTION_NAME, FRAME_TOOL_STATE, GUIDE_DISTANCE_LINE_DEFAULT_CONFIG, GUIDE_ENTER_SNAPPING_TOLERANCE, GUIDE_EXIT_SNAPPING_TOLERANCE, GUIDE_HORIZONTAL_LINE_NAME, GUIDE_LINE_DEFAULT_CONFIG, GUIDE_LINE_DRAG_SNAPPING_THRESHOLD, GUIDE_LINE_NAME, GUIDE_LINE_TRANSFORM_SNAPPING_THRESHOLD, GUIDE_ORIENTATION, GUIDE_VERTICAL_LINE_NAME, IMAGE_TOOL_ACTION_NAME, IMAGE_TOOL_LOAD_FROM, IMAGE_TOOL_STATE, LINE_TOOL_ACTION_NAME, LINE_TOOL_DEFAULT_CONFIG, LINE_TOOL_STATE, MEASURE_TOOL_ACTION_NAME, MEASURE_TOOL_STATE, MOVE_TOOL_ACTION_NAME, MOVE_TOOL_STATE, NODE_SNAP, NODE_SNAP_HORIZONTAL, NODE_SNAP_VERTICAL, PEN_TOOL_ACTION_NAME, PEN_TOOL_STATE, RECTANGLE_TOOL_ACTION_NAME, RECTANGLE_TOOL_STATE, REGULAR_POLYGON_TOOL_ACTION_NAME, REGULAR_POLYGON_TOOL_STATE, SELECTION_TOOL_ACTION_NAME, SELECTION_TOOL_STATE, STAGE_MINIMAP_DEFAULT_CONFIG, STAR_TOOL_ACTION_NAME, STAR_TOOL_STATE, TEXT_LAYOUT, TEXT_TOOL_ACTION_NAME, TEXT_TOOL_STATE, VIDEO_TOOL_ACTION_NAME, VIDEO_TOOL_STATE, WEAVE_ARROW_NODE_TYPE, WEAVE_COMMENTS_RENDERER_KEY, WEAVE_COMMENTS_TOOL_LAYER_ID, WEAVE_COMMENT_CREATE_ACTION, WEAVE_COMMENT_NODE_ACTION, WEAVE_COMMENT_NODE_DEFAULTS, WEAVE_COMMENT_NODE_TYPE, WEAVE_COMMENT_STATUS, WEAVE_COMMENT_TOOL_ACTION_NAME, WEAVE_COMMENT_TOOL_DEFAULT_CONFIG, WEAVE_COMMENT_TOOL_STATE, WEAVE_COMMENT_VIEW_ACTION, WEAVE_CONNECTOR_NODE_ANCHOR_ORIGIN, WEAVE_CONNECTOR_NODE_DECORATOR_TYPE, WEAVE_CONNECTOR_NODE_DEFAULT_CONFIG, WEAVE_CONNECTOR_NODE_LINE_ORIGIN, WEAVE_CONNECTOR_NODE_LINE_TYPE, WEAVE_CONNECTOR_NODE_TYPE, WEAVE_COPY_PASTE_CONFIG_DEFAULT, WEAVE_COPY_PASTE_NODES_KEY, WEAVE_COPY_PASTE_PASTE_CATCHER_ID, WEAVE_COPY_PASTE_PASTE_MODES, WEAVE_DEFAULT_USER_INFO_FUNCTION, WEAVE_ELLIPSE_NODE_TYPE, WEAVE_FRAME_DEFAULT_BACKGROUND_COLOR, WEAVE_FRAME_NODE_DEFAULT_CONFIG, WEAVE_FRAME_NODE_DEFAULT_PROPS, WEAVE_FRAME_NODE_TYPE, WEAVE_GRID_DEFAULT_COLOR, WEAVE_GRID_DEFAULT_DOT_MAX_DOTS_PER_AXIS, WEAVE_GRID_DEFAULT_MAJOR_DOT_RATIO, WEAVE_GRID_DEFAULT_MAJOR_EVERY, WEAVE_GRID_DEFAULT_MAJOR_LINE_RATIO, WEAVE_GRID_DEFAULT_ORIGIN_COLOR, WEAVE_GRID_DEFAULT_RADIUS, WEAVE_GRID_DEFAULT_SIZE, WEAVE_GRID_DEFAULT_STROKE, WEAVE_GRID_DEFAULT_TYPE, WEAVE_GRID_LAYER_ID, WEAVE_GRID_TYPES, WEAVE_GROUP_NODE_TYPE, WEAVE_IMAGE_CROP_ANCHOR_POSITION, WEAVE_IMAGE_CROP_END_TYPE, WEAVE_IMAGE_DEFAULT_CONFIG, WEAVE_IMAGE_NODE_TYPE, WEAVE_LAYER_NODE_TYPE, WEAVE_LINE_NODE_DEFAULT_CONFIG, WEAVE_LINE_NODE_TYPE, WEAVE_MEASURE_NODE_DEFAULT_CONFIG, WEAVE_MEASURE_NODE_TYPE, WEAVE_MEASURE_TOOL_DEFAULT_CONFIG, WEAVE_NODES_DISTANCE_SNAPPING_PLUGIN_KEY, WEAVE_NODES_EDGE_SNAPPING_PLUGIN_KEY, WEAVE_NODES_MULTI_SELECTION_FEEDBACK_PLUGIN_DEFAULT_CONFIG, WEAVE_NODES_MULTI_SELECTION_FEEDBACK_PLUGIN_KEY, WEAVE_NODES_MULTI_SELECTION_FEEDBACK_PLUGIN_LAYER_ID, WEAVE_NODES_SELECTION_DEFAULT_CONFIG, WEAVE_NODES_SELECTION_KEY, WEAVE_NODES_SELECTION_LAYER_ID, WEAVE_RECTANGLE_NODE_TYPE, WEAVE_REGULAR_POLYGON_NODE_TYPE, WEAVE_STAGE_DEFAULT_MODE, WEAVE_STAGE_GRID_PLUGIN_KEY, WEAVE_STAGE_IMAGE_CROPPING_MODE, WEAVE_STAGE_KEYBOARD_MOVE_DEFAULT_CONFIG, WEAVE_STAGE_KEYBOARD_MOVE_KEY, WEAVE_STAGE_MINIMAP_KEY, WEAVE_STAGE_NODE_TYPE, WEAVE_STAGE_PANNING_DEFAULT_CONFIG, WEAVE_STAGE_PANNING_KEY, WEAVE_STAGE_PANNING_THROTTLE_MS, WEAVE_STAGE_TEXT_EDITION_MODE, WEAVE_STAR_NODE_TYPE, WEAVE_STROKE_NODE_DEFAULT_CONFIG, WEAVE_STROKE_NODE_TYPE, WEAVE_STROKE_SINGLE_NODE_DEFAULT_CONFIG, WEAVE_STROKE_SINGLE_NODE_TIP_SIDE, WEAVE_STROKE_SINGLE_NODE_TIP_TYPE, WEAVE_STROKE_SINGLE_NODE_TYPE, WEAVE_STROKE_TOOL_ACTION_NAME, WEAVE_STROKE_TOOL_ACTION_NAME_ALIASES, WEAVE_STROKE_TOOL_DEFAULT_CONFIG, WEAVE_STROKE_TOOL_STATE, WEAVE_TEXT_NODE_DEFAULT_CONFIG, WEAVE_TEXT_NODE_TYPE, WEAVE_USERS_POINTERS_CONFIG_DEFAULT_PROPS, WEAVE_USERS_POINTERS_KEY, WEAVE_USERS_PRESENCE_CONFIG_DEFAULT_PROPS, WEAVE_USERS_PRESENCE_PLUGIN_KEY, WEAVE_USERS_SELECTION_KEY, WEAVE_USER_POINTER_KEY, WEAVE_USER_PRESENCE_KEY, WEAVE_USER_SELECTION_KEY, WEAVE_VIDEO_DEFAULT_CONFIG, WEAVE_VIDEO_NODE_TYPE, Weave, WeaveAction, WeaveAlignNodesToolAction, WeaveArrowNode, WeaveArrowToolAction, WeaveBrushToolAction, WeaveCommentNode, WeaveCommentToolAction, WeaveCommentsRendererPlugin, WeaveConnectedUsersPlugin, WeaveConnectorNode, WeaveConnectorToolAction, WeaveContextMenuPlugin, WeaveCopyPasteNodesPlugin, WeaveEllipseNode, WeaveEllipseToolAction, WeaveEraserToolAction, WeaveExportNodesToolAction, WeaveExportStageToolAction, WeaveFitToScreenToolAction, WeaveFitToSelectionToolAction, WeaveFrameNode, WeaveFrameToolAction, WeaveGroupNode, WeaveImageNode, WeaveImageToolAction, WeaveLayerNode, WeaveLineNode, WeaveLineToolAction, WeaveMeasureNode, WeaveMeasureToolAction, WeaveMoveToolAction, WeaveNode, WeaveNodesDistanceSnappingPlugin, WeaveNodesEdgeSnappingPlugin, WeaveNodesMultiSelectionFeedbackPlugin, WeaveNodesSelectionPlugin, WeavePenToolAction, WeavePlugin, WeaveRectangleNode, WeaveRectangleToolAction, WeaveRegularPolygonNode, WeaveRegularPolygonToolAction, WeaveRenderer, WeaveSelectionToolAction, WeaveStageDropAreaPlugin, WeaveStageGridPlugin, WeaveStageKeyboardMovePlugin, WeaveStageMinimapPlugin, WeaveStageNode, WeaveStagePanningPlugin, WeaveStageResizePlugin, WeaveStageZoomPlugin, WeaveStarNode, WeaveStarToolAction, WeaveStore, WeaveStrokeNode, WeaveStrokeSingleNode, WeaveStrokeToolAction, WeaveTextNode, WeaveTextToolAction, WeaveUsersPointersPlugin, WeaveUsersPresencePlugin, WeaveUsersSelectionPlugin, WeaveVideoNode, WeaveVideoToolAction, WeaveZoomInToolAction, WeaveZoomOutToolAction, canComposite, clearContainerTargets, containerOverCursor, containsNodeDeep, defaultInitialState, getBoundingBox, getExportBoundingBox, getJSONFromYjsBinary, getPositionRelativeToContainerOnPosition, getSelectedNodesMetadata, getStageClickPoint, getTargetAndSkipNodes, getTargetedNode, getTopmostShadowHost, getVisibleNodes, getVisibleNodesInViewport, hasFrames, hasImages, intersectArrays, isArray, isIOS, isInShadowDOM, isNodeInSelection, isObject, isServer, mapJsonToYjsArray, mapJsonToYjsElements, mapJsonToYjsMap, memoize, mergeExceptArrays, moveNodeToContainer, moveNodeToContainerNT, resetScale, weavejsToYjsBinary };
39680
+ export { ALIGN_NODES_ALIGN_TO, ALIGN_NODES_TOOL_ACTION_NAME, ALIGN_NODES_TOOL_STATE, ARROW_TOOL_ACTION_NAME, ARROW_TOOL_STATE, BRUSH_TOOL_ACTION_NAME, BRUSH_TOOL_DEFAULT_CONFIG, BRUSH_TOOL_STATE, CONNECTOR_TOOL_ACTION_NAME, CONNECTOR_TOOL_DEFAULT_CONFIG, CONNECTOR_TOOL_STATE, COPY_PASTE_NODES_PLUGIN_STATE, ELLIPSE_TOOL_ACTION_NAME, ELLIPSE_TOOL_STATE, ERASER_TOOL_ACTION_NAME, ERASER_TOOL_STATE, FRAME_TOOL_ACTION_NAME, FRAME_TOOL_STATE, GUIDE_DISTANCE_LINE_DEFAULT_CONFIG, GUIDE_ENTER_SNAPPING_TOLERANCE, GUIDE_EXIT_SNAPPING_TOLERANCE, GUIDE_HORIZONTAL_LINE_NAME, GUIDE_LINE_DEFAULT_CONFIG, GUIDE_LINE_DRAG_SNAPPING_THRESHOLD, GUIDE_LINE_NAME, GUIDE_LINE_TRANSFORM_SNAPPING_THRESHOLD, GUIDE_ORIENTATION, GUIDE_VERTICAL_LINE_NAME, LINE_TOOL_ACTION_NAME, LINE_TOOL_DEFAULT_CONFIG, LINE_TOOL_STATE, MEASURE_TOOL_ACTION_NAME, MEASURE_TOOL_STATE, MOVE_TOOL_ACTION_NAME, MOVE_TOOL_STATE, NODE_SNAP, NODE_SNAP_HORIZONTAL, NODE_SNAP_VERTICAL, PEN_TOOL_ACTION_NAME, PEN_TOOL_STATE, RECTANGLE_TOOL_ACTION_NAME, RECTANGLE_TOOL_STATE, REGULAR_POLYGON_TOOL_ACTION_NAME, REGULAR_POLYGON_TOOL_STATE, SELECTION_TOOL_ACTION_NAME, SELECTION_TOOL_STATE, STAGE_MINIMAP_DEFAULT_CONFIG, STAR_TOOL_ACTION_NAME, STAR_TOOL_STATE, TEXT_LAYOUT, TEXT_TOOL_ACTION_NAME, TEXT_TOOL_STATE, VIDEO_TOOL_ACTION_NAME, VIDEO_TOOL_STATE, WEAVE_ARROW_NODE_TYPE, WEAVE_COMMENTS_RENDERER_KEY, WEAVE_COMMENTS_TOOL_LAYER_ID, WEAVE_COMMENT_CREATE_ACTION, WEAVE_COMMENT_NODE_ACTION, WEAVE_COMMENT_NODE_DEFAULTS, WEAVE_COMMENT_NODE_TYPE, WEAVE_COMMENT_STATUS, WEAVE_COMMENT_TOOL_ACTION_NAME, WEAVE_COMMENT_TOOL_DEFAULT_CONFIG, WEAVE_COMMENT_TOOL_STATE, WEAVE_COMMENT_VIEW_ACTION, WEAVE_CONNECTOR_NODE_ANCHOR_ORIGIN, WEAVE_CONNECTOR_NODE_DECORATOR_TYPE, WEAVE_CONNECTOR_NODE_DEFAULT_CONFIG, WEAVE_CONNECTOR_NODE_LINE_ORIGIN, WEAVE_CONNECTOR_NODE_LINE_TYPE, WEAVE_CONNECTOR_NODE_TYPE, WEAVE_COPY_PASTE_CONFIG_DEFAULT, WEAVE_COPY_PASTE_NODES_KEY, WEAVE_COPY_PASTE_PASTE_CATCHER_ID, WEAVE_COPY_PASTE_PASTE_MODES, WEAVE_DEFAULT_USER_INFO_FUNCTION, WEAVE_ELLIPSE_NODE_TYPE, WEAVE_FRAME_DEFAULT_BACKGROUND_COLOR, WEAVE_FRAME_NODE_DEFAULT_CONFIG, WEAVE_FRAME_NODE_DEFAULT_PROPS, WEAVE_FRAME_NODE_TYPE, WEAVE_GRID_DEFAULT_COLOR, WEAVE_GRID_DEFAULT_DOT_MAX_DOTS_PER_AXIS, WEAVE_GRID_DEFAULT_MAJOR_DOT_RATIO, WEAVE_GRID_DEFAULT_MAJOR_EVERY, WEAVE_GRID_DEFAULT_MAJOR_LINE_RATIO, WEAVE_GRID_DEFAULT_ORIGIN_COLOR, WEAVE_GRID_DEFAULT_RADIUS, WEAVE_GRID_DEFAULT_SIZE, WEAVE_GRID_DEFAULT_STROKE, WEAVE_GRID_DEFAULT_TYPE, WEAVE_GRID_LAYER_ID, WEAVE_GRID_TYPES, WEAVE_GROUP_NODE_TYPE, WEAVE_IMAGES_TOOL_ACTION_NAME, WEAVE_IMAGES_TOOL_DEFAULT_CONFIG, WEAVE_IMAGES_TOOL_STATE, WEAVE_IMAGES_TOOL_UPLOAD_TYPE, WEAVE_IMAGE_CROP_ANCHOR_POSITION, WEAVE_IMAGE_CROP_END_TYPE, WEAVE_IMAGE_DEFAULT_CONFIG, WEAVE_IMAGE_NODE_TYPE, WEAVE_IMAGE_TOOL_ACTION_NAME, WEAVE_IMAGE_TOOL_CONFIG_DEFAULT, WEAVE_IMAGE_TOOL_STATE, WEAVE_IMAGE_TOOL_UPLOAD_TYPE, WEAVE_LAYER_NODE_TYPE, WEAVE_LINE_NODE_DEFAULT_CONFIG, WEAVE_LINE_NODE_TYPE, WEAVE_MEASURE_NODE_DEFAULT_CONFIG, WEAVE_MEASURE_NODE_TYPE, WEAVE_MEASURE_TOOL_DEFAULT_CONFIG, WEAVE_NODES_DISTANCE_SNAPPING_PLUGIN_KEY, WEAVE_NODES_EDGE_SNAPPING_PLUGIN_KEY, WEAVE_NODES_MULTI_SELECTION_FEEDBACK_PLUGIN_DEFAULT_CONFIG, WEAVE_NODES_MULTI_SELECTION_FEEDBACK_PLUGIN_KEY, WEAVE_NODES_MULTI_SELECTION_FEEDBACK_PLUGIN_LAYER_ID, WEAVE_NODES_SELECTION_DEFAULT_CONFIG, WEAVE_NODES_SELECTION_KEY, WEAVE_NODES_SELECTION_LAYER_ID, WEAVE_RECTANGLE_NODE_TYPE, WEAVE_REGULAR_POLYGON_NODE_TYPE, WEAVE_STAGE_DEFAULT_MODE, WEAVE_STAGE_DROP_AREA_KEY, WEAVE_STAGE_GRID_PLUGIN_KEY, WEAVE_STAGE_IMAGE_CROPPING_MODE, WEAVE_STAGE_KEYBOARD_MOVE_DEFAULT_CONFIG, WEAVE_STAGE_KEYBOARD_MOVE_KEY, WEAVE_STAGE_MINIMAP_KEY, WEAVE_STAGE_NODE_TYPE, WEAVE_STAGE_PANNING_DEFAULT_CONFIG, WEAVE_STAGE_PANNING_KEY, WEAVE_STAGE_PANNING_THROTTLE_MS, WEAVE_STAGE_TEXT_EDITION_MODE, WEAVE_STAR_NODE_TYPE, WEAVE_STROKE_NODE_DEFAULT_CONFIG, WEAVE_STROKE_NODE_TYPE, WEAVE_STROKE_SINGLE_NODE_DEFAULT_CONFIG, WEAVE_STROKE_SINGLE_NODE_TIP_SIDE, WEAVE_STROKE_SINGLE_NODE_TIP_TYPE, WEAVE_STROKE_SINGLE_NODE_TYPE, WEAVE_STROKE_TOOL_ACTION_NAME, WEAVE_STROKE_TOOL_ACTION_NAME_ALIASES, WEAVE_STROKE_TOOL_DEFAULT_CONFIG, WEAVE_STROKE_TOOL_STATE, WEAVE_TEXT_NODE_DEFAULT_CONFIG, WEAVE_TEXT_NODE_TYPE, WEAVE_USERS_POINTERS_CONFIG_DEFAULT_PROPS, WEAVE_USERS_POINTERS_KEY, WEAVE_USERS_PRESENCE_CONFIG_DEFAULT_PROPS, WEAVE_USERS_PRESENCE_PLUGIN_KEY, WEAVE_USERS_SELECTION_KEY, WEAVE_USER_POINTER_KEY, WEAVE_USER_PRESENCE_KEY, WEAVE_USER_SELECTION_KEY, WEAVE_VIDEO_DEFAULT_CONFIG, WEAVE_VIDEO_NODE_TYPE, Weave, WeaveAction, WeaveAlignNodesToolAction, WeaveArrowNode, WeaveArrowToolAction, WeaveBrushToolAction, WeaveCommentNode, WeaveCommentToolAction, WeaveCommentsRendererPlugin, WeaveConnectedUsersPlugin, WeaveConnectorNode, WeaveConnectorToolAction, WeaveContextMenuPlugin, WeaveCopyPasteNodesPlugin, WeaveEllipseNode, WeaveEllipseToolAction, WeaveEraserToolAction, WeaveExportNodesToolAction, WeaveExportStageToolAction, WeaveFitToScreenToolAction, WeaveFitToSelectionToolAction, WeaveFrameNode, WeaveFrameToolAction, WeaveGroupNode, WeaveImageNode, WeaveImageToolAction, WeaveImagesToolAction, WeaveLayerNode, WeaveLineNode, WeaveLineToolAction, WeaveMeasureNode, WeaveMeasureToolAction, WeaveMoveToolAction, WeaveNode, WeaveNodesDistanceSnappingPlugin, WeaveNodesEdgeSnappingPlugin, WeaveNodesMultiSelectionFeedbackPlugin, WeaveNodesSelectionPlugin, WeavePenToolAction, WeavePlugin, WeaveRectangleNode, WeaveRectangleToolAction, WeaveRegularPolygonNode, WeaveRegularPolygonToolAction, WeaveRenderer, WeaveSelectionToolAction, WeaveStageDropAreaPlugin, WeaveStageGridPlugin, WeaveStageKeyboardMovePlugin, WeaveStageMinimapPlugin, WeaveStageNode, WeaveStagePanningPlugin, WeaveStageResizePlugin, WeaveStageZoomPlugin, WeaveStarNode, WeaveStarToolAction, WeaveStore, WeaveStrokeNode, WeaveStrokeSingleNode, WeaveStrokeToolAction, WeaveTextNode, WeaveTextToolAction, WeaveUsersPointersPlugin, WeaveUsersPresencePlugin, WeaveUsersSelectionPlugin, WeaveVideoNode, WeaveVideoToolAction, WeaveZoomInToolAction, WeaveZoomOutToolAction, canComposite, clearContainerTargets, containerOverCursor, containsNodeDeep, defaultInitialState, downscaleImageFile, downscaleImageFromURL, getBoundingBox, getDownscaleRatio, getExportBoundingBox, getImageSizeFromFile, getJSONFromYjsBinary, getPositionRelativeToContainerOnPosition, getSelectedNodesMetadata, getStageClickPoint, getTargetAndSkipNodes, getTargetedNode, getTopmostShadowHost, getVisibleNodes, getVisibleNodesInViewport, hasFrames, hasImages, intersectArrays, isArray, isIOS, isInShadowDOM, isNodeInSelection, isObject, isServer, loadImageSource, mapJsonToYjsArray, mapJsonToYjsElements, mapJsonToYjsMap, memoize, mergeExceptArrays, moveNodeToContainer, moveNodeToContainerNT, resetScale, weavejsToYjsBinary };