@inditextech/weave-sdk 3.1.0 → 3.2.0-SNAPSHOT.112.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")) {
@@ -17923,7 +17925,7 @@ const getPositionRelativeToContainerOnPosition = (instance) => {
17923
17925
  };
17924
17926
  const canComposite = (node) => {
17925
17927
  const parent = node.getParent();
17926
- 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;
17927
17929
  };
17928
17930
  function mergeExceptArrays(object, source) {
17929
17931
  return (0, import_mergeWith.default)({}, object, source, (objValue, srcValue) => {
@@ -18791,7 +18793,11 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
18791
18793
  } else nodeHovered?.handleMouseout?.();
18792
18794
  });
18793
18795
  tr.on("mouseover", () => {
18794
- 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";
18795
18801
  });
18796
18802
  tr.on("mouseout", () => {
18797
18803
  this.instance.getStage().handleMouseover?.();
@@ -19514,7 +19520,7 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
19514
19520
  if (areNodesSelected) {
19515
19521
  stage.container().tabIndex = 1;
19516
19522
  stage.container().focus();
19517
- stage.container().style.cursor = "grab";
19523
+ stage.container().style.cursor = nodeTargeted.defineMousePointer() ?? "grab";
19518
19524
  }
19519
19525
  this.triggerSelectedNodesEvent();
19520
19526
  }
@@ -19788,32 +19794,25 @@ var WeaveCopyPasteNodesPlugin = class extends WeavePlugin {
19788
19794
  if (!this.enabled) return;
19789
19795
  }
19790
19796
  });
19791
- if (catcher) {
19792
- document.addEventListener("paste", async (e) => {
19793
- const dataList = e.clipboardData?.items;
19794
- if (!dataList) return;
19795
- if (dataList?.length > 0) this.sendExternalPasteEvent(dataList);
19796
- });
19797
- 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
- });
19816
- }
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
+ });
19817
19816
  }
