@inditextech/weave-sdk 0.72.0 → 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.0";
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);
@@ -24257,7 +24051,7 @@ var WeaveImageCrop = class WeaveImageCrop {
24257
24051
  ],
24258
24052
  stroke: "#0074ffcc",
24259
24053
  strokeWidth: 1,
24260
- strokeScaleEnabled: true
24054
+ strokeScaleEnabled: false
24261
24055
  });
24262
24056
  const hLine = new konva.default.Line({
24263
24057
  points: [
@@ -24268,7 +24062,7 @@ var WeaveImageCrop = class WeaveImageCrop {
24268
24062
  ],
24269
24063
  stroke: "#0074ffcc",
24270
24064
  strokeWidth: 1,
24271
- strokeScaleEnabled: true
24065
+ strokeScaleEnabled: false
24272
24066
  });
24273
24067
  this.grid.add(vLine, hLine);
24274
24068
  }
@@ -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;
@@ -24722,19 +24548,20 @@ var WeaveImageNode = class extends WeaveNode {
24722
24548
  const internalImage = image?.findOne(`#${imageAttrs.id}-image`);
24723
24549
  if (image && internalImage && !imageAttrs.adding && imageAttrs.cropInfo && !(0, import_lodash.isEqual)(imageAttrs.cropInfo, this.cachedCropInfo[imageAttrs.id ?? ""])) {
24724
24550
  const actualScale = imageAttrs.uncroppedImage.width / imageAttrs.imageInfo.width;
24551
+ const cropScale = imageAttrs.cropInfo ? imageAttrs.cropInfo.scaleX : actualScale;
24725
24552
  internalImage.width(imageAttrs.uncroppedImage.width);
24726
24553
  internalImage.height(imageAttrs.uncroppedImage.height);
24727
24554
  internalImage.rotation(0);
24728
24555
  internalImage.scaleX(1);
24729
24556
  internalImage.scaleY(1);
24730
24557
  internalImage.crop({
24731
- x: imageAttrs.cropInfo.x / actualScale,
24732
- y: imageAttrs.cropInfo.y / actualScale,
24733
- width: imageAttrs.cropInfo.width / actualScale,
24734
- height: imageAttrs.cropInfo.height / actualScale
24558
+ x: imageAttrs.cropInfo.x / cropScale,
24559
+ y: imageAttrs.cropInfo.y / cropScale,
24560
+ width: imageAttrs.cropInfo.width / cropScale,
24561
+ height: imageAttrs.cropInfo.height / cropScale
24735
24562
  });
24736
- internalImage.width(imageAttrs.cropSize.width);
24737
- internalImage.height(imageAttrs.cropSize.height);
24563
+ internalImage.width(imageAttrs.cropSize.width * (actualScale / cropScale));
24564
+ internalImage.height(imageAttrs.cropSize.height * (actualScale / cropScale));
24738
24565
  this.cachedCropInfo[imageAttrs.id ?? ""] = imageAttrs.cropInfo;
24739
24566
  }
24740
24567
  if (image && internalImage && !imageAttrs.adding && !imageAttrs.cropInfo && !(0, import_lodash.isEqual)(imageAttrs.cropInfo, this.cachedCropInfo[imageAttrs.id ?? ""])) {
@@ -24749,24 +24576,23 @@ var WeaveImageNode = class extends WeaveNode {
24749
24576
  this.cachedCropInfo[imageAttrs.id ?? ""] = void 0;
24750
24577
  }
24751
24578
  }
24752
- getImageToolAction() {
24753
- const imageToolAction = this.instance.getActionHandler(IMAGE_TOOL_ACTION_NAME);
24754
- if (!imageToolAction) throw new Error("Image Tool action not found");
24755
- return imageToolAction;
24579
+ getImageSource(imageId) {
24580
+ return this.imageSource[imageId];
24756
24581
  }
24757
24582
  scaleReset(node) {
24758
24583
  const scale = node.scale();
24584
+ const nodeAttrs = node.getAttrs();
24759
24585
  const widthNotNormalized = node.width();
24760
24586
  const heightNotNormalized = node.height();
24761
- const uncroppedWidth = node.getAttrs().uncroppedImage ? node.getAttrs().uncroppedImage.width : widthNotNormalized;
24762
- 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;
24763
24589
  node.setAttrs({ uncroppedImage: {
24764
24590
  width: uncroppedWidth * node.scaleX(),
24765
24591
  height: uncroppedHeight * node.scaleY()
24766
24592
  } });
24767
- const placeholder = node.findOne(`#${node.getAttrs().id}-placeholder`);
24768
- const internalImage = node.findOne(`#${node.getAttrs().id}-image`);
24769
- 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`);
24770
24596
  if (placeholder) {
24771
24597
  placeholder.width(Math.max(5, placeholder.width() * placeholder.scaleX()));
24772
24598
  placeholder.height(Math.max(5, placeholder.height() * placeholder.scaleY()));
@@ -24797,7 +24623,6 @@ var WeaveImageNode = class extends WeaveNode {
24797
24623
  x: 1,
24798
24624
  y: 1
24799
24625
  });
24800
- this.instance.getMainLayer()?.batchDraw();
24801
24626
  }
24802
24627
  };
24803
24628
 
@@ -26226,25 +26051,530 @@ var WeaveCommentNode = class extends WeaveNode {
26226
26051
  this.openCommentDOM(node);
26227
26052
  }
26228
26053
  });
26229
- 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));
26230
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;
26231
26426
  }
26232
- setCommentViewing(commentId) {
26233
- this.commentDomAction = commentId ? "viewing" : "idle";
26234
- this.commentDomVisible = !!commentId;
26235
- this.commentDomVisibleId = commentId;
26427
+ loadAsyncElement(nodeId) {
26428
+ this.instance.loadAsyncElement(nodeId, "video");
26236
26429
  }
26237
- isCommentViewing() {
26238
- 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
+ }
26239
26494
  }
26240
- isCommentCreating() {
26241
- return this.commentDomAction === WEAVE_COMMENT_NODE_ACTION.CREATING && this.commentDomVisible;
26495
+ areVideosPlaying() {
26496
+ return Object.values(this.videoState).some((state) => state.playing);
26242
26497
  }
26243
- getCommentId(node) {
26244
- return this.config.model.getId(node.getAttrs().commentModel);
26498
+ getVideoSource(videoId) {
26499
+ return this.videoSource[videoId];
26245
26500
  }
26246
- setShowResolved(show) {
26247
- 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
+ });
26248
26578
  }
26249
26579
  };
26250
26580
 
@@ -28042,67 +28372,345 @@ var WeaveTextToolAction = class extends WeaveAction {
28042
28372
  return;
28043
28373
  }
28044
28374
  });
28045
- 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");
28046
28580
  }
28047
- setState(state) {
28048
- this.state = state;
28581
+ isTouchDevice() {
28582
+ return window.matchMedia("(pointer: coarse)").matches;
28049
28583
  }
28050
- addText() {
28051
- const selectionPlugin = this.instance.getPlugin("nodesSelection");
28052
- if (selectionPlugin) {
28053
- const tr = selectionPlugin.getTransformer();
28054
- tr.hide();
28055
- }
28584
+ addImageNode(position) {
28585
+ const stage = this.instance.getStage();
28056
28586
  this.setCursor();
28057
28587
  this.setFocusStage();
28058
- 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
+ }
28059
28626
  this.clickPoint = null;
28060
- this.setState(TEXT_TOOL_STATE.ADDING);
28627
+ this.setState(IMAGE_TOOL_STATE.DEFINING_POSITION);
28061
28628
  }
28062
- handleAdding() {
28063
- const { mousePoint, container } = this.instance.getMousePointer();
28064
- this.clickPoint = mousePoint;
28065
- this.container = container;
28066
- this.textId = v4_default();
28067
- const nodeHandler = this.instance.getNodeHandler("text");
28068
- if (nodeHandler) {
28069
- const node = nodeHandler.create(this.textId, {
28070
- ...this.props,
28071
- x: this.clickPoint?.x ?? 0,
28072
- y: this.clickPoint?.y ?? 0,
28073
- draggable: true
28074
- });
28075
- this.instance.addNode(node, this.container?.getAttrs().id);
28076
- 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);
28077
28674
  }
28078
- this.setState(TEXT_TOOL_STATE.FINISHED);
28079
28675
  this.cancelAction();
28080
28676
  }
28081
- trigger(cancelAction) {
28677
+ trigger(cancelAction, params) {
28082
28678
  if (!this.instance) throw new Error("Instance not defined");
28083
28679
  if (!this.initialized) this.setupEvents();
28084
28680
  this.cancelAction = cancelAction;
28085
28681
  const selectionPlugin = this.instance.getPlugin("nodesSelection");
28086
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
+ }
28087
28689
  this.props = this.initProps();
28088
- this.addText();
28690
+ this.addImage();
28691
+ return { finishUploadCallback: this.loadImage.bind(this) };
28089
28692
  }
28090
28693
  cleanup() {
28091
28694
  const stage = this.instance.getStage();
28092
- stage.container().style.cursor = "default";
28695
+ if (this.tempImageNode) this.tempImageNode.destroy();
28093
28696
  const selectionPlugin = this.instance.getPlugin("nodesSelection");
28094
28697
  if (selectionPlugin) {
28095
- const node$1 = stage.findOne(`#${this.textId}`);
28096
- if (node$1) selectionPlugin.setSelectedNodes([node$1]);
28698
+ const node = stage.findOne(`#${this.imageId}`);
28699
+ if (node) selectionPlugin.setSelectedNodes([node]);
28097
28700
  this.instance.triggerAction(SELECTION_TOOL_ACTION_NAME);
28098
28701
  }
28099
- const node = stage.findOne(`#${this.textId}`);
28100
- if (node) node.getAttr("triggerEditMode")(node);
28702
+ stage.container().style.cursor = "default";
28101
28703
  this.initialCursor = null;
28102
- this.textId = null;
28704
+ this.imageId = null;
28705
+ this.forceMainContainer = false;
28103
28706
  this.container = void 0;
28707
+ this.tempImageNode = null;
28708
+ this.imageURL = null;
28104
28709
  this.clickPoint = null;
28105
- this.setState(TEXT_TOOL_STATE.IDLE);
28710
+ this.setState(IMAGE_TOOL_STATE.IDLE);
28711
+ }
28712
+ getImageNodeHandler() {
28713
+ return this.instance.getNodeHandler("image");
28106
28714
  }
28107
28715
  setCursor() {
28108
28716
  const stage = this.instance.getStage();
@@ -29526,6 +30134,182 @@ var WeaveCommentToolAction = class extends WeaveAction {
29526
30134
  }
29527
30135
  };
29528
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
+
29529
30313
  //#endregion
29530
30314
  //#region src/plugins/stage-grid/stage-grid.ts
29531
30315
  var WeaveStageGridPlugin = class extends WeavePlugin {
@@ -31760,6 +32544,8 @@ exports.STAR_TOOL_STATE = STAR_TOOL_STATE
31760
32544
  exports.TEXT_LAYOUT = TEXT_LAYOUT
31761
32545
  exports.TEXT_TOOL_ACTION_NAME = TEXT_TOOL_ACTION_NAME
31762
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
31763
32549
  exports.WEAVE_ARROW_NODE_TYPE = WEAVE_ARROW_NODE_TYPE
31764
32550
  exports.WEAVE_COMMENTS_RENDERER_KEY = WEAVE_COMMENTS_RENDERER_KEY
31765
32551
  exports.WEAVE_COMMENTS_TOOL_LAYER_ID = WEAVE_COMMENTS_TOOL_LAYER_ID
@@ -31820,6 +32606,8 @@ exports.WEAVE_USERS_POINTERS_KEY = WEAVE_USERS_POINTERS_KEY
31820
32606
  exports.WEAVE_USERS_SELECTION_KEY = WEAVE_USERS_SELECTION_KEY
31821
32607
  exports.WEAVE_USER_POINTER_KEY = WEAVE_USER_POINTER_KEY
31822
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
31823
32611
  exports.Weave = Weave
31824
32612
  exports.WeaveAction = WeaveAction
31825
32613
  exports.WeaveAlignNodesToolAction = WeaveAlignNodesToolAction
@@ -31874,6 +32662,8 @@ exports.WeaveTextNode = WeaveTextNode
31874
32662
  exports.WeaveTextToolAction = WeaveTextToolAction
31875
32663
  exports.WeaveUsersPointersPlugin = WeaveUsersPointersPlugin
31876
32664
  exports.WeaveUsersSelectionPlugin = WeaveUsersSelectionPlugin
32665
+ exports.WeaveVideoNode = WeaveVideoNode
32666
+ exports.WeaveVideoToolAction = WeaveVideoToolAction
31877
32667
  exports.WeaveZoomInToolAction = WeaveZoomInToolAction
31878
32668
  exports.WeaveZoomOutToolAction = WeaveZoomOutToolAction
31879
32669
  exports.clearContainerTargets = clearContainerTargets
@@ -31893,6 +32683,7 @@ exports.intersectArrays = intersectArrays
31893
32683
  exports.isIOS = isIOS
31894
32684
  exports.isInShadowDOM = isInShadowDOM
31895
32685
  exports.isNodeInSelection = isNodeInSelection
32686
+ exports.isServer = isServer
31896
32687
  exports.memoize = memoize
31897
32688
  exports.moveNodeToContainer = moveNodeToContainer
31898
32689
  exports.resetScale = resetScale