@inditextech/weave-sdk 0.72.1 → 0.73.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.cjs CHANGED
@@ -18320,6 +18320,7 @@ function memoize(fn) {
18320
18320
  function isIOS() {
18321
18321
  return /iPad|iPhone|iPod/.test(navigator.userAgent) || navigator.userAgent.includes("Mac") && "ontouchend" in document;
18322
18322
  }
18323
+ const isServer = () => typeof window === "undefined";
18323
18324
 
18324
18325
  //#endregion
18325
18326
  //#region src/actions/selection-tool/constants.ts
@@ -19074,6 +19075,27 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
19074
19075
  tr.on("transformstart", () => {
19075
19076
  this.triggerSelectedNodesEvent();
19076
19077
  });
19078
+ let nodeHovered = void 0;
19079
+ tr.on("mousemove", () => {
19080
+ const pointerPos = stage.getPointerPosition();
19081
+ if (!pointerPos) return;
19082
+ this.disable();
19083
+ const shape = stage.getIntersection(pointerPos);
19084
+ this.enable();
19085
+ if (shape) {
19086
+ const targetNode = this.instance.getInstanceRecursive(shape);
19087
+ this.instance.getStage().handleMouseout();
19088
+ if (targetNode?.handleMouseover) {
19089
+ targetNode?.handleMouseover();
19090
+ nodeHovered = targetNode;
19091
+ }
19092
+ }
19093
+ });
19094
+ tr.on("mouseout", () => {
19095
+ this.instance.getStage().handleMouseover();
19096
+ nodeHovered?.handleMouseout();
19097
+ nodeHovered = void 0;
19098
+ });
19077
19099
  const handleTransform = (e) => {
19078
19100
  const moved = this.checkMoved(e);
19079
19101
  if (moved) this.getContextMenuPlugin()?.cancelLongPressTimer();
@@ -19453,11 +19475,7 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
19453
19475
  const contextMenuPlugin = this.getContextMenuPlugin();
19454
19476
  if (moved) contextMenuPlugin?.cancelLongPressTimer();
19455
19477
  else this.hideSelectorArea();
19456
- if (contextMenuPlugin && contextMenuPlugin.isContextMenuVisible()) {
19457
- this.selecting = false;
19458
- this.stopPanLoop();
19459
- return;
19460
- }
19478
+ if (contextMenuPlugin?.isContextMenuVisible()) this.stopPanLoop();
19461
19479
  if (this.isSpaceKeyPressed) return;
19462
19480
  if (!this.selecting) return;
19463
19481
  this.updateSelectionRect();
@@ -19511,11 +19529,7 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
19511
19529
  this.hideSelectorArea();
19512
19530
  return;
19513
19531
  }
19514
- if (contextMenuPlugin && contextMenuPlugin.isContextMenuVisible()) {
19515
- this.selecting = false;
19516
- this.stopPanLoop();
19517
- return;
19518
- }
19532
+ if (contextMenuPlugin?.isContextMenuVisible()) this.stopPanLoop();
19519
19533
  if (!this.selectionRectangle.visible()) {
19520
19534
  this.hideSelectorArea();
19521
19535
  return;
@@ -19606,11 +19620,7 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
19606
19620
  if (!this.enabled) return;
19607
19621
  if (this.instance.getActiveAction() !== SELECTION_TOOL_ACTION_NAME) return;
19608
19622
  const contextMenuPlugin = this.getContextMenuPlugin();
19609
- if (contextMenuPlugin?.isContextMenuVisible()) {
19610
- this.selecting = false;
19611
- this.stopPanLoop();
19612
- return;
19613
- }
19623
+ if (contextMenuPlugin?.isContextMenuVisible()) this.stopPanLoop();
19614
19624
  this.hideHoverState();
19615
19625
  const selectedGroup = getTargetedNode(this.instance);
19616
19626
  if (!this.initialized) return;
@@ -20251,6 +20261,8 @@ var WeaveNode = class {
20251
20261
  node.movedToContainer = function() {};
20252
20262
  node.updatePosition = function() {};
20253
20263
  node.resetCrop = function() {};
20264
+ node.handleMouseover = function() {};
20265
+ node.handleMouseout = function() {};
20254
20266
  }
20255
20267
  isNodeSelected(ele) {
20256
20268
  const selectionPlugin = this.instance.getPlugin("nodesSelection");
@@ -20389,6 +20401,31 @@ var WeaveNode = class {
20389
20401
  if (!moved) this.instance.updateNode(this.serialize(node));
20390
20402
  }
20391
20403
  });
20404
+ node.handleMouseover = () => {
20405
+ const stage = this.instance.getStage();
20406
+ const activeAction = this.instance.getActiveAction();
20407
+ const isNodeSelectionEnabled = this.getSelectionPlugin()?.isEnabled();
20408
+ const realNode = this.instance.getInstanceRecursive(node);
20409
+ const isTargetable = realNode.getAttrs().isTargetable !== false;
20410
+ const isLocked$1 = realNode.getAttrs().locked ?? false;
20411
+ if ([MOVE_TOOL_ACTION_NAME].includes(activeAction ?? "")) return;
20412
+ if (isNodeSelectionEnabled && this.isSelecting() && !this.isNodeSelected(realNode) && !this.isPasting() && isLocked$1) {
20413
+ const stage$1 = this.instance.getStage();
20414
+ stage$1.container().style.cursor = "default";
20415
+ }
20416
+ if (isNodeSelectionEnabled && this.isSelecting() && !this.isNodeSelected(realNode) && !this.isPasting() && isTargetable && !isLocked$1 && stage.mode() === WEAVE_STAGE_DEFAULT_MODE) {
20417
+ const stage$1 = this.instance.getStage();
20418
+ stage$1.container().style.cursor = "pointer";
20419
+ }
20420
+ if (isNodeSelectionEnabled && this.isSelecting() && this.isNodeSelected(realNode) && !this.isPasting() && isTargetable && !isLocked$1 && stage.mode() === WEAVE_STAGE_DEFAULT_MODE) {
20421
+ const stage$1 = this.instance.getStage();
20422
+ stage$1.container().style.cursor = "grab";
20423
+ }
20424
+ if (this.isPasting()) {
20425
+ const stage$1 = this.instance.getStage();
20426
+ stage$1.container().style.cursor = "crosshair";
20427
+ }
20428
+ };
20392
20429
  node.on("pointerover", (e) => {
20393
20430
  const stage = this.instance.getStage();
20394
20431
  const activeAction = this.instance.getActiveAction();
@@ -21914,7 +21951,7 @@ var WeaveRegisterManager = class {
21914
21951
 
21915
21952
  //#endregion
21916
21953
  //#region package.json
21917
- var version = "0.72.1";
21954
+ var version = "0.73.1";
21918
21955
 
21919
21956
  //#endregion
21920
21957
  //#region src/managers/setup.ts
@@ -22965,6 +23002,10 @@ var WeaveStageNode = class extends WeaveNode {
22965
23002
  if (typeof allowSelection !== "undefined") this._allowSelection = allowSelection;
22966
23003
  return this._allowSelection;
22967
23004
  };
23005
+ stage.handleMouseover = function() {
23006
+ stage.container().style.cursor = "default";
23007
+ };
23008
+ stage.handleMouseout = function() {};
22968
23009
  stage.mode(WEAVE_STAGE_DEFAULT_MODE);
22969
23010
  stage.on("pointerdown", (e) => {
22970
23011
  if (e.evt.button === 1) this.wheelMousePressed = true;
@@ -23783,395 +23824,136 @@ var WeaveTextNode = class extends WeaveNode {
23783
23824
  };
23784
23825
 
23785
23826
  //#endregion
23786
- //#region src/actions/image-tool/constants.ts
23787
- const IMAGE_TOOL_ACTION_NAME = "imageTool";
23788
- const IMAGE_TOOL_STATE = {
23789
- ["IDLE"]: "idle",
23790
- ["UPLOADING"]: "uploading",
23791
- ["DEFINING_POSITION"]: "definingPosition",
23792
- ["SELECTED_POSITION"]: "selectedPosition",
23793
- ["ADDING"]: "adding",
23794
- ["FINISHED"]: "finished"
23795
- };
23796
-
23797
- //#endregion
23798
- //#region src/actions/image-tool/image-tool.ts
23799
- var WeaveImageToolAction = class extends WeaveAction {
23800
- initialized = false;
23801
- initialCursor = null;
23802
- cursorPadding = 5;
23803
- forceMainContainer = false;
23804
- onPropsChange = void 0;
23805
- update = void 0;
23806
- constructor() {
23807
- super();
23808
- this.pointers = new Map();
23809
- this.initialized = false;
23810
- this.state = IMAGE_TOOL_STATE.IDLE;
23811
- this.imageId = null;
23812
- this.tempImageId = null;
23813
- this.tempImageNode = null;
23814
- this.container = void 0;
23815
- this.imageURL = null;
23816
- this.preloadImgs = {};
23817
- this.clickPoint = null;
23818
- }
23819
- getName() {
23820
- return IMAGE_TOOL_ACTION_NAME;
23821
- }
23822
- getPreloadedImage(imageId) {
23823
- return this.preloadImgs?.[imageId];
23827
+ //#region src/nodes/image/crop.ts
23828
+ var WeaveImageCrop = class WeaveImageCrop {
23829
+ constructor(instance, node, image, internalImage, clipGroup) {
23830
+ this.instance = instance;
23831
+ this.node = node;
23832
+ this.image = image;
23833
+ this.internalImage = internalImage;
23834
+ this.cropGroup = clipGroup;
23835
+ this.cropping = false;
23836
+ this.onClose = () => {};
23837
+ this.handleHide = this.hide.bind(this);
23824
23838
  }
23825
- initProps() {
23826
- return {
23827
- width: 100,
23828
- height: 100,
23839
+ show(onClose) {
23840
+ this.onClose = onClose;
23841
+ this.cropping = true;
23842
+ const nodeEdgeSnappingPlugin = this.getNodesEdgeSnappingPlugin();
23843
+ if (nodeEdgeSnappingPlugin) nodeEdgeSnappingPlugin.disable();
23844
+ const nodeDistanceSnappingPlugin = this.getNodesDistanceSnappingPlugin();
23845
+ if (nodeDistanceSnappingPlugin) nodeDistanceSnappingPlugin.disable();
23846
+ const nodesSelectionPlugin = this.getNodesSelectionPlugin();
23847
+ if (nodesSelectionPlugin) nodesSelectionPlugin.disable();
23848
+ this.image.setAttrs({ cropping: true });
23849
+ const imageAttrs = this.image.getAttrs();
23850
+ this.internalImage.hide();
23851
+ this.cropGroup.destroyChildren();
23852
+ const actualScale = imageAttrs.uncroppedImage.width / imageAttrs.imageInfo.width;
23853
+ const cropScale = imageAttrs.cropInfo ? imageAttrs.cropInfo.scaleX : actualScale;
23854
+ const realScale = actualScale / cropScale;
23855
+ this.cropImage = new konva.default.Image({
23856
+ x: imageAttrs.cropInfo ? -imageAttrs.cropInfo.x * realScale : 0,
23857
+ y: imageAttrs.cropInfo ? -imageAttrs.cropInfo.y * realScale : 0,
23858
+ width: imageAttrs.uncroppedImage.width,
23859
+ height: imageAttrs.uncroppedImage.height,
23829
23860
  scaleX: 1,
23830
- scaleY: 1
23831
- };
23832
- }
23833
- onInit() {
23834
- this.instance.addEventListener("onStageDrop", (e) => {
23835
- if (window.weaveDragImageURL) {
23836
- this.instance.getStage().setPointersPositions(e);
23837
- const position = this.instance.getStage().getRelativePointerPosition();
23838
- this.instance.triggerAction(IMAGE_TOOL_ACTION_NAME, {
23839
- imageURL: window.weaveDragImageURL,
23840
- imageId: window.weaveDragImageId,
23841
- position
23842
- });
23843
- window.weaveDragImageURL = void 0;
23844
- window.weaveDragImageId = void 0;
23845
- }
23846
- });
23847
- }
23848
- setupEvents() {
23849
- const stage = this.instance.getStage();
23850
- window.addEventListener("keydown", (e) => {
23851
- if (e.key === "Escape" && this.instance.getActiveAction() === IMAGE_TOOL_ACTION_NAME) {
23852
- this.cancelAction();
23853
- return;
23854
- }
23861
+ scaleY: 1,
23862
+ image: this.internalImage.image(),
23863
+ crop: void 0,
23864
+ visible: true,
23865
+ listening: false,
23866
+ draggable: false
23855
23867
  });
23856
- stage.on("pointerdown", (e) => {
23857
- this.setTapStart(e);
23858
- this.pointers.set(e.evt.pointerId, {
23859
- x: e.evt.clientX,
23860
- y: e.evt.clientY
23861
- });
23862
- if (this.pointers.size === 2 && this.instance.getActiveAction() === IMAGE_TOOL_ACTION_NAME) {
23863
- this.state = IMAGE_TOOL_STATE.DEFINING_POSITION;
23864
- return;
23865
- }
23866
- if (this.state === IMAGE_TOOL_STATE.DEFINING_POSITION) this.state = IMAGE_TOOL_STATE.SELECTED_POSITION;
23868
+ this.imageOffsetX = imageAttrs.cropInfo ? imageAttrs.cropInfo.x * realScale : 0;
23869
+ this.imageOffsetY = imageAttrs.cropInfo ? imageAttrs.cropInfo.y * realScale : 0;
23870
+ this.cropRect = new konva.default.Rect({
23871
+ x: 0,
23872
+ y: 0,
23873
+ width: imageAttrs.cropInfo ? imageAttrs.cropInfo.width * realScale : imageAttrs.uncroppedImage.width,
23874
+ height: imageAttrs.cropInfo ? imageAttrs.cropInfo.height * realScale : imageAttrs.uncroppedImage.height,
23875
+ fill: "rgba(0,0,0,0.2)",
23876
+ stroke: "#ff0000ff",
23877
+ strokeWidth: 0,
23878
+ strokeScaleEnabled: true,
23879
+ draggable: true,
23880
+ rotation: 0
23867
23881
  });
23868
- stage.on("pointermove", (e) => {
23869
- if (this.state === IMAGE_TOOL_STATE.IDLE) return;
23870
- this.setCursor();
23871
- if (this.pointers.size === 2 && this.instance.getActiveAction() === IMAGE_TOOL_ACTION_NAME) {
23872
- this.state = IMAGE_TOOL_STATE.DEFINING_POSITION;
23873
- return;
23874
- }
23875
- 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") {
23876
- const mousePos = stage.getRelativePointerPosition();
23877
- this.tempImageNode.setAttrs({
23878
- x: (mousePos?.x ?? 0) + this.cursorPadding,
23879
- y: (mousePos?.y ?? 0) + this.cursorPadding
23882
+ this.transformer = new konva.default.Transformer({
23883
+ id: `${this.image.getAttrs().id}_transformer`,
23884
+ x: 0,
23885
+ y: 0,
23886
+ flipEnabled: false,
23887
+ keepRatio: false,
23888
+ ignoreStroke: false,
23889
+ rotateEnabled: false,
23890
+ enabledAnchors: [
23891
+ "top-left",
23892
+ "top-center",
23893
+ "top-right",
23894
+ "middle-right",
23895
+ "bottom-left",
23896
+ "middle-left",
23897
+ "bottom-right",
23898
+ "bottom-center"
23899
+ ],
23900
+ anchorDragBoundFunc: (_, newPos) => {
23901
+ let closestSnap = newPos;
23902
+ let minDist = 10;
23903
+ const nodeRotation = this.image.getAbsoluteRotation();
23904
+ const stage = this.instance.getStage();
23905
+ const rotation = nodeRotation * (Math.PI / 180);
23906
+ const center = this.cropImage.getAbsolutePosition();
23907
+ const width = this.cropImage.width() * stage.scaleX();
23908
+ const height = this.cropImage.height() * stage.scaleY();
23909
+ const offset = this.cropImage.offset();
23910
+ const corners = [
23911
+ {
23912
+ x: -offset.x,
23913
+ y: -offset.y
23914
+ },
23915
+ {
23916
+ x: width - offset.x,
23917
+ y: -offset.y
23918
+ },
23919
+ {
23920
+ x: width - offset.x,
23921
+ y: height - offset.y
23922
+ },
23923
+ {
23924
+ x: -offset.x,
23925
+ y: height - offset.y
23926
+ }
23927
+ ].map((pt) => {
23928
+ const cos = Math.cos(rotation);
23929
+ const sin = Math.sin(rotation);
23930
+ return {
23931
+ x: center.x + pt.x * cos - pt.y * sin,
23932
+ y: center.y + pt.x * sin + pt.y * cos
23933
+ };
23880
23934
  });
23881
- }
23935
+ const edges = [
23936
+ [corners[0], corners[1]],
23937
+ [corners[1], corners[2]],
23938
+ [corners[2], corners[3]],
23939
+ [corners[3], corners[0]]
23940
+ ];
23941
+ for (const [a, b] of edges) {
23942
+ const candidate = this.closestPointOnLine(newPos, a, b);
23943
+ const dist = Math.hypot(newPos.x - candidate.x, newPos.y - candidate.y);
23944
+ if (dist < minDist) {
23945
+ closestSnap = candidate;
23946
+ minDist = dist;
23947
+ }
23948
+ }
23949
+ return closestSnap;
23950
+ },
23951
+ rotation: 0
23882
23952
  });
23883
- stage.on("pointerup", (e) => {
23884
- this.pointers.delete(e.evt.pointerId);
23885
- if (this.state === IMAGE_TOOL_STATE.SELECTED_POSITION) this.handleAdding();
23886
- });
23887
- this.initialized = true;
23888
- }
23889
- setState(state) {
23890
- this.state = state;
23891
- }
23892
- loadImage(imageURL, options, position) {
23893
- const imageOptions = {
23894
- crossOrigin: "anonymous",
23895
- ...options
23896
- };
23897
- this.setCursor();
23898
- this.setFocusStage();
23899
- this.imageId = v4_default();
23900
- this.imageURL = imageURL;
23901
- this.preloadImgs[this.imageId] = new Image();
23902
- this.preloadImgs[this.imageId].crossOrigin = imageOptions.crossOrigin;
23903
- this.preloadImgs[this.imageId].onerror = () => {
23904
- this.instance.emitEvent("onImageLoadEnd", new Error("Error loading image"));
23905
- this.cancelAction();
23906
- };
23907
- this.preloadImgs[this.imageId].onload = () => {
23908
- this.instance.emitEvent("onImageLoadEnd", void 0);
23909
- if (this.imageId) this.props = {
23910
- ...this.props,
23911
- imageURL: this.imageURL,
23912
- width: this.preloadImgs[this.imageId].width,
23913
- height: this.preloadImgs[this.imageId].height
23914
- };
23915
- this.addImageNode(position);
23916
- };
23917
- this.preloadImgs[this.imageId].src = imageURL;
23918
- this.instance.emitEvent("onImageLoadStart");
23919
- }
23920
- isTouchDevice() {
23921
- return window.matchMedia("(pointer: coarse)").matches;
23922
- }
23923
- addImageNode(position) {
23924
- const stage = this.instance.getStage();
23925
- this.setCursor();
23926
- this.setFocusStage();
23927
- if (position) {
23928
- this.setState(IMAGE_TOOL_STATE.SELECTED_POSITION);
23929
- this.handleAdding(position);
23930
- return;
23931
- }
23932
- if (this.imageId) {
23933
- const mousePos = stage.getRelativePointerPosition();
23934
- this.tempImageId = v4_default();
23935
- const aspectRatio = this.preloadImgs[this.imageId].width / this.preloadImgs[this.imageId].height;
23936
- if (!this.tempImageNode && this.tempImageId && !this.isTouchDevice()) {
23937
- this.tempImageNode = new konva.default.Image({
23938
- id: this.tempImageId,
23939
- x: (mousePos?.x ?? 0) + this.cursorPadding,
23940
- y: (mousePos?.y ?? 0) + this.cursorPadding,
23941
- width: 240 * aspectRatio * (1 / stage.scaleX()),
23942
- height: 240 * (1 / stage.scaleY()),
23943
- opacity: 1,
23944
- adding: true,
23945
- image: this.preloadImgs[this.imageId],
23946
- stroke: "#000000ff",
23947
- strokeWidth: 0,
23948
- strokeScaleEnabled: true,
23949
- listening: false
23950
- });
23951
- this.instance.getMainLayer()?.add(this.tempImageNode);
23952
- }
23953
- this.instance.emitEvent("onAddingImage", { imageURL: this.props.imageURL });
23954
- }
23955
- this.clickPoint = null;
23956
- this.setState(IMAGE_TOOL_STATE.DEFINING_POSITION);
23957
- }
23958
- addImage(position) {
23959
- if (position) this.clickPoint = position;
23960
- this.setState(IMAGE_TOOL_STATE.UPLOADING);
23961
- }
23962
- handleAdding(position) {
23963
- if (this.imageId && this.imageURL && this.preloadImgs[this.imageId]) {
23964
- const { mousePoint, container } = this.instance.getMousePointer(position);
23965
- this.clickPoint = mousePoint;
23966
- this.container = container;
23967
- const nodeHandler = this.instance.getNodeHandler("image");
23968
- if (nodeHandler) {
23969
- const node = nodeHandler.create(this.imageId, {
23970
- ...this.props,
23971
- x: this.clickPoint?.x ?? 0,
23972
- y: this.clickPoint?.y ?? 0,
23973
- opacity: 1,
23974
- adding: false,
23975
- imageURL: this.imageURL,
23976
- stroke: "#000000ff",
23977
- strokeWidth: 0,
23978
- strokeScaleEnabled: true,
23979
- imageWidth: this.preloadImgs[this.imageId].width,
23980
- imageHeight: this.preloadImgs[this.imageId].height,
23981
- imageInfo: {
23982
- width: this.preloadImgs[this.imageId].width,
23983
- height: this.preloadImgs[this.imageId].height
23984
- }
23985
- });
23986
- this.instance.addNode(node, this.forceMainContainer ? this.instance.getMainLayer()?.getAttrs().id : this.container?.getAttrs().id);
23987
- this.instance.emitEvent("onAddedImage", {
23988
- imageURL: this.props.imageURL,
23989
- nodeId: this.imageId
23990
- });
23991
- }
23992
- this.setState(IMAGE_TOOL_STATE.FINISHED);
23993
- }
23994
- this.cancelAction();
23995
- }
23996
- trigger(cancelAction, params) {
23997
- if (!this.instance) throw new Error("Instance not defined");
23998
- if (!this.initialized) this.setupEvents();
23999
- this.cancelAction = cancelAction;
24000
- const selectionPlugin = this.instance.getPlugin("nodesSelection");
24001
- if (selectionPlugin) selectionPlugin.setSelectedNodes([]);
24002
- this.forceMainContainer = params?.forceMainContainer ?? false;
24003
- if (params?.imageId) this.updateProps({ imageId: params.imageId });
24004
- if (params?.imageURL) {
24005
- this.loadImage(params.imageURL, params?.options ?? void 0, params?.position ?? void 0);
24006
- return;
24007
- }
24008
- this.props = this.initProps();
24009
- this.addImage();
24010
- return { finishUploadCallback: this.loadImage.bind(this) };
24011
- }
24012
- cleanup() {
24013
- const stage = this.instance.getStage();
24014
- if (this.imageId) delete this.preloadImgs[this.imageId];
24015
- if (this.tempImageNode) this.tempImageNode.destroy();
24016
- const selectionPlugin = this.instance.getPlugin("nodesSelection");
24017
- if (selectionPlugin) {
24018
- const node = stage.findOne(`#${this.imageId}`);
24019
- if (node) selectionPlugin.setSelectedNodes([node]);
24020
- this.instance.triggerAction(SELECTION_TOOL_ACTION_NAME);
24021
- }
24022
- stage.container().style.cursor = "default";
24023
- this.initialCursor = null;
24024
- this.imageId = null;
24025
- this.forceMainContainer = false;
24026
- this.container = void 0;
24027
- this.tempImageNode = null;
24028
- this.imageURL = null;
24029
- this.clickPoint = null;
24030
- this.setState(IMAGE_TOOL_STATE.IDLE);
24031
- }
24032
- setCursor() {
24033
- const stage = this.instance.getStage();
24034
- stage.container().style.cursor = "crosshair";
24035
- }
24036
- setFocusStage() {
24037
- const stage = this.instance.getStage();
24038
- stage.container().tabIndex = 1;
24039
- stage.container().blur();
24040
- stage.container().focus();
24041
- }
24042
- };
24043
-
24044
- //#endregion
24045
- //#region src/nodes/image/crop.ts
24046
- var WeaveImageCrop = class WeaveImageCrop {
24047
- constructor(instance, node, image, internalImage, clipGroup) {
24048
- this.instance = instance;
24049
- this.node = node;
24050
- this.image = image;
24051
- this.internalImage = internalImage;
24052
- this.cropGroup = clipGroup;
24053
- this.cropping = false;
24054
- this.onClose = () => {};
24055
- this.handleHide = this.hide.bind(this);
24056
- }
24057
- show(onClose) {
24058
- this.onClose = onClose;
24059
- this.cropping = true;
24060
- const nodeEdgeSnappingPlugin = this.getNodesEdgeSnappingPlugin();
24061
- if (nodeEdgeSnappingPlugin) nodeEdgeSnappingPlugin.disable();
24062
- const nodeDistanceSnappingPlugin = this.getNodesDistanceSnappingPlugin();
24063
- if (nodeDistanceSnappingPlugin) nodeDistanceSnappingPlugin.disable();
24064
- const nodesSelectionPlugin = this.getNodesSelectionPlugin();
24065
- if (nodesSelectionPlugin) nodesSelectionPlugin.disable();
24066
- this.image.setAttrs({ cropping: true });
24067
- const imageAttrs = this.image.getAttrs();
24068
- this.internalImage.hide();
24069
- this.cropGroup.destroyChildren();
24070
- const actualScale = imageAttrs.uncroppedImage.width / imageAttrs.imageInfo.width;
24071
- const cropScale = imageAttrs.cropInfo ? imageAttrs.cropInfo.scaleX : actualScale;
24072
- const realScale = actualScale / cropScale;
24073
- this.cropImage = new konva.default.Image({
24074
- x: imageAttrs.cropInfo ? -imageAttrs.cropInfo.x * realScale : 0,
24075
- y: imageAttrs.cropInfo ? -imageAttrs.cropInfo.y * realScale : 0,
24076
- width: imageAttrs.uncroppedImage.width,
24077
- height: imageAttrs.uncroppedImage.height,
24078
- scaleX: 1,
24079
- scaleY: 1,
24080
- image: this.internalImage.image(),
24081
- crop: void 0,
24082
- visible: true,
24083
- listening: false,
24084
- draggable: false
24085
- });
24086
- this.imageOffsetX = imageAttrs.cropInfo ? imageAttrs.cropInfo.x * realScale : 0;
24087
- this.imageOffsetY = imageAttrs.cropInfo ? imageAttrs.cropInfo.y * realScale : 0;
24088
- this.cropRect = new konva.default.Rect({
24089
- x: 0,
24090
- y: 0,
24091
- width: imageAttrs.cropInfo ? imageAttrs.cropInfo.width * realScale : imageAttrs.uncroppedImage.width,
24092
- height: imageAttrs.cropInfo ? imageAttrs.cropInfo.height * realScale : imageAttrs.uncroppedImage.height,
24093
- fill: "rgba(0,0,0,0.2)",
24094
- stroke: "#ff0000ff",
24095
- strokeWidth: 0,
24096
- strokeScaleEnabled: true,
24097
- draggable: true,
24098
- rotation: 0
24099
- });
24100
- this.transformer = new konva.default.Transformer({
24101
- id: `${this.image.getAttrs().id}_transformer`,
24102
- x: 0,
24103
- y: 0,
24104
- flipEnabled: false,
24105
- keepRatio: false,
24106
- ignoreStroke: false,
24107
- rotateEnabled: false,
24108
- enabledAnchors: [
24109
- "top-left",
24110
- "top-center",
24111
- "top-right",
24112
- "middle-right",
24113
- "bottom-left",
24114
- "middle-left",
24115
- "bottom-right",
24116
- "bottom-center"
24117
- ],
24118
- anchorDragBoundFunc: (_, newPos) => {
24119
- let closestSnap = newPos;
24120
- let minDist = 10;
24121
- const nodeRotation = this.image.getAbsoluteRotation();
24122
- const stage = this.instance.getStage();
24123
- const rotation = nodeRotation * (Math.PI / 180);
24124
- const center = this.cropImage.getAbsolutePosition();
24125
- const width = this.cropImage.width() * stage.scaleX();
24126
- const height = this.cropImage.height() * stage.scaleY();
24127
- const offset = this.cropImage.offset();
24128
- const corners = [
24129
- {
24130
- x: -offset.x,
24131
- y: -offset.y
24132
- },
24133
- {
24134
- x: width - offset.x,
24135
- y: -offset.y
24136
- },
24137
- {
24138
- x: width - offset.x,
24139
- y: height - offset.y
24140
- },
24141
- {
24142
- x: -offset.x,
24143
- y: height - offset.y
24144
- }
24145
- ].map((pt) => {
24146
- const cos = Math.cos(rotation);
24147
- const sin = Math.sin(rotation);
24148
- return {
24149
- x: center.x + pt.x * cos - pt.y * sin,
24150
- y: center.y + pt.x * sin + pt.y * cos
24151
- };
24152
- });
24153
- const edges = [
24154
- [corners[0], corners[1]],
24155
- [corners[1], corners[2]],
24156
- [corners[2], corners[3]],
24157
- [corners[3], corners[0]]
24158
- ];
24159
- for (const [a, b] of edges) {
24160
- const candidate = this.closestPointOnLine(newPos, a, b);
24161
- const dist = Math.hypot(newPos.x - candidate.x, newPos.y - candidate.y);
24162
- if (dist < minDist) {
24163
- closestSnap = candidate;
24164
- minDist = dist;
24165
- }
24166
- }
24167
- return closestSnap;
24168
- },
24169
- rotation: 0
24170
- });
24171
- this.grid = new konva.default.Group();
24172
- const cropRect = this.cropRect.getClientRect({
24173
- relativeTo: this.cropGroup,
24174
- skipStroke: true
23953
+ this.grid = new konva.default.Group();
23954
+ const cropRect = this.cropRect.getClientRect({
23955
+ relativeTo: this.cropGroup,
23956
+ skipStroke: true
24175
23957
  });
24176
23958
  this.drawGridLines(0, 0, cropRect.width, cropRect.height);
24177
23959
  const handleGridLines = () => {
@@ -24402,6 +24184,8 @@ const WEAVE_IMAGE_DEFAULT_CONFIG = { crossOrigin: "anonymous" };
24402
24184
  //#endregion
24403
24185
  //#region src/nodes/image/image.ts
24404
24186
  var WeaveImageNode = class extends WeaveNode {
24187
+ imageSource = {};
24188
+ imageState = {};
24405
24189
  nodeType = WEAVE_IMAGE_NODE_TYPE;
24406
24190
  constructor(params) {
24407
24191
  super();
@@ -24560,31 +24344,29 @@ var WeaveImageNode = class extends WeaveNode {
24560
24344
  image.dblClick = () => {
24561
24345
  this.config.onDblClick?.(this, image);
24562
24346
  };
24563
- const imageActionTool = this.getImageToolAction();
24564
- const preloadImg = imageActionTool.getPreloadedImage(imageProps.id);
24565
- if (preloadImg) {
24347
+ if (this.imageSource[id]) {
24566
24348
  imagePlaceholder?.setAttrs({
24567
- width: imageProps.width ? imageProps.width : preloadImg.width,
24568
- height: imageProps.height ? imageProps.height : preloadImg.height,
24349
+ width: imageProps.width ? imageProps.width : this.imageSource[id].width,
24350
+ height: imageProps.height ? imageProps.height : this.imageSource[id].height,
24569
24351
  visible: false
24570
24352
  });
24571
24353
  internalImage?.setAttrs({
24572
- width: imageProps.width ? imageProps.width : preloadImg.width,
24573
- height: imageProps.height ? imageProps.height : preloadImg.height,
24574
- image: preloadImg,
24354
+ width: imageProps.width ? imageProps.width : this.imageSource[id].width,
24355
+ height: imageProps.height ? imageProps.height : this.imageSource[id].height,
24356
+ image: this.imageSource[id],
24575
24357
  visible: true
24576
24358
  });
24577
24359
  this.imageLoaded = true;
24578
- image.setAttr("width", image.width() ? image.width() : preloadImg.width);
24579
- image.setAttr("height", image.height() ? image.height() : preloadImg.height);
24360
+ image.setAttr("width", image.width() ? image.width() : this.imageSource[id].width);
24361
+ image.setAttr("height", image.height() ? image.height() : this.imageSource[id].height);
24580
24362
  image.setAttr("cropInfo", void 0);
24581
24363
  image.setAttr("uncroppedImage", {
24582
- width: image.width() ? image.width() : preloadImg.width,
24583
- height: image.height() ? image.height() : preloadImg.height
24364
+ width: image.width() ? image.width() : this.imageSource[id].width,
24365
+ height: image.height() ? image.height() : this.imageSource[id].height
24584
24366
  });
24585
24367
  image.setAttr("imageInfo", {
24586
- width: preloadImg.width,
24587
- height: preloadImg.height
24368
+ width: this.imageSource[id].width,
24369
+ height: this.imageSource[id].height
24588
24370
  });
24589
24371
  this.instance.updateNode(this.serialize(image));
24590
24372
  } else this.loadImage(imageProps, image);
@@ -24656,64 +24438,96 @@ var WeaveImageNode = class extends WeaveNode {
24656
24438
  this.updateImageCrop(nextProps);
24657
24439
  }
24658
24440
  }
24441
+ preloadImage(imageId, imageURL, { onLoad, onError }) {
24442
+ const realImageURL = this.config.urlTransformer?.(imageURL ?? "") ?? imageURL;
24443
+ this.imageSource[imageId] = new Image();
24444
+ this.imageSource[imageId].crossOrigin = this.config.crossOrigin;
24445
+ this.imageSource[imageId].onerror = (error) => {
24446
+ this.imageState[imageId] = {
24447
+ loaded: false,
24448
+ error: true
24449
+ };
24450
+ onError(error);
24451
+ };
24452
+ this.imageSource[imageId].onload = () => {
24453
+ this.imageState[imageId] = {
24454
+ loaded: true,
24455
+ error: false
24456
+ };
24457
+ onLoad();
24458
+ };
24459
+ this.imageState[imageId] = {
24460
+ loaded: false,
24461
+ error: false
24462
+ };
24463
+ if (realImageURL) this.imageSource[imageId].src = realImageURL;
24464
+ }
24659
24465
  loadImage(params, image) {
24660
24466
  const imageProps = params;
24661
- const imagePlaceholder = image.findOne(`#${imageProps.id}-placeholder`);
24662
- const internalImage = image.findOne(`#${imageProps.id}-image`);
24467
+ const { id } = imageProps;
24468
+ const imagePlaceholder = image.findOne(`#${id}-placeholder`);
24469
+ const internalImage = image.findOne(`#${id}-image`);
24663
24470
  const realImageURL = this.config.urlTransformer?.(imageProps.imageURL ?? "") ?? imageProps.imageURL;
24664
- this.loadAsyncElement(imageProps.id);
24665
- const imageObj = new Image();
24666
- imageObj.crossOrigin = this.config.crossOrigin;
24667
- imageObj.onerror = (error) => {
24668
- this.resolveAsyncElement(imageProps.id);
24669
- console.error("Error loading image", realImageURL, error);
24670
- imagePlaceholder?.setAttrs({ visible: true });
24671
- internalImage?.setAttrs({ visible: false });
24672
- };
24673
- imageObj.onload = () => {
24674
- if (image && imagePlaceholder && internalImage) {
24675
- image.setAttrs({
24676
- width: imageProps.width ? imageProps.width : imageObj.width,
24677
- height: imageProps.height ? imageProps.height : imageObj.height
24678
- });
24679
- imagePlaceholder.destroy();
24680
- internalImage.setAttrs({
24681
- width: imageProps.width ? imageProps.width : imageObj.width,
24682
- height: imageProps.height ? imageProps.height : imageObj.height,
24683
- image: imageObj,
24684
- visible: true
24685
- });
24686
- internalImage.setAttr("imageInfo", {
24687
- width: imageObj.width,
24688
- height: imageObj.height
24689
- });
24690
- internalImage.zIndex(0);
24691
- this.imageLoaded = true;
24692
- image.setAttrs({
24693
- width: imageProps.width ? imageProps.width : imageObj.width,
24694
- height: imageProps.height ? imageProps.height : imageObj.height
24695
- });
24696
- image.setAttr("imageInfo", {
24697
- width: imageObj.width,
24698
- height: imageObj.height
24699
- });
24700
- this.scaleReset(image);
24701
- const imageRect = image.getClientRect({ relativeTo: this.instance.getStage() });
24702
- if (imageProps.cropInfo && imageProps.uncroppedImage) image.setAttr("uncroppedImage", {
24703
- width: imageProps.uncroppedImage.width,
24704
- height: imageProps.uncroppedImage.height
24705
- });
24706
- if (!imageProps.cropInfo) image.setAttr("uncroppedImage", {
24707
- width: imageRect.width,
24708
- height: imageRect.height
24709
- });
24710
- this.updateImageCrop(imageProps);
24711
- this.resolveAsyncElement(imageProps.id);
24712
- const nodeHandler = this.instance.getNodeHandler(image.getAttrs().nodeType);
24713
- if (nodeHandler) this.instance.updateNode(nodeHandler.serialize(image));
24471
+ this.loadAsyncElement(id);
24472
+ this.preloadImage(id, realImageURL ?? "", {
24473
+ onLoad: () => {
24474
+ if (image && imagePlaceholder && internalImage) {
24475
+ image.setAttrs({
24476
+ width: imageProps.width ? imageProps.width : this.imageSource[id].width,
24477
+ height: imageProps.height ? imageProps.height : this.imageSource[id].height
24478
+ });
24479
+ imagePlaceholder.destroy();
24480
+ internalImage.setAttrs({
24481
+ width: imageProps.width ? imageProps.width : this.imageSource[id].width,
24482
+ height: imageProps.height ? imageProps.height : this.imageSource[id].height,
24483
+ image: this.imageSource[id],
24484
+ visible: true
24485
+ });
24486
+ internalImage.setAttr("imageInfo", {
24487
+ width: this.imageSource[id].width,
24488
+ height: this.imageSource[id].height
24489
+ });
24490
+ internalImage.zIndex(0);
24491
+ this.imageLoaded = true;
24492
+ image.setAttrs({
24493
+ width: imageProps.width ? imageProps.width : this.imageSource[id].width,
24494
+ height: imageProps.height ? imageProps.height : this.imageSource[id].height
24495
+ });
24496
+ image.setAttr("imageInfo", {
24497
+ width: this.imageSource[id].width,
24498
+ height: this.imageSource[id].height
24499
+ });
24500
+ this.scaleReset(image);
24501
+ const imageRect = image.getClientRect({ relativeTo: this.instance.getStage() });
24502
+ if (imageProps.cropInfo && imageProps.uncroppedImage) image.setAttr("uncroppedImage", {
24503
+ width: imageProps.uncroppedImage.width,
24504
+ height: imageProps.uncroppedImage.height
24505
+ });
24506
+ if (!imageProps.cropInfo) image.setAttr("uncroppedImage", {
24507
+ width: imageRect.width,
24508
+ height: imageRect.height
24509
+ });
24510
+ this.updateImageCrop(imageProps);
24511
+ this.imageState[id] = {
24512
+ loaded: true,
24513
+ error: false
24514
+ };
24515
+ this.resolveAsyncElement(id);
24516
+ const nodeHandler = this.instance.getNodeHandler(image.getAttrs().nodeType);
24517
+ if (nodeHandler) this.instance.updateNode(nodeHandler.serialize(image));
24518
+ }
24519
+ },
24520
+ onError: (error) => {
24521
+ this.imageState[id] = {
24522
+ loaded: false,
24523
+ error: true
24524
+ };
24525
+ this.resolveAsyncElement(id);
24526
+ console.error("Error loading image", realImageURL, error);
24527
+ imagePlaceholder?.setAttrs({ visible: true });
24528
+ internalImage?.setAttrs({ visible: false });
24714
24529
  }
24715
- };
24716
- if (realImageURL) imageObj.src = realImageURL;
24530
+ });
24717
24531
  }
24718
24532
  updateImageCrop(nextProps) {
24719
24533
  const imageAttrs = nextProps;
@@ -24750,24 +24564,23 @@ var WeaveImageNode = class extends WeaveNode {
24750
24564
  this.cachedCropInfo[imageAttrs.id ?? ""] = void 0;
24751
24565
  }
24752
24566
  }
24753
- getImageToolAction() {
24754
- const imageToolAction = this.instance.getActionHandler(IMAGE_TOOL_ACTION_NAME);
24755
- if (!imageToolAction) throw new Error("Image Tool action not found");
24756
- return imageToolAction;
24567
+ getImageSource(imageId) {
24568
+ return this.imageSource[imageId];
24757
24569
  }
24758
24570
  scaleReset(node) {
24759
24571
  const scale = node.scale();
24572
+ const nodeAttrs = node.getAttrs();
24760
24573
  const widthNotNormalized = node.width();
24761
24574
  const heightNotNormalized = node.height();
24762
- const uncroppedWidth = node.getAttrs().uncroppedImage ? node.getAttrs().uncroppedImage.width : widthNotNormalized;
24763
- const uncroppedHeight = node.getAttrs().uncroppedImage ? node.getAttrs().uncroppedImage.height : heightNotNormalized;
24575
+ const uncroppedWidth = nodeAttrs.uncroppedImage ? nodeAttrs.uncroppedImage.width : widthNotNormalized;
24576
+ const uncroppedHeight = nodeAttrs.uncroppedImage ? nodeAttrs.uncroppedImage.height : heightNotNormalized;
24764
24577
  node.setAttrs({ uncroppedImage: {
24765
24578
  width: uncroppedWidth * node.scaleX(),
24766
24579
  height: uncroppedHeight * node.scaleY()
24767
24580
  } });
24768
- const placeholder = node.findOne(`#${node.getAttrs().id}-placeholder`);
24769
- const internalImage = node.findOne(`#${node.getAttrs().id}-image`);
24770
- const cropGroup = node.findOne(`#${node.getAttrs().id}-cropGroup`);
24581
+ const placeholder = node.findOne(`#${nodeAttrs.id}-placeholder`);
24582
+ const internalImage = node.findOne(`#${nodeAttrs.id}-image`);
24583
+ const cropGroup = node.findOne(`#${nodeAttrs.id}-cropGroup`);
24771
24584
  if (placeholder) {
24772
24585
  placeholder.width(Math.max(5, placeholder.width() * placeholder.scaleX()));
24773
24586
  placeholder.height(Math.max(5, placeholder.height() * placeholder.scaleY()));
@@ -24798,7 +24611,6 @@ var WeaveImageNode = class extends WeaveNode {
24798
24611
  x: 1,
24799
24612
  y: 1
24800
24613
  });
24801
- this.instance.getMainLayer()?.batchDraw();
24802
24614
  }
24803
24615
  };
24804
24616
 
@@ -26227,25 +26039,530 @@ var WeaveCommentNode = class extends WeaveNode {
26227
26039
  this.openCommentDOM(node);
26228
26040
  }
26229
26041
  });
26230
- tween.play();
26042
+ tween.play();
26043
+ }
26044
+ }
26045
+ setCommentViewing(commentId) {
26046
+ this.commentDomAction = commentId ? "viewing" : "idle";
26047
+ this.commentDomVisible = !!commentId;
26048
+ this.commentDomVisibleId = commentId;
26049
+ }
26050
+ isCommentViewing() {
26051
+ return this.commentDomAction === WEAVE_COMMENT_NODE_ACTION.VIEWING && this.commentDomVisible;
26052
+ }
26053
+ isCommentCreating() {
26054
+ return this.commentDomAction === WEAVE_COMMENT_NODE_ACTION.CREATING && this.commentDomVisible;
26055
+ }
26056
+ getCommentId(node) {
26057
+ return this.config.model.getId(node.getAttrs().commentModel);
26058
+ }
26059
+ setShowResolved(show) {
26060
+ this.showResolved = show;
26061
+ }
26062
+ };
26063
+
26064
+ //#endregion
26065
+ //#region src/nodes/video/constants.ts
26066
+ const WEAVE_VIDEO_NODE_TYPE = "video";
26067
+ const WEAVE_VIDEO_DEFAULT_CONFIG = {
26068
+ crossOrigin: "anonymous",
26069
+ style: {
26070
+ playPauseOnDblClick: true,
26071
+ background: {
26072
+ color: "#C9C9C9FF",
26073
+ strokeWidth: 0,
26074
+ strokeColor: "#000000FF"
26075
+ },
26076
+ track: {
26077
+ resetOnEnd: true,
26078
+ onlyOnHover: false,
26079
+ color: "#FF0033FF",
26080
+ height: 5
26081
+ },
26082
+ iconBackground: {
26083
+ color: "#FFFFFFFF",
26084
+ strokeWidth: 0,
26085
+ strokeColor: "#000000FF"
26086
+ },
26087
+ icon: {
26088
+ internal: {
26089
+ paddingX: 12,
26090
+ paddingY: 8
26091
+ },
26092
+ external: {
26093
+ paddingX: 20,
26094
+ paddingY: 20
26095
+ },
26096
+ width: 24,
26097
+ height: 24,
26098
+ color: "#FFFFFFFF",
26099
+ dataURL: "data:image/png;base64,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"
26100
+ }
26101
+ }
26102
+ };
26103
+
26104
+ //#endregion
26105
+ //#region src/nodes/video/video.ts
26106
+ var WeaveVideoNode = class extends WeaveNode {
26107
+ videoState = {};
26108
+ videoSourceFrameId = {};
26109
+ videoSource = {};
26110
+ videoPlaceholder = {};
26111
+ nodeType = WEAVE_VIDEO_NODE_TYPE;
26112
+ constructor(params) {
26113
+ super();
26114
+ const { config } = params ?? {};
26115
+ this.config = (0, import_lodash.merge)(WEAVE_VIDEO_DEFAULT_CONFIG, config);
26116
+ }
26117
+ initVideoIcon() {
26118
+ if (!this.videoIconImage) {
26119
+ this.videoIconImage = new Image();
26120
+ this.videoIconImage.src = this.config.style.icon.dataURL;
26121
+ }
26122
+ }
26123
+ async loadPlaceholder(params, video) {
26124
+ const videoProps = params;
26125
+ const { id } = videoProps;
26126
+ const videoPlaceholder = video.findOne(`#${id}-video-placeholder`);
26127
+ const videoIconGroup = video.findOne(`#${id}-video-icon-group`);
26128
+ if (!videoPlaceholder || !videoIconGroup) return;
26129
+ const realVideoPlaceholderURL = this.config.urlTransformer?.(videoProps.videoPlaceholderURL ?? "") ?? videoProps.videoPlaceholderURL;
26130
+ this.videoPlaceholder[id] = new Image();
26131
+ this.videoPlaceholder[id].crossOrigin = this.config.crossOrigin;
26132
+ this.videoPlaceholder[id].src = realVideoPlaceholderURL;
26133
+ this.videoPlaceholder[id].onerror = (error) => {
26134
+ console.error("Error loading video placeholder", realVideoPlaceholderURL, error);
26135
+ this.resolveAsyncElement(id);
26136
+ };
26137
+ this.videoPlaceholder[id].onload = () => {
26138
+ videoPlaceholder.setAttrs({ image: this.videoPlaceholder[id] });
26139
+ const videoWidth = video.getAttrs().width ?? 0;
26140
+ const videoHeight = video.getAttrs().height ?? 0;
26141
+ const videoIconGroupWidth = this.config.style.icon.internal.paddingX * 2 + this.config.style.icon.width;
26142
+ const videoIconGroupHeight = this.config.style.icon.internal.paddingY * 2 + this.config.style.icon.height;
26143
+ videoIconGroup.x(videoWidth - videoIconGroupWidth - this.config.style.icon.external.paddingX);
26144
+ videoIconGroup.y(videoHeight - videoIconGroupHeight - this.config.style.icon.external.paddingY);
26145
+ const nodesSelectionPlugin = this.getNodeSelectionPlugin();
26146
+ if (nodesSelectionPlugin) nodesSelectionPlugin.getTransformer().forceUpdate();
26147
+ this.resolveAsyncElement(id);
26148
+ };
26149
+ }
26150
+ loadVideo(params, video) {
26151
+ const videoProps = params;
26152
+ const { id } = videoProps;
26153
+ const videoSource = document.createElement("video");
26154
+ videoSource.crossOrigin = this.config.crossOrigin;
26155
+ videoSource.preload = "auto";
26156
+ const bg = video.findOne(`#${id}-bg`);
26157
+ const videoProgress = video.findOne(`#${id}-video-progress`);
26158
+ const videoIconGroup = video.findOne(`#${id}-video-icon-group`);
26159
+ const videoPlaceholder = video.findOne(`#${id}-video-placeholder`);
26160
+ const videoPlayer = video.findOne(`#${id}-video`);
26161
+ if (!bg || !videoIconGroup || !videoProgress || !videoPlayer || !videoPlaceholder) return;
26162
+ const realVideoURL = this.config.urlTransformer?.(videoProps.videoURL ?? "") ?? videoProps.videoURL;
26163
+ if (realVideoURL) videoSource.src = realVideoURL;
26164
+ videoSource.addEventListener("loadeddata", () => {
26165
+ videoSource.currentTime = 0;
26166
+ this.videoState[id] = {
26167
+ ...this.videoState[id],
26168
+ loaded: true,
26169
+ playing: false,
26170
+ paused: false
26171
+ };
26172
+ });
26173
+ const onFrame = () => {
26174
+ const progress = this.videoSource[id].duration ? Math.max(this.videoSource[id].currentTime / this.videoSource[id].duration, 0) : 0;
26175
+ videoProgress.setAttrs({ width: (video.getAttrs().width ?? 0) * progress });
26176
+ this.videoSourceFrameId[id] = videoSource.requestVideoFrameCallback(onFrame);
26177
+ };
26178
+ videoSource.addEventListener("play", () => {
26179
+ const videoProgress$1 = video.findOne(`#${id}-video-progress`);
26180
+ if (videoProgress$1 && !this.config.style.track.onlyOnHover) videoProgress$1.show();
26181
+ this.videoSourceFrameId[id] = videoSource.requestVideoFrameCallback(onFrame);
26182
+ });
26183
+ videoSource.addEventListener("stop", () => {
26184
+ if (this.videoSourceFrameId[id]) videoSource.cancelVideoFrameCallback(this.videoSourceFrameId[id]);
26185
+ });
26186
+ videoSource.addEventListener("ended", () => {
26187
+ videoProgress.setAttrs({ width: video.getAttrs().width ?? 0 });
26188
+ if (this.config.style.track.resetOnEnd) this.stop(id);
26189
+ });
26190
+ videoSource.addEventListener("error", (error) => {
26191
+ console.error("Error loading image", realVideoURL, error);
26192
+ });
26193
+ videoSource.addEventListener("loadedmetadata", () => {
26194
+ const videoSource$1 = this.videoSource[id];
26195
+ const videoWidth = video.getAttrs().width ?? 0;
26196
+ const videoHeight = video.getAttrs().height ?? 0;
26197
+ videoPlayer.setAttrs({ image: videoSource$1 });
26198
+ videoProgress.width(0);
26199
+ videoProgress.y(videoHeight - this.config.style.track.height / this.instance.getStage().scaleY());
26200
+ const videoIconGroupWidth = this.config.style.icon.internal.paddingX * 2 + this.config.style.icon.width;
26201
+ const videoIconGroupHeight = this.config.style.icon.internal.paddingY * 2 + this.config.style.icon.height;
26202
+ videoIconGroup.x(videoWidth - videoIconGroupWidth - this.config.style.icon.external.paddingX);
26203
+ videoIconGroup.y(videoHeight - videoIconGroupHeight - this.config.style.icon.external.paddingY);
26204
+ });
26205
+ videoPlayer.setAttrs({ image: videoSource });
26206
+ this.videoSource[id] = videoSource;
26207
+ }
26208
+ onRender(props) {
26209
+ this.initVideoIcon();
26210
+ const videoProperties = props.videoProperties ?? {};
26211
+ const videoProps = props;
26212
+ const { id } = videoProps;
26213
+ const groupVideoProps = { ...videoProps };
26214
+ delete groupVideoProps.children;
26215
+ delete groupVideoProps.imageProperties;
26216
+ delete groupVideoProps.zIndex;
26217
+ const internalVideoProps = { ...props };
26218
+ delete internalVideoProps.videoProperties;
26219
+ delete internalVideoProps.videoPlaceholderURL;
26220
+ delete internalVideoProps.videoURL;
26221
+ delete internalVideoProps.zIndex;
26222
+ const videoGroup = new konva.default.Group({
26223
+ ...groupVideoProps,
26224
+ ...internalVideoProps,
26225
+ id,
26226
+ name: "node",
26227
+ strokeScaleEnabled: true
26228
+ });
26229
+ const bg = new konva.default.Rect({
26230
+ ...groupVideoProps,
26231
+ x: 0,
26232
+ y: 0,
26233
+ id: `${id}-bg`,
26234
+ fill: this.config.style.background.color,
26235
+ stroke: this.config.style.background.strokeColor,
26236
+ strokeWidth: this.config.style.background.strokeWidth
26237
+ });
26238
+ videoGroup.add(bg);
26239
+ if (!isServer()) {
26240
+ const video = new konva.default.Image({
26241
+ ...groupVideoProps,
26242
+ ...videoProperties,
26243
+ id: `${id}-video`,
26244
+ x: 0,
26245
+ y: 0,
26246
+ draggable: false,
26247
+ image: void 0,
26248
+ name: void 0
26249
+ });
26250
+ video.hide();
26251
+ videoGroup.add(video);
26252
+ const videoProgress = new konva.default.Rect({
26253
+ ...groupVideoProps,
26254
+ ...videoProperties,
26255
+ id: `${id}-video-progress`,
26256
+ x: 0,
26257
+ y: 0,
26258
+ height: this.config.style.track.height / this.instance.getStage().scaleY(),
26259
+ strokeWidth: 0,
26260
+ fill: this.config.style.track.color,
26261
+ name: void 0
26262
+ });
26263
+ this.instance.addEventListener("onZoomChange", () => {
26264
+ videoProgress.height(this.config.style.track.height / this.instance.getStage().scaleY());
26265
+ videoProgress.y((videoGroup.getAttrs().height ?? 0) - videoProgress.height());
26266
+ });
26267
+ videoProgress.hide();
26268
+ videoGroup.add(videoProgress);
26269
+ }
26270
+ const videoPlaceholder = new konva.default.Image({
26271
+ ...groupVideoProps,
26272
+ id: `${id}-video-placeholder`,
26273
+ x: 0,
26274
+ y: 0,
26275
+ draggable: false,
26276
+ image: void 0,
26277
+ name: void 0
26278
+ });
26279
+ videoPlaceholder.show();
26280
+ videoGroup.add(videoPlaceholder);
26281
+ const videoIconGroup = new konva.default.Group({
26282
+ id: `${id}-video-icon-group`,
26283
+ x: 0,
26284
+ y: 0
26285
+ });
26286
+ const videoIconBg = new konva.default.Rect({
26287
+ ...groupVideoProps,
26288
+ id: `${id}-video-icon-bg`,
26289
+ x: 0,
26290
+ y: 0,
26291
+ width: this.config.style.icon.internal.paddingX * 2 + this.config.style.icon.width,
26292
+ height: this.config.style.icon.internal.paddingY * 2 + this.config.style.icon.height,
26293
+ strokeWidth: this.config.style.iconBackground.strokeWidth,
26294
+ stroke: this.config.style.iconBackground.strokeColor,
26295
+ fill: this.config.style.iconBackground.color
26296
+ });
26297
+ videoIconGroup.add(videoIconBg);
26298
+ const videoIcon = new konva.default.Image({
26299
+ ...groupVideoProps,
26300
+ id: `${id}-video-icon`,
26301
+ x: this.config.style.icon.internal.paddingX,
26302
+ y: this.config.style.icon.internal.paddingY,
26303
+ width: this.config.style.icon.width,
26304
+ height: this.config.style.icon.height,
26305
+ fill: "transparent",
26306
+ image: this.videoIconImage
26307
+ });
26308
+ videoIconGroup.add(videoIcon);
26309
+ videoGroup.add(videoIconGroup);
26310
+ this.setupDefaultNodeAugmentation(videoGroup);
26311
+ const defaultTransformerProperties = this.defaultGetTransformerProperties(this.config.transform);
26312
+ videoGroup.getTransformerProperties = function() {
26313
+ return defaultTransformerProperties;
26314
+ };
26315
+ if (!this.anim) this.anim = new konva.default.Animation(() => {
26316
+ this.instance.getMainLayer()?.batchDraw();
26317
+ }, this.instance.getMainLayer());
26318
+ this.setupDefaultNodeEvents(videoGroup);
26319
+ videoGroup.allowedAnchors = function() {
26320
+ return [
26321
+ "top-left",
26322
+ "top-right",
26323
+ "bottom-left",
26324
+ "bottom-right"
26325
+ ];
26326
+ };
26327
+ let videoWasPlaying = false;
26328
+ let videoProgressWasVisible = false;
26329
+ const handleTransformStart = (e) => {
26330
+ const node = e.target;
26331
+ const videoProgress = node.findOne(`#${id}-video-progress`);
26332
+ if (videoProgress && videoProgress.isVisible()) {
26333
+ videoProgressWasVisible = true;
26334
+ videoProgress.hide();
26335
+ }
26336
+ if (this.videoState[id]?.playing) {
26337
+ videoWasPlaying = true;
26338
+ this.pause(id);
26339
+ }
26340
+ const videoIconGroup$1 = node.findOne(`#${id}-video-icon-group`);
26341
+ if (videoIconGroup$1) videoIconGroup$1.hide();
26342
+ };
26343
+ videoGroup.on("transformstart", handleTransformStart);
26344
+ const handleTransformEnd = (e) => {
26345
+ const node = e.target;
26346
+ const videoProgress = node.findOne(`#${id}-video-progress`);
26347
+ if (videoProgress && videoProgressWasVisible) videoProgress.show();
26348
+ const videoIconGroup$1 = node.findOne(`#${id}-video-icon-group`);
26349
+ if (videoIconGroup$1) videoIconGroup$1.show();
26350
+ if (this.videoState[id]?.paused && videoWasPlaying) this.play(id);
26351
+ videoProgressWasVisible = false;
26352
+ videoWasPlaying = false;
26353
+ };
26354
+ videoGroup.on("transformend", handleTransformEnd);
26355
+ const videoWidth = videoGroup.getAttrs().width ?? 0;
26356
+ const videoHeight = videoGroup.getAttrs().height ?? 0;
26357
+ const videoIconGroupWidth = this.config.style.icon.internal.paddingX * 2 + this.config.style.icon.width;
26358
+ const videoIconGroupHeight = this.config.style.icon.internal.paddingY * 2 + this.config.style.icon.height;
26359
+ videoIconGroup.x(videoWidth - videoIconGroupWidth - this.config.style.icon.external.paddingX);
26360
+ videoIconGroup.y(videoHeight - videoIconGroupHeight - this.config.style.icon.external.paddingY);
26361
+ this.loadAsyncElement(id);
26362
+ this.loadPlaceholder(props, videoGroup);
26363
+ const isLoaded = typeof this.videoSource[id] !== "undefined";
26364
+ if (!isLoaded && !isServer()) {
26365
+ this.videoState[id] = {
26366
+ placeholderLoaded: false,
26367
+ loaded: false,
26368
+ playing: false,
26369
+ paused: false
26370
+ };
26371
+ this.loadVideo(props, videoGroup);
26372
+ }
26373
+ if (isLoaded && !isServer()) {
26374
+ videoGroup.setAttr("videoInfo", {
26375
+ width: this.videoSource[id].videoWidth,
26376
+ height: this.videoSource[id].videoHeight
26377
+ });
26378
+ this.instance.updateNode(this.serialize(videoGroup));
26231
26379
  }
26380
+ if (isServer()) this.instance.updateNode(this.serialize(videoGroup));
26381
+ const defaultHandleMouseover = videoGroup.handleMouseover;
26382
+ videoGroup.handleMouseover = () => {
26383
+ defaultHandleMouseover.call(this);
26384
+ if (this.config.style.track.onlyOnHover && this.videoState[id].loaded) {
26385
+ const videoProgress = videoGroup.findOne(`#${id}-video-progress`);
26386
+ videoProgress?.show();
26387
+ }
26388
+ };
26389
+ const defaultHandleMouseout = videoGroup.handleMouseout;
26390
+ videoGroup.handleMouseout = () => {
26391
+ defaultHandleMouseout.call(this);
26392
+ if (this.config.style.track.onlyOnHover && this.videoState[id].loaded && !this.videoState[id].paused) {
26393
+ const videoProgress = videoGroup.findOne(`#${id}-video-progress`);
26394
+ videoProgress?.hide();
26395
+ }
26396
+ };
26397
+ videoGroup.on("mouseover", () => {
26398
+ videoGroup.handleMouseover();
26399
+ });
26400
+ videoGroup.on("mouseout", () => {
26401
+ videoGroup.handleMouseout();
26402
+ });
26403
+ videoGroup.dblClick = () => {
26404
+ if (this.config.style.playPauseOnDblClick && this.videoState[id].loaded && !this.videoState[id].playing) {
26405
+ this.play(id);
26406
+ return;
26407
+ }
26408
+ if (this.config.style.playPauseOnDblClick && this.videoState[id].loaded && this.videoState[id].playing) {
26409
+ this.pause(id);
26410
+ return;
26411
+ }
26412
+ };
26413
+ return videoGroup;
26232
26414
  }
26233
- setCommentViewing(commentId) {
26234
- this.commentDomAction = commentId ? "viewing" : "idle";
26235
- this.commentDomVisible = !!commentId;
26236
- this.commentDomVisibleId = commentId;
26415
+ loadAsyncElement(nodeId) {
26416
+ this.instance.loadAsyncElement(nodeId, "video");
26237
26417
  }
26238
- isCommentViewing() {
26239
- return this.commentDomAction === WEAVE_COMMENT_NODE_ACTION.VIEWING && this.commentDomVisible;
26418
+ resolveAsyncElement(nodeId) {
26419
+ this.instance.resolveAsyncElement(nodeId, "video");
26420
+ }
26421
+ getVideoState(nodeInstance) {
26422
+ return this.videoState[nodeInstance.getAttrs().id ?? ""];
26423
+ }
26424
+ play(videoId) {
26425
+ const video = this.instance.getStage().findOne(`#${videoId}`);
26426
+ if (!video) return;
26427
+ const videoPlaceholderNode = video.findOne(`#${videoId}-video-placeholder`);
26428
+ if (videoPlaceholderNode) videoPlaceholderNode.hide();
26429
+ const videoIconGroup = video.findOne(`#${videoId}-video-icon-group`);
26430
+ if (videoIconGroup) videoIconGroup.hide();
26431
+ const videoNode = video.findOne(`#${videoId}-video`);
26432
+ if (videoNode && this.videoSource[videoId]) {
26433
+ videoNode.show();
26434
+ this.videoState[videoId] = {
26435
+ ...this.videoState[videoId],
26436
+ playing: true,
26437
+ paused: false
26438
+ };
26439
+ this.videoSource[videoId].play();
26440
+ this.anim.start();
26441
+ this.instance.emitEvent("onVideoPlay", { nodeId: videoId });
26442
+ }
26443
+ }
26444
+ pause(videoId) {
26445
+ const video = this.instance.getStage().findOne(`#${videoId}`);
26446
+ if (!video) return;
26447
+ const videoIconGroup = video.findOne(`#${videoId}-video-icon-group`);
26448
+ if (videoIconGroup) videoIconGroup.show();
26449
+ const videoNode = video.findOne(`#${videoId}-video`);
26450
+ if (videoNode && this.videoSource[videoId]) {
26451
+ this.videoSource[videoId].pause();
26452
+ this.videoState[videoId] = {
26453
+ ...this.videoState[videoId],
26454
+ playing: false,
26455
+ paused: true
26456
+ };
26457
+ this.instance.emitEvent("onVideoPause", { nodeId: videoId });
26458
+ }
26459
+ }
26460
+ stop(videoId) {
26461
+ const video = this.instance.getStage().findOne(`#${videoId}`);
26462
+ if (!video) return;
26463
+ const videoPlaceholderNode = video.findOne(`#${videoId}-video-placeholder`);
26464
+ if (videoPlaceholderNode) videoPlaceholderNode.show();
26465
+ const videoProgress = video.findOne(`#${videoId}-video-progress`);
26466
+ if (videoProgress && !this.config.style.track.onlyOnHover) videoProgress.hide();
26467
+ const videoIconGroup = video.findOne(`#${videoId}-video-icon-group`);
26468
+ if (videoIconGroup) videoIconGroup.show();
26469
+ const videoNode = video.findOne(`#${videoId}-video`);
26470
+ if (videoNode && this.videoSource[videoId]) {
26471
+ this.videoSource[videoId].currentTime = 0;
26472
+ this.videoState[videoId] = {
26473
+ ...this.videoState[videoId],
26474
+ playing: false,
26475
+ paused: false
26476
+ };
26477
+ videoNode.hide();
26478
+ this.videoSource[videoId].pause();
26479
+ if (!this.areVideosPlaying()) this.anim.stop();
26480
+ this.instance.emitEvent("onVideoStop", { nodeId: videoId });
26481
+ }
26240
26482
  }
26241
- isCommentCreating() {
26242
- return this.commentDomAction === WEAVE_COMMENT_NODE_ACTION.CREATING && this.commentDomVisible;
26483
+ areVideosPlaying() {
26484
+ return Object.values(this.videoState).some((state) => state.playing);
26243
26485
  }
26244
- getCommentId(node) {
26245
- return this.config.model.getId(node.getAttrs().commentModel);
26486
+ getVideoSource(videoId) {
26487
+ return this.videoSource[videoId];
26246
26488
  }
26247
- setShowResolved(show) {
26248
- this.showResolved = show;
26489
+ onUpdate(nodeInstance, nextProps) {
26490
+ nodeInstance.setAttrs({ ...nextProps });
26491
+ const id = nodeInstance.getAttrs().id ?? "";
26492
+ const node = nodeInstance;
26493
+ const nodeAttrs = node.getAttrs();
26494
+ const internalVideoProps = { ...nodeAttrs };
26495
+ delete internalVideoProps.nodeType;
26496
+ delete internalVideoProps.videoProperties;
26497
+ delete internalVideoProps.videoPlaceholderURL;
26498
+ delete internalVideoProps.videoURL;
26499
+ delete internalVideoProps.zIndex;
26500
+ const bg = node.findOne(`#${id}-bg`);
26501
+ const videoIconGroup = node.findOne(`#${id}-video-icon-group`);
26502
+ const videoPlaceholder = node.findOne(`#${id}-video-placeholder`);
26503
+ if (!bg || !videoIconGroup || !videoPlaceholder) return;
26504
+ const videoWidth = node.getAttrs().width ?? 0;
26505
+ const videoHeight = node.getAttrs().height ?? 0;
26506
+ bg.setAttrs({
26507
+ ...internalVideoProps,
26508
+ id: `${id}-bg`,
26509
+ x: 0,
26510
+ y: 0
26511
+ });
26512
+ const video = node.findOne(`#${id}-video`);
26513
+ if (!isServer() && video) video.setAttrs({
26514
+ ...internalVideoProps,
26515
+ id: `${id}-video`,
26516
+ x: 0,
26517
+ y: 0
26518
+ });
26519
+ videoPlaceholder.setAttrs({
26520
+ ...internalVideoProps,
26521
+ id: `${id}-video-placeholder`,
26522
+ x: 0,
26523
+ y: 0
26524
+ });
26525
+ const videoIconGroupWidth = this.config.style.icon.internal.paddingX * 2 + this.config.style.icon.width;
26526
+ const videoIconGroupHeight = this.config.style.icon.internal.paddingY * 2 + this.config.style.icon.height;
26527
+ videoIconGroup.x(videoWidth - videoIconGroupWidth - this.config.style.icon.external.paddingX);
26528
+ videoIconGroup.y(videoHeight - videoIconGroupHeight - this.config.style.icon.external.paddingY);
26529
+ const nodesSelectionPlugin = this.getNodeSelectionPlugin();
26530
+ if (nodesSelectionPlugin) nodesSelectionPlugin.getTransformer().forceUpdate();
26531
+ }
26532
+ getNodeSelectionPlugin() {
26533
+ const nodesSelectionPlugin = this.instance.getPlugin("nodesSelection");
26534
+ return nodesSelectionPlugin;
26535
+ }
26536
+ scaleReset(node) {
26537
+ const scale = node.scale();
26538
+ const id = node.getAttr("id");
26539
+ const videoProgress = node.findOne(`#${id}-video-progress`);
26540
+ const videoIconGroup = node.findOne(`#${id}-video-icon-group`);
26541
+ if (videoIconGroup && videoProgress) {
26542
+ videoIconGroup.scaleX(1);
26543
+ videoIconGroup.scaleY(1);
26544
+ const videoIconGroupWidth = this.config.style.icon.internal.paddingX * 2 + this.config.style.icon.width;
26545
+ const videoIconGroupHeight = this.config.style.icon.internal.paddingY * 2 + this.config.style.icon.height;
26546
+ const stage = this.instance.getStage();
26547
+ const videoWidth = (node.getAttrs().width ?? 0) * stage.scaleX();
26548
+ const videoHeight = (node.getAttrs().height ?? 0) * stage.scaleY();
26549
+ videoIconGroup.x(videoWidth - videoIconGroupWidth - this.config.style.icon.external.paddingX);
26550
+ videoIconGroup.y(videoHeight - videoIconGroupHeight - this.config.style.icon.external.paddingY);
26551
+ }
26552
+ node.width(Math.max(5, node.width() * scale.x));
26553
+ node.height(Math.max(5, node.height() * scale.y));
26554
+ if (videoProgress) {
26555
+ videoProgress.scaleX(1);
26556
+ videoProgress.scaleY(1);
26557
+ const progress = this.videoSource[id].duration ? Math.min(this.videoSource[id].currentTime / this.videoSource[id].duration, 1) : 0;
26558
+ videoProgress.width((node.getAttrs().width ?? 0) * progress);
26559
+ videoProgress.height(this.config.style.track.height / this.instance.getStage().scaleY());
26560
+ videoProgress.y((node.getAttrs().height ?? 0) - videoProgress.height());
26561
+ }
26562
+ node.scale({
26563
+ x: 1,
26564
+ y: 1
26565
+ });
26249
26566
  }
26250
26567
  };
26251
26568
 
@@ -28043,67 +28360,345 @@ var WeaveTextToolAction = class extends WeaveAction {
28043
28360
  return;
28044
28361
  }
28045
28362
  });
28046
- this.initialized = true;
28363
+ this.initialized = true;
28364
+ }
28365
+ setState(state) {
28366
+ this.state = state;
28367
+ }
28368
+ addText() {
28369
+ const selectionPlugin = this.instance.getPlugin("nodesSelection");
28370
+ if (selectionPlugin) {
28371
+ const tr = selectionPlugin.getTransformer();
28372
+ tr.hide();
28373
+ }
28374
+ this.setCursor();
28375
+ this.setFocusStage();
28376
+ this.instance.emitEvent("onAddingText");
28377
+ this.clickPoint = null;
28378
+ this.setState(TEXT_TOOL_STATE.ADDING);
28379
+ }
28380
+ handleAdding() {
28381
+ const { mousePoint, container } = this.instance.getMousePointer();
28382
+ this.clickPoint = mousePoint;
28383
+ this.container = container;
28384
+ this.textId = v4_default();
28385
+ const nodeHandler = this.instance.getNodeHandler("text");
28386
+ if (nodeHandler) {
28387
+ const node = nodeHandler.create(this.textId, {
28388
+ ...this.props,
28389
+ x: this.clickPoint?.x ?? 0,
28390
+ y: this.clickPoint?.y ?? 0,
28391
+ draggable: true
28392
+ });
28393
+ this.instance.addNode(node, this.container?.getAttrs().id);
28394
+ this.instance.emitEvent("onAddedArrow");
28395
+ }
28396
+ this.setState(TEXT_TOOL_STATE.FINISHED);
28397
+ this.cancelAction();
28398
+ }
28399
+ trigger(cancelAction) {
28400
+ if (!this.instance) throw new Error("Instance not defined");
28401
+ if (!this.initialized) this.setupEvents();
28402
+ this.cancelAction = cancelAction;
28403
+ const selectionPlugin = this.instance.getPlugin("nodesSelection");
28404
+ if (selectionPlugin) selectionPlugin.setSelectedNodes([]);
28405
+ this.props = this.initProps();
28406
+ this.addText();
28407
+ }
28408
+ cleanup() {
28409
+ const stage = this.instance.getStage();
28410
+ stage.container().style.cursor = "default";
28411
+ const selectionPlugin = this.instance.getPlugin("nodesSelection");
28412
+ if (selectionPlugin) {
28413
+ const node$1 = stage.findOne(`#${this.textId}`);
28414
+ if (node$1) selectionPlugin.setSelectedNodes([node$1]);
28415
+ this.instance.triggerAction(SELECTION_TOOL_ACTION_NAME);
28416
+ }
28417
+ const node = stage.findOne(`#${this.textId}`);
28418
+ if (node) node.getAttr("triggerEditMode")(node);
28419
+ this.initialCursor = null;
28420
+ this.textId = null;
28421
+ this.container = void 0;
28422
+ this.clickPoint = null;
28423
+ this.setState(TEXT_TOOL_STATE.IDLE);
28424
+ }
28425
+ setCursor() {
28426
+ const stage = this.instance.getStage();
28427
+ stage.container().style.cursor = "crosshair";
28428
+ }
28429
+ setFocusStage() {
28430
+ const stage = this.instance.getStage();
28431
+ stage.container().tabIndex = 1;
28432
+ stage.container().blur();
28433
+ stage.container().focus();
28434
+ }
28435
+ };
28436
+
28437
+ //#endregion
28438
+ //#region src/actions/image-tool/constants.ts
28439
+ const IMAGE_TOOL_ACTION_NAME = "imageTool";
28440
+ const IMAGE_TOOL_STATE = {
28441
+ ["IDLE"]: "idle",
28442
+ ["UPLOADING"]: "uploading",
28443
+ ["DEFINING_POSITION"]: "definingPosition",
28444
+ ["SELECTED_POSITION"]: "selectedPosition",
28445
+ ["ADDING"]: "adding",
28446
+ ["FINISHED"]: "finished"
28447
+ };
28448
+
28449
+ //#endregion
28450
+ //#region src/actions/image-tool/image-tool.ts
28451
+ var WeaveImageToolAction = class extends WeaveAction {
28452
+ initialized = false;
28453
+ initialCursor = null;
28454
+ cursorPadding = 5;
28455
+ forceMainContainer = false;
28456
+ onPropsChange = void 0;
28457
+ update = void 0;
28458
+ constructor() {
28459
+ super();
28460
+ this.pointers = new Map();
28461
+ this.initialized = false;
28462
+ this.state = IMAGE_TOOL_STATE.IDLE;
28463
+ this.imageId = null;
28464
+ this.tempImageId = null;
28465
+ this.tempImageNode = null;
28466
+ this.container = void 0;
28467
+ this.imageURL = null;
28468
+ this.clickPoint = null;
28469
+ }
28470
+ getName() {
28471
+ return IMAGE_TOOL_ACTION_NAME;
28472
+ }
28473
+ initProps() {
28474
+ return {
28475
+ width: 100,
28476
+ height: 100,
28477
+ scaleX: 1,
28478
+ scaleY: 1
28479
+ };
28480
+ }
28481
+ onInit() {
28482
+ this.instance.addEventListener("onStageDrop", (e) => {
28483
+ if (window.weaveDragImageURL) {
28484
+ this.instance.getStage().setPointersPositions(e);
28485
+ const position = this.instance.getStage().getRelativePointerPosition();
28486
+ this.instance.triggerAction(IMAGE_TOOL_ACTION_NAME, {
28487
+ imageURL: window.weaveDragImageURL,
28488
+ imageId: window.weaveDragImageId,
28489
+ position
28490
+ });
28491
+ window.weaveDragImageURL = void 0;
28492
+ window.weaveDragImageId = void 0;
28493
+ }
28494
+ });
28495
+ }
28496
+ setupEvents() {
28497
+ const stage = this.instance.getStage();
28498
+ window.addEventListener("keydown", (e) => {
28499
+ if (e.key === "Escape" && this.instance.getActiveAction() === IMAGE_TOOL_ACTION_NAME) {
28500
+ this.cancelAction();
28501
+ return;
28502
+ }
28503
+ });
28504
+ stage.on("pointerdown", (e) => {
28505
+ this.setTapStart(e);
28506
+ this.pointers.set(e.evt.pointerId, {
28507
+ x: e.evt.clientX,
28508
+ y: e.evt.clientY
28509
+ });
28510
+ if (this.pointers.size === 2 && this.instance.getActiveAction() === IMAGE_TOOL_ACTION_NAME) {
28511
+ this.state = IMAGE_TOOL_STATE.DEFINING_POSITION;
28512
+ return;
28513
+ }
28514
+ if (this.state === IMAGE_TOOL_STATE.DEFINING_POSITION) this.state = IMAGE_TOOL_STATE.SELECTED_POSITION;
28515
+ });
28516
+ stage.on("pointermove", (e) => {
28517
+ if (this.state === IMAGE_TOOL_STATE.IDLE) return;
28518
+ this.setCursor();
28519
+ if (this.pointers.size === 2 && this.instance.getActiveAction() === IMAGE_TOOL_ACTION_NAME) {
28520
+ this.state = IMAGE_TOOL_STATE.DEFINING_POSITION;
28521
+ return;
28522
+ }
28523
+ 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") {
28524
+ const mousePos = stage.getRelativePointerPosition();
28525
+ this.tempImageNode.setAttrs({
28526
+ x: (mousePos?.x ?? 0) + this.cursorPadding,
28527
+ y: (mousePos?.y ?? 0) + this.cursorPadding
28528
+ });
28529
+ }
28530
+ });
28531
+ stage.on("pointerup", (e) => {
28532
+ this.pointers.delete(e.evt.pointerId);
28533
+ if (this.state === IMAGE_TOOL_STATE.SELECTED_POSITION) this.handleAdding();
28534
+ });
28535
+ this.initialized = true;
28536
+ }
28537
+ setState(state) {
28538
+ this.state = state;
28539
+ }
28540
+ loadImage(imageURL, options, position) {
28541
+ this.setCursor();
28542
+ this.setFocusStage();
28543
+ this.imageId = v4_default();
28544
+ this.imageURL = imageURL;
28545
+ const imageNodeHandler = this.getImageNodeHandler();
28546
+ if (!imageNodeHandler) {
28547
+ this.cancelAction();
28548
+ return;
28549
+ }
28550
+ imageNodeHandler.preloadImage(this.imageId, imageURL, {
28551
+ onLoad: () => {
28552
+ this.instance.emitEvent("onImageLoadEnd", void 0);
28553
+ const imageSource = imageNodeHandler.getImageSource(this.imageId);
28554
+ if (imageSource && this.imageId) this.props = {
28555
+ ...this.props,
28556
+ imageURL: this.imageURL,
28557
+ width: imageSource.width,
28558
+ height: imageSource.height
28559
+ };
28560
+ this.addImageNode(position);
28561
+ },
28562
+ onError: () => {
28563
+ this.instance.emitEvent("onImageLoadEnd", new Error("Error loading image"));
28564
+ this.cancelAction();
28565
+ }
28566
+ });
28567
+ this.instance.emitEvent("onImageLoadStart");
28047
28568
  }
28048
- setState(state) {
28049
- this.state = state;
28569
+ isTouchDevice() {
28570
+ return window.matchMedia("(pointer: coarse)").matches;
28050
28571
  }
28051
- addText() {
28052
- const selectionPlugin = this.instance.getPlugin("nodesSelection");
28053
- if (selectionPlugin) {
28054
- const tr = selectionPlugin.getTransformer();
28055
- tr.hide();
28056
- }
28572
+ addImageNode(position) {
28573
+ const stage = this.instance.getStage();
28057
28574
  this.setCursor();
28058
28575
  this.setFocusStage();
28059
- this.instance.emitEvent("onAddingText");
28576
+ if (position) {
28577
+ this.setState(IMAGE_TOOL_STATE.SELECTED_POSITION);
28578
+ this.handleAdding(position);
28579
+ return;
28580
+ }
28581
+ if (this.imageId) {
28582
+ const mousePos = stage.getRelativePointerPosition();
28583
+ this.tempImageId = v4_default();
28584
+ const imageNodeHandler = this.getImageNodeHandler();
28585
+ if (!imageNodeHandler) {
28586
+ this.cancelAction();
28587
+ return;
28588
+ }
28589
+ const imageSource = imageNodeHandler.getImageSource(this.imageId);
28590
+ if (!imageSource) {
28591
+ this.cancelAction();
28592
+ return;
28593
+ }
28594
+ const aspectRatio = imageSource.width / imageSource.height;
28595
+ if (!this.tempImageNode && this.tempImageId && !this.isTouchDevice()) {
28596
+ this.tempImageNode = new konva.default.Image({
28597
+ id: this.tempImageId,
28598
+ x: (mousePos?.x ?? 0) + this.cursorPadding,
28599
+ y: (mousePos?.y ?? 0) + this.cursorPadding,
28600
+ width: 240 * aspectRatio * (1 / stage.scaleX()),
28601
+ height: 240 * (1 / stage.scaleY()),
28602
+ opacity: 1,
28603
+ adding: true,
28604
+ image: imageSource,
28605
+ stroke: "#000000ff",
28606
+ strokeWidth: 0,
28607
+ strokeScaleEnabled: true,
28608
+ listening: false
28609
+ });
28610
+ this.instance.getMainLayer()?.add(this.tempImageNode);
28611
+ }
28612
+ this.instance.emitEvent("onAddingImage", { imageURL: this.props.imageURL });
28613
+ }
28060
28614
  this.clickPoint = null;
28061
- this.setState(TEXT_TOOL_STATE.ADDING);
28615
+ this.setState(IMAGE_TOOL_STATE.DEFINING_POSITION);
28062
28616
  }
28063
- handleAdding() {
28064
- const { mousePoint, container } = this.instance.getMousePointer();
28065
- this.clickPoint = mousePoint;
28066
- this.container = container;
28067
- this.textId = v4_default();
28068
- const nodeHandler = this.instance.getNodeHandler("text");
28069
- if (nodeHandler) {
28070
- const node = nodeHandler.create(this.textId, {
28071
- ...this.props,
28072
- x: this.clickPoint?.x ?? 0,
28073
- y: this.clickPoint?.y ?? 0,
28074
- draggable: true
28075
- });
28076
- this.instance.addNode(node, this.container?.getAttrs().id);
28077
- this.instance.emitEvent("onAddedArrow");
28617
+ addImage(position) {
28618
+ if (position) this.clickPoint = position;
28619
+ this.setState(IMAGE_TOOL_STATE.UPLOADING);
28620
+ }
28621
+ handleAdding(position) {
28622
+ if (this.imageId) {
28623
+ const imageNodeHandler = this.getImageNodeHandler();
28624
+ if (!imageNodeHandler) {
28625
+ this.cancelAction();
28626
+ return;
28627
+ }
28628
+ const imageSource = imageNodeHandler.getImageSource(this.imageId);
28629
+ if (!imageSource) {
28630
+ this.cancelAction();
28631
+ return;
28632
+ }
28633
+ const { mousePoint, container } = this.instance.getMousePointer(position);
28634
+ this.clickPoint = mousePoint;
28635
+ this.container = container;
28636
+ const nodeHandler = this.instance.getNodeHandler("image");
28637
+ if (nodeHandler) {
28638
+ const node = nodeHandler.create(this.imageId, {
28639
+ ...this.props,
28640
+ x: this.clickPoint?.x ?? 0,
28641
+ y: this.clickPoint?.y ?? 0,
28642
+ opacity: 1,
28643
+ adding: false,
28644
+ imageURL: this.imageURL,
28645
+ stroke: "#000000ff",
28646
+ strokeWidth: 0,
28647
+ strokeScaleEnabled: true,
28648
+ imageWidth: imageSource.width,
28649
+ imageHeight: imageSource.height,
28650
+ imageInfo: {
28651
+ width: imageSource.width,
28652
+ height: imageSource.height
28653
+ }
28654
+ });
28655
+ this.instance.addNode(node, this.forceMainContainer ? this.instance.getMainLayer()?.getAttrs().id : this.container?.getAttrs().id);
28656
+ this.instance.emitEvent("onAddedImage", {
28657
+ imageURL: this.props.imageURL,
28658
+ nodeId: this.imageId
28659
+ });
28660
+ }
28661
+ this.setState(IMAGE_TOOL_STATE.FINISHED);
28078
28662
  }
28079
- this.setState(TEXT_TOOL_STATE.FINISHED);
28080
28663
  this.cancelAction();
28081
28664
  }
28082
- trigger(cancelAction) {
28665
+ trigger(cancelAction, params) {
28083
28666
  if (!this.instance) throw new Error("Instance not defined");
28084
28667
  if (!this.initialized) this.setupEvents();
28085
28668
  this.cancelAction = cancelAction;
28086
28669
  const selectionPlugin = this.instance.getPlugin("nodesSelection");
28087
28670
  if (selectionPlugin) selectionPlugin.setSelectedNodes([]);
28671
+ this.forceMainContainer = params?.forceMainContainer ?? false;
28672
+ if (params?.imageId) this.updateProps({ imageId: params.imageId });
28673
+ if (params?.imageURL) {
28674
+ this.loadImage(params.imageURL, params?.options ?? void 0, params?.position ?? void 0);
28675
+ return;
28676
+ }
28088
28677
  this.props = this.initProps();
28089
- this.addText();
28678
+ this.addImage();
28679
+ return { finishUploadCallback: this.loadImage.bind(this) };
28090
28680
  }
28091
28681
  cleanup() {
28092
28682
  const stage = this.instance.getStage();
28093
- stage.container().style.cursor = "default";
28683
+ if (this.tempImageNode) this.tempImageNode.destroy();
28094
28684
  const selectionPlugin = this.instance.getPlugin("nodesSelection");
28095
28685
  if (selectionPlugin) {
28096
- const node$1 = stage.findOne(`#${this.textId}`);
28097
- if (node$1) selectionPlugin.setSelectedNodes([node$1]);
28686
+ const node = stage.findOne(`#${this.imageId}`);
28687
+ if (node) selectionPlugin.setSelectedNodes([node]);
28098
28688
  this.instance.triggerAction(SELECTION_TOOL_ACTION_NAME);
28099
28689
  }
28100
- const node = stage.findOne(`#${this.textId}`);
28101
- if (node) node.getAttr("triggerEditMode")(node);
28690
+ stage.container().style.cursor = "default";
28102
28691
  this.initialCursor = null;
28103
- this.textId = null;
28692
+ this.imageId = null;
28693
+ this.forceMainContainer = false;
28104
28694
  this.container = void 0;
28695
+ this.tempImageNode = null;
28696
+ this.imageURL = null;
28105
28697
  this.clickPoint = null;
28106
- this.setState(TEXT_TOOL_STATE.IDLE);
28698
+ this.setState(IMAGE_TOOL_STATE.IDLE);
28699
+ }
28700
+ getImageNodeHandler() {
28701
+ return this.instance.getNodeHandler("image");
28107
28702
  }
28108
28703
  setCursor() {
28109
28704
  const stage = this.instance.getStage();
@@ -29527,6 +30122,182 @@ var WeaveCommentToolAction = class extends WeaveAction {
29527
30122
  }
29528
30123
  };
29529
30124
 
30125
+ //#endregion
30126
+ //#region src/actions/video-tool/constants.ts
30127
+ const VIDEO_TOOL_ACTION_NAME = "videoTool";
30128
+ const VIDEO_TOOL_STATE = {
30129
+ ["IDLE"]: "idle",
30130
+ ["UPLOADING"]: "uploading",
30131
+ ["DEFINING_POSITION"]: "definingPosition",
30132
+ ["SELECTED_POSITION"]: "selectedPosition",
30133
+ ["ADDING"]: "adding",
30134
+ ["FINISHED"]: "finished"
30135
+ };
30136
+
30137
+ //#endregion
30138
+ //#region src/actions/video-tool/video-tool.ts
30139
+ var WeaveVideoToolAction = class extends WeaveAction {
30140
+ initialized = false;
30141
+ initialCursor = null;
30142
+ cursorPadding = 5;
30143
+ forceMainContainer = false;
30144
+ onPropsChange = void 0;
30145
+ update = void 0;
30146
+ constructor() {
30147
+ super();
30148
+ this.pointers = new Map();
30149
+ this.initialized = false;
30150
+ this.state = VIDEO_TOOL_STATE.IDLE;
30151
+ this.videoId = null;
30152
+ this.container = void 0;
30153
+ this.videoParams = null;
30154
+ this.clickPoint = null;
30155
+ }
30156
+ getName() {
30157
+ return VIDEO_TOOL_ACTION_NAME;
30158
+ }
30159
+ getVideoSource(videoId) {
30160
+ const nodeHandler = this.instance.getNodeHandler("video");
30161
+ if (!nodeHandler) return void 0;
30162
+ return nodeHandler.getVideoSource(videoId);
30163
+ }
30164
+ initProps() {
30165
+ return {
30166
+ width: 100,
30167
+ height: 100,
30168
+ scaleX: 1,
30169
+ scaleY: 1
30170
+ };
30171
+ }
30172
+ onInit() {
30173
+ this.instance.addEventListener("onStageDrop", (e) => {
30174
+ if (window.weaveDragVideoId && window.weaveDragVideoParams) {
30175
+ this.instance.getStage().setPointersPositions(e);
30176
+ const position = this.instance.getStage().getRelativePointerPosition();
30177
+ this.instance.triggerAction(VIDEO_TOOL_ACTION_NAME, {
30178
+ videoId: window.weaveDragVideoId,
30179
+ videoParams: window.weaveDragVideoParams,
30180
+ position
30181
+ });
30182
+ window.weaveDragVideoParams = void 0;
30183
+ window.weaveDragVideoId = void 0;
30184
+ }
30185
+ });
30186
+ }
30187
+ setupEvents() {
30188
+ const stage = this.instance.getStage();
30189
+ window.addEventListener("keydown", (e) => {
30190
+ if (e.key === "Escape" && this.instance.getActiveAction() === VIDEO_TOOL_ACTION_NAME) {
30191
+ this.cancelAction();
30192
+ return;
30193
+ }
30194
+ });
30195
+ stage.on("pointerdown", (e) => {
30196
+ this.setTapStart(e);
30197
+ this.pointers.set(e.evt.pointerId, {
30198
+ x: e.evt.clientX,
30199
+ y: e.evt.clientY
30200
+ });
30201
+ if (this.state === VIDEO_TOOL_STATE.DEFINING_POSITION) this.state = VIDEO_TOOL_STATE.SELECTED_POSITION;
30202
+ });
30203
+ stage.on("pointermove", () => {
30204
+ if (this.state === VIDEO_TOOL_STATE.IDLE) return;
30205
+ this.setCursor();
30206
+ });
30207
+ stage.on("pointerup", (e) => {
30208
+ this.pointers.delete(e.evt.pointerId);
30209
+ if (this.state === VIDEO_TOOL_STATE.SELECTED_POSITION) this.handleAdding();
30210
+ });
30211
+ this.initialized = true;
30212
+ }
30213
+ setState(state) {
30214
+ this.state = state;
30215
+ }
30216
+ doVideoAdding(videoParams, position) {
30217
+ this.videoId = v4_default();
30218
+ this.videoParams = videoParams;
30219
+ this.setState(VIDEO_TOOL_STATE.DEFINING_POSITION);
30220
+ if (!position) {
30221
+ this.clickPoint = null;
30222
+ this.instance.emitEvent("onAddingVideo", { videoURL: this.videoParams.url });
30223
+ } else this.handleAdding(position);
30224
+ }
30225
+ addVideo(position) {
30226
+ if (position) this.clickPoint = position;
30227
+ this.setState(VIDEO_TOOL_STATE.UPLOADING);
30228
+ }
30229
+ handleAdding(position) {
30230
+ if (this.videoId && this.videoParams) {
30231
+ const { mousePoint, container } = this.instance.getMousePointer(position);
30232
+ this.clickPoint = mousePoint;
30233
+ this.container = container;
30234
+ const nodeHandler = this.instance.getNodeHandler("video");
30235
+ if (nodeHandler) {
30236
+ const node = nodeHandler.create(this.videoId, {
30237
+ ...this.props,
30238
+ x: this.clickPoint?.x ?? 0,
30239
+ y: this.clickPoint?.y ?? 0,
30240
+ opacity: 1,
30241
+ adding: false,
30242
+ videoPlaceholderURL: this.videoParams.placeholderUrl,
30243
+ videoURL: this.videoParams.url,
30244
+ stroke: "#000000ff",
30245
+ strokeWidth: 0,
30246
+ strokeScaleEnabled: true
30247
+ });
30248
+ this.instance.addNode(node, this.forceMainContainer ? this.instance.getMainLayer()?.getAttrs().id : this.container?.getAttrs().id);
30249
+ this.instance.emitEvent("onAddedVideo", {
30250
+ videoURL: this.videoParams.url,
30251
+ nodeId: this.videoId
30252
+ });
30253
+ }
30254
+ this.setState(VIDEO_TOOL_STATE.FINISHED);
30255
+ }
30256
+ this.cancelAction();
30257
+ }
30258
+ trigger(cancelAction, params) {
30259
+ if (!this.instance) throw new Error("Instance not defined");
30260
+ if (!this.initialized) this.setupEvents();
30261
+ this.cancelAction = cancelAction;
30262
+ const selectionPlugin = this.instance.getPlugin("nodesSelection");
30263
+ if (selectionPlugin) selectionPlugin.setSelectedNodes([]);
30264
+ this.forceMainContainer = params?.forceMainContainer ?? false;
30265
+ if (params?.videoId) this.updateProps({ videoId: params.videoId });
30266
+ if (params?.videoParams) {
30267
+ this.updateProps({
30268
+ width: params.videoParams.width,
30269
+ height: params.videoParams.height
30270
+ });
30271
+ this.doVideoAdding(params.videoParams, params?.position ?? void 0);
30272
+ return;
30273
+ }
30274
+ this.props = this.initProps();
30275
+ this.addVideo();
30276
+ return { finishUploadCallback: this.doVideoAdding.bind(this) };
30277
+ }
30278
+ cleanup() {
30279
+ const stage = this.instance.getStage();
30280
+ const selectionPlugin = this.instance.getPlugin("nodesSelection");
30281
+ if (selectionPlugin) {
30282
+ const node = stage.findOne(`#${this.videoId}`);
30283
+ if (node) selectionPlugin.setSelectedNodes([node]);
30284
+ this.instance.triggerAction(SELECTION_TOOL_ACTION_NAME);
30285
+ }
30286
+ stage.container().style.cursor = "default";
30287
+ this.initialCursor = null;
30288
+ this.videoId = null;
30289
+ this.forceMainContainer = false;
30290
+ this.container = void 0;
30291
+ this.videoParams = null;
30292
+ this.clickPoint = null;
30293
+ this.setState(VIDEO_TOOL_STATE.IDLE);
30294
+ }
30295
+ setCursor() {
30296
+ const stage = this.instance.getStage();
30297
+ stage.container().style.cursor = "crosshair";
30298
+ }
30299
+ };
30300
+
29530
30301
  //#endregion
29531
30302
  //#region src/plugins/stage-grid/stage-grid.ts
29532
30303
  var WeaveStageGridPlugin = class extends WeavePlugin {
@@ -31761,6 +32532,8 @@ exports.STAR_TOOL_STATE = STAR_TOOL_STATE
31761
32532
  exports.TEXT_LAYOUT = TEXT_LAYOUT
31762
32533
  exports.TEXT_TOOL_ACTION_NAME = TEXT_TOOL_ACTION_NAME
31763
32534
  exports.TEXT_TOOL_STATE = TEXT_TOOL_STATE
32535
+ exports.VIDEO_TOOL_ACTION_NAME = VIDEO_TOOL_ACTION_NAME
32536
+ exports.VIDEO_TOOL_STATE = VIDEO_TOOL_STATE
31764
32537
  exports.WEAVE_ARROW_NODE_TYPE = WEAVE_ARROW_NODE_TYPE
31765
32538
  exports.WEAVE_COMMENTS_RENDERER_KEY = WEAVE_COMMENTS_RENDERER_KEY
31766
32539
  exports.WEAVE_COMMENTS_TOOL_LAYER_ID = WEAVE_COMMENTS_TOOL_LAYER_ID
@@ -31821,6 +32594,8 @@ exports.WEAVE_USERS_POINTERS_KEY = WEAVE_USERS_POINTERS_KEY
31821
32594
  exports.WEAVE_USERS_SELECTION_KEY = WEAVE_USERS_SELECTION_KEY
31822
32595
  exports.WEAVE_USER_POINTER_KEY = WEAVE_USER_POINTER_KEY
31823
32596
  exports.WEAVE_USER_SELECTION_KEY = WEAVE_USER_SELECTION_KEY
32597
+ exports.WEAVE_VIDEO_DEFAULT_CONFIG = WEAVE_VIDEO_DEFAULT_CONFIG
32598
+ exports.WEAVE_VIDEO_NODE_TYPE = WEAVE_VIDEO_NODE_TYPE
31824
32599
  exports.Weave = Weave
31825
32600
  exports.WeaveAction = WeaveAction
31826
32601
  exports.WeaveAlignNodesToolAction = WeaveAlignNodesToolAction
@@ -31875,6 +32650,8 @@ exports.WeaveTextNode = WeaveTextNode
31875
32650
  exports.WeaveTextToolAction = WeaveTextToolAction
31876
32651
  exports.WeaveUsersPointersPlugin = WeaveUsersPointersPlugin
31877
32652
  exports.WeaveUsersSelectionPlugin = WeaveUsersSelectionPlugin
32653
+ exports.WeaveVideoNode = WeaveVideoNode
32654
+ exports.WeaveVideoToolAction = WeaveVideoToolAction
31878
32655
  exports.WeaveZoomInToolAction = WeaveZoomInToolAction
31879
32656
  exports.WeaveZoomOutToolAction = WeaveZoomOutToolAction
31880
32657
  exports.clearContainerTargets = clearContainerTargets
@@ -31894,6 +32671,7 @@ exports.intersectArrays = intersectArrays
31894
32671
  exports.isIOS = isIOS
31895
32672
  exports.isInShadowDOM = isInShadowDOM
31896
32673
  exports.isNodeInSelection = isNodeInSelection
32674
+ exports.isServer = isServer
31897
32675
  exports.memoize = memoize
31898
32676
  exports.moveNodeToContainer = moveNodeToContainer
31899
32677
  exports.resetScale = resetScale