19818
19817
  sendExternalPasteEvent(dataList, items) {
19819
19818
  const stage = this.instance.getStage();
@@ -20149,10 +20148,10 @@ const augmentKonvaNodeClass = (config) => {
20149
20148
  Konva.Node.prototype.dblClick = function() {};
20150
20149
  };
20151
20150
  var WeaveNode = class {
20152
- register(instance) {
20151
+ async register(instance) {
20153
20152
  this.instance = instance;
20154
20153
  this.logger = this.instance.getChildLogger(this.getNodeType());
20155
- this.onRegister();
20154
+ await this.onRegister();
20156
20155
  this.instance.getChildLogger(`node-${this.getNodeType()}`).debug(`Node with type [${this.getNodeType()}] registered`);
20157
20156
  return this;
20158
20157
  }
@@ -20198,6 +20197,11 @@ var WeaveNode = class {
20198
20197
  node.handleMouseout = function() {};
20199
20198
  node.handleSelectNode = function() {};
20200
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
+ };
20201
20205
  node.canBeHovered = function() {
20202
20206
  return true;
20203
20207
  };
@@ -20684,12 +20688,12 @@ var WeaveNode = class {
20684
20688
  }
20685
20689
  if (isNodeSelectionEnabled && this.isSelecting() && !this.isNodeSelected(realNode) && !this.isPasting() && isTargetable && !(isLocked || isMutexLocked) && stage.mode() === WEAVE_STAGE_DEFAULT_MODE) {
20686
20690
  showHover = true;
20687
- stage.container().style.cursor = "pointer";
20691
+ stage.container().style.cursor = realNode?.defineMousePointer() ?? "pointer";
20688
20692
  cancelBubble = true;
20689
20693
  }
20690
20694
  if (isNodeSelectionEnabled && this.isSelecting() && this.isNodeSelected(realNode) && !this.isPasting() && isTargetable && !(isLocked || isMutexLocked) && stage.mode() === WEAVE_STAGE_DEFAULT_MODE) {
20691
20695
  showHover = true;
20692
- stage.container().style.cursor = "grab";
20696
+ stage.container().style.cursor = realNode?.defineMousePointer() ?? "grab";
20693
20697
  cancelBubble = true;
20694
20698
  }
20695
20699
  if (!isTargetable) cancelBubble = true;
@@ -20719,7 +20723,9 @@ var WeaveNode = class {
20719
20723
  }
20720
20724
  };
20721
20725
  }
20722
- onRegister() {}
20726
+ async onRegister() {
20727
+ return Promise.resolve();
20728
+ }
20723
20729
  onAdd(nodeInstance) {}
20724
20730
  onDestroy(nodeInstance) {
20725
20731
  nodeInstance.destroy();
@@ -20875,6 +20881,9 @@ var WeaveAction = class {
20875
20881
  hasAliases() {
20876
20882
  return false;
20877
20883
  }
20884
+ setForceExecution(forceExecution) {
20885
+ this.forceExecution = forceExecution;
20886
+ }
20878
20887
  getAliases() {
20879
20888
  return [];
20880
20889
  }
@@ -21352,8 +21361,10 @@ var WeaveTargetingManager = class {
21352
21361
  };
21353
21362
  let measureContainer = mainLayer;
21354
21363
  let container = mainLayer;
21364
+ const utilityLayer = this.instance.getUtilityLayer();
21365
+ if (utilityLayer) utilityLayer.visible(false);
21355
21366
  const nodesSelection = this.instance.getPlugin("nodesSelection");
21356
- if (nodesSelection) nodesSelection.disable();
21367
+ if (nodesSelection) nodesSelection.getTransformer().visible(false);
21357
21368
  const dummyRect = new Konva.Rect({
21358
21369
  width: 10,
21359
21370
  height: 10,
@@ -21374,7 +21385,8 @@ var WeaveTargetingManager = class {
21374
21385
  x: 0,
21375
21386
  y: 0
21376
21387
  };
21377
- if (nodesSelection) nodesSelection.enable();
21388
+ if (utilityLayer) utilityLayer.visible(true);
21389
+ if (nodesSelection) nodesSelection.getTransformer().visible(true);
21378
21390
  dummyRect.destroy();
21379
21391
  return {
21380
21392
  mousePoint: relativeMousePointer,
@@ -21778,13 +21790,13 @@ var WeaveStateManager = class {
21778
21790
  updateNodes(nodes) {
21779
21791
  for (const node of nodes) this.updateNode(node);
21780
21792
  }
21781
- stateTransactional(callback) {
21793
+ stateTransactional(callback, origin) {
21782
21794
  const state = this.instance.getStore().getState();
21783
21795
  const doc = getYjsDoc(state);
21784
- const userId = this.instance.getStore().getUser().id;
21796
+ const transactionOrigin = origin ?? this.instance.getStore().getUser().id;
21785
21797
  doc.transact(() => {
21786
21798
  callback();
21787
- }, userId);
21799
+ }, transactionOrigin);
21788
21800
  }
21789
21801
  removeNode(node) {
21790
21802
  const state = this.instance.getStore().getState();
@@ -21901,25 +21913,24 @@ var WeaveRegisterManager = class {
21901
21913
  plugin.register(this.instance);
21902
21914
  this.plugins[pluginName] = plugin;
21903
21915
  }
21904
- registerNodesHandlers() {
21916
+ async registerNodesHandlers() {
21905
21917
  const config = this.instance.getConfiguration();
21906
- if (config.nodes) for (const node of config.nodes) this.registerNodeHandler(node);
21918
+ if (config.nodes) for (const node of config.nodes) await this.registerNodeHandler(node);
21907
21919
  this.logger.info(`Nodes handlers registered`);
21908
21920
  }
21909
- registerNodeHandler(node) {
21921
+ async registerNodeHandler(node) {
21910
21922
  const nodeType = node.getNodeType();
21911
21923
  if (this.nodesHandlers[nodeType]) {
21912
21924
  const msg = `Node handler with type [${nodeType}] already exists`;
21913
21925
  this.logger.error(msg);
21914
21926
  throw new Error(msg);
21915
21927
  }
21916
- node.register(this.instance);
21928
+ await node.register(this.instance);
21917
21929
  this.nodesHandlers[nodeType] = node;
21918
21930
  }
21919
21931
  registerActionsHandlers() {
21920
21932
  const config = this.instance.getConfiguration();
21921
21933
  if (config.actions) for (const action of config.actions) this.registerActionHandler(action);
21922
- this.logger.info(`Actions handlers registered`);
21923
21934
  }
21924
21935
  registerActionHandler(action) {
21925
21936
  const actionName = action.getName();
@@ -21946,7 +21957,7 @@ var WeaveRegisterManager = class {
21946
21957
 
21947
21958
  //#endregion
21948
21959
  //#region package.json
21949
- var version = "3.1.0";
21960
+ var version = "3.2.0-SNAPSHOT.112.1";
21950
21961
 
21951
21962
  //#endregion
21952
21963
  //#region src/managers/setup.ts
@@ -22086,14 +22097,15 @@ var WeaveActionsManager = class {
22086
22097
  getActiveAction() {
22087
22098
  return this.activeAction;
22088
22099
  }
22089
- triggerAction(actionName, params) {
22100
+ triggerAction(actionName, params, forceExecution = false) {
22090
22101
  const actionsHandlers = this.instance.getActionsHandlers();
22091
22102
  if (typeof actionName === "undefined") throw new Error("Action name is required");
22092
22103
  if (actionName && !actionsHandlers[actionName]) throw new Error(`Action handler with name [${actionName}] not registered`);
22093
- if (typeof this.activeAction !== "undefined") this.cancelAction(this.activeAction);
22094
- this.activeAction = actionName;
22104
+ if (this.activeAction !== void 0 && !forceExecution) this.cancelAction(this.activeAction);
22105
+ if (!forceExecution) this.activeAction = actionName;
22106
+ actionsHandlers[actionName].setForceExecution(forceExecution);
22095
22107
  const payload = actionsHandlers[actionName].trigger(this.cancelActionCallback(actionName), params);
22096
- this.instance.emitEvent("onActiveActionChange", this.activeAction);
22108
+ if (!forceExecution) this.instance.emitEvent("onActiveActionChange", this.activeAction);
22097
22109
  return payload;
22098
22110
  }
22099
22111
  updatePropsAction(actionName, props) {
@@ -22593,7 +22605,7 @@ var WeaveMutexManager = class {
22593
22605
  };
22594
22606
 
22595
22607
  //#endregion
22596
- //#region src/utils/watch-map.ts
22608
+ //#region src/internal-utils/watch-map.ts
22597
22609
  function watchMap(onChange, map = new Map()) {
22598
22610
  const handler = { get(target, prop, receiver) {
22599
22611
  if (prop === "set") return (key, value$1) => {
@@ -22648,14 +22660,13 @@ var WeaveAsyncManager = class {
22648
22660
  this.asyncElements = watchMap(() => {
22649
22661
  this.instance.emitEvent("onAsyncElementChange");
22650
22662
  }, new Map());
22651
- this.instance.addEventListener("onRoomLoaded", (isRoomLoaded) => {
22652
- if (!isRoomLoaded) return;
22653
- const roomHasResourcesToLoad = this.roomHasResourcesToLoad();
22654
- if (!roomHasResourcesToLoad && !this.asyncElementsLoadedEventEmitted) {
22655
- this.instance.emitEvent("onAsyncElementsLoaded");
22656
- this.asyncElementsLoadedEventEmitted = true;
22657
- }
22658
- });
22663
+ }
22664
+ checkForAsyncElements(elements) {
22665
+ const amountAsyncResourcesExtracted = this.extractAsyncResources(elements);
22666
+ if (amountAsyncResourcesExtracted === 0 && !this.asyncElementsLoadedEventEmitted) {
22667
+ this.instance.emitEvent("onAsyncElementsLoaded");
22668
+ this.asyncElementsLoadedEventEmitted = true;
22669
+ }
22659
22670
  }
22660
22671
  extractAsyncElements(state) {
22661
22672
  const asyncElements = [];
@@ -22671,11 +22682,20 @@ var WeaveAsyncManager = class {
22671
22682
  } else for (const element of Object.values(state.weave)) traverse(element);
22672
22683
  return asyncElements;
22673
22684
  }
22674
- roomHasResourcesToLoad() {
22685
+ extractAsyncResources(elements) {
22675
22686
  const roomData = this.instance.getStore().getState();
22676
- const jsonRoomData = JSON.parse(JSON.stringify(roomData));
22687
+ let jsonRoomData = JSON.parse(JSON.stringify(roomData));
22688
+ if (elements) jsonRoomData = elements;
22677
22689
  const asyncElements = this.extractAsyncElements(jsonRoomData);
22678
- return asyncElements.length > 0;
22690
+ for (const element of asyncElements) {
22691
+ const elementId = element.props?.id;
22692
+ if (!elementId) continue;
22693
+ if (!this.asyncElements.has(elementId)) this.asyncElements.set(elementId, {
22694
+ type: element.type,
22695
+ status: WEAVE_ASYNC_STATUS.NOT_LOADED
22696
+ });
22697
+ }
22698
+ return asyncElements.length;
22679
22699
  }
22680
22700
  asyncElementsLoaded() {
22681
22701
  return [...this.asyncElements.values()].every((el) => el.status === WEAVE_ASYNC_STATUS.LOADED);
@@ -22910,7 +22930,7 @@ var Weave = class {
22910
22930
  this.emitEvent("onRoomLoaded", false);
22911
22931
  this.status = WEAVE_INSTANCE_STATUS.STARTING;
22912
22932
  this.emitEvent("onInstanceStatus", this.status);
22913
- this.registerManager.registerNodesHandlers();
22933
+ await this.registerManager.registerNodesHandlers();
22914
22934
  this.augmentKonvaStageClass();
22915
22935
  this.augmentKonvaNodeClass();
22916
22936
  this.registerManager.registerPlugins();
@@ -23121,8 +23141,8 @@ var Weave = class {
23121
23141
  getActiveAction() {
23122
23142
  return this.actionsManager.getActiveAction();
23123
23143
  }
23124
- triggerAction(actionName, params) {
23125
- return this.actionsManager.triggerAction(actionName, params);
23144
+ triggerAction(actionName, params, forceExecution = false) {
23145
+ return this.actionsManager.triggerAction(actionName, params, forceExecution);
23126
23146
  }
23127
23147
  getPropsAction(actionName) {
23128
23148
  return this.actionsManager.getPropsAction(actionName);
@@ -23154,9 +23174,10 @@ var Weave = class {
23154
23174
  return this.stateManager.getNode(nodeKey);
23155
23175
  }
23156
23176
  addNode(node, parentId = "mainLayer", options = DEFAULT_ADD_NODE_OPTIONS) {
23177
+ const { origin,...restOptions } = options;
23157
23178
  this.stateTransactional(() => {
23158
- this.addNodeNT(node, parentId, options);
23159
- });
23179
+ this.addNodeNT(node, parentId, restOptions);
23180
+ }, origin);
23160
23181
  }
23161
23182
  addNodeNT(node, parentId = "mainLayer", options = DEFAULT_ADD_NODE_OPTIONS) {
23162
23183
  const { index, emitUserChangeEvent, overrideUserChangeType } = mergeExceptArrays(DEFAULT_ADD_NODE_OPTIONS, options);
@@ -23177,9 +23198,10 @@ var Weave = class {
23177
23198
  }
23178
23199
  }
23179
23200
  updateNode(node, options = DEFAULT_UPDATE_NODE_OPTIONS) {
23201
+ const { origin,...restOptions } = options;
23180
23202
  this.stateTransactional(() => {
23181
- this.updateNodeNT(node, options);
23182
- });
23203
+ this.updateNodeNT(node, restOptions);
23204
+ }, origin);
23183
23205
  }
23184
23206
  updateNodeNT(node, options = DEFAULT_UPDATE_NODE_OPTIONS) {
23185
23207
  const { emitUserChangeEvent } = mergeExceptArrays(DEFAULT_UPDATE_NODE_OPTIONS, options);
@@ -23197,9 +23219,10 @@ var Weave = class {
23197
23219
  }
23198
23220
  }
23199
23221
  updateNodes(nodes, options = DEFAULT_UPDATE_NODE_OPTIONS) {
23222
+ const { origin,...restOptions } = options;
23200
23223
  this.stateTransactional(() => {
23201
- this.updateNodesNT(nodes, options);
23202
- });
23224
+ this.updateNodesNT(nodes, restOptions);
23225
+ }, origin);
23203
23226
  }
23204
23227
  updateNodesNT(nodes, options = DEFAULT_UPDATE_NODE_OPTIONS) {
23205
23228
  const { emitUserChangeEvent } = mergeExceptArrays(DEFAULT_UPDATE_NODE_OPTIONS, options);
@@ -23223,9 +23246,10 @@ var Weave = class {
23223
23246
  }
23224
23247
  }
23225
23248
  removeNode(node, options = DEFAULT_REMOVE_NODE_OPTIONS) {
23249
+ const { origin,...restOptions } = options;
23226
23250
  this.stateTransactional(() => {
23227
- this.removeNodeNT(node, options);
23228
- });
23251
+ this.removeNodeNT(node, restOptions);
23252
+ }, origin);
23229
23253
  }
23230
23254
  removeNodeNT(node, options = DEFAULT_REMOVE_NODE_OPTIONS) {
23231
23255
  const { emitUserChangeEvent } = mergeExceptArrays(DEFAULT_REMOVE_NODE_OPTIONS, options);
@@ -23257,9 +23281,10 @@ var Weave = class {
23257
23281
  if (selectionPlugin) selectionPlugin.setSelectedNodes([]);
23258
23282
  }
23259
23283
  removeNodes(nodes, options = DEFAULT_REMOVE_NODE_OPTIONS) {
23284
+ const { origin,...restOptions } = options;
23260
23285
  this.stateTransactional(() => {
23261
- this.removeNodesNT(nodes, options);
23262
- });
23286
+ this.removeNodesNT(nodes, restOptions);
23287
+ }, origin);
23263
23288
  }
23264
23289
  removeNodesNT(nodes, options = DEFAULT_REMOVE_NODE_OPTIONS) {
23265
23290
  for (const node of nodes) this.removeNodeNT(node, options);
@@ -23267,9 +23292,10 @@ var Weave = class {
23267
23292
  if (selectionPlugin) selectionPlugin.setSelectedNodes([]);
23268
23293
  }
23269
23294
  zMoveNode(node, position, options = DEFAULT_MOVE_NODE_OPTIONS) {
23295
+ const { origin,...restOptions } = options;
23270
23296
  this.stateTransactional(() => {
23271
- this.zMoveNodeNT(node, position, options);
23272
- });
23297
+ this.zMoveNodeNT(node, position, restOptions);
23298
+ }, origin);
23273
23299
  }
23274
23300
  zMoveNodeNT(node, position, options = DEFAULT_MOVE_NODE_OPTIONS) {
23275
23301
  const { emitUserChangeEvent } = mergeExceptArrays(DEFAULT_MOVE_NODE_OPTIONS, options);
@@ -23323,8 +23349,8 @@ var Weave = class {
23323
23349
  getBoundingBox(nodes, config) {
23324
23350
  return getBoundingBox(nodes, config);
23325
23351
  }
23326
- stateTransactional(callback) {
23327
- this.stateManager.stateTransactional(callback);
23352
+ stateTransactional(callback, origin) {
23353
+ this.stateManager.stateTransactional(callback, origin);
23328
23354
  }
23329
23355
  moveUp(node) {
23330
23356
  this.zIndexManager.moveUp(node);
@@ -23488,6 +23514,9 @@ var Weave = class {
23488
23514
  nodeHandler.show(node);
23489
23515
  }
23490
23516
  }
23517
+ checkForAsyncElements(elements) {
23518
+ this.asyncManager.checkForAsyncElements(elements);
23519
+ }
23491
23520
  asyncElementsLoaded() {
23492
23521
  return this.asyncManager.asyncElementsLoaded();
23493
23522
  }
@@ -23558,7 +23587,93 @@ var Weave = class {
23558
23587
  };
23559
23588
 
23560
23589
  //#endregion
23561
- //#region src/utils/upscale.ts
23590
+ //#region src/utils/image.ts
23591
+ function loadImageSource(image, options) {
23592
+ return new Promise((resolve, reject) => {
23593
+ const { crossOrigin } = mergeExceptArrays({ crossOrigin: "anonymous" }, options);
23594
+ const reader = new FileReader();
23595
+ reader.onloadend = () => {
23596
+ const imageSource = Konva.Util.createImageElement();
23597
+ imageSource.crossOrigin = crossOrigin;
23598
+ imageSource.onerror = () => {
23599
+ reject();
23600
+ };
23601
+ imageSource.onload = async () => {
23602
+ resolve(imageSource);
23603
+ };
23604
+ imageSource.src = reader.result;
23605
+ };
23606
+ reader.onerror = () => {
23607
+ reject(new Error("Failed to read image file"));
23608
+ };
23609
+ reader.readAsDataURL(image);
23610
+ });
23611
+ }
23612
+ async function downscaleImageFile(file, ratio) {
23613
+ const bitmap = await createImageBitmap(file);
23614
+ const width = Math.round(bitmap.width * ratio);
23615
+ const height = Math.round(bitmap.height * ratio);
23616
+ const canvas = document.createElement("canvas");
23617
+ canvas.width = width;
23618
+ canvas.height = height;
23619
+ const ctx = canvas.getContext("2d");
23620
+ ctx.drawImage(bitmap, 0, 0, width, height);
23621
+ return new Promise((resolve) => {
23622
+ canvas.toBlob((blob) => resolve(blob), file.type, .9);
23623
+ });
23624
+ }
23625
+ function getImageSizeFromFile(file) {
23626
+ return new Promise((resolve, reject) => {
23627
+ const img = new Image();
23628
+ const url = URL.createObjectURL(file);
23629
+ img.onload = () => {
23630
+ resolve({
23631
+ width: img.naturalWidth,
23632
+ height: img.naturalHeight
23633
+ });
23634
+ URL.revokeObjectURL(url);
23635
+ };
23636
+ img.onerror = reject;
23637
+ img.src = url;
23638
+ });
23639
+ }
23640
+ function getDownscaleRatio(width, height, options) {
23641
+ const { maxWidth, maxHeight } = mergeExceptArrays({
23642
+ maxWidth: 200,
23643
+ maxHeight: 200
23644
+ }, options);
23645
+ const widthRatio = maxWidth / width;
23646
+ const heightRatio = maxHeight / height;
23647
+ return Math.min(widthRatio, heightRatio, 1);
23648
+ }
23649
+ const downscaleImageFromURL = (url, options) => {
23650
+ return new Promise((resolve, reject) => {
23651
+ const { type, crossOrigin, maxWidth, maxHeight } = mergeExceptArrays({
23652
+ type: "image/png",
23653
+ crossOrigin: "anonymous",
23654
+ maxWidth: 200,
23655
+ maxHeight: 200
23656
+ }, options);
23657
+ const img = new Image();
23658
+ img.crossOrigin = crossOrigin;
23659
+ img.onload = () => {
23660
+ const ratio = Math.min(maxWidth / img.width, maxHeight / img.height, 1);
23661
+ const width = Math.round(img.width * ratio);
23662
+ const height = Math.round(img.height * ratio);
23663
+ const canvas = document.createElement("canvas");
23664
+ canvas.width = width;
23665
+ canvas.height = height;
23666
+ const ctx = canvas.getContext("2d");
23667
+ ctx.drawImage(img, 0, 0, width, height);
23668
+ resolve(canvas.toDataURL(type));
23669
+ };
23670
+ img.onerror = reject;
23671
+ img.src = url;
23672
+ });
23673
+ };
23674
+
23675
+ //#endregion
23676
+ //#region src/internal-utils/upscale.ts
23562
23677
  const setupUpscaleStage = (instance, stage) => {
23563
23678
  const config = instance.getConfiguration();
23564
23679
  const doUpscale = config.performance?.upscale?.enabled ?? false;
@@ -23992,7 +24107,7 @@ const WEAVE_LINE_NODE_DEFAULT_CONFIG = { snapAngles: {
23992
24107
  } };
23993
24108
 
23994
24109
  //#endregion
23995
- //#region src/utils/greedy-snapper.ts
24110
+ //#region src/internal-utils/greedy-snapper.ts
23996
24111
  var GreedySnapper = class {
23997
24112
  snappedAngle = null;
23998
24113
  constructor(config) {
@@ -25008,8 +25123,16 @@ const WEAVE_IMAGE_CROP_ANCHOR_POSITION = {
25008
25123
  };
25009
25124
  const WEAVE_IMAGE_DEFAULT_CONFIG = {
25010
25125
  performance: { cache: { enabled: false } },
25011
- style: { placeholder: { fill: "#aaaaaa" } },
25126
+ style: {
25127
+ placeholder: { fill: "#aaaaaa" },
25128
+ cursor: { loading: "wait" }
25129
+ },
25130
+ imageLoading: {
25131
+ maxRetryAttempts: 15,
25132
+ retryDelayMs: 2e3
25133
+ },
25012
25134
  crossOrigin: "anonymous",
25135
+ useFallbackImage: true,
25013
25136
  cropMode: {
25014
25137
  gridLines: { enabled: true },
25015
25138
  overlay: { fill: "rgba(0,0,0,0.2)" },
@@ -25579,8 +25702,10 @@ var WeaveImageCrop = class WeaveImageCrop {
25579
25702
  var WeaveImageNode = class extends WeaveNode {
25580
25703
  imageBitmapCache = {};
25581
25704
  imageSource = {};
25705
+ imageFallback = {};
25582
25706
  imageState = {};
25583
- imageIconSource = null;
25707
+ imageTryoutAttempts = {};
25708
+ imageTryoutIds = {};
25584
25709
  nodeType = WEAVE_IMAGE_NODE_TYPE;
25585
25710
  constructor(params) {
25586
25711
  super();
@@ -25590,14 +25715,50 @@ var WeaveImageNode = class extends WeaveNode {
25590
25715
  y: 0,
25591
25716
  time: 0
25592
25717
  };
25593
- this.lastTapTime = 0;
25594
25718
  this.config = mergeExceptArrays(WEAVE_IMAGE_DEFAULT_CONFIG, config);
25595
25719
  this.imageCrop = null;
25720
+ this.imageBitmapCache = {};
25721
+ this.imageSource = {};
25722
+ this.imageState = {};
25723
+ this.imageTryoutIds = {};
25724
+ this.imageTryoutAttempts = {};
25725
+ this.imageFallback = {};
25726
+ }
25727
+ preloadCursors() {
25728
+ return new Promise((resolve) => {
25729
+ (async () => {
25730
+ const cursors = Object.keys(this.config.style.cursor);
25731
+ const cursorUrls = [];
25732
+ const cursorFallback = { loading: "wait" };
25733
+ for (const cursorKey of cursors) {
25734
+ const cursorValue = this.config.style.cursor[cursorKey];
25735
+ const { preload, cursor } = this.extractCursorUrl(cursorValue, cursorFallback[cursorKey]);
25736
+ if (preload) cursorUrls.push({ src: cursor });
25737
+ }
25738
+ if (cursorUrls.length > 0) {
25739
+ const promises = cursorUrls.map(({ src }) => {
25740
+ new Promise((resolveInt, rejectInt) => {
25741
+ const img = Konva.Util.createImageElement();
25742
+ img.onload = () => {
25743
+ resolveInt();
25744
+ };
25745
+ img.onerror = () => {
25746
+ rejectInt();
25747
+ };
25748
+ img.src = src;
25749
+ });
25750
+ });
25751
+ await Promise.allSettled(promises);
25752
+ }
25753
+ resolve();
25754
+ })();
25755
+ });
25596
25756
  }
25597
25757
  getConfiguration() {
25598
25758
  return this.config;
25599
25759
  }
25600
- onRegister() {
25760
+ async onRegister() {
25761
+ await this.preloadCursors();
25601
25762
  this.logger.info(`image caching enabled: ${this.config.performance.cache.enabled}`);
25602
25763
  }
25603
25764
  triggerCrop(imageNode, options) {
@@ -25673,6 +25834,12 @@ var WeaveImageNode = class extends WeaveNode {
25673
25834
  cropping: false
25674
25835
  });
25675
25836
  this.setupDefaultNodeAugmentation(image);
25837
+ image.defineMousePointer = () => {
25838
+ if (this.imageState[id]?.status === "loading") return this.config.style.cursor.loading;
25839
+ const selectedNodes = this.getSelectionPlugin()?.getSelectedNodes() ?? [];
25840
+ if (this.isSelecting() && selectedNodes.includes(image)) return "grab";
25841
+ return "pointer";
25842
+ };
25676
25843
  image.movedToContainer = () => {
25677
25844
  const stage = this.instance.getStage();
25678
25845
  const image$1 = stage.findOne(`#${id}`);
@@ -25751,8 +25918,8 @@ var WeaveImageNode = class extends WeaveNode {
25751
25918
  image.dblClick = () => {
25752
25919
  if (this.imageState[id]?.loaded && !this.imageState[id]?.error) this.config.onDblClick?.(this, image);
25753
25920
  };
25754
- if (this.imageSource[id]) {
25755
- imagePlaceholder.destroy();
25921
+ if (this.imageSource[id] && imageProps.imageURL) {
25922
+ imagePlaceholder?.destroy();
25756
25923
  const imageSource = this.imageSource[id];
25757
25924
  internalImage.setAttrs({
25758
25925
  image: imageSource,
@@ -25777,13 +25944,14 @@ var WeaveImageNode = class extends WeaveNode {
25777
25944
  height: sourceImageHeight
25778
25945
  });
25779
25946
  this.imageState[id] = {
25947
+ status: "loaded",
25780
25948
  loaded: true,
25781
25949
  error: false
25782
25950
  };
25783
25951
  this.updateImageCrop(image);
25784
25952
  } else {
25785
25953
  this.updatePlaceholderSize(image, imagePlaceholder);
25786
- this.loadImage(imageProps, image);
25954
+ this.loadImage(imageProps, image, true);
25787
25955
  }
25788
25956
  if (this.config.performance.cache.enabled) image.on("transformend", () => {
25789
25957
  this.cacheNode(image);
@@ -26014,7 +26182,7 @@ var WeaveImageNode = class extends WeaveNode {
26014
26182
  scaleY: 1,
26015
26183
  rotation: 0,
26016
26184
  visible: true,
26017
- fill: "#ccccccff",
26185
+ fill: this.config.style.placeholder.fill,
26018
26186
  strokeWidth: 0,
26019
26187
  draggable: false,
26020
26188
  zIndex: 0
@@ -26048,7 +26216,7 @@ var WeaveImageNode = class extends WeaveNode {
26048
26216
  scaleY: 1,
26049
26217
  rotation: 0,
26050
26218
  visible: true,
26051
- fill: "#ccccccff",
26219
+ fill: this.config.style.placeholder.fill,
26052
26220
  strokeWidth: 0,
26053
26221
  draggable: false,
26054
26222
  zIndex: 0
@@ -26090,59 +26258,113 @@ var WeaveImageNode = class extends WeaveNode {
26090
26258
  }
26091
26259
  this.cacheNode(nodeInstance);
26092
26260
  }
26093
- preloadImage(imageId, imageURL, { onLoad, onError }) {
26261
+ preloadFallbackImage(imageId, imageURL, { onLoad, onError }) {
26262
+ const imageURLToLoad = imageURL ?? "http://localhost/false-image";
26263
+ this.imageFallback[imageId] = Konva.Util.createImageElement();
26264
+ this.imageFallback[imageId].crossOrigin = this.config.crossOrigin;
26265
+ this.imageFallback[imageId].onerror = (error) => {
26266
+ this.imageState[imageId] = {
26267
+ status: "error-fallback",
26268
+ loaded: false,
26269
+ error: true
26270
+ };
26271
+ onError(error);
26272
+ };
26273
+ this.imageFallback[imageId].onload = async () => {
26274
+ this.imageState[imageId] = {
26275
+ status: "loading",
26276
+ loaded: true,
26277
+ error: false
26278
+ };
26279
+ onLoad();
26280
+ };
26281
+ this.imageState[imageId] = {
26282
+ status: "loading",
26283
+ loaded: false,
26284
+ error: false
26285
+ };
26286
+ try {
26287
+ this.imageFallback[imageId].src = imageURLToLoad;
26288
+ } catch (ex) {
26289
+ console.error(ex);
26290
+ }
26291
+ }
26292
+ preloadImage(imageId, imageURL, { onLoad, onError }, loadingTryout = false) {
26293
+ const imageURLToLoad = imageURL ?? "http://localhost/false-image";
26094
26294
  this.imageSource[imageId] = Konva.Util.createImageElement();
26095
26295
  this.imageSource[imageId].crossOrigin = this.config.crossOrigin;
26096
26296
  this.imageSource[imageId].onerror = (error) => {
26097
- this.imageState[imageId] = {
26297
+ if (!loadingTryout) this.imageState[imageId] = {
26298
+ status: "error",
26098
26299
  loaded: false,
26099
26300
  error: true
26100
26301
  };
26101
26302
  delete this.imageSource[imageId];
26102
- delete this.imageState[imageId];
26103
26303
  onError(error);
26104
26304
  };
26105
26305
  this.imageSource[imageId].onload = async () => {
26306
+ const stage = this.instance.getStage();
26307
+ stage.container().style.cursor = "pointer";
26106
26308
  this.imageState[imageId] = {
26309
+ status: "loaded",
26107
26310
  loaded: true,
26108
26311
  error: false
26109
26312
  };
26110
26313
  onLoad();
26111
26314
  };
26112
- this.imageState[imageId] = {
26315
+ if (this.imageState[imageId]) this.imageState[imageId].status = "loading";
26316
+ else this.imageState[imageId] = {
26317
+ status: "loading",
26113
26318
  loaded: false,
26114
26319
  error: false
26115
26320
  };
26116
26321
  try {
26117
- if (imageURL) this.imageSource[imageId].src = imageURL;
26322
+ this.imageSource[imageId].src = imageURLToLoad;
26118
26323
  } catch (ex) {
26119
26324
  console.error(ex);
26120
26325
  }
26121
26326
  }
26122
- loadImage(params, image) {
26327
+ loadImage(params, image, useFallback = false, loadTryout = false) {
26123
26328
  const imageProps = params;
26124
26329
  const { id } = imageProps;
26125
26330
  const imagePlaceholder = image.findOne(`#${id}-placeholder`);
26126
26331
  const internalImage = image.findOne(`#${id}-image`);
26127
- const realImageURL = this.config.urlTransformer?.(imageProps.imageURL ?? "", image) ?? imageProps.imageURL;
26332
+ let realImageURL = this.config.urlTransformer?.(imageProps.imageURL ?? "", image) ?? imageProps.imageURL;
26333
+ let preloadFunction = this.preloadImage.bind(this);
26334
+ const loadFallback = useFallback && imageProps.imageFallback && this.config.useFallbackImage;
26335
+ if (loadFallback) {
26336
+ preloadFunction = this.preloadFallbackImage.bind(this);
26337
+ realImageURL = imageProps.imageFallback;
26338
+ }
26128
26339
  this.loadAsyncElement(id);
26129
- this.preloadImage(id, realImageURL ?? "", {
26340
+ preloadFunction(id, realImageURL ?? "", {
26130
26341
  onLoad: () => {
26131
- if (image && imagePlaceholder && internalImage) {
26342
+ if (useFallback) this.imageTryoutIds[id] = setTimeout(() => {
26343
+ const node = this.instance.getStage().findOne(`#${id}`);
26344
+ if (node) {
26345
+ this.imageTryoutAttempts[id] = (this.imageTryoutAttempts[id] ?? 0) + 1;
26346
+ this.loadImage(node.getAttrs(), node, false, true);
26347
+ }
26348
+ }, this.config.imageLoading.retryDelayMs);
26349
+ if (useFallback && loadTryout && this.imageTryoutIds[id]) {
26350
+ clearTimeout(this.imageTryoutIds[id]);
26351
+ delete this.imageTryoutIds[id];
26352
+ }
26353
+ if (image && internalImage) {
26132
26354
  image.setAttrs({
26133
26355
  width: imageProps.width ? imageProps.width : this.imageSource[id].width,
26134
26356
  height: imageProps.height ? imageProps.height : this.imageSource[id].height
26135
26357
  });
26136
- imagePlaceholder.destroy();
26137
- const imageSource = this.imageSource[id];
26358
+ imagePlaceholder?.destroy();
26359
+ const imageSource = loadFallback ? this.imageFallback[id] : this.imageSource[id];
26138
26360
  internalImage.setAttrs({
26139
26361
  width: imageProps.width ? imageProps.width : this.imageSource[id].width,
26140
26362
  height: imageProps.height ? imageProps.height : this.imageSource[id].height,
26141
26363
  image: imageSource,
26142
26364
  visible: true
26143
26365
  });
26144
- let sourceImageWidth = this.imageSource[id].width;
26145
- let sourceImageHeight = this.imageSource[id].height;
26366
+ let sourceImageWidth = imageProps.width ? imageProps.width : this.imageSource[id].width;
26367
+ let sourceImageHeight = imageProps.height ? imageProps.height : this.imageSource[id].height;
26146
26368
  if (image.getAttrs().imageInfo) {
26147
26369
  sourceImageWidth = image.getAttrs().imageInfo.width;
26148
26370
  sourceImageHeight = image.getAttrs().imageInfo.height;
@@ -26161,7 +26383,8 @@ var WeaveImageNode = class extends WeaveNode {
26161
26383
  width: imageRect.width,
26162
26384
  height: imageRect.height
26163
26385
  });
26164
- this.imageState[id] = {
26386
+ if (!loadFallback) this.imageState[id] = {
26387
+ status: "loaded",
26165
26388
  loaded: true,
26166
26389
  error: false
26167
26390
  };
@@ -26171,40 +26394,45 @@ var WeaveImageNode = class extends WeaveNode {
26171
26394
  }
26172
26395
  },
26173
26396
  onError: (error) => {
26397
+ if (!this.config.useFallbackImage) this.imageTryoutIds[id] = setTimeout(() => {
26398
+ const node = this.instance.getStage().findOne(`#${id}`);
26399
+ if (node) {
26400
+ this.imageTryoutAttempts[id] = (this.imageTryoutAttempts[id] ?? 0) + 1;
26401
+ this.loadImage(node.getAttrs(), node, false, true);
26402
+ }
26403
+ }, this.config.imageLoading.retryDelayMs);
26404
+ if (loadTryout) {
26405
+ const tryoutAttempts = this.imageTryoutAttempts[id] ?? 0;
26406
+ if (tryoutAttempts < this.config.imageLoading.maxRetryAttempts) this.imageTryoutIds[id] = setTimeout(() => {
26407
+ const node = this.instance.getStage().findOne(`#${id}`);
26408
+ if (node) {
26409
+ this.imageTryoutAttempts[id] = tryoutAttempts + 1;
26410
+ this.loadImage(node.getAttrs(), node, false, true);
26411
+ }
26412
+ }, this.config.imageLoading.retryDelayMs);
26413
+ return;
26414
+ }
26415
+ if (this.config.useFallbackImage && !useFallback && !loadTryout && imageProps.imageFallback) {
26416
+ this.loadImage({ ...params }, image, true);
26417
+ return;
26418
+ }
26174
26419
  this.imageState[id] = {
26420
+ status: "error",
26175
26421
  loaded: false,
26176
26422
  error: true
26177
26423
  };
26178
- image.setAttrs({
26179
- image: void 0,
26180
- width: 100,
26181
- height: 100,
26182
- imageInfo: {
26183
- width: 100,
26184
- height: 100
26185
- },
26186
- uncroppedImage: {
26187
- width: 100,
26188
- height: 100
26189
- }
26190
- });
26424
+ image.setAttrs({ image: void 0 });
26191
26425
  this.resolveAsyncElement(id);
26192
26426
  console.error("Error loading image", realImageURL, error);
26193
26427
  imagePlaceholder?.setAttrs({ visible: true });
26194
26428
  internalImage?.setAttrs({ visible: false });
26195
26429
  this.cacheNode(image);
26196
26430
  }
26197
- });
26431
+ }, loadTryout);
26198
26432
  }
26199
26433
  updatePlaceholderSize(image, imagePlaceholder) {
26200
26434
  const imageAttrs = image.getAttrs();
26201
26435
  if (!this.imageState[imageAttrs.id ?? ""]?.loaded) return;
26202
- if (!imageAttrs.adding && imageAttrs.cropInfo) {
26203
- const actualScale = imageAttrs.uncroppedImage.width / imageAttrs.imageInfo.width;
26204
- const cropScale = imageAttrs.cropInfo ? imageAttrs.cropInfo.scaleX : actualScale;
26205
- imagePlaceholder.width(imageAttrs.cropSize.width * (actualScale / cropScale));
26206
- imagePlaceholder.height(imageAttrs.cropSize.height * (actualScale / cropScale));
26207
- }
26208
26436
  if (!imageAttrs.adding && !imageAttrs.cropInfo) {
26209
26437
  imagePlaceholder.width(imageAttrs.uncroppedImage.width);
26210
26438
  imagePlaceholder.height(imageAttrs.uncroppedImage.height);
@@ -26215,8 +26443,16 @@ var WeaveImageNode = class extends WeaveNode {
26215
26443
  const internalImage = image?.findOne(`#${imageAttrs.id}-image`);
26216
26444
  if (!this.imageState[imageAttrs.id ?? ""]?.loaded) return;
26217
26445
  if (image && internalImage && !imageAttrs.adding && imageAttrs.cropInfo && imageAttrs.uncroppedImage) {
26446
+ const imageId = imageAttrs.id ?? "";
26218
26447
  const originalImageInfo = imageAttrs.imageInfo;
26219
- const actualImageInfo = this.imageSource[imageAttrs.id ?? ""];
26448
+ let actualImageInfo = {
26449
+ width: this.imageSource[imageId]?.width ?? 0,
26450
+ height: this.imageSource[imageId]?.height ?? 0
26451
+ };
26452
+ if (actualImageInfo.width === 0 && actualImageInfo.height === 0 && this.imageFallback[imageId]) actualImageInfo = {
26453
+ width: this.imageFallback[imageId].width,
26454
+ height: this.imageFallback[imageId].height
26455
+ };
26220
26456
  const originalActualDiffScale = originalImageInfo ? actualImageInfo.width / originalImageInfo.width : 1;
26221
26457
  const actualScale = imageAttrs.uncroppedImage.width / imageAttrs.imageInfo.width;
26222
26458
  const cropScale = imageAttrs.cropInfo ? imageAttrs.cropInfo.scaleX : actualScale;
@@ -26245,6 +26481,9 @@ var WeaveImageNode = class extends WeaveNode {
26245
26481
  internalImage.height(imageAttrs.uncroppedImage.height);
26246
26482
  }
26247
26483
  }
26484
+ getFallbackImageSource(imageId) {
26485
+ return this.imageFallback[imageId];
26486
+ }
26248
26487
  getImageSource(imageId) {
26249
26488
  return this.imageSource[imageId];
26250
26489
  }
@@ -26296,6 +26535,71 @@ var WeaveImageNode = class extends WeaveNode {
26296
26535
  getIsAsync() {
26297
26536
  return true;
26298
26537
  }
26538
+ forceLoadImage(nodeInstance) {
26539
+ const nodeId = nodeInstance.getAttrs().id ?? "";
26540
+ const node = this.instance.getStage().findOne(`#${nodeId}`);
26541
+ if (this.imageTryoutIds[nodeId]) {
26542
+ clearTimeout(this.imageTryoutIds[nodeId]);
26543
+ delete this.imageTryoutIds[nodeId];
26544
+ }
26545
+ if (node) this.loadImage(node.getAttrs(), node, false, false);
26546
+ }
26547
+ onDestroy(nodeInstance) {
26548
+ const nodeId = nodeInstance.getAttrs().id ?? "";
26549
+ delete this.imageSource[nodeId];
26550
+ delete this.imageState[nodeId];
26551
+ delete this.imageTryoutAttempts[nodeId];
26552
+ delete this.imageFallback[nodeId];
26553
+ nodeInstance.destroy();
26554
+ }
26555
+ extractCursorUrl(cursor, fallback) {
26556
+ const lower = cursor.toLowerCase();
26557
+ const start = lower.indexOf("url(");
26558
+ if (start === -1) return {
26559
+ preload: false,
26560
+ cursor
26561
+ };
26562
+ let i = start + 4;
26563
+ const len = cursor.length;
26564
+ while (i < len && /\s/.test(cursor[i])) i++;
26565
+ let quote = null;
26566
+ if (cursor[i] === "\"" || cursor[i] === "'") {
26567
+ quote = cursor[i];
26568
+ i++;
26569
+ }
26570
+ let buf = "";
26571
+ for (; i < len; i++) {
26572
+ const ch = cursor[i];
26573
+ if (quote) {
26574
+ if (ch === quote) {
26575
+ i++;
26576
+ break;
26577
+ }
26578
+ buf += ch;
26579
+ } else {
26580
+ if (ch === ")") break;
26581
+ buf += ch;
26582
+ }
26583
+ }
26584
+ const url = buf.trim();
26585
+ if (!url) return {
26586
+ preload: false,
26587
+ cursor: fallback
26588
+ };
26589
+ if (!this.isAllowedUrl(url)) return {
26590
+ preload: false,
26591
+ cursor: fallback
26592
+ };
26593
+ return {
26594
+ preload: true,
26595
+ cursor: url
26596
+ };
26597
+ }
26598
+ isAllowedUrl(value) {
26599
+ if (/^https?:\/\//i.test(value)) return true;
26600
+ if (/^(javascript|data|blob|ftp):/i.test(value)) return false;
26601
+ return true;
26602
+ }
26299
26603
  };
26300
26604
 
26301
26605
  //#endregion
@@ -28659,7 +28963,7 @@ var WeaveVideoNode = class extends WeaveNode {
28659
28963
  videoIconGroup.x(videoWidth - videoIconGroupWidth - this.config.style.icon.external.paddingX);
28660
28964
  videoIconGroup.y(videoHeight - videoIconGroupHeight - this.config.style.icon.external.paddingY);
28661
28965
  const nodesSelectionPlugin = this.getNodeSelectionPlugin();
28662
- if (nodesSelectionPlugin) nodesSelectionPlugin.getTransformer().forceUpdate();
28966
+ if (nodesSelectionPlugin) nodesSelectionPlugin.getTransformer()?.forceUpdate();
28663
28967
  this.resolveAsyncElement(id);
28664
28968
  };
28665
28969
  }
@@ -29052,7 +29356,7 @@ var WeaveVideoNode = class extends WeaveNode {
29052
29356
  videoIconGroup.x(videoWidth - videoIconGroupWidth - this.config.style.icon.external.paddingX);
29053
29357
  videoIconGroup.y(videoHeight - videoIconGroupHeight - this.config.style.icon.external.paddingY);
29054
29358
  const nodesSelectionPlugin = this.getNodeSelectionPlugin();
29055
- if (nodesSelectionPlugin) nodesSelectionPlugin.getTransformer().forceUpdate();
29359
+ if (nodesSelectionPlugin) nodesSelectionPlugin.getTransformer()?.forceUpdate();
29056
29360
  }
29057
29361
  getNodeSelectionPlugin() {
29058
29362
  const nodesSelectionPlugin = this.instance.getPlugin("nodesSelection");
@@ -33019,14 +33323,19 @@ var WeaveBrushToolAction = class extends WeaveAction {
33019
33323
  });
33020
33324
  window.addEventListener("keydown", (e) => {
33021
33325
  if (e.code === "Enter" && this.instance.getActiveAction() === BRUSH_TOOL_ACTION_NAME) {
33326
+ e.stopPropagation();
33022
33327
  this.cancelAction();
33023
33328
  return;
33024
33329
  }
33025
33330
  if (e.code === "Space" && this.instance.getActiveAction() === BRUSH_TOOL_ACTION_NAME) {
33331
+ e.stopPropagation();
33026
33332
  this.isSpacePressed = true;
33027
33333
  return;
33028
33334
  }
33029
- if (e.code === "Escape" && this.instance.getActiveAction() === BRUSH_TOOL_ACTION_NAME) this.cancelAction();
33335
+ if (e.code === "Escape" && this.instance.getActiveAction() === BRUSH_TOOL_ACTION_NAME) {
33336
+ e.stopPropagation();
33337
+ this.cancelAction();
33338
+ }
33030
33339
  });
33031
33340
  const handlePointerDown = (e) => {
33032
33341
  if (this.state === BRUSH_TOOL_STATE.INACTIVE) return;
@@ -33353,42 +33662,62 @@ var WeaveTextToolAction = class extends WeaveAction {
33353
33662
 
33354
33663
  //#endregion
33355
33664
  //#region src/actions/image-tool/constants.ts
33356
- const IMAGE_TOOL_ACTION_NAME = "imageTool";
33357
- const IMAGE_TOOL_STATE = {
33665
+ const WEAVE_IMAGE_TOOL_ACTION_NAME = "imageTool";
33666
+ const WEAVE_IMAGE_TOOL_UPLOAD_TYPE = {
33667
+ ["FILE"]: "file",
33668
+ ["IMAGE_URL"]: "imageURL"
33669
+ };
33670
+ const WEAVE_IMAGE_TOOL_STATE = {
33358
33671
  ["IDLE"]: "idle",
33359
33672
  ["DEFINING_POSITION"]: "definingPosition",
33360
33673
  ["SELECTED_POSITION"]: "selectedPosition",
33361
33674
  ["ADDING"]: "adding",
33362
33675
  ["FINISHED"]: "finished"
33363
33676
  };
33364
- const IMAGE_TOOL_LOAD_FROM = {
33365
- ["DATAURL"]: "dataURL",
33366
- ["URL"]: "url"
33367
- };
33677
+ const WEAVE_IMAGE_TOOL_CONFIG_DEFAULT = { style: { cursor: {
33678
+ padding: 5,
33679
+ imageThumbnail: {
33680
+ width: 250,
33681
+ height: 250,
33682
+ shadowColor: "#aaaaaa",
33683
+ shadowBlur: 10,
33684
+ shadowOffset: {
33685
+ x: 2,
33686
+ y: 2
33687
+ },
33688
+ shadowOpacity: .5
33689
+ }
33690
+ } } };
33368
33691
 
33369
33692
  //#endregion
33370
33693
  //#region src/actions/image-tool/image-tool.ts
33371
33694
  var WeaveImageToolAction = class extends WeaveAction {
33372
33695
  initialized = false;
33373
33696
  initialCursor = null;
33374
- cursorPadding = 5;
33697
+ imageFile = null;
33698
+ imageURL = null;
33375
33699
  forceMainContainer = false;
33700
+ ignoreKeyboardEvents = false;
33701
+ ignorePointerEvents = false;
33702
+ uploadType = null;
33376
33703
  onPropsChange = void 0;
33377
33704
  update = void 0;
33378
- constructor() {
33705
+ constructor(params) {
33379
33706
  super();
33707
+ this.config = mergeExceptArrays(WEAVE_IMAGE_TOOL_CONFIG_DEFAULT, params?.config ?? {});
33380
33708
  this.pointers = new Map();
33381
33709
  this.initialized = false;
33382
- this.state = IMAGE_TOOL_STATE.IDLE;
33710
+ this.state = WEAVE_IMAGE_TOOL_STATE.IDLE;
33383
33711
  this.imageId = null;
33384
33712
  this.tempImageId = null;
33385
33713
  this.tempImageNode = null;
33386
33714
  this.container = void 0;
33387
33715
  this.imageURL = null;
33716
+ this.uploadType = null;
33388
33717
  this.clickPoint = null;
33389
33718
  }
33390
33719
  getName() {
33391
- return IMAGE_TOOL_ACTION_NAME;
33720
+ return WEAVE_IMAGE_TOOL_ACTION_NAME;
33392
33721
  }
33393
33722
  initProps() {
33394
33723
  return {
@@ -33402,14 +33731,15 @@ var WeaveImageToolAction = class extends WeaveAction {
33402
33731
  this.instance.addEventListener("onStageDrop", (e) => {
33403
33732
  const dragId = this.instance.getDragStartedId();
33404
33733
  const dragProperties = this.instance.getDragProperties();
33405
- if (dragProperties && dragId === IMAGE_TOOL_ACTION_NAME) {
33734
+ if (dragProperties && dragId === WEAVE_IMAGE_TOOL_ACTION_NAME) {
33406
33735
  this.instance.getStage().setPointersPositions(e);
33407
33736
  const position = getPositionRelativeToContainerOnPosition(this.instance);
33408
- this.instance.triggerAction(IMAGE_TOOL_ACTION_NAME, {
33409
- imageURL: dragProperties.imageURL,
33410
- ...dragProperties.imageId && { imageId: dragProperties.imageId },
33411
- ...dragProperties.imageWidth && { imageWidth: dragProperties.imageWidth },
33412
- ...dragProperties.imageHeight && { imageHeight: dragProperties.imageHeight },
33737
+ if (!position) return;
33738
+ this.instance.triggerAction(WEAVE_IMAGE_TOOL_ACTION_NAME, {
33739
+ type: WEAVE_IMAGE_TOOL_UPLOAD_TYPE.IMAGE_URL,
33740
+ image: dragProperties.imageURL,
33741
+ ...dragProperties.imageId ? { imageId: dragProperties.imageId } : {},
33742
+ ...dragProperties.forceMainContainer && { forceMainContainer: dragProperties.forceMainContainer },
33413
33743
  position
33414
33744
  });
33415
33745
  }
@@ -33418,87 +33748,93 @@ var WeaveImageToolAction = class extends WeaveAction {
33418
33748
  setupEvents() {
33419
33749
  const stage = this.instance.getStage();
33420
33750
  window.addEventListener("keydown", (e) => {
33421
- if (e.code === "Escape" && this.instance.getActiveAction() === IMAGE_TOOL_ACTION_NAME) {
33751
+ if (e.code === "Escape" && this.instance.getActiveAction() === WEAVE_IMAGE_TOOL_ACTION_NAME && !this.ignoreKeyboardEvents) {
33422
33752
  this.cancelAction();
33423
33753
  return;
33424
33754
  }
33425
33755
  });
33426
33756
  stage.on("pointerdown", (e) => {
33427
33757
  this.setTapStart(e);
33758
+ if (this.ignorePointerEvents) return;
33428
33759
  this.pointers.set(e.evt.pointerId, {
33429
33760
  x: e.evt.clientX,
33430
33761
  y: e.evt.clientY
33431
33762
  });
33432
- if (this.pointers.size === 2 && this.instance.getActiveAction() === IMAGE_TOOL_ACTION_NAME) {
33433
- this.state = IMAGE_TOOL_STATE.DEFINING_POSITION;
33763
+ if (this.pointers.size === 2 && this.instance.getActiveAction() === WEAVE_IMAGE_TOOL_ACTION_NAME) {
33764
+ this.state = WEAVE_IMAGE_TOOL_STATE.DEFINING_POSITION;
33434
33765
  return;
33435
33766
  }
33436
- if (this.state === IMAGE_TOOL_STATE.DEFINING_POSITION) this.state = IMAGE_TOOL_STATE.SELECTED_POSITION;
33767
+ if (this.state === WEAVE_IMAGE_TOOL_STATE.DEFINING_POSITION) this.state = WEAVE_IMAGE_TOOL_STATE.SELECTED_POSITION;
33437
33768
  });
33438
33769
  stage.on("pointermove", (e) => {
33439
- if (this.state === IMAGE_TOOL_STATE.IDLE) return;
33770
+ if (this.ignorePointerEvents) return;
33771
+ if (this.state === WEAVE_IMAGE_TOOL_STATE.IDLE) return;
33440
33772
  this.setCursor();
33441
- if (this.pointers.size === 2 && this.instance.getActiveAction() === IMAGE_TOOL_ACTION_NAME) {
33442
- this.state = IMAGE_TOOL_STATE.DEFINING_POSITION;
33773
+ if (this.pointers.size === 2 && this.instance.getActiveAction() === WEAVE_IMAGE_TOOL_ACTION_NAME) {
33774
+ this.state = WEAVE_IMAGE_TOOL_STATE.DEFINING_POSITION;
33443
33775
  return;
33444
33776
  }
33445
- 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") {
33777
+ 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") {
33446
33778
  const mousePos = stage.getRelativePointerPosition();
33779
+ const cursorPadding = this.config.style.cursor.padding;
33447
33780
  this.tempImageNode.setAttrs({
33448
- x: (mousePos?.x ?? 0) + this.cursorPadding,
33449
- y: (mousePos?.y ?? 0) + this.cursorPadding
33781
+ x: (mousePos?.x ?? 0) + cursorPadding / stage.scaleX(),
33782
+ y: (mousePos?.y ?? 0) + cursorPadding / stage.scaleX()
33450
33783
  });
33451
33784
  }
33452
33785
  });
33453
33786
  stage.on("pointerup", (e) => {
33787
+ if (this.ignorePointerEvents) return;
33454
33788
  this.pointers.delete(e.evt.pointerId);
33455
- if (this.state === IMAGE_TOOL_STATE.SELECTED_POSITION) this.handleAdding();
33789
+ if (this.state === WEAVE_IMAGE_TOOL_STATE.SELECTED_POSITION) this.handleAdding();
33456
33790
  });
33457
33791
  this.initialized = true;
33458
33792
  }
33459
33793
  setState(state) {
33460
33794
  this.state = state;
33461
33795
  }
33462
- loadImage(imageData, kind, position) {
33796
+ async loadImage(params) {
33463
33797
  this.setCursor();
33464
33798
  this.setFocusStage();
33465
33799
  if (!this.imageId) {
33466
33800
  this.cancelAction();
33467
33801
  return;
33468
33802
  }
33469
- this.imageURL = kind === IMAGE_TOOL_LOAD_FROM.DATAURL ? "not-defined" : imageData;
33470
33803
  const imageNodeHandler = this.getImageNodeHandler();
33471
- if (!imageNodeHandler) {
33472
- this.cancelAction();
33473
- return;
33474
- }
33475
- if (IMAGE_TOOL_LOAD_FROM.URL === kind) {
33476
- this.props = {
33477
- ...this.props,
33478
- imageURL: this.imageURL,
33479
- width: this.props.loadImageWidth,
33480
- height: this.props.loadImageHeight
33804
+ if (!imageNodeHandler) return;
33805
+ const actualImageId = this.imageId;
33806
+ if (params.type === WEAVE_IMAGE_TOOL_UPLOAD_TYPE.FILE) {
33807
+ const image = params.image;
33808
+ const realImageSize = await getImageSizeFromFile(image.file);
33809
+ const downscaledImage = await downscaleImageFile(image.file, image.downscaleRatio);
33810
+ const reader = new FileReader();
33811
+ reader.onloadend = () => {
33812
+ imageNodeHandler.preloadFallbackImage(actualImageId, reader.result, {
33813
+ onLoad: () => {
33814
+ this.props = {
33815
+ ...this.props,
33816
+ imageFallback: reader.result,
33817
+ imageURL: void 0,
33818
+ width: realImageSize.width,
33819
+ height: realImageSize.height
33820
+ };
33821
+ this.addImageNode(params?.position);
33822
+ },
33823
+ onError: () => {
33824
+ this.cancelAction();
33825
+ }
33826
+ });
33481
33827
  };
33482
- this.addImageNode(position);
33828
+ reader.onerror = () => {};
33829
+ reader.readAsDataURL(downscaledImage);
33830
+ }
33831
+ if (params.type === WEAVE_IMAGE_TOOL_UPLOAD_TYPE.IMAGE_URL) {
33832
+ const image = params.image;
33833
+ setTimeout(() => {
33834
+ this.saveImageUrl(actualImageId, image.url);
33835
+ }, 0);
33836
+ this.addImageNode(params?.position);
33483
33837
  }
33484
- imageNodeHandler.preloadImage(this.imageId, imageData, {
33485
- onLoad: () => {
33486
- this.instance.emitEvent("onImageLoadEnd", void 0);
33487
- const imageSource = imageNodeHandler.getImageSource(this.imageId);
33488
- if (imageSource && this.imageId) this.props = {
33489
- ...this.props,
33490
- imageURL: this.imageURL,
33491
- width: imageSource.width,
33492
- height: imageSource.height
33493
- };
33494
- this.addImageNode(position);
33495
- },
33496
- onError: () => {
33497
- this.instance.emitEvent("onImageLoadEnd", new Error("Error loading image"));
33498
- this.cancelAction();
33499
- }
33500
- });
33501
- this.instance.emitEvent("onImageLoadStart");
33502
33838
  }
33503
33839
  isTouchDevice() {
33504
33840
  return window.matchMedia("(pointer: coarse)").matches;
@@ -33508,54 +33844,67 @@ var WeaveImageToolAction = class extends WeaveAction {
33508
33844
  this.setCursor();
33509
33845
  this.setFocusStage();
33510
33846
  if (position) {
33511
- this.setState(IMAGE_TOOL_STATE.SELECTED_POSITION);
33847
+ this.setState(WEAVE_IMAGE_TOOL_STATE.SELECTED_POSITION);
33512
33848
  this.handleAdding(position);
33513
33849
  return;
33514
33850
  }
33851
+ const imageNodeHandler = this.getImageNodeHandler();
33852
+ if (!imageNodeHandler) {
33853
+ this.cancelAction();
33854
+ return;
33855
+ }
33515
33856
  if (this.imageId) {
33516
33857
  const mousePos = stage.getRelativePointerPosition();
33517
33858
  this.tempImageId = v4_default();
33518
- const imageNodeHandler = this.getImageNodeHandler();
33519
- if (!imageNodeHandler) {
33520
- this.cancelAction();
33521
- return;
33522
- }
33523
- const imageSource = imageNodeHandler.getImageSource(this.imageId);
33859
+ let imageSource = imageNodeHandler.getImageSource(this.imageId);
33860
+ if (this.uploadType === "file") imageSource = imageNodeHandler.getFallbackImageSource(this.imageId);
33524
33861
  if (!imageSource) {
33525
33862
  this.cancelAction();
33526
33863
  return;
33527
33864
  }
33528
33865
  const aspectRatio = imageSource.width / imageSource.height;
33529
33866
  if (!this.tempImageNode && this.tempImageId && !this.isTouchDevice()) {
33867
+ const cursorPadding = this.config.style.cursor.padding;
33868
+ const imageThumbnailWidth = this.config.style.cursor.imageThumbnail.width;
33869
+ const imageThumbnailHeight = this.config.style.cursor.imageThumbnail.height;
33870
+ const shadowColor = this.config.style.cursor.imageThumbnail.shadowColor;
33871
+ const shadowBlur = this.config.style.cursor.imageThumbnail.shadowBlur;
33872
+ const shadowOffset = this.config.style.cursor.imageThumbnail.shadowOffset;
33873
+ const shadowOpacity = this.config.style.cursor.imageThumbnail.shadowOpacity;
33530
33874
  this.tempImageNode = new Konva.Image({
33531
33875
  id: this.tempImageId,
33532
- x: (mousePos?.x ?? 0) + this.cursorPadding,
33533
- y: (mousePos?.y ?? 0) + this.cursorPadding,
33534
- width: 240 * aspectRatio * (1 / stage.scaleX()),
33535
- height: 240 * (1 / stage.scaleY()),
33876
+ x: (mousePos?.x ?? 0) + cursorPadding / stage.scaleX(),
33877
+ y: (mousePos?.y ?? 0) + cursorPadding / stage.scaleY(),
33878
+ width: imageThumbnailWidth * aspectRatio * (1 / stage.scaleX()),
33879
+ height: imageThumbnailHeight * (1 / stage.scaleY()),
33536
33880
  opacity: 1,
33537
33881
  adding: true,
33538
33882
  image: imageSource,
33539
33883
  stroke: "#000000ff",
33540
33884
  strokeWidth: 0,
33541
33885
  strokeScaleEnabled: true,
33542
- listening: false
33886
+ listening: false,
33887
+ shadowColor,
33888
+ shadowBlur,
33889
+ shadowOffset,
33890
+ shadowOpacity
33543
33891
  });
33544
33892
  this.instance.getMainLayer()?.add(this.tempImageNode);
33545
33893
  }
33546
33894
  this.instance.emitEvent("onAddingImage", { imageURL: this.props.imageURL });
33547
33895
  }
33548
33896
  this.clickPoint = null;
33549
- this.setState(IMAGE_TOOL_STATE.DEFINING_POSITION);
33897
+ this.setState(WEAVE_IMAGE_TOOL_STATE.DEFINING_POSITION);
33550
33898
  }
33551
33899
  handleAdding(position) {
33900
+ const imageNodeHandler = this.getImageNodeHandler();
33901
+ if (!imageNodeHandler) {
33902
+ this.cancelAction();
33903
+ return;
33904
+ }
33552
33905
  if (this.imageId) {
33553
- const imageNodeHandler = this.getImageNodeHandler();
33554
- if (!imageNodeHandler) {
33555
- this.cancelAction();
33556
- return;
33557
- }
33558
- const imageSource = imageNodeHandler.getImageSource(this.imageId);
33906
+ let imageSource = imageNodeHandler.getImageSource(this.imageId);
33907
+ if (this.uploadType === WEAVE_IMAGE_TOOL_UPLOAD_TYPE.FILE) imageSource = imageNodeHandler.getFallbackImageSource(this.imageId);
33559
33908
  if (!imageSource && !position) {
33560
33909
  this.cancelAction();
33561
33910
  return;
@@ -33564,8 +33913,10 @@ var WeaveImageToolAction = class extends WeaveAction {
33564
33913
  this.clickPoint = mousePoint;
33565
33914
  this.container = container;
33566
33915
  const nodeHandler = this.instance.getNodeHandler("image");
33567
- const imageWidth = this.props.loadImageWidth ? this.props.loadImageWidth : imageSource?.width;
33568
- const imageHeight = this.props.loadImageHeight ? this.props.loadImageHeight : imageSource?.height;
33916
+ const imageWidth = this.props.width ? this.props.width : imageSource?.width;
33917
+ const imageHeight = this.props.height ? this.props.height : imageSource?.height;
33918
+ let realImageURL = void 0;
33919
+ if (this.uploadType === WEAVE_IMAGE_TOOL_UPLOAD_TYPE.IMAGE_URL && this.imageURL) realImageURL = this.imageURL?.url;
33569
33920
  if (nodeHandler) {
33570
33921
  const node = nodeHandler.create(this.imageId, {
33571
33922
  ...this.props,
@@ -33573,7 +33924,7 @@ var WeaveImageToolAction = class extends WeaveAction {
33573
33924
  y: this.clickPoint?.y ?? 0,
33574
33925
  opacity: 1,
33575
33926
  adding: false,
33576
- imageURL: this.imageURL,
33927
+ imageURL: realImageURL,
33577
33928
  stroke: "#000000ff",
33578
33929
  strokeWidth: 0,
33579
33930
  strokeScaleEnabled: true,
@@ -33582,15 +33933,32 @@ var WeaveImageToolAction = class extends WeaveAction {
33582
33933
  imageInfo: {
33583
33934
  width: imageWidth,
33584
33935
  height: imageHeight
33936
+ },
33937
+ uncroppedImage: {
33938
+ width: imageWidth,
33939
+ height: imageHeight
33585
33940
  }
33586
33941
  });
33587
33942
  this.instance.addNode(node, this.forceMainContainer ? this.instance.getMainLayer()?.getAttrs().id : this.container?.getAttrs().id);
33588
- this.instance.emitEvent("onAddedImage", {
33589
- imageURL: this.props.imageURL,
33590
- nodeId: this.imageId
33591
- });
33943
+ this.instance.emitEvent("onAddedImage", { nodeId: this.imageId });
33944
+ if (this.uploadType === WEAVE_IMAGE_TOOL_UPLOAD_TYPE.FILE) {
33945
+ const uploadImageFunctionInternal = async () => {
33946
+ const nodeId = this.imageId ?? "";
33947
+ try {
33948
+ const imageURL = await this.uploadImageFunction(this.imageFile.file);
33949
+ this.saveImageUrl(nodeId, imageURL);
33950
+ this.instance.emitEvent("onImageUploaded", {
33951
+ imageURL,
33952
+ nodeId
33953
+ });
33954
+ } catch (error) {
33955
+ this.instance.emitEvent("onImageUploadedError", { error });
33956
+ }
33957
+ };
33958
+ uploadImageFunctionInternal();
33959
+ }
33592
33960
  }
33593
- this.setState(IMAGE_TOOL_STATE.FINISHED);
33961
+ this.setState(WEAVE_IMAGE_TOOL_STATE.FINISHED);
33594
33962
  }
33595
33963
  this.cancelAction();
33596
33964
  }
@@ -33600,55 +33968,507 @@ var WeaveImageToolAction = class extends WeaveAction {
33600
33968
  this.cancelAction = cancelAction;
33601
33969
  const selectionPlugin = this.instance.getPlugin("nodesSelection");
33602
33970
  if (selectionPlugin) selectionPlugin.setSelectedNodes([]);
33971
+ this.ignorePointerEvents = false;
33972
+ this.ignoreKeyboardEvents = false;
33603
33973
  this.forceMainContainer = params?.forceMainContainer ?? false;
33974
+ this.imageFile = null;
33975
+ this.imageURL = null;
33604
33976
  this.imageId = v4_default();
33605
33977
  this.props = this.initProps();
33606
33978
  if (params?.imageId) this.updateProps({ imageId: params.imageId });
33607
- if (params?.imageId) this.updateProps({ loadImageWidth: params.imageWidth });
33608
- if (params?.imageId) this.updateProps({ loadImageHeight: params.imageHeight });
33609
- if (params.imageData) this.loadImage(params.imageData, IMAGE_TOOL_LOAD_FROM.DATAURL, params?.position ?? void 0);
33610
- if (params.imageURL) this.loadImage(params.imageURL, IMAGE_TOOL_LOAD_FROM.URL, params?.position ?? void 0);
33611
- return {
33612
- nodeId: this.imageId,
33613
- finishUploadCallback: (nodeId, imageURL) => {
33614
- return this.saveImageUrl.bind(this)(nodeId, imageURL);
33979
+ if (this.forceExecution) {
33980
+ this.ignorePointerEvents = true;
33981
+ this.ignoreKeyboardEvents = true;
33982
+ }
33983
+ if (params?.position) this.setState(WEAVE_IMAGE_TOOL_STATE.SELECTED_POSITION);
33984
+ if (params.type === WEAVE_IMAGE_TOOL_UPLOAD_TYPE.FILE && params.image) {
33985
+ this.uploadType = WEAVE_IMAGE_TOOL_UPLOAD_TYPE.FILE;
33986
+ this.imageFile = params.image;
33987
+ this.uploadImageFunction = params.uploadImageFunction;
33988
+ this.loadImage({
33989
+ type: WEAVE_IMAGE_TOOL_UPLOAD_TYPE.FILE,
33990
+ image: params.image,
33991
+ position: params?.position
33992
+ });
33993
+ }
33994
+ if (params.type === WEAVE_IMAGE_TOOL_UPLOAD_TYPE.IMAGE_URL && params.image) {
33995
+ this.uploadType = WEAVE_IMAGE_TOOL_UPLOAD_TYPE.IMAGE_URL;
33996
+ this.imageURL = params.image;
33997
+ this.updateProps({
33998
+ imageFallback: params.image.fallback,
33999
+ width: params.image.width,
34000
+ height: params.image.height
34001
+ });
34002
+ this.loadImage({
34003
+ type: WEAVE_IMAGE_TOOL_UPLOAD_TYPE.IMAGE_URL,
34004
+ image: params.image,
34005
+ position: params?.position
34006
+ });
34007
+ }
34008
+ return { nodeId: this.imageId };
34009
+ }
34010
+ saveImageUrl(nodeId, imageURL) {
34011
+ const stage = this.instance.getStage();
34012
+ const nodeHandler = this.instance.getNodeHandler("image");
34013
+ const node = stage.findOne(`#${nodeId}`);
34014
+ if (nodeHandler && node) {
34015
+ node.setAttr("imageURL", imageURL);
34016
+ nodeHandler.forceLoadImage(node);
34017
+ this.instance.updateNode(nodeHandler.serialize(node), { origin: "system" });
34018
+ }
34019
+ }
34020
+ cleanup() {
34021
+ const stage = this.instance.getStage();
34022
+ if (this.tempImageNode) this.tempImageNode.destroy();
34023
+ if (!this.forceExecution) {
34024
+ const selectionPlugin = this.instance.getPlugin("nodesSelection");
34025
+ if (selectionPlugin) {
34026
+ const node = stage.findOne(`#${this.imageId}`);
34027
+ if (node) selectionPlugin.setSelectedNodes([node]);
34028
+ this.instance.triggerAction(SELECTION_TOOL_ACTION_NAME);
34029
+ }
34030
+ stage.container().style.cursor = "default";
34031
+ this.instance.endDrag(WEAVE_IMAGE_TOOL_ACTION_NAME);
34032
+ }
34033
+ this.initialCursor = null;
34034
+ this.forceMainContainer = false;
34035
+ this.container = void 0;
34036
+ this.tempImageNode = null;
34037
+ this.imageURL = null;
34038
+ this.clickPoint = null;
34039
+ this.setState(WEAVE_IMAGE_TOOL_STATE.IDLE);
34040
+ }
34041
+ getImageNodeHandler() {
34042
+ return this.instance.getNodeHandler("image");
34043
+ }
34044
+ setCursor() {
34045
+ const stage = this.instance.getStage();
34046
+ stage.container().style.cursor = "crosshair";
34047
+ }
34048
+ setFocusStage() {
34049
+ const stage = this.instance.getStage();
34050
+ stage.container().tabIndex = 1;
34051
+ stage.container().blur();
34052
+ stage.container().focus();
34053
+ }
34054
+ setDragAndDropProperties(properties) {
34055
+ this.instance.startDrag(WEAVE_IMAGE_TOOL_ACTION_NAME);
34056
+ this.instance.setDragProperties(properties);
34057
+ }
34058
+ getActualState() {
34059
+ return this.state;
34060
+ }
34061
+ };
34062
+
34063
+ //#endregion
34064
+ //#region src/actions/images-tool/constants.ts
34065
+ const WEAVE_IMAGES_TOOL_ACTION_NAME = "imagesTool";
34066
+ const WEAVE_IMAGES_TOOL_UPLOAD_TYPE = {
34067
+ ["FILE"]: "file",
34068
+ ["IMAGE_URL"]: "imageURL"
34069
+ };
34070
+ const WEAVE_IMAGES_TOOL_STATE = {
34071
+ ["IDLE"]: "idle",
34072
+ ["UPLOADING"]: "uploading",
34073
+ ["DEFINING_POSITION"]: "definingPosition",
34074
+ ["SELECTED_POSITION"]: "selectedPosition",
34075
+ ["ADDING"]: "adding",
34076
+ ["FINISHED"]: "finished"
34077
+ };
34078
+ const WEAVE_IMAGES_TOOL_DEFAULT_CONFIG = {
34079
+ style: {
34080
+ cursor: {
34081
+ padding: 5,
34082
+ imageThumbnails: {
34083
+ padding: 15,
34084
+ width: 250,
34085
+ height: 250,
34086
+ shadowColor: "#aaaaaa",
34087
+ shadowBlur: 10,
34088
+ shadowOffset: {
34089
+ x: 2,
34090
+ y: 2
34091
+ },
34092
+ shadowOpacity: .5
33615
34093
  }
34094
+ },
34095
+ moreImages: {
34096
+ paddingX: 12,
34097
+ paddingY: 8,
34098
+ fontSize: 16,
34099
+ fontFamily: "Arial",
34100
+ textColor: "#000000",
34101
+ backgroundColor: "#FFFFFF",
34102
+ backgroundOpacity: 1
34103
+ },
34104
+ images: { padding: 20 }
34105
+ },
34106
+ layout: { columns: 4 }
34107
+ };
34108
+
34109
+ //#endregion
34110
+ //#region src/internal-utils/generic.ts
34111
+ function sleep(ms) {
34112
+ return new Promise((resolve) => setTimeout(resolve, ms));
34113
+ }
34114
+
34115
+ //#endregion
34116
+ //#region src/actions/images-tool/images-tool.ts
34117
+ var WeaveImagesToolAction = class extends WeaveAction {
34118
+ initialized = false;
34119
+ initialCursor = null;
34120
+ nodesIds = [];
34121
+ imagesFile = [];
34122
+ imagesURL = [];
34123
+ forceMainContainer = false;
34124
+ uploadType = null;
34125
+ onPropsChange = void 0;
34126
+ update = void 0;
34127
+ constructor(params) {
34128
+ super();
34129
+ this.config = mergeExceptArrays(WEAVE_IMAGES_TOOL_DEFAULT_CONFIG, params ?? {});
34130
+ this.pointers = new Map();
34131
+ this.initialized = false;
34132
+ this.tempPointerFeedbackNode = null;
34133
+ this.state = WEAVE_IMAGES_TOOL_STATE.IDLE;
34134
+ this.imagesFile = [];
34135
+ this.imagesURL = [];
34136
+ this.container = void 0;
34137
+ this.preloadImgs = {};
34138
+ this.uploadType = null;
34139
+ this.clickPoint = null;
34140
+ }
34141
+ getName() {
34142
+ return WEAVE_IMAGES_TOOL_ACTION_NAME;
34143
+ }
34144
+ getPreloadedImage(imageId) {
34145
+ return this.preloadImgs?.[imageId];
34146
+ }
34147
+ initProps() {
34148
+ return {
34149
+ width: 100,
34150
+ height: 100,
34151
+ scaleX: 1,
34152
+ scaleY: 1
33616
34153
  };
33617
34154
  }
34155
+ onInit() {
34156
+ this.instance.addEventListener("onStageDrop", (e) => {
34157
+ const dragId = this.instance.getDragStartedId();
34158
+ const dragProperties = this.instance.getDragProperties();
34159
+ if (dragProperties && dragId === WEAVE_IMAGES_TOOL_ACTION_NAME) {
34160
+ this.instance.getStage().setPointersPositions(e);
34161
+ const position = getPositionRelativeToContainerOnPosition(this.instance);
34162
+ if (!position) return;
34163
+ this.instance.triggerAction(WEAVE_IMAGES_TOOL_ACTION_NAME, {
34164
+ type: WEAVE_IMAGES_TOOL_UPLOAD_TYPE.IMAGE_URL,
34165
+ images: dragProperties.imagesURL,
34166
+ position,
34167
+ ...dragProperties.forceMainContainer && { forceMainContainer: dragProperties.forceMainContainer }
34168
+ });
34169
+ }
34170
+ });
34171
+ }
34172
+ setupEvents() {
34173
+ const stage = this.instance.getStage();
34174
+ stage.container().addEventListener("keydown", (e) => {
34175
+ if (e.key === "Escape" && this.instance.getActiveAction() === WEAVE_IMAGES_TOOL_ACTION_NAME) this.cancelAction();
34176
+ });
34177
+ stage.on("pointerdown", (e) => {
34178
+ this.setTapStart(e);
34179
+ this.pointers.set(e.evt.pointerId, {
34180
+ x: e.evt.clientX,
34181
+ y: e.evt.clientY
34182
+ });
34183
+ if (this.pointers.size === 2 && this.instance.getActiveAction() === WEAVE_IMAGES_TOOL_ACTION_NAME) {
34184
+ this.state = WEAVE_IMAGES_TOOL_STATE.DEFINING_POSITION;
34185
+ return;
34186
+ }
34187
+ if (this.state === WEAVE_IMAGES_TOOL_STATE.DEFINING_POSITION) this.state = WEAVE_IMAGES_TOOL_STATE.SELECTED_POSITION;
34188
+ });
34189
+ stage.on("pointermove", (e) => {
34190
+ if (this.state === WEAVE_IMAGES_TOOL_STATE.IDLE) return;
34191
+ this.setCursor();
34192
+ this.setFocusStage();
34193
+ if (this.pointers.size === 2 && this.instance.getActiveAction() === WEAVE_IMAGES_TOOL_ACTION_NAME) {
34194
+ this.state = WEAVE_IMAGES_TOOL_STATE.DEFINING_POSITION;
34195
+ return;
34196
+ }
34197
+ 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") {
34198
+ const mousePos = stage.getRelativePointerPosition();
34199
+ const cursorPadding = this.config.style.cursor.padding;
34200
+ this.tempPointerFeedbackNode.setAttrs({
34201
+ x: (mousePos?.x ?? 0) + cursorPadding / stage.scaleX(),
34202
+ y: (mousePos?.y ?? 0) + cursorPadding / stage.scaleY()
34203
+ });
34204
+ }
34205
+ });
34206
+ stage.on("pointerup", (e) => {
34207
+ this.pointers.delete(e.evt.pointerId);
34208
+ if (this.state === WEAVE_IMAGES_TOOL_STATE.SELECTED_POSITION) this.handleAdding();
34209
+ });
34210
+ this.initialized = true;
34211
+ }
34212
+ setState(state) {
34213
+ this.state = state;
34214
+ }
34215
+ async addImages(position) {
34216
+ const stage = this.instance.getStage();
34217
+ this.setCursor();
34218
+ this.setFocusStage();
34219
+ if (position) {
34220
+ this.setState(WEAVE_IMAGES_TOOL_STATE.SELECTED_POSITION);
34221
+ this.handleAdding(position);
34222
+ return;
34223
+ }
34224
+ if (!this.tempPointerFeedbackNode && !this.isTouchDevice() && this.imagesFile && this.uploadType === WEAVE_IMAGES_TOOL_UPLOAD_TYPE.FILE) {
34225
+ const mousePos = stage.getRelativePointerPosition();
34226
+ const cursorPadding = this.config.style.cursor.padding;
34227
+ const imageThumbnailsPadding = this.config.style.cursor.imageThumbnails.padding;
34228
+ this.tempPointerFeedbackNode = new Konva.Group({
34229
+ x: (mousePos?.x ?? 0) + cursorPadding / stage.scaleX(),
34230
+ y: (mousePos?.y ?? 0) + cursorPadding / stage.scaleY(),
34231
+ listening: false
34232
+ });
34233
+ const imagesTop3 = this.imagesFile.slice(0, 3) ?? [];
34234
+ let maxWidth = 0;
34235
+ let maxHeight = 0;
34236
+ let position$1 = {
34237
+ x: 0,
34238
+ y: 0
34239
+ };
34240
+ for (const image of imagesTop3) {
34241
+ const imageSource = await loadImageSource(image.file);
34242
+ const maxImageWidth = this.config.style.cursor.imageThumbnails.width;
34243
+ const maxImageHeight = this.config.style.cursor.imageThumbnails.height;
34244
+ const shadowColor = this.config.style.cursor.imageThumbnails.shadowColor;
34245
+ const shadowBlur = this.config.style.cursor.imageThumbnails.shadowBlur;
34246
+ const shadowOffset = this.config.style.cursor.imageThumbnails.shadowOffset;
34247
+ const shadowOpacity = this.config.style.cursor.imageThumbnails.shadowOpacity;
34248
+ const aspectRatio = imageSource.width / imageSource.height || 1;
34249
+ const imageWidth = maxImageWidth * aspectRatio * (1 / stage.scaleX());
34250
+ const imageHeight = maxImageHeight * (1 / stage.scaleY());
34251
+ const imageNode = new Konva.Image({
34252
+ x: position$1.x,
34253
+ y: position$1.y,
34254
+ width: imageWidth,
34255
+ height: imageHeight,
34256
+ opacity: 1,
34257
+ adding: true,
34258
+ image: imageSource,
34259
+ stroke: "#000000ff",
34260
+ strokeWidth: 0,
34261
+ strokeScaleEnabled: true,
34262
+ listening: false,
34263
+ shadowColor,
34264
+ shadowBlur,
34265
+ shadowOffset,
34266
+ shadowOpacity
34267
+ });
34268
+ maxWidth = position$1.x + imageWidth;
34269
+ maxHeight = Math.max(maxHeight, position$1.y + imageHeight);
34270
+ position$1 = {
34271
+ x: position$1.x + imageThumbnailsPadding / stage.scaleX(),
34272
+ y: position$1.y + imageThumbnailsPadding / stage.scaleY()
34273
+ };
34274
+ this.tempPointerFeedbackNode.add(imageNode);
34275
+ imageNode.moveToBottom();
34276
+ }
34277
+ if (this.imagesFile.length > 3) {
34278
+ const paddingX = this.config.style.moreImages.paddingX;
34279
+ const paddingY = this.config.style.moreImages.paddingY;
34280
+ const fontSize = this.config.style.moreImages.fontSize;
34281
+ const fontFamily = this.config.style.moreImages.fontFamily;
34282
+ const textColor = this.config.style.moreImages.textColor;
34283
+ const backgroundColor = this.config.style.moreImages.backgroundColor;
34284
+ const backgroundOpacity = this.config.style.moreImages.backgroundOpacity;
34285
+ const text = `and ${this.imagesFile.length - 3} more image(s)`;
34286
+ const textNode = new Konva.Text({
34287
+ x: maxWidth + paddingX / stage.scaleX() + cursorPadding / stage.scaleX(),
34288
+ y: position$1.y,
34289
+ fontFamily,
34290
+ fontSize: fontSize / stage.scaleX(),
34291
+ text,
34292
+ fill: textColor,
34293
+ listening: false
34294
+ });
34295
+ const textSize = textNode.measureSize(text);
34296
+ textNode.y((maxHeight - textSize.height) / 2);
34297
+ this.tempPointerFeedbackNode.add(textNode);
34298
+ const textBg = new Konva.Rect({
34299
+ x: textNode.x() - paddingX / stage.scaleX(),
34300
+ y: textNode.y() - paddingY / stage.scaleY(),
34301
+ width: textNode.width() + 2 * paddingX / stage.scaleX(),
34302
+ height: textNode.height() + 2 * paddingY / stage.scaleY(),
34303
+ fill: backgroundColor,
34304
+ opacity: backgroundOpacity
34305
+ });
34306
+ this.tempPointerFeedbackNode.add(textBg);
34307
+ textBg.moveToBottom();
34308
+ textNode.moveToTop();
34309
+ }
34310
+ this.instance.getUtilityLayer()?.add(this.tempPointerFeedbackNode);
34311
+ this.instance.emitEvent("onAddingImages");
34312
+ }
34313
+ this.clickPoint = null;
34314
+ this.setState(WEAVE_IMAGES_TOOL_STATE.DEFINING_POSITION);
34315
+ }
34316
+ async handleAdding(position) {
34317
+ const stage = this.instance.getStage();
34318
+ this.tempPointerFeedbackNode?.destroy();
34319
+ this.tempPointerFeedbackNode = null;
34320
+ this.instance.getUtilityLayer()?.batchDraw();
34321
+ stage.container().style.cursor = "default";
34322
+ const { mousePoint, container } = this.instance.getMousePointer(position);
34323
+ this.clickPoint = mousePoint;
34324
+ this.container = container;
34325
+ const originPoint = {
34326
+ x: this.clickPoint?.x ?? 0,
34327
+ y: this.clickPoint?.y ?? 0
34328
+ };
34329
+ if (!this.imagesFile && !this.imagesURL) return;
34330
+ const imageToolActionHandler = this.instance.getActionHandler(WEAVE_IMAGE_TOOL_ACTION_NAME);
34331
+ if (!imageToolActionHandler) return;
34332
+ const imagesPadding = this.config.style.images.padding;
34333
+ const layoutColumns = this.config.layout.columns;
34334
+ let imagePositionX = originPoint.x;
34335
+ let imagePositionY = originPoint.y;
34336
+ let maxHeight = 0;
34337
+ if (this.uploadType === WEAVE_IMAGES_TOOL_UPLOAD_TYPE.FILE && this.imagesFile) {
34338
+ const imagesToUpload = this.imagesFile.length;
34339
+ let imagesUploaded = 0;
34340
+ await this.onStartUploading();
34341
+ const handleUploadImage = async () => {
34342
+ imagesUploaded++;
34343
+ if (imagesUploaded >= imagesToUpload) {
34344
+ await this.onFinishedUploading();
34345
+ this.instance.removeEventListener("onImageUploaded", handleUploadImage);
34346
+ }
34347
+ };
34348
+ this.instance.addEventListener("onImageUploaded", handleUploadImage);
34349
+ for (let i = 0; i < this.imagesFile.length; i++) {
34350
+ const imageFile = this.imagesFile[i];
34351
+ const { imageId, width, height,...restImageFile } = imageFile;
34352
+ const uploadImageFunctionInternal = async () => {
34353
+ const imageURL = await this.uploadImageFunction(imageFile.file);
34354
+ return imageURL;
34355
+ };
34356
+ const { nodeId } = this.instance.triggerAction(WEAVE_IMAGE_TOOL_ACTION_NAME, {
34357
+ type: WEAVE_IMAGE_TOOL_UPLOAD_TYPE.FILE,
34358
+ image: restImageFile,
34359
+ uploadImageFunction: uploadImageFunctionInternal,
34360
+ ...imageId && { imageId },
34361
+ position: {
34362
+ x: imagePositionX,
34363
+ y: imagePositionY
34364
+ },
34365
+ forceMainContainer: this.forceMainContainer
34366
+ }, true);
34367
+ this.nodesIds.push(nodeId);
34368
+ maxHeight = Math.max(maxHeight, height);
34369
+ imagePositionX += imagesPadding + width;
34370
+ if ((i + 1) % layoutColumns === 0) {
34371
+ imagePositionX = originPoint.x;
34372
+ imagePositionY = imagePositionY + maxHeight + imagesPadding;
34373
+ maxHeight = 0;
34374
+ }
34375
+ while (imageToolActionHandler.getActualState() !== WEAVE_IMAGES_TOOL_STATE.IDLE) await sleep(10);
34376
+ }
34377
+ this.instance.emitEvent("onAddedImages", { nodesIds: this.nodesIds });
34378
+ }
34379
+ if (this.uploadType === WEAVE_IMAGES_TOOL_UPLOAD_TYPE.IMAGE_URL && this.imagesURL) {
34380
+ for (let i = 0; i < this.imagesURL.length; i++) {
34381
+ const imageURL = this.imagesURL[i];
34382
+ const { imageId, options,...restImageURL } = imageURL;
34383
+ const imageURLElement = restImageURL;
34384
+ const { nodeId } = this.instance.triggerAction(WEAVE_IMAGE_TOOL_ACTION_NAME, {
34385
+ type: WEAVE_IMAGE_TOOL_UPLOAD_TYPE.IMAGE_URL,
34386
+ image: imageURLElement,
34387
+ ...imageId && { imageId },
34388
+ ...options && { options },
34389
+ position: {
34390
+ x: imagePositionX,
34391
+ y: imagePositionY
34392
+ },
34393
+ forceMainContainer: this.forceMainContainer
34394
+ }, true);
34395
+ this.nodesIds.push(nodeId);
34396
+ maxHeight = Math.max(maxHeight, imageURL.height);
34397
+ imagePositionX += imagesPadding + imageURL.width;
34398
+ if ((i + 1) % layoutColumns === 0) {
34399
+ imagePositionX = originPoint.x;
34400
+ imagePositionY = imagePositionY + maxHeight + imagesPadding;
34401
+ maxHeight = 0;
34402
+ }
34403
+ while (imageToolActionHandler.getActualState() !== WEAVE_IMAGES_TOOL_STATE.IDLE) await sleep(10);
34404
+ }
34405
+ this.instance.emitEvent("onAddedImages", { nodesIds: this.nodesIds });
34406
+ }
34407
+ this.setState(WEAVE_IMAGES_TOOL_STATE.FINISHED);
34408
+ this.cancelAction();
34409
+ }
34410
+ trigger(cancelAction, params) {
34411
+ if (!this.instance) throw new Error("Instance not defined");
34412
+ if (!this.initialized) this.setupEvents();
34413
+ this.cancelAction = cancelAction;
34414
+ const selectionPlugin = this.instance.getPlugin("nodesSelection");
34415
+ if (selectionPlugin) selectionPlugin.setSelectedNodes([]);
34416
+ if (params?.position) this.setState(WEAVE_IMAGES_TOOL_STATE.SELECTED_POSITION);
34417
+ this.forceMainContainer = params.forceMainContainer ?? false;
34418
+ if (params.type === WEAVE_IMAGES_TOOL_UPLOAD_TYPE.FILE) {
34419
+ this.uploadType = WEAVE_IMAGES_TOOL_UPLOAD_TYPE.FILE;
34420
+ this.onStartUploading = params.onStartUploading;
34421
+ this.onFinishedUploading = params.onFinishedUploading;
34422
+ this.uploadImageFunction = params.uploadImageFunction;
34423
+ this.nodesIds = [];
34424
+ this.imagesFile = params.images;
34425
+ }
34426
+ if (params.type === WEAVE_IMAGES_TOOL_UPLOAD_TYPE.IMAGE_URL) {
34427
+ this.uploadType = WEAVE_IMAGES_TOOL_UPLOAD_TYPE.IMAGE_URL;
34428
+ this.nodesIds = [];
34429
+ this.imagesURL = params.images;
34430
+ }
34431
+ if (![WEAVE_IMAGES_TOOL_UPLOAD_TYPE.FILE, WEAVE_IMAGES_TOOL_UPLOAD_TYPE.IMAGE_URL].includes(params.type)) {
34432
+ this.cancelAction();
34433
+ return;
34434
+ }
34435
+ this.addImages(params?.position);
34436
+ }
33618
34437
  saveImageUrl(nodeId, imageURL) {
33619
- this.imageURL = imageURL;
33620
- if (this.state !== IMAGE_TOOL_STATE.DEFINING_POSITION) {
34438
+ if (this.state !== WEAVE_IMAGES_TOOL_STATE.DEFINING_POSITION) {
33621
34439
  const stage = this.instance.getStage();
33622
34440
  const nodeHandler = this.instance.getNodeHandler("image");
33623
34441
  const node = stage.findOne(`#${nodeId}`);
33624
34442
  if (nodeHandler && node) {
33625
34443
  node.setAttr("imageURL", imageURL);
33626
- this.instance.updateNode(nodeHandler.serialize(node));
34444
+ nodeHandler.forceLoadImage(node);
34445
+ this.instance.updateNode(nodeHandler.serialize(node), { origin: "system" });
33627
34446
  }
33628
34447
  }
33629
34448
  }
33630
34449
  cleanup() {
33631
34450
  const stage = this.instance.getStage();
33632
- if (this.tempImageNode) this.tempImageNode.destroy();
34451
+ this.tempPointerFeedbackNode?.destroy();
34452
+ this.tempPointerFeedbackNode = null;
34453
+ this.instance.getUtilityLayer()?.batchDraw();
33633
34454
  const selectionPlugin = this.instance.getPlugin("nodesSelection");
33634
34455
  if (selectionPlugin) {
33635
- const node = stage.findOne(`#${this.imageId}`);
33636
- if (node) selectionPlugin.setSelectedNodes([node]);
34456
+ const addedNodes = [];
34457
+ for (const nodeId of this.nodesIds) {
34458
+ const node = stage.findOne(`#${nodeId}`);
34459
+ if (node) addedNodes.push(node);
34460
+ }
34461
+ selectionPlugin.setSelectedNodes(addedNodes);
33637
34462
  this.instance.triggerAction(SELECTION_TOOL_ACTION_NAME);
33638
34463
  }
34464
+ this.instance.endDrag(WEAVE_IMAGES_TOOL_ACTION_NAME);
33639
34465
  stage.container().style.cursor = "default";
33640
- this.instance.endDrag(IMAGE_TOOL_ACTION_NAME);
33641
- this.initialCursor = null;
33642
- this.imageId = null;
34466
+ this.uploadType = null;
33643
34467
  this.forceMainContainer = false;
34468
+ this.initialCursor = null;
33644
34469
  this.container = void 0;
33645
- this.tempImageNode = null;
33646
- this.imageURL = null;
33647
34470
  this.clickPoint = null;
33648
- this.setState(IMAGE_TOOL_STATE.IDLE);
33649
- }
33650
- getImageNodeHandler() {
33651
- return this.instance.getNodeHandler("image");
34471
+ this.setState(WEAVE_IMAGES_TOOL_STATE.IDLE);
33652
34472
  }
33653
34473
  setCursor() {
33654
34474
  const stage = this.instance.getStage();
@@ -33660,8 +34480,11 @@ var WeaveImageToolAction = class extends WeaveAction {
33660
34480
  stage.container().blur();
33661
34481
  stage.container().focus();
33662
34482
  }
34483
+ isTouchDevice() {
34484
+ return window.matchMedia("(pointer: coarse)").matches;
34485
+ }
33663
34486
  setDragAndDropProperties(properties) {
33664
- this.instance.startDrag(IMAGE_TOOL_ACTION_NAME);
34487
+ this.instance.startDrag(WEAVE_IMAGES_TOOL_ACTION_NAME);
33665
34488
  this.instance.setDragProperties(properties);
33666
34489
  }
33667
34490
  };
@@ -38884,7 +39707,7 @@ var WeaveStageKeyboardMovePlugin = class extends WeavePlugin {
38884
39707
  };
38885
39708
 
38886
39709
  //#endregion
38887
- //#region src/utils/mapping.ts
39710
+ //#region src/internal-utils/mapping.ts
38888
39711
  const isArray = (val) => {
38889
39712
  return Array.isArray(val);
38890
39713
  };
@@ -38930,4 +39753,4 @@ function getJSONFromYjsBinary(actualState) {
38930
39753
  }
38931
39754
 
38932
39755
  //#endregion
38933
- 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 };
39756
+ 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 };