@inditextech/weave-sdk 0.62.4 → 0.64.0

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
@@ -2,7 +2,7 @@ import Konva from "konva";
2
2
  import "konva/lib/types";
3
3
  import { WEAVE_AWARENESS_LAYER_ID, WEAVE_EXPORT_BACKGROUND_COLOR, WEAVE_EXPORT_FORMATS, WEAVE_INSTANCE_STATUS, WEAVE_NODE_CUSTOM_EVENTS, WEAVE_NODE_LAYER_ID, WEAVE_NODE_POSITION, WEAVE_STORE_CONNECTION_STATUS, WEAVE_UTILITY_LAYER_ID } from "@inditextech/weave-types";
4
4
  import { getYjsDoc, getYjsValue, observeDeep, syncedStore } from "@syncedstore/core";
5
- import { Doc, UndoManager } from "yjs";
5
+ import * as Y from "yjs";
6
6
  import { Transformer } from "konva/lib/shapes/Transformer";
7
7
  import React from "react";
8
8
  import ReactReconciler from "react-reconciler";
@@ -15540,6 +15540,10 @@ var WeaveStore = class {
15540
15540
  getStateJson() {
15541
15541
  return JSON.parse(JSON.stringify(this.state, void 0, 2));
15542
15542
  }
15543
+ getStateSnapshot() {
15544
+ const doc = this.getDocument();
15545
+ return Y.encodeStateAsUpdate(doc);
15546
+ }
15543
15547
  setup() {
15544
15548
  this.isRoomLoaded = false;
15545
15549
  this.instance.emitEvent("onRoomLoaded", this.isRoomLoaded);
@@ -15549,7 +15553,7 @@ var WeaveStore = class {
15549
15553
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
15550
15554
  );
15551
15555
  if (weaveStateValues) {
15552
- this.undoManager = new UndoManager([weaveStateValues], {
15556
+ this.undoManager = new Y.UndoManager([weaveStateValues], {
15553
15557
  captureTimeout: 250,
15554
15558
  trackedOrigins: new Set([this.config.getUser().id]),
15555
15559
  ...this.config?.undoManagerOptions
@@ -20112,7 +20116,7 @@ var WeaveCopyPasteNodesPlugin = class extends WeavePlugin {
20112
20116
  const items = await navigator.clipboard.read();
20113
20117
  if (await canHandleExternal(items)) return WEAVE_COPY_PASTE_PASTE_MODES.EXTERNAL;
20114
20118
  } catch (e) {
20115
- this.getLogger().error("Error reading clipboard data", e);
20119
+ this.getLogger().error({ error: e }, "Error reading clipboard data");
20116
20120
  return WEAVE_COPY_PASTE_PASTE_MODES.CLIPBOARD_API_ERROR;
20117
20121
  }
20118
20122
  return WEAVE_COPY_PASTE_PASTE_MODES.NOT_ALLOWED;
@@ -22049,7 +22053,7 @@ var WeaveRegisterManager = class {
22049
22053
 
22050
22054
  //#endregion
22051
22055
  //#region package.json
22052
- var version = "0.62.4";
22056
+ var version = "0.64.0";
22053
22057
 
22054
22058
  //#endregion
22055
22059
  //#region src/managers/setup.ts
@@ -22307,7 +22311,7 @@ var WeaveExportManager = class {
22307
22311
  outH
22308
22312
  };
22309
22313
  }
22310
- exportNodes(nodes, boundingNodes, options) {
22314
+ exportNodesAsImage(nodes, boundingNodes, options) {
22311
22315
  return new Promise((resolve) => {
22312
22316
  const { format: format$2 = WEAVE_EXPORT_FORMATS.PNG, padding = 0, pixelRatio = 1, backgroundColor = WEAVE_EXPORT_BACKGROUND_COLOR } = options;
22313
22317
  this.getNodesSelectionPlugin()?.disable();
@@ -22384,6 +22388,112 @@ var WeaveExportManager = class {
22384
22388
  }
22385
22389
  });
22386
22390
  }
22391
+ async exportNodesAsBuffer(nodes, boundingNodes, options) {
22392
+ const { format: format$2 = WEAVE_EXPORT_FORMATS.PNG, padding = 0, pixelRatio = 1, backgroundColor = WEAVE_EXPORT_BACKGROUND_COLOR } = options;
22393
+ this.getNodesSelectionPlugin()?.disable();
22394
+ this.getNodesDistanceSnappingPlugin()?.disable();
22395
+ this.getNodesEdgeSnappingPlugin()?.disable();
22396
+ this.getStageGridPlugin()?.disable();
22397
+ const stage = this.instance.getStage();
22398
+ const mainLayer = this.instance.getMainLayer();
22399
+ const originalPosition = {
22400
+ x: stage.x(),
22401
+ y: stage.y()
22402
+ };
22403
+ const originalScale = {
22404
+ x: stage.scaleX(),
22405
+ y: stage.scaleY()
22406
+ };
22407
+ stage.scale({
22408
+ x: 1,
22409
+ y: 1
22410
+ });
22411
+ let realNodes = [...nodes];
22412
+ if (nodes.length === 0) realNodes = mainLayer?.getChildren().map((node) => node.getAttrs().id ?? "") ?? [];
22413
+ const konvaNodes = [];
22414
+ for (const nodeId of realNodes) {
22415
+ const node = stage.findOne(`#${nodeId}`);
22416
+ if (node) konvaNodes.push(node);
22417
+ }
22418
+ if (mainLayer) {
22419
+ const bounds = getExportBoundingBox(stage, boundingNodes(konvaNodes));
22420
+ const scaleX = stage.scaleX();
22421
+ const scaleY = stage.scaleY();
22422
+ const unscaledBounds = {
22423
+ x: bounds.x / scaleX,
22424
+ y: bounds.y / scaleY,
22425
+ width: bounds.width / scaleX,
22426
+ height: bounds.height / scaleY
22427
+ };
22428
+ const exportGroup = new Konva.Group();
22429
+ const background = new Konva.Rect({
22430
+ x: unscaledBounds.x - padding,
22431
+ y: unscaledBounds.y - padding,
22432
+ width: unscaledBounds.width + 2 * padding,
22433
+ height: unscaledBounds.height + 2 * padding,
22434
+ strokeWidth: 0,
22435
+ fill: backgroundColor
22436
+ });
22437
+ exportGroup.add(background);
22438
+ for (const node of konvaNodes) {
22439
+ const clonedNode = node.clone({ id: v4_default() });
22440
+ const absPos = node.getAbsolutePosition();
22441
+ clonedNode.absolutePosition({
22442
+ x: absPos.x / scaleX,
22443
+ y: absPos.y / scaleY
22444
+ });
22445
+ exportGroup.add(clonedNode);
22446
+ }
22447
+ mainLayer.add(exportGroup);
22448
+ const backgroundRect = background.getClientRect();
22449
+ stage.batchDraw();
22450
+ const composites = [];
22451
+ const maxRenderSize = 1920;
22452
+ const tileSize = Math.floor(maxRenderSize / pixelRatio);
22453
+ const imageWidth = Math.round(backgroundRect.width);
22454
+ const imageHeight = Math.round(backgroundRect.height);
22455
+ let compositeX = 0;
22456
+ let compositeY = 0;
22457
+ for (let y = Math.round(backgroundRect.y); y < imageHeight; y += tileSize) {
22458
+ compositeX = 0;
22459
+ for (let x = Math.round(backgroundRect.x); x < imageWidth; x += tileSize) {
22460
+ const width = Math.min(tileSize, imageWidth - x);
22461
+ const height = Math.min(tileSize, imageHeight - y);
22462
+ const canvas = await exportGroup.toCanvas({
22463
+ x,
22464
+ y,
22465
+ width,
22466
+ height,
22467
+ mimeType: format$2,
22468
+ pixelRatio,
22469
+ quality: options.quality ?? 1
22470
+ });
22471
+ const buffer = canvas.toBuffer();
22472
+ composites.push({
22473
+ top: compositeY * pixelRatio,
22474
+ left: compositeX * pixelRatio,
22475
+ input: buffer
22476
+ });
22477
+ compositeX = compositeX + tileSize;
22478
+ }
22479
+ compositeY = compositeY + tileSize;
22480
+ }
22481
+ exportGroup.destroy();
22482
+ stage.position(originalPosition);
22483
+ stage.scale(originalScale);
22484
+ stage.batchDraw();
22485
+ this.getNodesSelectionPlugin()?.enable();
22486
+ this.getNodesDistanceSnappingPlugin()?.enable();
22487
+ this.getNodesEdgeSnappingPlugin()?.enable();
22488
+ this.getStageGridPlugin()?.enable();
22489
+ return {
22490
+ composites,
22491
+ width: imageWidth * pixelRatio,
22492
+ height: imageHeight * pixelRatio
22493
+ };
22494
+ }
22495
+ throw new Error("Failed to export nodes as data URL");
22496
+ }
22387
22497
  imageToBase64(img, mimeType) {
22388
22498
  const canvas = document.createElement("canvas");
22389
22499
  canvas.width = img.naturalWidth;
@@ -22436,6 +22546,51 @@ var WeavePluginsManager = class {
22436
22546
  }
22437
22547
  };
22438
22548
 
22549
+ //#endregion
22550
+ //#region src/watch-map.ts
22551
+ function watchMap(onChange, map = new Map()) {
22552
+ const handler = { get(target, prop, receiver) {
22553
+ if (prop === "set") return (key, value$1) => {
22554
+ const had = target.has(key);
22555
+ const prev = had ? target.get(key) : void 0;
22556
+ target.set(key, value$1);
22557
+ onChange({
22558
+ type: had ? "update" : "add",
22559
+ key,
22560
+ value: value$1,
22561
+ prevValue: prev,
22562
+ size: target.size
22563
+ });
22564
+ return receiver;
22565
+ };
22566
+ if (prop === "delete") return (key) => {
22567
+ const had = target.has(key);
22568
+ const prev = had ? target.get(key) : void 0;
22569
+ const ok = target.delete(key);
22570
+ if (ok && had) onChange({
22571
+ type: "delete",
22572
+ key,
22573
+ prevValue: prev,
22574
+ size: target.size
22575
+ });
22576
+ return ok;
22577
+ };
22578
+ if (prop === "clear") return () => {
22579
+ if (target.size > 0) {
22580
+ target.clear();
22581
+ onChange({
22582
+ type: "clear",
22583
+ size: 0
22584
+ });
22585
+ }
22586
+ };
22587
+ const value = Reflect.get(target, prop, receiver);
22588
+ if (typeof value === "function") return value.bind(target);
22589
+ return value;
22590
+ } };
22591
+ return new Proxy(map, handler);
22592
+ }
22593
+
22439
22594
  //#endregion
22440
22595
  //#region src/weave.ts
22441
22596
  var Weave = class {
@@ -22446,7 +22601,10 @@ var Weave = class {
22446
22601
  Konva.showWarnings = false;
22447
22602
  this.id = v4_default();
22448
22603
  this.initialized = false;
22449
- this.config = weaveConfig;
22604
+ this.asyncElements = watchMap(() => {
22605
+ this.emitEvent("onAsyncElementChange");
22606
+ }, new Map());
22607
+ this.config = (0, import_lodash.merge)({ serverSide: false }, weaveConfig);
22450
22608
  this.logger = new WeaveLogger(this.config?.logger ?? {
22451
22609
  disabled: false,
22452
22610
  level: "error"
@@ -22468,9 +22626,6 @@ var Weave = class {
22468
22626
  this.exportManager = new WeaveExportManager(this);
22469
22627
  this.actionsManager = new WeaveActionsManager(this);
22470
22628
  this.pluginsManager = new WeavePluginsManager(this);
22471
- if (!window.weave) window.weave = this;
22472
- window.weaveTextEditing = {};
22473
- window.weaveDragImageURL = void 0;
22474
22629
  this.setupManager.welcomeLog();
22475
22630
  }
22476
22631
  setupRenderer() {
@@ -22506,6 +22661,19 @@ var Weave = class {
22506
22661
  }
22507
22662
  async start() {
22508
22663
  this.moduleLogger.info("Start instance");
22664
+ if (!this.config.serverSide) {
22665
+ if (!window.weave) window.weave = this;
22666
+ window.weaveTextEditing = {};
22667
+ window.weaveDragImageURL = void 0;
22668
+ }
22669
+ if (this.config.serverSide) {
22670
+ const { createCanvas, Image: Image$1 } = await import("canvas");
22671
+ globalThis.Image = Image$1;
22672
+ globalThis.document = { createElement(tag) {
22673
+ if (tag === "canvas") return createCanvas(1, 1);
22674
+ throw new Error(`Unsupported element: ${tag}`);
22675
+ } };
22676
+ }
22509
22677
  this.emitEvent("onRoomLoaded", false);
22510
22678
  this.status = WEAVE_INSTANCE_STATUS.STARTING;
22511
22679
  this.emitEvent("onInstanceStatus", this.status);
@@ -22800,7 +22968,10 @@ var Weave = class {
22800
22968
  return this.exportManager.imageToBase64(img, mimeType);
22801
22969
  }
22802
22970
  async exportNodes(nodes, boundingNodes, options) {
22803
- return await this.exportManager.exportNodes(nodes, boundingNodes, options);
22971
+ return await this.exportManager.exportNodesAsImage(nodes, boundingNodes, options);
22972
+ }
22973
+ async exportNodesAsBuffer(nodes, boundingNodes, options) {
22974
+ return await this.exportManager.exportNodesAsBuffer(nodes, boundingNodes, options);
22804
22975
  }
22805
22976
  allNodesLocked(nodes) {
22806
22977
  let allNodesLocked = true;
@@ -22886,6 +23057,30 @@ var Weave = class {
22886
23057
  nodeHandler.show(node);
22887
23058
  }
22888
23059
  }
23060
+ asyncElementsLoaded() {
23061
+ return [...this.asyncElements.values()].every((el) => el.status === "loaded");
23062
+ }
23063
+ loadAsyncElement(nodeId, type) {
23064
+ let element = this.asyncElements.get(nodeId);
23065
+ if (element) element.status = "loading";
23066
+ else element = {
23067
+ type,
23068
+ status: "loading"
23069
+ };
23070
+ this.asyncElements.set(nodeId, element);
23071
+ }
23072
+ resolveAsyncElement(nodeId, type) {
23073
+ let element = this.asyncElements.get(nodeId);
23074
+ if (element) element.status = "loaded";
23075
+ else element = {
23076
+ type,
23077
+ status: "loaded"
23078
+ };
23079
+ this.asyncElements.set(nodeId, element);
23080
+ }
23081
+ isServerSide() {
23082
+ return this.config.serverSide ?? false;
23083
+ }
22889
23084
  };
22890
23085
 
22891
23086
  //#endregion
@@ -22903,14 +23098,16 @@ var WeaveStageNode = class extends WeaveNode {
22903
23098
  x: 0,
22904
23099
  y: 0
22905
23100
  });
22906
- const container = stage.container();
22907
- container.setAttribute("tabindex", "0");
22908
- stage.container().addEventListener("focus", () => {
22909
- this.stageFocused = true;
22910
- });
22911
- stage.container().addEventListener("blur", () => {
22912
- this.stageFocused = false;
22913
- });
23101
+ if (!this.instance.isServerSide()) {
23102
+ const container = stage.container();
23103
+ container.setAttribute("tabindex", "0");
23104
+ stage.container().addEventListener("focus", () => {
23105
+ this.stageFocused = true;
23106
+ });
23107
+ stage.container().addEventListener("blur", () => {
23108
+ this.stageFocused = false;
23109
+ });
23110
+ }
22914
23111
  Konva.Stage.prototype.mode = function(mode) {
22915
23112
  if (typeof mode !== "undefined") this._mode = mode;
22916
23113
  return this._mode;
@@ -22930,11 +23127,11 @@ var WeaveStageNode = class extends WeaveNode {
22930
23127
  stage.mode(WEAVE_STAGE_DEFAULT_MODE);
22931
23128
  stage.on("pointerdown", (e) => {
22932
23129
  if (e.evt.button === 1) this.wheelMousePressed = true;
22933
- if ([MOVE_TOOL_ACTION_NAME].includes(this.instance.getActiveAction() ?? "")) stage.container().style.cursor = "grabbing";
23130
+ if (!this.instance.isServerSide() && [MOVE_TOOL_ACTION_NAME].includes(this.instance.getActiveAction() ?? "")) stage.container().style.cursor = "grabbing";
22934
23131
  });
22935
23132
  stage.on("pointermove", (e) => {
22936
23133
  const activeAction = this.instance.getActiveAction();
22937
- if (![MOVE_TOOL_ACTION_NAME].includes(activeAction ?? "") && stage.allowSelection() && !stage.allowActions().includes(this.instance.getActiveAction() ?? "") && !stage.allowSelectNodes().includes(e.target.getAttrs()?.nodeType ?? "")) {
23134
+ if (!this.instance.isServerSide() && ![MOVE_TOOL_ACTION_NAME].includes(activeAction ?? "") && stage.allowSelection() && !stage.allowActions().includes(this.instance.getActiveAction() ?? "") && !stage.allowSelectNodes().includes(e.target.getAttrs()?.nodeType ?? "")) {
22938
23135
  const stage$1 = this.instance.getStage();
22939
23136
  stage$1.container().style.cursor = "default";
22940
23137
  }
@@ -22946,7 +23143,7 @@ var WeaveStageNode = class extends WeaveNode {
22946
23143
  stage.on("pointerup", (e) => {
22947
23144
  const activeAction = this.instance.getActiveAction();
22948
23145
  if (e.evt.button === 1) this.wheelMousePressed = false;
22949
- if ([MOVE_TOOL_ACTION_NAME].includes(activeAction ?? "")) stage.container().style.cursor = "grab";
23146
+ if (!this.instance.isServerSide() && [MOVE_TOOL_ACTION_NAME].includes(activeAction ?? "")) stage.container().style.cursor = "grab";
22950
23147
  });
22951
23148
  stage.on("pointerover", (e) => {
22952
23149
  const activeAction = this.instance.getActiveAction();
@@ -22955,7 +23152,7 @@ var WeaveStageNode = class extends WeaveNode {
22955
23152
  const parent = e.target.getParent();
22956
23153
  if (parent && parent instanceof Konva.Transformer) return;
22957
23154
  this.hideHoverState();
22958
- stage.container().style.cursor = "default";
23155
+ if (!this.instance.isServerSide()) stage.container().style.cursor = "default";
22959
23156
  });
22960
23157
  return stage;
22961
23158
  }
@@ -23343,7 +23540,7 @@ var WeaveTextNode = class extends WeaveNode {
23343
23540
  text.on("transformend", () => {
23344
23541
  this.instance.emitEvent("onTransform", null);
23345
23542
  });
23346
- window.addEventListener("keypress", (e) => {
23543
+ if (!this.instance.getConfiguration().serverSide) window.addEventListener("keypress", (e) => {
23347
23544
  if (e.key === "Enter" && this.instance.getActiveAction() === SELECTION_TOOL_ACTION_NAME && !this.editing && e.target !== this.textArea) {
23348
23545
  e.preventDefault();
23349
23546
  if (this.isSelecting() && this.isNodeSelected(text)) {
@@ -24402,6 +24599,12 @@ var WeaveImageNode = class extends WeaveNode {
24402
24599
  imageCrop.unCrop();
24403
24600
  this.cachedCropInfo[imageNode.getAttrs().id ?? ""] = void 0;
24404
24601
  };
24602
+ loadAsyncElement(nodeId) {
24603
+ this.instance.loadAsyncElement(nodeId, "image");
24604
+ }
24605
+ resolveAsyncElement(nodeId) {
24606
+ this.instance.resolveAsyncElement(nodeId, "image");
24607
+ }
24405
24608
  onRender(props) {
24406
24609
  const imageProperties = props.imageProperties;
24407
24610
  const imageProps = props;
@@ -24601,13 +24804,15 @@ var WeaveImageNode = class extends WeaveNode {
24601
24804
  const imageProps = params;
24602
24805
  const imagePlaceholder = image.findOne(`#${imageProps.id}-placeholder`);
24603
24806
  const internalImage = image.findOne(`#${imageProps.id}-image`);
24807
+ const realImageURL = this.config.urlTransformer?.(imageProps.imageURL ?? "") ?? imageProps.imageURL;
24604
24808
  const imageObj = new Image();
24605
24809
  imageObj.crossOrigin = this.config.crossOrigin;
24606
24810
  imageObj.onerror = (error) => {
24607
- console.error("Error loading image", imageProps.imageURL, error);
24811
+ console.error("Error loading image", realImageURL, error);
24608
24812
  imagePlaceholder?.setAttrs({ visible: true });
24609
24813
  internalImage?.setAttrs({ visible: false });
24610
24814
  };
24815
+ this.loadAsyncElement(imageProps.id);
24611
24816
  imageObj.onload = () => {
24612
24817
  if (image && imagePlaceholder && internalImage) {
24613
24818
  image.setAttrs({
@@ -24646,11 +24851,12 @@ var WeaveImageNode = class extends WeaveNode {
24646
24851
  height: imageRect.height
24647
24852
  });
24648
24853
  this.updateImageCrop(imageProps);
24854
+ this.resolveAsyncElement(imageProps.id);
24649
24855
  const nodeHandler = this.instance.getNodeHandler(image.getAttrs().nodeType);
24650
24856
  if (nodeHandler) this.instance.updateNode(nodeHandler.serialize(image));
24651
24857
  }
24652
24858
  };
24653
- if (imageProps.imageURL) imageObj.src = imageProps.imageURL;
24859
+ if (realImageURL) imageObj.src = realImageURL;
24654
24860
  }
24655
24861
  updateImageCrop(nextProps) {
24656
24862
  const imageAttrs = nextProps;
@@ -28882,12 +29088,7 @@ var WeaveExportStageToolAction = class extends WeaveAction {
28882
29088
  }
28883
29089
  async exportStage(boundingNodes) {
28884
29090
  const mainLayer = this.instance.getMainLayer();
28885
- const img = await this.instance.exportNodes(
28886
- // mainLayer?.find('.node') ?? [],
28887
- mainLayer?.getChildren() ?? [],
28888
- boundingNodes,
28889
- this.options
28890
- );
29091
+ const img = await this.instance.exportNodes(mainLayer?.getChildren() ?? [], boundingNodes, this.options);
28891
29092
  return img;
28892
29093
  }
28893
29094
  async trigger(cancelAction, { boundingNodes, options }) {