@inditextech/weave-sdk 3.2.3 → 3.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/sdk.js CHANGED
@@ -21971,7 +21971,7 @@ var WeaveRegisterManager = class {
21971
21971
 
21972
21972
  //#endregion
21973
21973
  //#region package.json
21974
- var version = "3.2.3";
21974
+ var version = "3.2.5";
21975
21975
 
21976
21976
  //#endregion
21977
21977
  //#region src/managers/setup.ts
@@ -25722,13 +25722,59 @@ var WeaveImageCrop = class WeaveImageCrop {
25722
25722
  };
25723
25723
 
25724
25724
  //#endregion
25725
- //#region src/nodes/image/utils.ts
25726
- const extractCursorUrl = (cursor, fallback) => {
25725
+ //#region src/utils/cursors.ts
25726
+ const doPreloadCursors = async (cursorsToPreload, setCursor, getFallbackCursor, resetCursors) => {
25727
+ resetCursors();
25728
+ const promiseHandler = (state, value, src) => new Promise((resolveInt, rejectInt) => {
25729
+ const img = Konva.Util.createImageElement();
25730
+ img.onload = () => {
25731
+ const canvas = document.createElement("canvas");
25732
+ canvas.width = img.width;
25733
+ canvas.height = img.height;
25734
+ const ctx = canvas.getContext("2d");
25735
+ ctx?.drawImage(img, 0, 0);
25736
+ const dataURL = canvas.toDataURL("image/png");
25737
+ const tokens = value.split(" ");
25738
+ tokens[0] = `url(${dataURL})`;
25739
+ setCursor(state, tokens.join(" "));
25740
+ resolveInt();
25741
+ };
25742
+ img.onerror = () => {
25743
+ setCursor(state, getFallbackCursor(state));
25744
+ rejectInt(new Error(`Failed to load cursor: ${src}`));
25745
+ };
25746
+ img.src = src;
25747
+ });
25748
+ return new Promise((resolve) => {
25749
+ (async () => {
25750
+ const cursors = Object.keys(cursorsToPreload);
25751
+ const cursorUrls = [];
25752
+ for (const cursorKey of cursors) {
25753
+ const cursorValue = cursorsToPreload[cursorKey];
25754
+ if (hasValidUrl(cursorValue)) {
25755
+ const { preload, cursor } = extractCursorUrl(cursorValue);
25756
+ if (preload) cursorUrls.push({
25757
+ state: cursorKey,
25758
+ value: cursorValue,
25759
+ src: cursor
25760
+ });
25761
+ } else setCursor(cursorKey, cursorValue);
25762
+ }
25763
+ if (cursorUrls.length > 0) {
25764
+ const cursorsPreloading = [];
25765
+ for (const { state, value, src } of cursorUrls) cursorsPreloading.push(promiseHandler(state, value, src));
25766
+ await Promise.allSettled(cursorsPreloading);
25767
+ }
25768
+ resolve();
25769
+ })();
25770
+ });
25771
+ };
25772
+ const extractCursorUrl = (cursor) => {
25727
25773
  const lower = cursor.toLowerCase();
25728
25774
  const start = lower.indexOf("url(");
25729
25775
  if (start === -1) return {
25730
25776
  preload: false,
25731
- cursor
25777
+ cursor: null
25732
25778
  };
25733
25779
  let i = start + 4;
25734
25780
  const len = cursor.length;
@@ -25741,31 +25787,29 @@ const extractCursorUrl = (cursor, fallback) => {
25741
25787
  let buf = "";
25742
25788
  for (; i < len; i++) {
25743
25789
  const ch = cursor[i];
25744
- if (quote) {
25745
- if (ch === quote) {
25746
- i++;
25747
- break;
25748
- }
25749
- buf += ch;
25750
- } else {
25790
+ if (quote && ch === quote) {
25791
+ i++;
25792
+ break;
25793
+ }
25794
+ if (quote) buf += ch;
25795
+ else {
25751
25796
  if (ch === ")") break;
25752
25797
  buf += ch;
25753
25798
  }
25754
25799
  }
25755
25800
  const url = buf.trim();
25756
- if (!url) return {
25757
- preload: false,
25758
- cursor: fallback
25759
- };
25760
- if (!isAllowedUrl(url)) return {
25801
+ if (!url || url && !isAllowedUrl(url)) return {
25761
25802
  preload: false,
25762
- cursor: fallback
25803
+ cursor: null
25763
25804
  };
25764
25805
  return {
25765
25806
  preload: true,
25766
25807
  cursor: url
25767
25808
  };
25768
25809
  };
25810
+ const hasValidUrl = (value) => {
25811
+ return /url\(["']?.+?["']?\)/i.test(value);
25812
+ };
25769
25813
  const isAllowedUrl = (value) => {
25770
25814
  if (/^https?:\/\//i.test(value)) return true;
25771
25815
  if (/^(javascript|data|blob|ftp):/i.test(value)) return false;
@@ -25782,6 +25826,8 @@ var WeaveImageNode = class extends WeaveNode {
25782
25826
  imageTryoutAttempts = {};
25783
25827
  imageTryoutIds = {};
25784
25828
  nodeType = WEAVE_IMAGE_NODE_TYPE;
25829
+ cursorsFallback = { loading: "wait" };
25830
+ cursors = {};
25785
25831
  constructor(params) {
25786
25832
  super();
25787
25833
  const { config } = params ?? {};
@@ -25800,31 +25846,15 @@ var WeaveImageNode = class extends WeaveNode {
25800
25846
  this.imageFallback = {};
25801
25847
  }
25802
25848
  preloadCursors() {
25803
- const promiseHandler = (src) => new Promise((resolveInt, rejectInt) => {
25804
- const img = Konva.Util.createImageElement();
25805
- img.onload = () => {
25806
- resolveInt();
25807
- };
25808
- img.onerror = () => {
25809
- rejectInt(new Error(`Failed to load cursor image: ${src}`));
25810
- };
25811
- img.src = src;
25812
- });
25813
25849
  return new Promise((resolve) => {
25814
25850
  (async () => {
25815
- const cursors = Object.keys(this.config.style.cursor);
25816
- const cursorUrls = [];
25817
- const cursorFallback = { loading: "wait" };
25818
- for (const cursorKey of cursors) {
25819
- const cursorValue = this.config.style.cursor[cursorKey];
25820
- const { preload, cursor } = extractCursorUrl(cursorValue, cursorFallback[cursorKey]);
25821
- if (preload) cursorUrls.push({ src: cursor });
25822
- }
25823
- if (cursorUrls.length > 0) {
25824
- const cursorsPreloading = [];
25825
- for (const { src } of cursorUrls) cursorsPreloading.push(promiseHandler(src));
25826
- await Promise.allSettled(cursorsPreloading);
25827
- }
25851
+ await doPreloadCursors(this.config.style.cursor, (state, cursor) => {
25852
+ this.cursors[state] = cursor;
25853
+ }, (state) => {
25854
+ return this.cursorsFallback[state] || "default";
25855
+ }, () => {
25856
+ this.cursors = {};
25857
+ });
25828
25858
  resolve();
25829
25859
  })();
25830
25860
  });
@@ -25908,7 +25938,7 @@ var WeaveImageNode = class extends WeaveNode {
25908
25938
  });
25909
25939
  this.setupDefaultNodeAugmentation(image);
25910
25940
  image.defineMousePointer = () => {
25911
- if (this.imageState[id]?.status === "loading") return this.config.style.cursor.loading;
25941
+ if (this.imageState[id]?.status === "loading") return this.cursors["loading"];
25912
25942
  const selectedNodes = this.getSelectionPlugin()?.getSelectedNodes() ?? [];
25913
25943
  if (this.isSelecting() && selectedNodes.includes(image)) return "grab";
25914
25944
  return "pointer";
@@ -25991,15 +26021,17 @@ var WeaveImageNode = class extends WeaveNode {
25991
26021
  image.dblClick = () => {
25992
26022
  if (this.imageState[id]?.loaded && !this.imageState[id]?.error) this.config.onDblClick?.(this, image);
25993
26023
  };
25994
- if (this.imageSource[id] && imageProps.imageURL) {
26024
+ const hasFinalImageLoaded = this.imageSource[id] && imageProps.imageURL;
26025
+ const hasFallbackAndFinalImageNotLoaded = !imageProps.imageURL && this.imageFallback[id] && this.config.useFallbackImage;
26026
+ if (hasFinalImageLoaded || hasFallbackAndFinalImageNotLoaded) {
25995
26027
  imagePlaceholder?.destroy();
25996
- const imageSource = this.imageSource[id];
26028
+ const imageSource = hasFallbackAndFinalImageNotLoaded ? this.imageFallback[id] : this.imageSource[id];
25997
26029
  internalImage.setAttrs({
25998
26030
  image: imageSource,
25999
26031
  visible: true
26000
26032
  });
26001
- let sourceImageWidth = this.imageSource[id].width;
26002
- let sourceImageHeight = this.imageSource[id].height;
26033
+ let sourceImageWidth = imageSource.width;
26034
+ let sourceImageHeight = imageSource.height;
26003
26035
  if (image.getAttrs().imageInfo) {
26004
26036
  sourceImageWidth = image.getAttrs().imageInfo.width;
26005
26037
  sourceImageHeight = image.getAttrs().imageInfo.height;
@@ -26017,7 +26049,7 @@ var WeaveImageNode = class extends WeaveNode {
26017
26049
  height: sourceImageHeight
26018
26050
  });
26019
26051
  this.imageState[id] = {
26020
- status: "loaded",
26052
+ status: hasFallbackAndFinalImageNotLoaded ? "loading" : "loaded",
26021
26053
  loaded: true,
26022
26054
  error: false
26023
26055
  };
@@ -26620,12 +26652,16 @@ var WeaveImageNode = class extends WeaveNode {
26620
26652
  const nodeId = nodeInstance.getAttrs().id ?? "";
26621
26653
  const isMoveContainer = nodeInstance.getAttr("onMoveContainer");
26622
26654
  nodeInstance.setAttr("onMoveContainer", void 0);
26655
+ if (this.imageTryoutIds[nodeId]) {
26656
+ clearTimeout(this.imageTryoutIds[nodeId]);
26657
+ delete this.imageTryoutIds[nodeId];
26658
+ }
26623
26659
  if (!isMoveContainer) {
26624
26660
  delete this.imageSource[nodeId];
26625
26661
  delete this.imageState[nodeId];
26662
+ delete this.imageTryoutAttempts[nodeId];
26663
+ delete this.imageFallback[nodeId];
26626
26664
  }
26627
- delete this.imageTryoutAttempts[nodeId];
26628
- delete this.imageFallback[nodeId];
26629
26665
  nodeInstance.destroy();
26630
26666
  }
26631
26667
  };
@@ -36050,50 +36086,17 @@ var WeaveCommentToolAction = class extends WeaveAction {
36050
36086
  opacity: 1
36051
36087
  };
36052
36088
  }
36053
- extractCursorUrl(cursor) {
36054
- const lower = cursor.toLowerCase();
36055
- const start = lower.indexOf("url(");
36056
- if (start === -1) return null;
36057
- let i = start + 4;
36058
- const len = cursor.length;
36059
- while (i < len && /\s/.test(cursor[i])) i++;
36060
- let quote = null;
36061
- if (cursor[i] === "\"" || cursor[i] === "'") {
36062
- quote = cursor[i];
36063
- i++;
36064
- }
36065
- let buf = "";
36066
- for (; i < len; i++) {
36067
- const ch = cursor[i];
36068
- if (quote) {
36069
- if (ch === quote) {
36070
- i++;
36071
- break;
36072
- }
36073
- buf += ch;
36074
- } else {
36075
- if (ch === ")") break;
36076
- buf += ch;
36077
- }
36078
- }
36079
- const url = buf.trim();
36080
- if (!url) return null;
36081
- return this.isAllowedUrl(url) ? url : null;
36082
- }
36083
- isAllowedUrl(value) {
36084
- if (/^https?:\/\//i.test(value)) return true;
36085
- if (/^(javascript|data|blob|ftp):/i.test(value)) return false;
36086
- return true;
36087
- }
36088
36089
  preloadCursors() {
36089
36090
  const stage = this.instance.getStage();
36090
- const cursorUrls = [{
36091
- src: this.extractCursorUrl(this.config.style.cursor.add) ?? "",
36092
- cursor: this.config.style.cursor.add
36093
- }, {
36094
- src: this.extractCursorUrl(this.config.style.cursor.block) ?? "",
36095
- cursor: this.config.style.cursor.block
36096
- }];
36091
+ const cursorUrls = [];
36092
+ for (const cursorKey in this.config.style.cursor) {
36093
+ const cursorValue = this.config.style.cursor[cursorKey];
36094
+ const { preload, cursor } = extractCursorUrl(this.config.style.cursor.add) ?? "";
36095
+ if (preload) cursorUrls.push({
36096
+ src: cursor,
36097
+ cursor: cursorValue
36098
+ });
36099
+ }
36097
36100
  const actualCursor = stage.container().style.cursor;
36098
36101
  cursorUrls.forEach(({ src, cursor }) => {
36099
36102
  const img = Konva.Util.createImageElement();
@@ -39847,4 +39850,4 @@ function getJSONFromYjsBinary(actualState) {
39847
39850
  }
39848
39851
 
39849
39852
  //#endregion
39850
- export { ALIGN_NODES_ALIGN_TO, ALIGN_NODES_TOOL_ACTION_NAME, ALIGN_NODES_TOOL_STATE, ARROW_TOOL_ACTION_NAME, ARROW_TOOL_STATE, BRUSH_TOOL_ACTION_NAME, BRUSH_TOOL_DEFAULT_CONFIG, BRUSH_TOOL_STATE, CONNECTOR_TOOL_ACTION_NAME, CONNECTOR_TOOL_DEFAULT_CONFIG, CONNECTOR_TOOL_STATE, COPY_PASTE_NODES_PLUGIN_STATE, ELLIPSE_TOOL_ACTION_NAME, ELLIPSE_TOOL_STATE, ERASER_TOOL_ACTION_NAME, ERASER_TOOL_STATE, FRAME_TOOL_ACTION_NAME, FRAME_TOOL_STATE, GUIDE_DISTANCE_LINE_DEFAULT_CONFIG, GUIDE_ENTER_SNAPPING_TOLERANCE, GUIDE_EXIT_SNAPPING_TOLERANCE, GUIDE_HORIZONTAL_LINE_NAME, GUIDE_LINE_DEFAULT_CONFIG, GUIDE_LINE_DRAG_SNAPPING_THRESHOLD, GUIDE_LINE_NAME, GUIDE_LINE_TRANSFORM_SNAPPING_THRESHOLD, GUIDE_ORIENTATION, GUIDE_VERTICAL_LINE_NAME, LINE_TOOL_ACTION_NAME, LINE_TOOL_DEFAULT_CONFIG, LINE_TOOL_STATE, MEASURE_TOOL_ACTION_NAME, MEASURE_TOOL_STATE, MOVE_TOOL_ACTION_NAME, MOVE_TOOL_STATE, NODE_SNAP, NODE_SNAP_HORIZONTAL, NODE_SNAP_VERTICAL, PEN_TOOL_ACTION_NAME, PEN_TOOL_STATE, RECTANGLE_TOOL_ACTION_NAME, RECTANGLE_TOOL_STATE, REGULAR_POLYGON_TOOL_ACTION_NAME, REGULAR_POLYGON_TOOL_STATE, SELECTION_TOOL_ACTION_NAME, SELECTION_TOOL_STATE, STAGE_MINIMAP_DEFAULT_CONFIG, STAR_TOOL_ACTION_NAME, STAR_TOOL_STATE, TEXT_LAYOUT, TEXT_TOOL_ACTION_NAME, TEXT_TOOL_STATE, VIDEO_TOOL_ACTION_NAME, VIDEO_TOOL_STATE, WEAVE_ARROW_NODE_TYPE, WEAVE_COMMENTS_RENDERER_KEY, WEAVE_COMMENTS_TOOL_LAYER_ID, WEAVE_COMMENT_CREATE_ACTION, WEAVE_COMMENT_NODE_ACTION, WEAVE_COMMENT_NODE_DEFAULTS, WEAVE_COMMENT_NODE_TYPE, WEAVE_COMMENT_STATUS, WEAVE_COMMENT_TOOL_ACTION_NAME, WEAVE_COMMENT_TOOL_DEFAULT_CONFIG, WEAVE_COMMENT_TOOL_STATE, WEAVE_COMMENT_VIEW_ACTION, WEAVE_CONNECTOR_NODE_ANCHOR_ORIGIN, WEAVE_CONNECTOR_NODE_DECORATOR_TYPE, WEAVE_CONNECTOR_NODE_DEFAULT_CONFIG, WEAVE_CONNECTOR_NODE_LINE_ORIGIN, WEAVE_CONNECTOR_NODE_LINE_TYPE, WEAVE_CONNECTOR_NODE_TYPE, WEAVE_COPY_PASTE_CONFIG_DEFAULT, WEAVE_COPY_PASTE_NODES_KEY, WEAVE_COPY_PASTE_PASTE_CATCHER_ID, WEAVE_COPY_PASTE_PASTE_MODES, WEAVE_DEFAULT_USER_INFO_FUNCTION, WEAVE_ELLIPSE_NODE_TYPE, WEAVE_FRAME_DEFAULT_BACKGROUND_COLOR, WEAVE_FRAME_NODE_DEFAULT_CONFIG, WEAVE_FRAME_NODE_DEFAULT_PROPS, WEAVE_FRAME_NODE_TYPE, WEAVE_GRID_DEFAULT_COLOR, WEAVE_GRID_DEFAULT_DOT_MAX_DOTS_PER_AXIS, WEAVE_GRID_DEFAULT_MAJOR_DOT_RATIO, WEAVE_GRID_DEFAULT_MAJOR_EVERY, WEAVE_GRID_DEFAULT_MAJOR_LINE_RATIO, WEAVE_GRID_DEFAULT_ORIGIN_COLOR, WEAVE_GRID_DEFAULT_RADIUS, WEAVE_GRID_DEFAULT_SIZE, WEAVE_GRID_DEFAULT_STROKE, WEAVE_GRID_DEFAULT_TYPE, WEAVE_GRID_LAYER_ID, WEAVE_GRID_TYPES, WEAVE_GROUP_NODE_TYPE, WEAVE_IMAGES_TOOL_ACTION_NAME, WEAVE_IMAGES_TOOL_DEFAULT_CONFIG, WEAVE_IMAGES_TOOL_STATE, WEAVE_IMAGES_TOOL_UPLOAD_TYPE, WEAVE_IMAGE_CROP_ANCHOR_POSITION, WEAVE_IMAGE_CROP_END_TYPE, WEAVE_IMAGE_DEFAULT_CONFIG, WEAVE_IMAGE_NODE_TYPE, WEAVE_IMAGE_TOOL_ACTION_NAME, WEAVE_IMAGE_TOOL_CONFIG_DEFAULT, WEAVE_IMAGE_TOOL_STATE, WEAVE_IMAGE_TOOL_UPLOAD_TYPE, WEAVE_LAYER_NODE_TYPE, WEAVE_LINE_NODE_DEFAULT_CONFIG, WEAVE_LINE_NODE_TYPE, WEAVE_MEASURE_NODE_DEFAULT_CONFIG, WEAVE_MEASURE_NODE_TYPE, WEAVE_MEASURE_TOOL_DEFAULT_CONFIG, WEAVE_NODES_DISTANCE_SNAPPING_PLUGIN_KEY, WEAVE_NODES_EDGE_SNAPPING_PLUGIN_KEY, WEAVE_NODES_MULTI_SELECTION_FEEDBACK_PLUGIN_DEFAULT_CONFIG, WEAVE_NODES_MULTI_SELECTION_FEEDBACK_PLUGIN_KEY, WEAVE_NODES_MULTI_SELECTION_FEEDBACK_PLUGIN_LAYER_ID, WEAVE_NODES_SELECTION_DEFAULT_CONFIG, WEAVE_NODES_SELECTION_KEY, WEAVE_NODES_SELECTION_LAYER_ID, WEAVE_RECTANGLE_NODE_TYPE, WEAVE_REGULAR_POLYGON_NODE_TYPE, WEAVE_STAGE_DEFAULT_MODE, WEAVE_STAGE_DROP_AREA_KEY, WEAVE_STAGE_GRID_PLUGIN_KEY, WEAVE_STAGE_IMAGE_CROPPING_MODE, WEAVE_STAGE_KEYBOARD_MOVE_DEFAULT_CONFIG, WEAVE_STAGE_KEYBOARD_MOVE_KEY, WEAVE_STAGE_MINIMAP_KEY, WEAVE_STAGE_NODE_TYPE, WEAVE_STAGE_PANNING_DEFAULT_CONFIG, WEAVE_STAGE_PANNING_KEY, WEAVE_STAGE_PANNING_THROTTLE_MS, WEAVE_STAGE_TEXT_EDITION_MODE, WEAVE_STAR_NODE_TYPE, WEAVE_STROKE_NODE_DEFAULT_CONFIG, WEAVE_STROKE_NODE_TYPE, WEAVE_STROKE_SINGLE_NODE_DEFAULT_CONFIG, WEAVE_STROKE_SINGLE_NODE_TIP_SIDE, WEAVE_STROKE_SINGLE_NODE_TIP_TYPE, WEAVE_STROKE_SINGLE_NODE_TYPE, WEAVE_STROKE_TOOL_ACTION_NAME, WEAVE_STROKE_TOOL_ACTION_NAME_ALIASES, WEAVE_STROKE_TOOL_DEFAULT_CONFIG, WEAVE_STROKE_TOOL_STATE, WEAVE_TEXT_NODE_DEFAULT_CONFIG, WEAVE_TEXT_NODE_TYPE, WEAVE_USERS_POINTERS_CONFIG_DEFAULT_PROPS, WEAVE_USERS_POINTERS_KEY, WEAVE_USERS_PRESENCE_CONFIG_DEFAULT_PROPS, WEAVE_USERS_PRESENCE_PLUGIN_KEY, WEAVE_USERS_SELECTION_KEY, WEAVE_USER_POINTER_KEY, WEAVE_USER_PRESENCE_KEY, WEAVE_USER_SELECTION_KEY, WEAVE_VIDEO_DEFAULT_CONFIG, WEAVE_VIDEO_NODE_TYPE, Weave, WeaveAction, WeaveAlignNodesToolAction, WeaveArrowNode, WeaveArrowToolAction, WeaveBrushToolAction, WeaveCommentNode, WeaveCommentToolAction, WeaveCommentsRendererPlugin, WeaveConnectedUsersPlugin, WeaveConnectorNode, WeaveConnectorToolAction, WeaveContextMenuPlugin, WeaveCopyPasteNodesPlugin, WeaveEllipseNode, WeaveEllipseToolAction, WeaveEraserToolAction, WeaveExportNodesToolAction, WeaveExportStageToolAction, WeaveFitToScreenToolAction, WeaveFitToSelectionToolAction, WeaveFrameNode, WeaveFrameToolAction, WeaveGroupNode, WeaveImageNode, WeaveImageToolAction, WeaveImagesToolAction, WeaveLayerNode, WeaveLineNode, WeaveLineToolAction, WeaveMeasureNode, WeaveMeasureToolAction, WeaveMoveToolAction, WeaveNode, WeaveNodesDistanceSnappingPlugin, WeaveNodesEdgeSnappingPlugin, WeaveNodesMultiSelectionFeedbackPlugin, WeaveNodesSelectionPlugin, WeavePenToolAction, WeavePlugin, WeaveRectangleNode, WeaveRectangleToolAction, WeaveRegularPolygonNode, WeaveRegularPolygonToolAction, WeaveRenderer, WeaveSelectionToolAction, WeaveStageDropAreaPlugin, WeaveStageGridPlugin, WeaveStageKeyboardMovePlugin, WeaveStageMinimapPlugin, WeaveStageNode, WeaveStagePanningPlugin, WeaveStageResizePlugin, WeaveStageZoomPlugin, WeaveStarNode, WeaveStarToolAction, WeaveStore, WeaveStrokeNode, WeaveStrokeSingleNode, WeaveStrokeToolAction, WeaveTextNode, WeaveTextToolAction, WeaveUsersPointersPlugin, WeaveUsersPresencePlugin, WeaveUsersSelectionPlugin, WeaveVideoNode, WeaveVideoToolAction, WeaveZoomInToolAction, WeaveZoomOutToolAction, canComposite, clearContainerTargets, containerOverCursor, containsNodeDeep, defaultInitialState, downscaleImageFile, downscaleImageFromURL, getBoundingBox, getDownscaleRatio, getExportBoundingBox, getImageSizeFromFile, getJSONFromYjsBinary, getPositionRelativeToContainerOnPosition, getSelectedNodesMetadata, getStageClickPoint, getTargetAndSkipNodes, getTargetedNode, getTopmostShadowHost, getVisibleNodes, getVisibleNodesInViewport, hasFrames, hasImages, intersectArrays, isArray, isIOS, isInShadowDOM, isNodeInSelection, isObject, isServer, loadImageSource, mapJsonToYjsArray, mapJsonToYjsElements, mapJsonToYjsMap, memoize, mergeExceptArrays, moveNodeToContainer, moveNodeToContainerNT, resetScale, weavejsToYjsBinary };
39853
+ 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_STAGE_ZOOM_DEFAULT_CONFIG, WEAVE_STAGE_ZOOM_KEY, WEAVE_STAGE_ZOOM_TYPE, WEAVE_STAR_NODE_TYPE, WEAVE_STROKE_NODE_DEFAULT_CONFIG, WEAVE_STROKE_NODE_TYPE, WEAVE_STROKE_SINGLE_NODE_DEFAULT_CONFIG, WEAVE_STROKE_SINGLE_NODE_TIP_SIDE, WEAVE_STROKE_SINGLE_NODE_TIP_TYPE, WEAVE_STROKE_SINGLE_NODE_TYPE, WEAVE_STROKE_TOOL_ACTION_NAME, WEAVE_STROKE_TOOL_ACTION_NAME_ALIASES, WEAVE_STROKE_TOOL_DEFAULT_CONFIG, WEAVE_STROKE_TOOL_STATE, WEAVE_TEXT_NODE_DEFAULT_CONFIG, WEAVE_TEXT_NODE_TYPE, WEAVE_USERS_POINTERS_CONFIG_DEFAULT_PROPS, WEAVE_USERS_POINTERS_KEY, WEAVE_USERS_PRESENCE_CONFIG_DEFAULT_PROPS, WEAVE_USERS_PRESENCE_PLUGIN_KEY, WEAVE_USERS_SELECTION_KEY, WEAVE_USER_POINTER_KEY, WEAVE_USER_PRESENCE_KEY, WEAVE_USER_SELECTION_KEY, WEAVE_VIDEO_DEFAULT_CONFIG, WEAVE_VIDEO_NODE_TYPE, Weave, WeaveAction, WeaveAlignNodesToolAction, WeaveArrowNode, WeaveArrowToolAction, WeaveBrushToolAction, WeaveCommentNode, WeaveCommentToolAction, WeaveCommentsRendererPlugin, WeaveConnectedUsersPlugin, WeaveConnectorNode, WeaveConnectorToolAction, WeaveContextMenuPlugin, WeaveCopyPasteNodesPlugin, WeaveEllipseNode, WeaveEllipseToolAction, WeaveEraserToolAction, WeaveExportNodesToolAction, WeaveExportStageToolAction, WeaveFitToScreenToolAction, WeaveFitToSelectionToolAction, WeaveFrameNode, WeaveFrameToolAction, WeaveGroupNode, WeaveImageNode, WeaveImageToolAction, WeaveImagesToolAction, WeaveLayerNode, WeaveLineNode, WeaveLineToolAction, WeaveMeasureNode, WeaveMeasureToolAction, WeaveMoveToolAction, WeaveNode, WeaveNodesDistanceSnappingPlugin, WeaveNodesEdgeSnappingPlugin, WeaveNodesMultiSelectionFeedbackPlugin, WeaveNodesSelectionPlugin, WeavePenToolAction, WeavePlugin, WeaveRectangleNode, WeaveRectangleToolAction, WeaveRegularPolygonNode, WeaveRegularPolygonToolAction, WeaveRenderer, WeaveSelectionToolAction, WeaveStageDropAreaPlugin, WeaveStageGridPlugin, WeaveStageKeyboardMovePlugin, WeaveStageMinimapPlugin, WeaveStageNode, WeaveStagePanningPlugin, WeaveStageResizePlugin, WeaveStageZoomPlugin, WeaveStarNode, WeaveStarToolAction, WeaveStore, WeaveStrokeNode, WeaveStrokeSingleNode, WeaveStrokeToolAction, WeaveTextNode, WeaveTextToolAction, WeaveUsersPointersPlugin, WeaveUsersPresencePlugin, WeaveUsersSelectionPlugin, WeaveVideoNode, WeaveVideoToolAction, WeaveZoomInToolAction, WeaveZoomOutToolAction, canComposite, clearContainerTargets, containerOverCursor, containsNodeDeep, defaultInitialState, downscaleImageFile, downscaleImageFromURL, getBoundingBox, getDownscaleRatio, getExportBoundingBox, getImageSizeFromFile, getJSONFromYjsBinary, getPositionRelativeToContainerOnPosition, getSelectedNodesMetadata, getStageClickPoint, getTargetAndSkipNodes, getTargetedNode, getTopmostShadowHost, getVisibleNodes, getVisibleNodesInViewport, hasFrames, hasImages, intersectArrays, isArray, isIOS, isInShadowDOM, isNodeInSelection, isObject, isServer, loadImageSource, mapJsonToYjsArray, mapJsonToYjsElements, mapJsonToYjsMap, memoize, mergeExceptArrays, moveNodeToContainer, moveNodeToContainerNT, resetScale, weavejsToYjsBinary };
package/dist/sdk.node.js CHANGED
@@ -21970,7 +21970,7 @@ var WeaveRegisterManager = class {
21970
21970
 
21971
21971
  //#endregion
21972
21972
  //#region package.json
21973
- var version = "3.2.3";
21973
+ var version = "3.2.5";
21974
21974
 
21975
21975
  //#endregion
21976
21976
  //#region src/managers/setup.ts
@@ -25721,13 +25721,59 @@ var WeaveImageCrop = class WeaveImageCrop {
25721
25721
  };
25722
25722
 
25723
25723
  //#endregion
25724
- //#region src/nodes/image/utils.ts
25725
- const extractCursorUrl = (cursor, fallback) => {
25724
+ //#region src/utils/cursors.ts
25725
+ const doPreloadCursors = async (cursorsToPreload, setCursor, getFallbackCursor, resetCursors) => {
25726
+ resetCursors();
25727
+ const promiseHandler = (state, value, src) => new Promise((resolveInt, rejectInt) => {
25728
+ const img = Konva.Util.createImageElement();
25729
+ img.onload = () => {
25730
+ const canvas = document.createElement("canvas");
25731
+ canvas.width = img.width;
25732
+ canvas.height = img.height;
25733
+ const ctx = canvas.getContext("2d");
25734
+ ctx?.drawImage(img, 0, 0);
25735
+ const dataURL = canvas.toDataURL("image/png");
25736
+ const tokens = value.split(" ");
25737
+ tokens[0] = `url(${dataURL})`;
25738
+ setCursor(state, tokens.join(" "));
25739
+ resolveInt();
25740
+ };
25741
+ img.onerror = () => {
25742
+ setCursor(state, getFallbackCursor(state));
25743
+ rejectInt(new Error(`Failed to load cursor: ${src}`));
25744
+ };
25745
+ img.src = src;
25746
+ });
25747
+ return new Promise((resolve) => {
25748
+ (async () => {
25749
+ const cursors = Object.keys(cursorsToPreload);
25750
+ const cursorUrls = [];
25751
+ for (const cursorKey of cursors) {
25752
+ const cursorValue = cursorsToPreload[cursorKey];
25753
+ if (hasValidUrl(cursorValue)) {
25754
+ const { preload, cursor } = extractCursorUrl(cursorValue);
25755
+ if (preload) cursorUrls.push({
25756
+ state: cursorKey,
25757
+ value: cursorValue,
25758
+ src: cursor
25759
+ });
25760
+ } else setCursor(cursorKey, cursorValue);
25761
+ }
25762
+ if (cursorUrls.length > 0) {
25763
+ const cursorsPreloading = [];
25764
+ for (const { state, value, src } of cursorUrls) cursorsPreloading.push(promiseHandler(state, value, src));
25765
+ await Promise.allSettled(cursorsPreloading);
25766
+ }
25767
+ resolve();
25768
+ })();
25769
+ });
25770
+ };
25771
+ const extractCursorUrl = (cursor) => {
25726
25772
  const lower = cursor.toLowerCase();
25727
25773
  const start = lower.indexOf("url(");
25728
25774
  if (start === -1) return {
25729
25775
  preload: false,
25730
- cursor
25776
+ cursor: null
25731
25777
  };
25732
25778
  let i = start + 4;
25733
25779
  const len = cursor.length;
@@ -25740,31 +25786,29 @@ const extractCursorUrl = (cursor, fallback) => {
25740
25786
  let buf = "";
25741
25787
  for (; i < len; i++) {
25742
25788
  const ch = cursor[i];
25743
- if (quote) {
25744
- if (ch === quote) {
25745
- i++;
25746
- break;
25747
- }
25748
- buf += ch;
25749
- } else {
25789
+ if (quote && ch === quote) {
25790
+ i++;
25791
+ break;
25792
+ }
25793
+ if (quote) buf += ch;
25794
+ else {
25750
25795
  if (ch === ")") break;
25751
25796
  buf += ch;
25752
25797
  }
25753
25798
  }
25754
25799
  const url = buf.trim();
25755
- if (!url) return {
25756
- preload: false,
25757
- cursor: fallback
25758
- };
25759
- if (!isAllowedUrl(url)) return {
25800
+ if (!url || url && !isAllowedUrl(url)) return {
25760
25801
  preload: false,
25761
- cursor: fallback
25802
+ cursor: null
25762
25803
  };
25763
25804
  return {
25764
25805
  preload: true,
25765
25806
  cursor: url
25766
25807
  };
25767
25808
  };
25809
+ const hasValidUrl = (value) => {
25810
+ return /url\(["']?.+?["']?\)/i.test(value);
25811
+ };
25768
25812
  const isAllowedUrl = (value) => {
25769
25813
  if (/^https?:\/\//i.test(value)) return true;
25770
25814
  if (/^(javascript|data|blob|ftp):/i.test(value)) return false;
@@ -25781,6 +25825,8 @@ var WeaveImageNode = class extends WeaveNode {
25781
25825
  imageTryoutAttempts = {};
25782
25826
  imageTryoutIds = {};
25783
25827
  nodeType = WEAVE_IMAGE_NODE_TYPE;
25828
+ cursorsFallback = { loading: "wait" };
25829
+ cursors = {};
25784
25830
  constructor(params) {
25785
25831
  super();
25786
25832
  const { config } = params ?? {};
@@ -25799,31 +25845,15 @@ var WeaveImageNode = class extends WeaveNode {
25799
25845
  this.imageFallback = {};
25800
25846
  }
25801
25847
  preloadCursors() {
25802
- const promiseHandler = (src) => new Promise((resolveInt, rejectInt) => {
25803
- const img = Konva.Util.createImageElement();
25804
- img.onload = () => {
25805
- resolveInt();
25806
- };
25807
- img.onerror = () => {
25808
- rejectInt(new Error(`Failed to load cursor image: ${src}`));
25809
- };
25810
- img.src = src;
25811
- });
25812
25848
  return new Promise((resolve) => {
25813
25849
  (async () => {
25814
- const cursors = Object.keys(this.config.style.cursor);
25815
- const cursorUrls = [];
25816
- const cursorFallback = { loading: "wait" };
25817
- for (const cursorKey of cursors) {
25818
- const cursorValue = this.config.style.cursor[cursorKey];
25819
- const { preload, cursor } = extractCursorUrl(cursorValue, cursorFallback[cursorKey]);
25820
- if (preload) cursorUrls.push({ src: cursor });
25821
- }
25822
- if (cursorUrls.length > 0) {
25823
- const cursorsPreloading = [];
25824
- for (const { src } of cursorUrls) cursorsPreloading.push(promiseHandler(src));
25825
- await Promise.allSettled(cursorsPreloading);
25826
- }
25850
+ await doPreloadCursors(this.config.style.cursor, (state, cursor) => {
25851
+ this.cursors[state] = cursor;
25852
+ }, (state) => {
25853
+ return this.cursorsFallback[state] || "default";
25854
+ }, () => {
25855
+ this.cursors = {};
25856
+ });
25827
25857
  resolve();
25828
25858
  })();
25829
25859
  });
@@ -25907,7 +25937,7 @@ var WeaveImageNode = class extends WeaveNode {
25907
25937
  });
25908
25938
  this.setupDefaultNodeAugmentation(image);
25909
25939
  image.defineMousePointer = () => {
25910
- if (this.imageState[id]?.status === "loading") return this.config.style.cursor.loading;
25940
+ if (this.imageState[id]?.status === "loading") return this.cursors["loading"];
25911
25941
  const selectedNodes = this.getSelectionPlugin()?.getSelectedNodes() ?? [];
25912
25942
  if (this.isSelecting() && selectedNodes.includes(image)) return "grab";
25913
25943
  return "pointer";
@@ -25990,15 +26020,17 @@ var WeaveImageNode = class extends WeaveNode {
25990
26020
  image.dblClick = () => {
25991
26021
  if (this.imageState[id]?.loaded && !this.imageState[id]?.error) this.config.onDblClick?.(this, image);
25992
26022
  };
25993
- if (this.imageSource[id] && imageProps.imageURL) {
26023
+ const hasFinalImageLoaded = this.imageSource[id] && imageProps.imageURL;
26024
+ const hasFallbackAndFinalImageNotLoaded = !imageProps.imageURL && this.imageFallback[id] && this.config.useFallbackImage;
26025
+ if (hasFinalImageLoaded || hasFallbackAndFinalImageNotLoaded) {
25994
26026
  imagePlaceholder?.destroy();
25995
- const imageSource = this.imageSource[id];
26027
+ const imageSource = hasFallbackAndFinalImageNotLoaded ? this.imageFallback[id] : this.imageSource[id];
25996
26028
  internalImage.setAttrs({
25997
26029
  image: imageSource,
25998
26030
  visible: true
25999
26031
  });
26000
- let sourceImageWidth = this.imageSource[id].width;
26001
- let sourceImageHeight = this.imageSource[id].height;
26032
+ let sourceImageWidth = imageSource.width;
26033
+ let sourceImageHeight = imageSource.height;
26002
26034
  if (image.getAttrs().imageInfo) {
26003
26035
  sourceImageWidth = image.getAttrs().imageInfo.width;
26004
26036
  sourceImageHeight = image.getAttrs().imageInfo.height;
@@ -26016,7 +26048,7 @@ var WeaveImageNode = class extends WeaveNode {
26016
26048
  height: sourceImageHeight
26017
26049
  });
26018
26050
  this.imageState[id] = {
26019
- status: "loaded",
26051
+ status: hasFallbackAndFinalImageNotLoaded ? "loading" : "loaded",
26020
26052
  loaded: true,
26021
26053
  error: false
26022
26054
  };
@@ -26619,12 +26651,16 @@ var WeaveImageNode = class extends WeaveNode {
26619
26651
  const nodeId = nodeInstance.getAttrs().id ?? "";
26620
26652
  const isMoveContainer = nodeInstance.getAttr("onMoveContainer");
26621
26653
  nodeInstance.setAttr("onMoveContainer", void 0);
26654
+ if (this.imageTryoutIds[nodeId]) {
26655
+ clearTimeout(this.imageTryoutIds[nodeId]);
26656
+ delete this.imageTryoutIds[nodeId];
26657
+ }
26622
26658
  if (!isMoveContainer) {
26623
26659
  delete this.imageSource[nodeId];
26624
26660
  delete this.imageState[nodeId];
26661
+ delete this.imageTryoutAttempts[nodeId];
26662
+ delete this.imageFallback[nodeId];
26625
26663
  }
26626
- delete this.imageTryoutAttempts[nodeId];
26627
- delete this.imageFallback[nodeId];
26628
26664
  nodeInstance.destroy();
26629
26665
  }
26630
26666
  };
@@ -36049,50 +36085,17 @@ var WeaveCommentToolAction = class extends WeaveAction {
36049
36085
  opacity: 1
36050
36086
  };
36051
36087
  }
36052
- extractCursorUrl(cursor) {
36053
- const lower = cursor.toLowerCase();
36054
- const start = lower.indexOf("url(");
36055
- if (start === -1) return null;
36056
- let i = start + 4;
36057
- const len = cursor.length;
36058
- while (i < len && /\s/.test(cursor[i])) i++;
36059
- let quote = null;
36060
- if (cursor[i] === "\"" || cursor[i] === "'") {
36061
- quote = cursor[i];
36062
- i++;
36063
- }
36064
- let buf = "";
36065
- for (; i < len; i++) {
36066
- const ch = cursor[i];
36067
- if (quote) {
36068
- if (ch === quote) {
36069
- i++;
36070
- break;
36071
- }
36072
- buf += ch;
36073
- } else {
36074
- if (ch === ")") break;
36075
- buf += ch;
36076
- }
36077
- }
36078
- const url = buf.trim();
36079
- if (!url) return null;
36080
- return this.isAllowedUrl(url) ? url : null;
36081
- }
36082
- isAllowedUrl(value) {
36083
- if (/^https?:\/\//i.test(value)) return true;
36084
- if (/^(javascript|data|blob|ftp):/i.test(value)) return false;
36085
- return true;
36086
- }
36087
36088
  preloadCursors() {
36088
36089
  const stage = this.instance.getStage();
36089
- const cursorUrls = [{
36090
- src: this.extractCursorUrl(this.config.style.cursor.add) ?? "",
36091
- cursor: this.config.style.cursor.add
36092
- }, {
36093
- src: this.extractCursorUrl(this.config.style.cursor.block) ?? "",
36094
- cursor: this.config.style.cursor.block
36095
- }];
36090
+ const cursorUrls = [];
36091
+ for (const cursorKey in this.config.style.cursor) {
36092
+ const cursorValue = this.config.style.cursor[cursorKey];
36093
+ const { preload, cursor } = extractCursorUrl(this.config.style.cursor.add) ?? "";
36094
+ if (preload) cursorUrls.push({
36095
+ src: cursor,
36096
+ cursor: cursorValue
36097
+ });
36098
+ }
36096
36099
  const actualCursor = stage.container().style.cursor;
36097
36100
  cursorUrls.forEach(({ src, cursor }) => {
36098
36101
  const img = Konva.Util.createImageElement();
@@ -39811,4 +39814,4 @@ const setupCanvasBackend = async () => {
39811
39814
  };
39812
39815
 
39813
39816
  //#endregion
39814
- 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 };
39817
+ 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_STAGE_ZOOM_DEFAULT_CONFIG, WEAVE_STAGE_ZOOM_KEY, WEAVE_STAGE_ZOOM_TYPE, 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 };