@inditextech/weave-sdk 0.72.1 → 0.73.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.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();
@@ -20251,6 +20273,8 @@ var WeaveNode = class {
20251
20273
  node.movedToContainer = function() {};
20252
20274
  node.updatePosition = function() {};
20253
20275
  node.resetCrop = function() {};
20276
+ node.handleMouseover = function() {};
20277
+ node.handleMouseout = function() {};
20254
20278
  }
20255
20279
  isNodeSelected(ele) {
20256
20280
  const selectionPlugin = this.instance.getPlugin("nodesSelection");
@@ -20389,6 +20413,31 @@ var WeaveNode = class {
20389
20413
  if (!moved) this.instance.updateNode(this.serialize(node));
20390
20414
  }
20391
20415
  });
20416
+ node.handleMouseover = () => {
20417
+ const stage = this.instance.getStage();
20418
+ const activeAction = this.instance.getActiveAction();
20419
+ const isNodeSelectionEnabled = this.getSelectionPlugin()?.isEnabled();
20420
+ const realNode = this.instance.getInstanceRecursive(node);
20421
+ const isTargetable = realNode.getAttrs().isTargetable !== false;
20422
+ const isLocked$1 = realNode.getAttrs().locked ?? false;
20423
+ if ([MOVE_TOOL_ACTION_NAME].includes(activeAction ?? "")) return;
20424
+ if (isNodeSelectionEnabled && this.isSelecting() && !this.isNodeSelected(realNode) && !this.isPasting() && isLocked$1) {
20425
+ const stage$1 = this.instance.getStage();
20426
+ stage$1.container().style.cursor = "default";
20427
+ }
20428
+ if (isNodeSelectionEnabled && this.isSelecting() && !this.isNodeSelected(realNode) && !this.isPasting() && isTargetable && !isLocked$1 && stage.mode() === WEAVE_STAGE_DEFAULT_MODE) {
20429
+ const stage$1 = this.instance.getStage();
20430
+ stage$1.container().style.cursor = "pointer";
20431
+ }
20432
+ if (isNodeSelectionEnabled && this.isSelecting() && this.isNodeSelected(realNode) && !this.isPasting() && isTargetable && !isLocked$1 && stage.mode() === WEAVE_STAGE_DEFAULT_MODE) {
20433
+ const stage$1 = this.instance.getStage();
20434
+ stage$1.container().style.cursor = "grab";
20435
+ }
20436
+ if (this.isPasting()) {
20437
+ const stage$1 = this.instance.getStage();
20438
+ stage$1.container().style.cursor = "crosshair";
20439
+ }
20440
+ };
20392
20441
  node.on("pointerover", (e) => {
20393
20442
  const stage = this.instance.getStage();
20394
20443
  const activeAction = this.instance.getActiveAction();
@@ -21914,7 +21963,7 @@ var WeaveRegisterManager = class {
21914
21963
 
21915
21964
  //#endregion
21916
21965
  //#region package.json
21917
- var version = "0.72.1";
21966
+ var version = "0.73.0";
21918
21967
 
21919
21968
  //#endregion
21920
21969
  //#region src/managers/setup.ts
@@ -22965,6 +23014,10 @@ var WeaveStageNode = class extends WeaveNode {
22965
23014
  if (typeof allowSelection !== "undefined") this._allowSelection = allowSelection;
22966
23015
  return this._allowSelection;
22967
23016
  };
23017
+ stage.handleMouseover = function() {
23018
+ stage.container().style.cursor = "default";
23019
+ };
23020
+ stage.handleMouseout = function() {};
22968
23021
  stage.mode(WEAVE_STAGE_DEFAULT_MODE);
22969
23022
  stage.on("pointerdown", (e) => {
22970
23023
  if (e.evt.button === 1) this.wheelMousePressed = true;
@@ -23783,412 +23836,153 @@ var WeaveTextNode = class extends WeaveNode {
23783
23836
  };
23784
23837
 
23785
23838
  //#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];
23839
+ //#region src/nodes/image/crop.ts
23840
+ var WeaveImageCrop = class WeaveImageCrop {
23841
+ constructor(instance, node, image, internalImage, clipGroup) {
23842
+ this.instance = instance;
23843
+ this.node = node;
23844
+ this.image = image;
23845
+ this.internalImage = internalImage;
23846
+ this.cropGroup = clipGroup;
23847
+ this.cropping = false;
23848
+ this.onClose = () => {};
23849
+ this.handleHide = this.hide.bind(this);
23824
23850
  }
23825
- initProps() {
23826
- return {
23827
- width: 100,
23828
- height: 100,
23851
+ show(onClose) {
23852
+ this.onClose = onClose;
23853
+ this.cropping = true;
23854
+ const nodeEdgeSnappingPlugin = this.getNodesEdgeSnappingPlugin();
23855
+ if (nodeEdgeSnappingPlugin) nodeEdgeSnappingPlugin.disable();
23856
+ const nodeDistanceSnappingPlugin = this.getNodesDistanceSnappingPlugin();
23857
+ if (nodeDistanceSnappingPlugin) nodeDistanceSnappingPlugin.disable();
23858
+ const nodesSelectionPlugin = this.getNodesSelectionPlugin();
23859
+ if (nodesSelectionPlugin) nodesSelectionPlugin.disable();
23860
+ this.image.setAttrs({ cropping: true });
23861
+ const imageAttrs = this.image.getAttrs();
23862
+ this.internalImage.hide();
23863
+ this.cropGroup.destroyChildren();
23864
+ const actualScale = imageAttrs.uncroppedImage.width / imageAttrs.imageInfo.width;
23865
+ const cropScale = imageAttrs.cropInfo ? imageAttrs.cropInfo.scaleX : actualScale;
23866
+ const realScale = actualScale / cropScale;
23867
+ this.cropImage = new konva.default.Image({
23868
+ x: imageAttrs.cropInfo ? -imageAttrs.cropInfo.x * realScale : 0,
23869
+ y: imageAttrs.cropInfo ? -imageAttrs.cropInfo.y * realScale : 0,
23870
+ width: imageAttrs.uncroppedImage.width,
23871
+ height: imageAttrs.uncroppedImage.height,
23829
23872
  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
23873
+ scaleY: 1,
23874
+ image: this.internalImage.image(),
23875
+ crop: void 0,
23876
+ visible: true,
23877
+ listening: false,
23878
+ draggable: false
23879
+ });
23880
+ this.imageOffsetX = imageAttrs.cropInfo ? imageAttrs.cropInfo.x * realScale : 0;
23881
+ this.imageOffsetY = imageAttrs.cropInfo ? imageAttrs.cropInfo.y * realScale : 0;
23882
+ this.cropRect = new konva.default.Rect({
23883
+ x: 0,
23884
+ y: 0,
23885
+ width: imageAttrs.cropInfo ? imageAttrs.cropInfo.width * realScale : imageAttrs.uncroppedImage.width,
23886
+ height: imageAttrs.cropInfo ? imageAttrs.cropInfo.height * realScale : imageAttrs.uncroppedImage.height,
23887
+ fill: "rgba(0,0,0,0.2)",
23888
+ stroke: "#ff0000ff",
23889
+ strokeWidth: 0,
23890
+ strokeScaleEnabled: true,
23891
+ draggable: true,
23892
+ rotation: 0
23893
+ });
23894
+ this.transformer = new konva.default.Transformer({
23895
+ id: `${this.image.getAttrs().id}_transformer`,
23896
+ x: 0,
23897
+ y: 0,
23898
+ flipEnabled: false,
23899
+ keepRatio: false,
23900
+ ignoreStroke: false,
23901
+ rotateEnabled: false,
23902
+ enabledAnchors: [
23903
+ "top-left",
23904
+ "top-center",
23905
+ "top-right",
23906
+ "middle-right",
23907
+ "bottom-left",
23908
+ "middle-left",
23909
+ "bottom-right",
23910
+ "bottom-center"
23911
+ ],
23912
+ anchorDragBoundFunc: (_, newPos) => {
23913
+ let closestSnap = newPos;
23914
+ let minDist = 10;
23915
+ const nodeRotation = this.image.getAbsoluteRotation();
23916
+ const stage = this.instance.getStage();
23917
+ const rotation = nodeRotation * (Math.PI / 180);
23918
+ const center = this.cropImage.getAbsolutePosition();
23919
+ const width = this.cropImage.width() * stage.scaleX();
23920
+ const height = this.cropImage.height() * stage.scaleY();
23921
+ const offset = this.cropImage.offset();
23922
+ const corners = [
23923
+ {
23924
+ x: -offset.x,
23925
+ y: -offset.y
23926
+ },
23927
+ {
23928
+ x: width - offset.x,
23929
+ y: -offset.y
23930
+ },
23931
+ {
23932
+ x: width - offset.x,
23933
+ y: height - offset.y
23934
+ },
23935
+ {
23936
+ x: -offset.x,
23937
+ y: height - offset.y
23938
+ }
23939
+ ].map((pt) => {
23940
+ const cos = Math.cos(rotation);
23941
+ const sin = Math.sin(rotation);
23942
+ return {
23943
+ x: center.x + pt.x * cos - pt.y * sin,
23944
+ y: center.y + pt.x * sin + pt.y * cos
23945
+ };
23842
23946
  });
23843
- window.weaveDragImageURL = void 0;
23844
- window.weaveDragImageId = void 0;
23845
- }
23947
+ const edges = [
23948
+ [corners[0], corners[1]],
23949
+ [corners[1], corners[2]],
23950
+ [corners[2], corners[3]],
23951
+ [corners[3], corners[0]]
23952
+ ];
23953
+ for (const [a, b] of edges) {
23954
+ const candidate = this.closestPointOnLine(newPos, a, b);
23955
+ const dist = Math.hypot(newPos.x - candidate.x, newPos.y - candidate.y);
23956
+ if (dist < minDist) {
23957
+ closestSnap = candidate;
23958
+ minDist = dist;
23959
+ }
23960
+ }
23961
+ return closestSnap;
23962
+ },
23963
+ rotation: 0
23846
23964
  });
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
- }
23965
+ this.grid = new konva.default.Group();
23966
+ const cropRect = this.cropRect.getClientRect({
23967
+ relativeTo: this.cropGroup,
23968
+ skipStroke: true
23855
23969
  });
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
23970
+ this.drawGridLines(0, 0, cropRect.width, cropRect.height);
23971
+ const handleGridLines = () => {
23972
+ const cropRect$1 = this.cropRect.getClientRect({
23973
+ relativeTo: this.cropGroup,
23974
+ skipStroke: true
23861
23975
  });
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;
23976
+ this.drawGridLines(cropRect$1.x, cropRect$1.y, cropRect$1.width, cropRect$1.height);
23977
+ };
23978
+ this.instance.getStage().on("pointerdown", (e) => {
23979
+ if (!this.cropping) return;
23980
+ const isStage = e.target instanceof konva.default.Stage;
23981
+ const isContainerEmptyArea = typeof e.target.getAttrs().isContainerPrincipal !== "undefined" && !e.target.getAttrs().isContainerPrincipal;
23982
+ if (isStage || isContainerEmptyArea) this.cancel();
23867
23983
  });
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
23880
- });
23881
- }
23882
- });
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
24175
- });
24176
- this.drawGridLines(0, 0, cropRect.width, cropRect.height);
24177
- const handleGridLines = () => {
24178
- const cropRect$1 = this.cropRect.getClientRect({
24179
- relativeTo: this.cropGroup,
24180
- skipStroke: true
24181
- });
24182
- this.drawGridLines(cropRect$1.x, cropRect$1.y, cropRect$1.width, cropRect$1.height);
24183
- };
24184
- this.instance.getStage().on("pointerdown", (e) => {
24185
- if (!this.cropping) return;
24186
- const isStage = e.target instanceof konva.default.Stage;
24187
- const isContainerEmptyArea = typeof e.target.getAttrs().isContainerPrincipal !== "undefined" && !e.target.getAttrs().isContainerPrincipal;
24188
- if (isStage || isContainerEmptyArea) this.cancel();
24189
- });
24190
- this.instance.addEventListener("onActiveActionChange", (activeAction) => {
24191
- if (typeof activeAction !== "undefined") this.cancel();
23984
+ this.instance.addEventListener("onActiveActionChange", (activeAction) => {
23985
+ if (typeof activeAction !== "undefined") this.cancel();
24192
23986
  });
24193
23987
  this.cropRect.on("dragstart", (e) => {
24194
23988
  this.instance.emitEvent("onDrag", e.target);
@@ -24402,6 +24196,8 @@ const WEAVE_IMAGE_DEFAULT_CONFIG = { crossOrigin: "anonymous" };
24402
24196
  //#endregion
24403
24197
  //#region src/nodes/image/image.ts
24404
24198
  var WeaveImageNode = class extends WeaveNode {
24199
+ imageSource = {};
24200
+ imageState = {};
24405
24201
  nodeType = WEAVE_IMAGE_NODE_TYPE;
24406
24202
  constructor(params) {
24407
24203
  super();
@@ -24560,31 +24356,29 @@ var WeaveImageNode = class extends WeaveNode {
24560
24356
  image.dblClick = () => {
24561
24357
  this.config.onDblClick?.(this, image);
24562
24358
  };
24563
- const imageActionTool = this.getImageToolAction();
24564
- const preloadImg = imageActionTool.getPreloadedImage(imageProps.id);
24565
- if (preloadImg) {
24359
+ if (this.imageSource[id]) {
24566
24360
  imagePlaceholder?.setAttrs({
24567
- width: imageProps.width ? imageProps.width : preloadImg.width,
24568
- height: imageProps.height ? imageProps.height : preloadImg.height,
24361
+ width: imageProps.width ? imageProps.width : this.imageSource[id].width,
24362
+ height: imageProps.height ? imageProps.height : this.imageSource[id].height,
24569
24363
  visible: false
24570
24364
  });
24571
24365
  internalImage?.setAttrs({
24572
- width: imageProps.width ? imageProps.width : preloadImg.width,
24573
- height: imageProps.height ? imageProps.height : preloadImg.height,
24574
- image: preloadImg,
24366
+ width: imageProps.width ? imageProps.width : this.imageSource[id].width,
24367
+ height: imageProps.height ? imageProps.height : this.imageSource[id].height,
24368
+ image: this.imageSource[id],
24575
24369
  visible: true
24576
24370
  });
24577
24371
  this.imageLoaded = true;
24578
- image.setAttr("width", image.width() ? image.width() : preloadImg.width);
24579
- image.setAttr("height", image.height() ? image.height() : preloadImg.height);
24372
+ image.setAttr("width", image.width() ? image.width() : this.imageSource[id].width);
24373
+ image.setAttr("height", image.height() ? image.height() : this.imageSource[id].height);
24580
24374
  image.setAttr("cropInfo", void 0);
24581
24375
  image.setAttr("uncroppedImage", {
24582
- width: image.width() ? image.width() : preloadImg.width,
24583
- height: image.height() ? image.height() : preloadImg.height
24376
+ width: image.width() ? image.width() : this.imageSource[id].width,
24377
+ height: image.height() ? image.height() : this.imageSource[id].height
24584
24378
  });
24585
24379
  image.setAttr("imageInfo", {
24586
- width: preloadImg.width,
24587
- height: preloadImg.height
24380
+ width: this.imageSource[id].width,
24381
+ height: this.imageSource[id].height
24588
24382
  });
24589
24383
  this.instance.updateNode(this.serialize(image));
24590
24384
  } else this.loadImage(imageProps, image);
@@ -24656,64 +24450,96 @@ var WeaveImageNode = class extends WeaveNode {
24656
24450
  this.updateImageCrop(nextProps);
24657
24451
  }
24658
24452
  }
24453
+ preloadImage(imageId, imageURL, { onLoad, onError }) {
24454
+ const realImageURL = this.config.urlTransformer?.(imageURL ?? "") ?? imageURL;
24455
+ this.imageSource[imageId] = new Image();
24456
+ this.imageSource[imageId].crossOrigin = this.config.crossOrigin;
24457
+ this.imageSource[imageId].onerror = (error) => {
24458
+ this.imageState[imageId] = {
24459
+ loaded: false,
24460
+ error: true
24461
+ };
24462
+ onError(error);
24463
+ };
24464
+ this.imageSource[imageId].onload = () => {
24465
+ this.imageState[imageId] = {
24466
+ loaded: true,
24467
+ error: false
24468
+ };
24469
+ onLoad();
24470
+ };
24471
+ this.imageState[imageId] = {
24472
+ loaded: false,
24473
+ error: false
24474
+ };
24475
+ if (realImageURL) this.imageSource[imageId].src = realImageURL;
24476
+ }
24659
24477
  loadImage(params, image) {
24660
24478
  const imageProps = params;
24661
- const imagePlaceholder = image.findOne(`#${imageProps.id}-placeholder`);
24662
- const internalImage = image.findOne(`#${imageProps.id}-image`);
24479
+ const { id } = imageProps;
24480
+ const imagePlaceholder = image.findOne(`#${id}-placeholder`);
24481
+ const internalImage = image.findOne(`#${id}-image`);
24663
24482
  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));
24483
+ this.loadAsyncElement(id);
24484
+ this.preloadImage(id, realImageURL ?? "", {
24485
+ onLoad: () => {
24486
+ if (image && imagePlaceholder && internalImage) {
24487
+ image.setAttrs({
24488
+ width: imageProps.width ? imageProps.width : this.imageSource[id].width,
24489
+ height: imageProps.height ? imageProps.height : this.imageSource[id].height
24490
+ });
24491
+ imagePlaceholder.destroy();
24492
+ internalImage.setAttrs({
24493
+ width: imageProps.width ? imageProps.width : this.imageSource[id].width,
24494
+ height: imageProps.height ? imageProps.height : this.imageSource[id].height,
24495
+ image: this.imageSource[id],
24496
+ visible: true
24497
+ });
24498
+ internalImage.setAttr("imageInfo", {
24499
+ width: this.imageSource[id].width,
24500
+ height: this.imageSource[id].height
24501
+ });
24502
+ internalImage.zIndex(0);
24503
+ this.imageLoaded = true;
24504
+ image.setAttrs({
24505
+ width: imageProps.width ? imageProps.width : this.imageSource[id].width,
24506
+ height: imageProps.height ? imageProps.height : this.imageSource[id].height
24507
+ });
24508
+ image.setAttr("imageInfo", {
24509
+ width: this.imageSource[id].width,
24510
+ height: this.imageSource[id].height
24511
+ });
24512
+ this.scaleReset(image);
24513
+ const imageRect = image.getClientRect({ relativeTo: this.instance.getStage() });
24514
+ if (imageProps.cropInfo && imageProps.uncroppedImage) image.setAttr("uncroppedImage", {
24515
+ width: imageProps.uncroppedImage.width,
24516
+ height: imageProps.uncroppedImage.height
24517
+ });
24518
+ if (!imageProps.cropInfo) image.setAttr("uncroppedImage", {
24519
+ width: imageRect.width,
24520
+ height: imageRect.height
24521
+ });
24522
+ this.updateImageCrop(imageProps);
24523
+ this.imageState[id] = {
24524
+ loaded: true,
24525
+ error: false
24526
+ };
24527
+ this.resolveAsyncElement(id);
24528
+ const nodeHandler = this.instance.getNodeHandler(image.getAttrs().nodeType);
24529
+ if (nodeHandler) this.instance.updateNode(nodeHandler.serialize(image));
24530
+ }
24531
+ },
24532
+ onError: (error) => {
24533
+ this.imageState[id] = {
24534
+ loaded: false,
24535
+ error: true
24536
+ };
24537
+ this.resolveAsyncElement(id);
24538
+ console.error("Error loading image", realImageURL, error);
24539
+ imagePlaceholder?.setAttrs({ visible: true });
24540
+ internalImage?.setAttrs({ visible: false });
24714
24541
  }
24715
- };
24716
- if (realImageURL) imageObj.src = realImageURL;
24542
+ });
24717
24543
  }
24718
24544
  updateImageCrop(nextProps) {
24719
24545
  const imageAttrs = nextProps;
@@ -24750,24 +24576,23 @@ var WeaveImageNode = class extends WeaveNode {
24750
24576
  this.cachedCropInfo[imageAttrs.id ?? ""] = void 0;
24751
24577
  }
24752
24578
  }
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;
24579
+ getImageSource(imageId) {
24580
+ return this.imageSource[imageId];
24757
24581
  }
24758
24582
  scaleReset(node) {
24759
24583
  const scale = node.scale();
24584
+ const nodeAttrs = node.getAttrs();
24760
24585
  const widthNotNormalized = node.width();
24761
24586
  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;
24587
+ const uncroppedWidth = nodeAttrs.uncroppedImage ? nodeAttrs.uncroppedImage.width : widthNotNormalized;
24588
+ const uncroppedHeight = nodeAttrs.uncroppedImage ? nodeAttrs.uncroppedImage.height : heightNotNormalized;
24764
24589
  node.setAttrs({ uncroppedImage: {
24765
24590
  width: uncroppedWidth * node.scaleX(),
24766
24591
  height: uncroppedHeight * node.scaleY()
24767
24592
  } });
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`);
24593
+ const placeholder = node.findOne(`#${nodeAttrs.id}-placeholder`);
24594
+ const internalImage = node.findOne(`#${nodeAttrs.id}-image`);
24595
+ const cropGroup = node.findOne(`#${nodeAttrs.id}-cropGroup`);
24771
24596
  if (placeholder) {
24772
24597
  placeholder.width(Math.max(5, placeholder.width() * placeholder.scaleX()));
24773
24598
  placeholder.height(Math.max(5, placeholder.height() * placeholder.scaleY()));
@@ -24798,7 +24623,6 @@ var WeaveImageNode = class extends WeaveNode {
24798
24623
  x: 1,
24799
24624
  y: 1
24800
24625
  });
24801
- this.instance.getMainLayer()?.batchDraw();
24802
24626
  }
24803
24627
  };
24804
24628
 
@@ -26227,25 +26051,530 @@ var WeaveCommentNode = class extends WeaveNode {
26227
26051
  this.openCommentDOM(node);
26228
26052
  }
26229
26053
  });
26230
- tween.play();
26054
+ tween.play();
26055
+ }
26056
+ }
26057
+ setCommentViewing(commentId) {
26058
+ this.commentDomAction = commentId ? "viewing" : "idle";
26059
+ this.commentDomVisible = !!commentId;
26060
+ this.commentDomVisibleId = commentId;
26061
+ }
26062
+ isCommentViewing() {
26063
+ return this.commentDomAction === WEAVE_COMMENT_NODE_ACTION.VIEWING && this.commentDomVisible;
26064
+ }
26065
+ isCommentCreating() {
26066
+ return this.commentDomAction === WEAVE_COMMENT_NODE_ACTION.CREATING && this.commentDomVisible;
26067
+ }
26068
+ getCommentId(node) {
26069
+ return this.config.model.getId(node.getAttrs().commentModel);
26070
+ }
26071
+ setShowResolved(show) {
26072
+ this.showResolved = show;
26073
+ }
26074
+ };
26075
+
26076
+ //#endregion
26077
+ //#region src/nodes/video/constants.ts
26078
+ const WEAVE_VIDEO_NODE_TYPE = "video";
26079
+ const WEAVE_VIDEO_DEFAULT_CONFIG = {
26080
+ crossOrigin: "anonymous",
26081
+ style: {
26082
+ playPauseOnDblClick: true,
26083
+ background: {
26084
+ color: "#C9C9C9FF",
26085
+ strokeWidth: 0,
26086
+ strokeColor: "#000000FF"
26087
+ },
26088
+ track: {
26089
+ resetOnEnd: true,
26090
+ onlyOnHover: false,
26091
+ color: "#FF0033FF",
26092
+ height: 5
26093
+ },
26094
+ iconBackground: {
26095
+ color: "#FFFFFFFF",
26096
+ strokeWidth: 0,
26097
+ strokeColor: "#000000FF"
26098
+ },
26099
+ icon: {
26100
+ internal: {
26101
+ paddingX: 12,
26102
+ paddingY: 8
26103
+ },
26104
+ external: {
26105
+ paddingX: 20,
26106
+ paddingY: 20
26107
+ },
26108
+ width: 24,
26109
+ height: 24,
26110
+ color: "#FFFFFFFF",
26111
+ dataURL: "data:image/png;base64,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"
26112
+ }
26113
+ }
26114
+ };
26115
+
26116
+ //#endregion
26117
+ //#region src/nodes/video/video.ts
26118
+ var WeaveVideoNode = class extends WeaveNode {
26119
+ videoState = {};
26120
+ videoSourceFrameId = {};
26121
+ videoSource = {};
26122
+ videoPlaceholder = {};
26123
+ nodeType = WEAVE_VIDEO_NODE_TYPE;
26124
+ constructor(params) {
26125
+ super();
26126
+ const { config } = params ?? {};
26127
+ this.config = (0, import_lodash.merge)(WEAVE_VIDEO_DEFAULT_CONFIG, config);
26128
+ }
26129
+ initVideoIcon() {
26130
+ if (!this.videoIconImage) {
26131
+ this.videoIconImage = new Image();
26132
+ this.videoIconImage.src = this.config.style.icon.dataURL;
26133
+ }
26134
+ }
26135
+ async loadPlaceholder(params, video) {
26136
+ const videoProps = params;
26137
+ const { id } = videoProps;
26138
+ const videoPlaceholder = video.findOne(`#${id}-video-placeholder`);
26139
+ const videoIconGroup = video.findOne(`#${id}-video-icon-group`);
26140
+ if (!videoPlaceholder || !videoIconGroup) return;
26141
+ const realVideoPlaceholderURL = this.config.urlTransformer?.(videoProps.videoPlaceholderURL ?? "") ?? videoProps.videoPlaceholderURL;
26142
+ this.videoPlaceholder[id] = new Image();
26143
+ this.videoPlaceholder[id].crossOrigin = this.config.crossOrigin;
26144
+ this.videoPlaceholder[id].src = realVideoPlaceholderURL;
26145
+ this.videoPlaceholder[id].onerror = (error) => {
26146
+ console.error("Error loading video placeholder", realVideoPlaceholderURL, error);
26147
+ this.resolveAsyncElement(id);
26148
+ };
26149
+ this.videoPlaceholder[id].onload = () => {
26150
+ videoPlaceholder.setAttrs({ image: this.videoPlaceholder[id] });
26151
+ const videoWidth = video.getAttrs().width ?? 0;
26152
+ const videoHeight = video.getAttrs().height ?? 0;
26153
+ const videoIconGroupWidth = this.config.style.icon.internal.paddingX * 2 + this.config.style.icon.width;
26154
+ const videoIconGroupHeight = this.config.style.icon.internal.paddingY * 2 + this.config.style.icon.height;
26155
+ videoIconGroup.x(videoWidth - videoIconGroupWidth - this.config.style.icon.external.paddingX);
26156
+ videoIconGroup.y(videoHeight - videoIconGroupHeight - this.config.style.icon.external.paddingY);
26157
+ const nodesSelectionPlugin = this.getNodeSelectionPlugin();
26158
+ if (nodesSelectionPlugin) nodesSelectionPlugin.getTransformer().forceUpdate();
26159
+ this.resolveAsyncElement(id);
26160
+ };
26161
+ }
26162
+ loadVideo(params, video) {
26163
+ const videoProps = params;
26164
+ const { id } = videoProps;
26165
+ const videoSource = document.createElement("video");
26166
+ videoSource.crossOrigin = this.config.crossOrigin;
26167
+ videoSource.preload = "auto";
26168
+ const bg = video.findOne(`#${id}-bg`);
26169
+ const videoProgress = video.findOne(`#${id}-video-progress`);
26170
+ const videoIconGroup = video.findOne(`#${id}-video-icon-group`);
26171
+ const videoPlaceholder = video.findOne(`#${id}-video-placeholder`);
26172
+ const videoPlayer = video.findOne(`#${id}-video`);
26173
+ if (!bg || !videoIconGroup || !videoProgress || !videoPlayer || !videoPlaceholder) return;
26174
+ const realVideoURL = this.config.urlTransformer?.(videoProps.videoURL ?? "") ?? videoProps.videoURL;
26175
+ if (realVideoURL) videoSource.src = realVideoURL;
26176
+ videoSource.addEventListener("loadeddata", () => {
26177
+ videoSource.currentTime = 0;
26178
+ this.videoState[id] = {
26179
+ ...this.videoState[id],
26180
+ loaded: true,
26181
+ playing: false,
26182
+ paused: false
26183
+ };
26184
+ });
26185
+ const onFrame = () => {
26186
+ const progress = this.videoSource[id].duration ? Math.max(this.videoSource[id].currentTime / this.videoSource[id].duration, 0) : 0;
26187
+ videoProgress.setAttrs({ width: (video.getAttrs().width ?? 0) * progress });
26188
+ this.videoSourceFrameId[id] = videoSource.requestVideoFrameCallback(onFrame);
26189
+ };
26190
+ videoSource.addEventListener("play", () => {
26191
+ const videoProgress$1 = video.findOne(`#${id}-video-progress`);
26192
+ if (videoProgress$1 && !this.config.style.track.onlyOnHover) videoProgress$1.show();
26193
+ this.videoSourceFrameId[id] = videoSource.requestVideoFrameCallback(onFrame);
26194
+ });
26195
+ videoSource.addEventListener("stop", () => {
26196
+ if (this.videoSourceFrameId[id]) videoSource.cancelVideoFrameCallback(this.videoSourceFrameId[id]);
26197
+ });
26198
+ videoSource.addEventListener("ended", () => {
26199
+ videoProgress.setAttrs({ width: video.getAttrs().width ?? 0 });
26200
+ if (this.config.style.track.resetOnEnd) this.stop(id);
26201
+ });
26202
+ videoSource.addEventListener("error", (error) => {
26203
+ console.error("Error loading image", realVideoURL, error);
26204
+ });
26205
+ videoSource.addEventListener("loadedmetadata", () => {
26206
+ const videoSource$1 = this.videoSource[id];
26207
+ const videoWidth = video.getAttrs().width ?? 0;
26208
+ const videoHeight = video.getAttrs().height ?? 0;
26209
+ videoPlayer.setAttrs({ image: videoSource$1 });
26210
+ videoProgress.width(0);
26211
+ videoProgress.y(videoHeight - this.config.style.track.height / this.instance.getStage().scaleY());
26212
+ const videoIconGroupWidth = this.config.style.icon.internal.paddingX * 2 + this.config.style.icon.width;
26213
+ const videoIconGroupHeight = this.config.style.icon.internal.paddingY * 2 + this.config.style.icon.height;
26214
+ videoIconGroup.x(videoWidth - videoIconGroupWidth - this.config.style.icon.external.paddingX);
26215
+ videoIconGroup.y(videoHeight - videoIconGroupHeight - this.config.style.icon.external.paddingY);
26216
+ });
26217
+ videoPlayer.setAttrs({ image: videoSource });
26218
+ this.videoSource[id] = videoSource;
26219
+ }
26220
+ onRender(props) {
26221
+ this.initVideoIcon();
26222
+ const videoProperties = props.videoProperties ?? {};
26223
+ const videoProps = props;
26224
+ const { id } = videoProps;
26225
+ const groupVideoProps = { ...videoProps };
26226
+ delete groupVideoProps.children;
26227
+ delete groupVideoProps.imageProperties;
26228
+ delete groupVideoProps.zIndex;
26229
+ const internalVideoProps = { ...props };
26230
+ delete internalVideoProps.videoProperties;
26231
+ delete internalVideoProps.videoPlaceholderURL;
26232
+ delete internalVideoProps.videoURL;
26233
+ delete internalVideoProps.zIndex;
26234
+ const videoGroup = new konva.default.Group({
26235
+ ...groupVideoProps,
26236
+ ...internalVideoProps,
26237
+ id,
26238
+ name: "node",
26239
+ strokeScaleEnabled: true
26240
+ });
26241
+ const bg = new konva.default.Rect({
26242
+ ...groupVideoProps,
26243
+ x: 0,
26244
+ y: 0,
26245
+ id: `${id}-bg`,
26246
+ fill: this.config.style.background.color,
26247
+ stroke: this.config.style.background.strokeColor,
26248
+ strokeWidth: this.config.style.background.strokeWidth
26249
+ });
26250
+ videoGroup.add(bg);
26251
+ if (!isServer()) {
26252
+ const video = new konva.default.Image({
26253
+ ...groupVideoProps,
26254
+ ...videoProperties,
26255
+ id: `${id}-video`,
26256
+ x: 0,
26257
+ y: 0,
26258
+ draggable: false,
26259
+ image: void 0,
26260
+ name: void 0
26261
+ });
26262
+ video.hide();
26263
+ videoGroup.add(video);
26264
+ const videoProgress = new konva.default.Rect({
26265
+ ...groupVideoProps,
26266
+ ...videoProperties,
26267
+ id: `${id}-video-progress`,
26268
+ x: 0,
26269
+ y: 0,
26270
+ height: this.config.style.track.height / this.instance.getStage().scaleY(),
26271
+ strokeWidth: 0,
26272
+ fill: this.config.style.track.color,
26273
+ name: void 0
26274
+ });
26275
+ this.instance.addEventListener("onZoomChange", () => {
26276
+ videoProgress.height(this.config.style.track.height / this.instance.getStage().scaleY());
26277
+ videoProgress.y((videoGroup.getAttrs().height ?? 0) - videoProgress.height());
26278
+ });
26279
+ videoProgress.hide();
26280
+ videoGroup.add(videoProgress);
26281
+ }
26282
+ const videoPlaceholder = new konva.default.Image({
26283
+ ...groupVideoProps,
26284
+ id: `${id}-video-placeholder`,
26285
+ x: 0,
26286
+ y: 0,
26287
+ draggable: false,
26288
+ image: void 0,
26289
+ name: void 0
26290
+ });
26291
+ videoPlaceholder.show();
26292
+ videoGroup.add(videoPlaceholder);
26293
+ const videoIconGroup = new konva.default.Group({
26294
+ id: `${id}-video-icon-group`,
26295
+ x: 0,
26296
+ y: 0
26297
+ });
26298
+ const videoIconBg = new konva.default.Rect({
26299
+ ...groupVideoProps,
26300
+ id: `${id}-video-icon-bg`,
26301
+ x: 0,
26302
+ y: 0,
26303
+ width: this.config.style.icon.internal.paddingX * 2 + this.config.style.icon.width,
26304
+ height: this.config.style.icon.internal.paddingY * 2 + this.config.style.icon.height,
26305
+ strokeWidth: this.config.style.iconBackground.strokeWidth,
26306
+ stroke: this.config.style.iconBackground.strokeColor,
26307
+ fill: this.config.style.iconBackground.color
26308
+ });
26309
+ videoIconGroup.add(videoIconBg);
26310
+ const videoIcon = new konva.default.Image({
26311
+ ...groupVideoProps,
26312
+ id: `${id}-video-icon`,
26313
+ x: this.config.style.icon.internal.paddingX,
26314
+ y: this.config.style.icon.internal.paddingY,
26315
+ width: this.config.style.icon.width,
26316
+ height: this.config.style.icon.height,
26317
+ fill: "transparent",
26318
+ image: this.videoIconImage
26319
+ });
26320
+ videoIconGroup.add(videoIcon);
26321
+ videoGroup.add(videoIconGroup);
26322
+ this.setupDefaultNodeAugmentation(videoGroup);
26323
+ const defaultTransformerProperties = this.defaultGetTransformerProperties(this.config.transform);
26324
+ videoGroup.getTransformerProperties = function() {
26325
+ return defaultTransformerProperties;
26326
+ };
26327
+ if (!this.anim) this.anim = new konva.default.Animation(() => {
26328
+ this.instance.getMainLayer()?.batchDraw();
26329
+ }, this.instance.getMainLayer());
26330
+ this.setupDefaultNodeEvents(videoGroup);
26331
+ videoGroup.allowedAnchors = function() {
26332
+ return [
26333
+ "top-left",
26334
+ "top-right",
26335
+ "bottom-left",
26336
+ "bottom-right"
26337
+ ];
26338
+ };
26339
+ let videoWasPlaying = false;
26340
+ let videoProgressWasVisible = false;
26341
+ const handleTransformStart = (e) => {
26342
+ const node = e.target;
26343
+ const videoProgress = node.findOne(`#${id}-video-progress`);
26344
+ if (videoProgress && videoProgress.isVisible()) {
26345
+ videoProgressWasVisible = true;
26346
+ videoProgress.hide();
26347
+ }
26348
+ if (this.videoState[id]?.playing) {
26349
+ videoWasPlaying = true;
26350
+ this.pause(id);
26351
+ }
26352
+ const videoIconGroup$1 = node.findOne(`#${id}-video-icon-group`);
26353
+ if (videoIconGroup$1) videoIconGroup$1.hide();
26354
+ };
26355
+ videoGroup.on("transformstart", handleTransformStart);
26356
+ const handleTransformEnd = (e) => {
26357
+ const node = e.target;
26358
+ const videoProgress = node.findOne(`#${id}-video-progress`);
26359
+ if (videoProgress && videoProgressWasVisible) videoProgress.show();
26360
+ const videoIconGroup$1 = node.findOne(`#${id}-video-icon-group`);
26361
+ if (videoIconGroup$1) videoIconGroup$1.show();
26362
+ if (this.videoState[id]?.paused && videoWasPlaying) this.play(id);
26363
+ videoProgressWasVisible = false;
26364
+ videoWasPlaying = false;
26365
+ };
26366
+ videoGroup.on("transformend", handleTransformEnd);
26367
+ const videoWidth = videoGroup.getAttrs().width ?? 0;
26368
+ const videoHeight = videoGroup.getAttrs().height ?? 0;
26369
+ const videoIconGroupWidth = this.config.style.icon.internal.paddingX * 2 + this.config.style.icon.width;
26370
+ const videoIconGroupHeight = this.config.style.icon.internal.paddingY * 2 + this.config.style.icon.height;
26371
+ videoIconGroup.x(videoWidth - videoIconGroupWidth - this.config.style.icon.external.paddingX);
26372
+ videoIconGroup.y(videoHeight - videoIconGroupHeight - this.config.style.icon.external.paddingY);
26373
+ this.loadAsyncElement(id);
26374
+ this.loadPlaceholder(props, videoGroup);
26375
+ const isLoaded = typeof this.videoSource[id] !== "undefined";
26376
+ if (!isLoaded && !isServer()) {
26377
+ this.videoState[id] = {
26378
+ placeholderLoaded: false,
26379
+ loaded: false,
26380
+ playing: false,
26381
+ paused: false
26382
+ };
26383
+ this.loadVideo(props, videoGroup);
26384
+ }
26385
+ if (isLoaded && !isServer()) {
26386
+ videoGroup.setAttr("videoInfo", {
26387
+ width: this.videoSource[id].videoWidth,
26388
+ height: this.videoSource[id].videoHeight
26389
+ });
26390
+ this.instance.updateNode(this.serialize(videoGroup));
26231
26391
  }
26392
+ if (isServer()) this.instance.updateNode(this.serialize(videoGroup));
26393
+ const defaultHandleMouseover = videoGroup.handleMouseover;
26394
+ videoGroup.handleMouseover = () => {
26395
+ defaultHandleMouseover.call(this);
26396
+ if (this.config.style.track.onlyOnHover && this.videoState[id].loaded) {
26397
+ const videoProgress = videoGroup.findOne(`#${id}-video-progress`);
26398
+ videoProgress?.show();
26399
+ }
26400
+ };
26401
+ const defaultHandleMouseout = videoGroup.handleMouseout;
26402
+ videoGroup.handleMouseout = () => {
26403
+ defaultHandleMouseout.call(this);
26404
+ if (this.config.style.track.onlyOnHover && this.videoState[id].loaded && !this.videoState[id].paused) {
26405
+ const videoProgress = videoGroup.findOne(`#${id}-video-progress`);
26406
+ videoProgress?.hide();
26407
+ }
26408
+ };
26409
+ videoGroup.on("mouseover", () => {
26410
+ videoGroup.handleMouseover();
26411
+ });
26412
+ videoGroup.on("mouseout", () => {
26413
+ videoGroup.handleMouseout();
26414
+ });
26415
+ videoGroup.dblClick = () => {
26416
+ if (this.config.style.playPauseOnDblClick && this.videoState[id].loaded && !this.videoState[id].playing) {
26417
+ this.play(id);
26418
+ return;
26419
+ }
26420
+ if (this.config.style.playPauseOnDblClick && this.videoState[id].loaded && this.videoState[id].playing) {
26421
+ this.pause(id);
26422
+ return;
26423
+ }
26424
+ };
26425
+ return videoGroup;
26232
26426
  }
26233
- setCommentViewing(commentId) {
26234
- this.commentDomAction = commentId ? "viewing" : "idle";
26235
- this.commentDomVisible = !!commentId;
26236
- this.commentDomVisibleId = commentId;
26427
+ loadAsyncElement(nodeId) {
26428
+ this.instance.loadAsyncElement(nodeId, "video");
26237
26429
  }
26238
- isCommentViewing() {
26239
- return this.commentDomAction === WEAVE_COMMENT_NODE_ACTION.VIEWING && this.commentDomVisible;
26430
+ resolveAsyncElement(nodeId) {
26431
+ this.instance.resolveAsyncElement(nodeId, "video");
26432
+ }
26433
+ getVideoState(nodeInstance) {
26434
+ return this.videoState[nodeInstance.getAttrs().id ?? ""];
26435
+ }
26436
+ play(videoId) {
26437
+ const video = this.instance.getStage().findOne(`#${videoId}`);
26438
+ if (!video) return;
26439
+ const videoPlaceholderNode = video.findOne(`#${videoId}-video-placeholder`);
26440
+ if (videoPlaceholderNode) videoPlaceholderNode.hide();
26441
+ const videoIconGroup = video.findOne(`#${videoId}-video-icon-group`);
26442
+ if (videoIconGroup) videoIconGroup.hide();
26443
+ const videoNode = video.findOne(`#${videoId}-video`);
26444
+ if (videoNode && this.videoSource[videoId]) {
26445
+ videoNode.show();
26446
+ this.videoState[videoId] = {
26447
+ ...this.videoState[videoId],
26448
+ playing: true,
26449
+ paused: false
26450
+ };
26451
+ this.videoSource[videoId].play();
26452
+ this.anim.start();
26453
+ this.instance.emitEvent("onVideoPlay", { nodeId: videoId });
26454
+ }
26455
+ }
26456
+ pause(videoId) {
26457
+ const video = this.instance.getStage().findOne(`#${videoId}`);
26458
+ if (!video) return;
26459
+ const videoIconGroup = video.findOne(`#${videoId}-video-icon-group`);
26460
+ if (videoIconGroup) videoIconGroup.show();
26461
+ const videoNode = video.findOne(`#${videoId}-video`);
26462
+ if (videoNode && this.videoSource[videoId]) {
26463
+ this.videoSource[videoId].pause();
26464
+ this.videoState[videoId] = {
26465
+ ...this.videoState[videoId],
26466
+ playing: false,
26467
+ paused: true
26468
+ };
26469
+ this.instance.emitEvent("onVideoPause", { nodeId: videoId });
26470
+ }
26471
+ }
26472
+ stop(videoId) {
26473
+ const video = this.instance.getStage().findOne(`#${videoId}`);
26474
+ if (!video) return;
26475
+ const videoPlaceholderNode = video.findOne(`#${videoId}-video-placeholder`);
26476
+ if (videoPlaceholderNode) videoPlaceholderNode.show();
26477
+ const videoProgress = video.findOne(`#${videoId}-video-progress`);
26478
+ if (videoProgress && !this.config.style.track.onlyOnHover) videoProgress.hide();
26479
+ const videoIconGroup = video.findOne(`#${videoId}-video-icon-group`);
26480
+ if (videoIconGroup) videoIconGroup.show();
26481
+ const videoNode = video.findOne(`#${videoId}-video`);
26482
+ if (videoNode && this.videoSource[videoId]) {
26483
+ this.videoSource[videoId].currentTime = 0;
26484
+ this.videoState[videoId] = {
26485
+ ...this.videoState[videoId],
26486
+ playing: false,
26487
+ paused: false
26488
+ };
26489
+ videoNode.hide();
26490
+ this.videoSource[videoId].pause();
26491
+ if (!this.areVideosPlaying()) this.anim.stop();
26492
+ this.instance.emitEvent("onVideoStop", { nodeId: videoId });
26493
+ }
26240
26494
  }
26241
- isCommentCreating() {
26242
- return this.commentDomAction === WEAVE_COMMENT_NODE_ACTION.CREATING && this.commentDomVisible;
26495
+ areVideosPlaying() {
26496
+ return Object.values(this.videoState).some((state) => state.playing);
26243
26497
  }
26244
- getCommentId(node) {
26245
- return this.config.model.getId(node.getAttrs().commentModel);
26498
+ getVideoSource(videoId) {
26499
+ return this.videoSource[videoId];
26246
26500
  }
26247
- setShowResolved(show) {
26248
- this.showResolved = show;
26501
+ onUpdate(nodeInstance, nextProps) {
26502
+ nodeInstance.setAttrs({ ...nextProps });
26503
+ const id = nodeInstance.getAttrs().id ?? "";
26504
+ const node = nodeInstance;
26505
+ const nodeAttrs = node.getAttrs();
26506
+ const internalVideoProps = { ...nodeAttrs };
26507
+ delete internalVideoProps.nodeType;
26508
+ delete internalVideoProps.videoProperties;
26509
+ delete internalVideoProps.videoPlaceholderURL;
26510
+ delete internalVideoProps.videoURL;
26511
+ delete internalVideoProps.zIndex;
26512
+ const bg = node.findOne(`#${id}-bg`);
26513
+ const videoIconGroup = node.findOne(`#${id}-video-icon-group`);
26514
+ const videoPlaceholder = node.findOne(`#${id}-video-placeholder`);
26515
+ if (!bg || !videoIconGroup || !videoPlaceholder) return;
26516
+ const videoWidth = node.getAttrs().width ?? 0;
26517
+ const videoHeight = node.getAttrs().height ?? 0;
26518
+ bg.setAttrs({
26519
+ ...internalVideoProps,
26520
+ id: `${id}-bg`,
26521
+ x: 0,
26522
+ y: 0
26523
+ });
26524
+ const video = node.findOne(`#${id}-video`);
26525
+ if (!isServer() && video) video.setAttrs({
26526
+ ...internalVideoProps,
26527
+ id: `${id}-video`,
26528
+ x: 0,
26529
+ y: 0
26530
+ });
26531
+ videoPlaceholder.setAttrs({
26532
+ ...internalVideoProps,
26533
+ id: `${id}-video-placeholder`,
26534
+ x: 0,
26535
+ y: 0
26536
+ });
26537
+ const videoIconGroupWidth = this.config.style.icon.internal.paddingX * 2 + this.config.style.icon.width;
26538
+ const videoIconGroupHeight = this.config.style.icon.internal.paddingY * 2 + this.config.style.icon.height;
26539
+ videoIconGroup.x(videoWidth - videoIconGroupWidth - this.config.style.icon.external.paddingX);
26540
+ videoIconGroup.y(videoHeight - videoIconGroupHeight - this.config.style.icon.external.paddingY);
26541
+ const nodesSelectionPlugin = this.getNodeSelectionPlugin();
26542
+ if (nodesSelectionPlugin) nodesSelectionPlugin.getTransformer().forceUpdate();
26543
+ }
26544
+ getNodeSelectionPlugin() {
26545
+ const nodesSelectionPlugin = this.instance.getPlugin("nodesSelection");
26546
+ return nodesSelectionPlugin;
26547
+ }
26548
+ scaleReset(node) {
26549
+ const scale = node.scale();
26550
+ const id = node.getAttr("id");
26551
+ const videoProgress = node.findOne(`#${id}-video-progress`);
26552
+ const videoIconGroup = node.findOne(`#${id}-video-icon-group`);
26553
+ if (videoIconGroup && videoProgress) {
26554
+ videoIconGroup.scaleX(1);
26555
+ videoIconGroup.scaleY(1);
26556
+ const videoIconGroupWidth = this.config.style.icon.internal.paddingX * 2 + this.config.style.icon.width;
26557
+ const videoIconGroupHeight = this.config.style.icon.internal.paddingY * 2 + this.config.style.icon.height;
26558
+ const stage = this.instance.getStage();
26559
+ const videoWidth = (node.getAttrs().width ?? 0) * stage.scaleX();
26560
+ const videoHeight = (node.getAttrs().height ?? 0) * stage.scaleY();
26561
+ videoIconGroup.x(videoWidth - videoIconGroupWidth - this.config.style.icon.external.paddingX);
26562
+ videoIconGroup.y(videoHeight - videoIconGroupHeight - this.config.style.icon.external.paddingY);
26563
+ }
26564
+ node.width(Math.max(5, node.width() * scale.x));
26565
+ node.height(Math.max(5, node.height() * scale.y));
26566
+ if (videoProgress) {
26567
+ videoProgress.scaleX(1);
26568
+ videoProgress.scaleY(1);
26569
+ const progress = this.videoSource[id].duration ? Math.min(this.videoSource[id].currentTime / this.videoSource[id].duration, 1) : 0;
26570
+ videoProgress.width((node.getAttrs().width ?? 0) * progress);
26571
+ videoProgress.height(this.config.style.track.height / this.instance.getStage().scaleY());
26572
+ videoProgress.y((node.getAttrs().height ?? 0) - videoProgress.height());
26573
+ }
26574
+ node.scale({
26575
+ x: 1,
26576
+ y: 1
26577
+ });
26249
26578
  }
26250
26579
  };
26251
26580
 
@@ -28043,67 +28372,345 @@ var WeaveTextToolAction = class extends WeaveAction {
28043
28372
  return;
28044
28373
  }
28045
28374
  });
28046
- this.initialized = true;
28375
+ this.initialized = true;
28376
+ }
28377
+ setState(state) {
28378
+ this.state = state;
28379
+ }
28380
+ addText() {
28381
+ const selectionPlugin = this.instance.getPlugin("nodesSelection");
28382
+ if (selectionPlugin) {
28383
+ const tr = selectionPlugin.getTransformer();
28384
+ tr.hide();
28385
+ }
28386
+ this.setCursor();
28387
+ this.setFocusStage();
28388
+ this.instance.emitEvent("onAddingText");
28389
+ this.clickPoint = null;
28390
+ this.setState(TEXT_TOOL_STATE.ADDING);
28391
+ }
28392
+ handleAdding() {
28393
+ const { mousePoint, container } = this.instance.getMousePointer();
28394
+ this.clickPoint = mousePoint;
28395
+ this.container = container;
28396
+ this.textId = v4_default();
28397
+ const nodeHandler = this.instance.getNodeHandler("text");
28398
+ if (nodeHandler) {
28399
+ const node = nodeHandler.create(this.textId, {
28400
+ ...this.props,
28401
+ x: this.clickPoint?.x ?? 0,
28402
+ y: this.clickPoint?.y ?? 0,
28403
+ draggable: true
28404
+ });
28405
+ this.instance.addNode(node, this.container?.getAttrs().id);
28406
+ this.instance.emitEvent("onAddedArrow");
28407
+ }
28408
+ this.setState(TEXT_TOOL_STATE.FINISHED);
28409
+ this.cancelAction();
28410
+ }
28411
+ trigger(cancelAction) {
28412
+ if (!this.instance) throw new Error("Instance not defined");
28413
+ if (!this.initialized) this.setupEvents();
28414
+ this.cancelAction = cancelAction;
28415
+ const selectionPlugin = this.instance.getPlugin("nodesSelection");
28416
+ if (selectionPlugin) selectionPlugin.setSelectedNodes([]);
28417
+ this.props = this.initProps();
28418
+ this.addText();
28419
+ }
28420
+ cleanup() {
28421
+ const stage = this.instance.getStage();
28422
+ stage.container().style.cursor = "default";
28423
+ const selectionPlugin = this.instance.getPlugin("nodesSelection");
28424
+ if (selectionPlugin) {
28425
+ const node$1 = stage.findOne(`#${this.textId}`);
28426
+ if (node$1) selectionPlugin.setSelectedNodes([node$1]);
28427
+ this.instance.triggerAction(SELECTION_TOOL_ACTION_NAME);
28428
+ }
28429
+ const node = stage.findOne(`#${this.textId}`);
28430
+ if (node) node.getAttr("triggerEditMode")(node);
28431
+ this.initialCursor = null;
28432
+ this.textId = null;
28433
+ this.container = void 0;
28434
+ this.clickPoint = null;
28435
+ this.setState(TEXT_TOOL_STATE.IDLE);
28436
+ }
28437
+ setCursor() {
28438
+ const stage = this.instance.getStage();
28439
+ stage.container().style.cursor = "crosshair";
28440
+ }
28441
+ setFocusStage() {
28442
+ const stage = this.instance.getStage();
28443
+ stage.container().tabIndex = 1;
28444
+ stage.container().blur();
28445
+ stage.container().focus();
28446
+ }
28447
+ };
28448
+
28449
+ //#endregion
28450
+ //#region src/actions/image-tool/constants.ts
28451
+ const IMAGE_TOOL_ACTION_NAME = "imageTool";
28452
+ const IMAGE_TOOL_STATE = {
28453
+ ["IDLE"]: "idle",
28454
+ ["UPLOADING"]: "uploading",
28455
+ ["DEFINING_POSITION"]: "definingPosition",
28456
+ ["SELECTED_POSITION"]: "selectedPosition",
28457
+ ["ADDING"]: "adding",
28458
+ ["FINISHED"]: "finished"
28459
+ };
28460
+
28461
+ //#endregion
28462
+ //#region src/actions/image-tool/image-tool.ts
28463
+ var WeaveImageToolAction = class extends WeaveAction {
28464
+ initialized = false;
28465
+ initialCursor = null;
28466
+ cursorPadding = 5;
28467
+ forceMainContainer = false;
28468
+ onPropsChange = void 0;
28469
+ update = void 0;
28470
+ constructor() {
28471
+ super();
28472
+ this.pointers = new Map();
28473
+ this.initialized = false;
28474
+ this.state = IMAGE_TOOL_STATE.IDLE;
28475
+ this.imageId = null;
28476
+ this.tempImageId = null;
28477
+ this.tempImageNode = null;
28478
+ this.container = void 0;
28479
+ this.imageURL = null;
28480
+ this.clickPoint = null;
28481
+ }
28482
+ getName() {
28483
+ return IMAGE_TOOL_ACTION_NAME;
28484
+ }
28485
+ initProps() {
28486
+ return {
28487
+ width: 100,
28488
+ height: 100,
28489
+ scaleX: 1,
28490
+ scaleY: 1
28491
+ };
28492
+ }
28493
+ onInit() {
28494
+ this.instance.addEventListener("onStageDrop", (e) => {
28495
+ if (window.weaveDragImageURL) {
28496
+ this.instance.getStage().setPointersPositions(e);
28497
+ const position = this.instance.getStage().getRelativePointerPosition();
28498
+ this.instance.triggerAction(IMAGE_TOOL_ACTION_NAME, {
28499
+ imageURL: window.weaveDragImageURL,
28500
+ imageId: window.weaveDragImageId,
28501
+ position
28502
+ });
28503
+ window.weaveDragImageURL = void 0;
28504
+ window.weaveDragImageId = void 0;
28505
+ }
28506
+ });
28507
+ }
28508
+ setupEvents() {
28509
+ const stage = this.instance.getStage();
28510
+ window.addEventListener("keydown", (e) => {
28511
+ if (e.key === "Escape" && this.instance.getActiveAction() === IMAGE_TOOL_ACTION_NAME) {
28512
+ this.cancelAction();
28513
+ return;
28514
+ }
28515
+ });
28516
+ stage.on("pointerdown", (e) => {
28517
+ this.setTapStart(e);
28518
+ this.pointers.set(e.evt.pointerId, {
28519
+ x: e.evt.clientX,
28520
+ y: e.evt.clientY
28521
+ });
28522
+ if (this.pointers.size === 2 && this.instance.getActiveAction() === IMAGE_TOOL_ACTION_NAME) {
28523
+ this.state = IMAGE_TOOL_STATE.DEFINING_POSITION;
28524
+ return;
28525
+ }
28526
+ if (this.state === IMAGE_TOOL_STATE.DEFINING_POSITION) this.state = IMAGE_TOOL_STATE.SELECTED_POSITION;
28527
+ });
28528
+ stage.on("pointermove", (e) => {
28529
+ if (this.state === IMAGE_TOOL_STATE.IDLE) return;
28530
+ this.setCursor();
28531
+ if (this.pointers.size === 2 && this.instance.getActiveAction() === IMAGE_TOOL_ACTION_NAME) {
28532
+ this.state = IMAGE_TOOL_STATE.DEFINING_POSITION;
28533
+ return;
28534
+ }
28535
+ 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") {
28536
+ const mousePos = stage.getRelativePointerPosition();
28537
+ this.tempImageNode.setAttrs({
28538
+ x: (mousePos?.x ?? 0) + this.cursorPadding,
28539
+ y: (mousePos?.y ?? 0) + this.cursorPadding
28540
+ });
28541
+ }
28542
+ });
28543
+ stage.on("pointerup", (e) => {
28544
+ this.pointers.delete(e.evt.pointerId);
28545
+ if (this.state === IMAGE_TOOL_STATE.SELECTED_POSITION) this.handleAdding();
28546
+ });
28547
+ this.initialized = true;
28548
+ }
28549
+ setState(state) {
28550
+ this.state = state;
28551
+ }
28552
+ loadImage(imageURL, options, position) {
28553
+ this.setCursor();
28554
+ this.setFocusStage();
28555
+ this.imageId = v4_default();
28556
+ this.imageURL = imageURL;
28557
+ const imageNodeHandler = this.getImageNodeHandler();
28558
+ if (!imageNodeHandler) {
28559
+ this.cancelAction();
28560
+ return;
28561
+ }
28562
+ imageNodeHandler.preloadImage(this.imageId, imageURL, {
28563
+ onLoad: () => {
28564
+ this.instance.emitEvent("onImageLoadEnd", void 0);
28565
+ const imageSource = imageNodeHandler.getImageSource(this.imageId);
28566
+ if (imageSource && this.imageId) this.props = {
28567
+ ...this.props,
28568
+ imageURL: this.imageURL,
28569
+ width: imageSource.width,
28570
+ height: imageSource.height
28571
+ };
28572
+ this.addImageNode(position);
28573
+ },
28574
+ onError: () => {
28575
+ this.instance.emitEvent("onImageLoadEnd", new Error("Error loading image"));
28576
+ this.cancelAction();
28577
+ }
28578
+ });
28579
+ this.instance.emitEvent("onImageLoadStart");
28047
28580
  }
28048
- setState(state) {
28049
- this.state = state;
28581
+ isTouchDevice() {
28582
+ return window.matchMedia("(pointer: coarse)").matches;
28050
28583
  }
28051
- addText() {
28052
- const selectionPlugin = this.instance.getPlugin("nodesSelection");
28053
- if (selectionPlugin) {
28054
- const tr = selectionPlugin.getTransformer();
28055
- tr.hide();
28056
- }
28584
+ addImageNode(position) {
28585
+ const stage = this.instance.getStage();
28057
28586
  this.setCursor();
28058
28587
  this.setFocusStage();
28059
- this.instance.emitEvent("onAddingText");
28588
+ if (position) {
28589
+ this.setState(IMAGE_TOOL_STATE.SELECTED_POSITION);
28590
+ this.handleAdding(position);
28591
+ return;
28592
+ }
28593
+ if (this.imageId) {
28594
+ const mousePos = stage.getRelativePointerPosition();
28595
+ this.tempImageId = v4_default();
28596
+ const imageNodeHandler = this.getImageNodeHandler();
28597
+ if (!imageNodeHandler) {
28598
+ this.cancelAction();
28599
+ return;
28600
+ }
28601
+ const imageSource = imageNodeHandler.getImageSource(this.imageId);
28602
+ if (!imageSource) {
28603
+ this.cancelAction();
28604
+ return;
28605
+ }
28606
+ const aspectRatio = imageSource.width / imageSource.height;
28607
+ if (!this.tempImageNode && this.tempImageId && !this.isTouchDevice()) {
28608
+ this.tempImageNode = new konva.default.Image({
28609
+ id: this.tempImageId,
28610
+ x: (mousePos?.x ?? 0) + this.cursorPadding,
28611
+ y: (mousePos?.y ?? 0) + this.cursorPadding,
28612
+ width: 240 * aspectRatio * (1 / stage.scaleX()),
28613
+ height: 240 * (1 / stage.scaleY()),
28614
+ opacity: 1,
28615
+ adding: true,
28616
+ image: imageSource,
28617
+ stroke: "#000000ff",
28618
+ strokeWidth: 0,
28619
+ strokeScaleEnabled: true,
28620
+ listening: false
28621
+ });
28622
+ this.instance.getMainLayer()?.add(this.tempImageNode);
28623
+ }
28624
+ this.instance.emitEvent("onAddingImage", { imageURL: this.props.imageURL });
28625
+ }
28060
28626
  this.clickPoint = null;
28061
- this.setState(TEXT_TOOL_STATE.ADDING);
28627
+ this.setState(IMAGE_TOOL_STATE.DEFINING_POSITION);
28062
28628
  }
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");
28629
+ addImage(position) {
28630
+ if (position) this.clickPoint = position;
28631
+ this.setState(IMAGE_TOOL_STATE.UPLOADING);
28632
+ }
28633
+ handleAdding(position) {
28634
+ if (this.imageId) {
28635
+ const imageNodeHandler = this.getImageNodeHandler();
28636
+ if (!imageNodeHandler) {
28637
+ this.cancelAction();
28638
+ return;
28639
+ }
28640
+ const imageSource = imageNodeHandler.getImageSource(this.imageId);
28641
+ if (!imageSource) {
28642
+ this.cancelAction();
28643
+ return;
28644
+ }
28645
+ const { mousePoint, container } = this.instance.getMousePointer(position);
28646
+ this.clickPoint = mousePoint;
28647
+ this.container = container;
28648
+ const nodeHandler = this.instance.getNodeHandler("image");
28649
+ if (nodeHandler) {
28650
+ const node = nodeHandler.create(this.imageId, {
28651
+ ...this.props,
28652
+ x: this.clickPoint?.x ?? 0,
28653
+ y: this.clickPoint?.y ?? 0,
28654
+ opacity: 1,
28655
+ adding: false,
28656
+ imageURL: this.imageURL,
28657
+ stroke: "#000000ff",
28658
+ strokeWidth: 0,
28659
+ strokeScaleEnabled: true,
28660
+ imageWidth: imageSource.width,
28661
+ imageHeight: imageSource.height,
28662
+ imageInfo: {
28663
+ width: imageSource.width,
28664
+ height: imageSource.height
28665
+ }
28666
+ });
28667
+ this.instance.addNode(node, this.forceMainContainer ? this.instance.getMainLayer()?.getAttrs().id : this.container?.getAttrs().id);
28668
+ this.instance.emitEvent("onAddedImage", {
28669
+ imageURL: this.props.imageURL,
28670
+ nodeId: this.imageId
28671
+ });
28672
+ }
28673
+ this.setState(IMAGE_TOOL_STATE.FINISHED);
28078
28674
  }
28079
- this.setState(TEXT_TOOL_STATE.FINISHED);
28080
28675
  this.cancelAction();
28081
28676
  }
28082
- trigger(cancelAction) {
28677
+ trigger(cancelAction, params) {
28083
28678
  if (!this.instance) throw new Error("Instance not defined");
28084
28679
  if (!this.initialized) this.setupEvents();
28085
28680
  this.cancelAction = cancelAction;
28086
28681
  const selectionPlugin = this.instance.getPlugin("nodesSelection");
28087
28682
  if (selectionPlugin) selectionPlugin.setSelectedNodes([]);
28683
+ this.forceMainContainer = params?.forceMainContainer ?? false;
28684
+ if (params?.imageId) this.updateProps({ imageId: params.imageId });
28685
+ if (params?.imageURL) {
28686
+ this.loadImage(params.imageURL, params?.options ?? void 0, params?.position ?? void 0);
28687
+ return;
28688
+ }
28088
28689
  this.props = this.initProps();
28089
- this.addText();
28690
+ this.addImage();
28691
+ return { finishUploadCallback: this.loadImage.bind(this) };
28090
28692
  }
28091
28693
  cleanup() {
28092
28694
  const stage = this.instance.getStage();
28093
- stage.container().style.cursor = "default";
28695
+ if (this.tempImageNode) this.tempImageNode.destroy();
28094
28696
  const selectionPlugin = this.instance.getPlugin("nodesSelection");
28095
28697
  if (selectionPlugin) {
28096
- const node$1 = stage.findOne(`#${this.textId}`);
28097
- if (node$1) selectionPlugin.setSelectedNodes([node$1]);
28698
+ const node = stage.findOne(`#${this.imageId}`);
28699
+ if (node) selectionPlugin.setSelectedNodes([node]);
28098
28700
  this.instance.triggerAction(SELECTION_TOOL_ACTION_NAME);
28099
28701
  }
28100
- const node = stage.findOne(`#${this.textId}`);
28101
- if (node) node.getAttr("triggerEditMode")(node);
28702
+ stage.container().style.cursor = "default";
28102
28703
  this.initialCursor = null;
28103
- this.textId = null;
28704
+ this.imageId = null;
28705
+ this.forceMainContainer = false;
28104
28706
  this.container = void 0;
28707
+ this.tempImageNode = null;
28708
+ this.imageURL = null;
28105
28709
  this.clickPoint = null;
28106
- this.setState(TEXT_TOOL_STATE.IDLE);
28710
+ this.setState(IMAGE_TOOL_STATE.IDLE);
28711
+ }
28712
+ getImageNodeHandler() {
28713
+ return this.instance.getNodeHandler("image");
28107
28714
  }
28108
28715
  setCursor() {
28109
28716
  const stage = this.instance.getStage();
@@ -29527,6 +30134,182 @@ var WeaveCommentToolAction = class extends WeaveAction {
29527
30134
  }
29528
30135
  };
29529
30136
 
30137
+ //#endregion
30138
+ //#region src/actions/video-tool/constants.ts
30139
+ const VIDEO_TOOL_ACTION_NAME = "videoTool";
30140
+ const VIDEO_TOOL_STATE = {
30141
+ ["IDLE"]: "idle",
30142
+ ["UPLOADING"]: "uploading",
30143
+ ["DEFINING_POSITION"]: "definingPosition",
30144
+ ["SELECTED_POSITION"]: "selectedPosition",
30145
+ ["ADDING"]: "adding",
30146
+ ["FINISHED"]: "finished"
30147
+ };
30148
+
30149
+ //#endregion
30150
+ //#region src/actions/video-tool/video-tool.ts
30151
+ var WeaveVideoToolAction = class extends WeaveAction {
30152
+ initialized = false;
30153
+ initialCursor = null;
30154
+ cursorPadding = 5;
30155
+ forceMainContainer = false;
30156
+ onPropsChange = void 0;
30157
+ update = void 0;
30158
+ constructor() {
30159
+ super();
30160
+ this.pointers = new Map();
30161
+ this.initialized = false;
30162
+ this.state = VIDEO_TOOL_STATE.IDLE;
30163
+ this.videoId = null;
30164
+ this.container = void 0;
30165
+ this.videoParams = null;
30166
+ this.clickPoint = null;
30167
+ }
30168
+ getName() {
30169
+ return VIDEO_TOOL_ACTION_NAME;
30170
+ }
30171
+ getVideoSource(videoId) {
30172
+ const nodeHandler = this.instance.getNodeHandler("video");
30173
+ if (!nodeHandler) return void 0;
30174
+ return nodeHandler.getVideoSource(videoId);
30175
+ }
30176
+ initProps() {
30177
+ return {
30178
+ width: 100,
30179
+ height: 100,
30180
+ scaleX: 1,
30181
+ scaleY: 1
30182
+ };
30183
+ }
30184
+ onInit() {
30185
+ this.instance.addEventListener("onStageDrop", (e) => {
30186
+ if (window.weaveDragVideoId && window.weaveDragVideoParams) {
30187
+ this.instance.getStage().setPointersPositions(e);
30188
+ const position = this.instance.getStage().getRelativePointerPosition();
30189
+ this.instance.triggerAction(VIDEO_TOOL_ACTION_NAME, {
30190
+ videoId: window.weaveDragVideoId,
30191
+ videoParams: window.weaveDragVideoParams,
30192
+ position
30193
+ });
30194
+ window.weaveDragVideoParams = void 0;
30195
+ window.weaveDragVideoId = void 0;
30196
+ }
30197
+ });
30198
+ }
30199
+ setupEvents() {
30200
+ const stage = this.instance.getStage();
30201
+ window.addEventListener("keydown", (e) => {
30202
+ if (e.key === "Escape" && this.instance.getActiveAction() === VIDEO_TOOL_ACTION_NAME) {
30203
+ this.cancelAction();
30204
+ return;
30205
+ }
30206
+ });
30207
+ stage.on("pointerdown", (e) => {
30208
+ this.setTapStart(e);
30209
+ this.pointers.set(e.evt.pointerId, {
30210
+ x: e.evt.clientX,
30211
+ y: e.evt.clientY
30212
+ });
30213
+ if (this.state === VIDEO_TOOL_STATE.DEFINING_POSITION) this.state = VIDEO_TOOL_STATE.SELECTED_POSITION;
30214
+ });
30215
+ stage.on("pointermove", () => {
30216
+ if (this.state === VIDEO_TOOL_STATE.IDLE) return;
30217
+ this.setCursor();
30218
+ });
30219
+ stage.on("pointerup", (e) => {
30220
+ this.pointers.delete(e.evt.pointerId);
30221
+ if (this.state === VIDEO_TOOL_STATE.SELECTED_POSITION) this.handleAdding();
30222
+ });
30223
+ this.initialized = true;
30224
+ }
30225
+ setState(state) {
30226
+ this.state = state;
30227
+ }
30228
+ doVideoAdding(videoParams, position) {
30229
+ this.videoId = v4_default();
30230
+ this.videoParams = videoParams;
30231
+ this.setState(VIDEO_TOOL_STATE.DEFINING_POSITION);
30232
+ if (!position) {
30233
+ this.clickPoint = null;
30234
+ this.instance.emitEvent("onAddingVideo", { videoURL: this.videoParams.url });
30235
+ } else this.handleAdding(position);
30236
+ }
30237
+ addVideo(position) {
30238
+ if (position) this.clickPoint = position;
30239
+ this.setState(VIDEO_TOOL_STATE.UPLOADING);
30240
+ }
30241
+ handleAdding(position) {
30242
+ if (this.videoId && this.videoParams) {
30243
+ const { mousePoint, container } = this.instance.getMousePointer(position);
30244
+ this.clickPoint = mousePoint;
30245
+ this.container = container;
30246
+ const nodeHandler = this.instance.getNodeHandler("video");
30247
+ if (nodeHandler) {
30248
+ const node = nodeHandler.create(this.videoId, {
30249
+ ...this.props,
30250
+ x: this.clickPoint?.x ?? 0,
30251
+ y: this.clickPoint?.y ?? 0,
30252
+ opacity: 1,
30253
+ adding: false,
30254
+ videoPlaceholderURL: this.videoParams.placeholderUrl,
30255
+ videoURL: this.videoParams.url,
30256
+ stroke: "#000000ff",
30257
+ strokeWidth: 0,
30258
+ strokeScaleEnabled: true
30259
+ });
30260
+ this.instance.addNode(node, this.forceMainContainer ? this.instance.getMainLayer()?.getAttrs().id : this.container?.getAttrs().id);
30261
+ this.instance.emitEvent("onAddedVideo", {
30262
+ videoURL: this.videoParams.url,
30263
+ nodeId: this.videoId
30264
+ });
30265
+ }
30266
+ this.setState(VIDEO_TOOL_STATE.FINISHED);
30267
+ }
30268
+ this.cancelAction();
30269
+ }
30270
+ trigger(cancelAction, params) {
30271
+ if (!this.instance) throw new Error("Instance not defined");
30272
+ if (!this.initialized) this.setupEvents();
30273
+ this.cancelAction = cancelAction;
30274
+ const selectionPlugin = this.instance.getPlugin("nodesSelection");
30275
+ if (selectionPlugin) selectionPlugin.setSelectedNodes([]);
30276
+ this.forceMainContainer = params?.forceMainContainer ?? false;
30277
+ if (params?.videoId) this.updateProps({ videoId: params.videoId });
30278
+ if (params?.videoParams) {
30279
+ this.updateProps({
30280
+ width: params.videoParams.width,
30281
+ height: params.videoParams.height
30282
+ });
30283
+ this.doVideoAdding(params.videoParams, params?.position ?? void 0);
30284
+ return;
30285
+ }
30286
+ this.props = this.initProps();
30287
+ this.addVideo();
30288
+ return { finishUploadCallback: this.doVideoAdding.bind(this) };
30289
+ }
30290
+ cleanup() {
30291
+ const stage = this.instance.getStage();
30292
+ const selectionPlugin = this.instance.getPlugin("nodesSelection");
30293
+ if (selectionPlugin) {
30294
+ const node = stage.findOne(`#${this.videoId}`);
30295
+ if (node) selectionPlugin.setSelectedNodes([node]);
30296
+ this.instance.triggerAction(SELECTION_TOOL_ACTION_NAME);
30297
+ }
30298
+ stage.container().style.cursor = "default";
30299
+ this.initialCursor = null;
30300
+ this.videoId = null;
30301
+ this.forceMainContainer = false;
30302
+ this.container = void 0;
30303
+ this.videoParams = null;
30304
+ this.clickPoint = null;
30305
+ this.setState(VIDEO_TOOL_STATE.IDLE);
30306
+ }
30307
+ setCursor() {
30308
+ const stage = this.instance.getStage();
30309
+ stage.container().style.cursor = "crosshair";
30310
+ }
30311
+ };
30312
+
29530
30313
  //#endregion
29531
30314
  //#region src/plugins/stage-grid/stage-grid.ts
29532
30315
  var WeaveStageGridPlugin = class extends WeavePlugin {
@@ -31761,6 +32544,8 @@ exports.STAR_TOOL_STATE = STAR_TOOL_STATE
31761
32544
  exports.TEXT_LAYOUT = TEXT_LAYOUT
31762
32545
  exports.TEXT_TOOL_ACTION_NAME = TEXT_TOOL_ACTION_NAME
31763
32546
  exports.TEXT_TOOL_STATE = TEXT_TOOL_STATE
32547
+ exports.VIDEO_TOOL_ACTION_NAME = VIDEO_TOOL_ACTION_NAME
32548
+ exports.VIDEO_TOOL_STATE = VIDEO_TOOL_STATE
31764
32549
  exports.WEAVE_ARROW_NODE_TYPE = WEAVE_ARROW_NODE_TYPE
31765
32550
  exports.WEAVE_COMMENTS_RENDERER_KEY = WEAVE_COMMENTS_RENDERER_KEY
31766
32551
  exports.WEAVE_COMMENTS_TOOL_LAYER_ID = WEAVE_COMMENTS_TOOL_LAYER_ID
@@ -31821,6 +32606,8 @@ exports.WEAVE_USERS_POINTERS_KEY = WEAVE_USERS_POINTERS_KEY
31821
32606
  exports.WEAVE_USERS_SELECTION_KEY = WEAVE_USERS_SELECTION_KEY
31822
32607
  exports.WEAVE_USER_POINTER_KEY = WEAVE_USER_POINTER_KEY
31823
32608
  exports.WEAVE_USER_SELECTION_KEY = WEAVE_USER_SELECTION_KEY
32609
+ exports.WEAVE_VIDEO_DEFAULT_CONFIG = WEAVE_VIDEO_DEFAULT_CONFIG
32610
+ exports.WEAVE_VIDEO_NODE_TYPE = WEAVE_VIDEO_NODE_TYPE
31824
32611
  exports.Weave = Weave
31825
32612
  exports.WeaveAction = WeaveAction
31826
32613
  exports.WeaveAlignNodesToolAction = WeaveAlignNodesToolAction
@@ -31875,6 +32662,8 @@ exports.WeaveTextNode = WeaveTextNode
31875
32662
  exports.WeaveTextToolAction = WeaveTextToolAction
31876
32663
  exports.WeaveUsersPointersPlugin = WeaveUsersPointersPlugin
31877
32664
  exports.WeaveUsersSelectionPlugin = WeaveUsersSelectionPlugin
32665
+ exports.WeaveVideoNode = WeaveVideoNode
32666
+ exports.WeaveVideoToolAction = WeaveVideoToolAction
31878
32667
  exports.WeaveZoomInToolAction = WeaveZoomInToolAction
31879
32668
  exports.WeaveZoomOutToolAction = WeaveZoomOutToolAction
31880
32669
  exports.clearContainerTargets = clearContainerTargets
@@ -31894,6 +32683,7 @@ exports.intersectArrays = intersectArrays
31894
32683
  exports.isIOS = isIOS
31895
32684
  exports.isInShadowDOM = isInShadowDOM
31896
32685
  exports.isNodeInSelection = isNodeInSelection
32686
+ exports.isServer = isServer
31897
32687
  exports.memoize = memoize
31898
32688
  exports.moveNodeToContainer = moveNodeToContainer
31899
32689
  exports.resetScale = resetScale