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