From 02ee83b61a7961d0c730fc8c496db264efb3d1b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesus=20Manuel=20Pi=C3=B1eiro=20Cid?= Date: Fri, 10 Oct 2025 08:12:20 +0200 Subject: [PATCH 1/5] chore: initial commit From 0c39787eec1c8bc277b0898fd7cd64d05dac932e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesus=20Manuel=20Pi=C3=B1eiro=20Cid?= Date: Fri, 10 Oct 2025 08:18:06 +0200 Subject: [PATCH 2/5] fix: avoid moving original node when cloning with click+alt --- code/CHANGELOG.md | 1 + code/packages/sdk/src/nodes/node.ts | 64 +++++++++++++++---- .../nodes-selection/nodes-selection.ts | 12 +++- .../docs/main/changelog/prerelease/0.74.1.mdx | 5 +- .../docs/main/changelog/prerelease/meta.json | 1 + 5 files changed, 65 insertions(+), 18 deletions(-) diff --git a/code/CHANGELOG.md b/code/CHANGELOG.md index 477b19e6a..8b7259cf7 100644 --- a/code/CHANGELOG.md +++ b/code/CHANGELOG.md @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - [#701](https://github.com/InditexTech/weavejs/issues/701) Fix Video node TS types issues and rotation +- [#705](https://github.com/InditexTech/weavejs/issues/705) When ctrl + alt and drag, original node is moved a delta, but when reload its OK ## [0.74.0] - 2025-10-09 diff --git a/code/packages/sdk/src/nodes/node.ts b/code/packages/sdk/src/nodes/node.ts index e3f412ef5..fb88c53c1 100644 --- a/code/packages/sdk/src/nodes/node.ts +++ b/code/packages/sdk/src/nodes/node.ts @@ -283,7 +283,18 @@ export abstract class WeaveNode implements WeaveNodeBase { } }); - let clone: Konva.Node | undefined = undefined; + const stage = this.instance.getStage(); + + let originalPosition: Vector2d | null = null; + + node.on('mousedown', (e) => { + const nodeTarget = e.target; + originalPosition = nodeTarget.getAbsolutePosition(); + }); + + node.on('mouseup', () => { + originalPosition = null; + }); node.on('dragstart', (e) => { const nodeTarget = e.target; @@ -295,8 +306,6 @@ export abstract class WeaveNode implements WeaveNodeBase { return; } - const stage = this.instance.getStage(); - const isErasing = this.instance.getActiveAction() === 'eraseTool'; if (isErasing) { @@ -318,13 +327,18 @@ export abstract class WeaveNode implements WeaveNodeBase { } if (e.evt?.altKey) { + nodeTarget.setAttrs({ isCloneOrigin: true }); + nodeTarget.setAttrs({ isCloned: false }); nodeTarget.stopDrag(e.evt); e.cancelBubble = true; - clone = this.instance.getCloningManager().cloneNode(realNodeTarget); + const clone = this.instance + .getCloningManager() + .cloneNode(realNodeTarget); if (clone && !this.instance.getCloningManager().isClone(clone)) { + clone.setAttrs({ isCloneOrigin: false }); clone.setAttrs({ isCloned: true }); this.instance.getCloningManager().addClone(clone); } @@ -334,12 +348,22 @@ export abstract class WeaveNode implements WeaveNodeBase { const nodesSelectionPlugin = this.getNodesSelectionPlugin(); nodesSelectionPlugin?.setSelectedNodes([]); - setTimeout(() => { + if (originalPosition) { + nodeTarget.setAbsolutePosition(originalPosition); + originalPosition = null; + } + + requestAnimationFrame(() => { + if (originalPosition) { + nodeTarget.setAbsolutePosition(originalPosition); + originalPosition = null; + } + nodesSelectionPlugin?.setSelectedNodes( this.instance.getCloningManager().getClones() ); clone?.startDrag(e.evt); - }, 0); + }); } }); @@ -372,9 +396,12 @@ export abstract class WeaveNode implements WeaveNodeBase { const realNodeTarget: Konva.Node = this.getRealSelectedNode(nodeTarget); + if (nodeTarget.getAttrs().isCloneOrigin && originalPosition) { + nodeTarget.setAbsolutePosition(originalPosition); + } + if ( this.isSelecting() && - // this.isNodeSelected(node) && this.getSelectionPlugin()?.getSelectedNodes().length === 1 ) { clearContainerTargets(this.instance); @@ -402,10 +429,17 @@ export abstract class WeaveNode implements WeaveNodeBase { e.cancelBubble = true; - if (clone) { - clone = undefined; + if (nodeTarget.getAttrs().isCloneOrigin && originalPosition) { + nodeTarget.setAbsolutePosition(originalPosition); } + if (nodeTarget.getAttrs().isCloneOrigin) { + nodeTarget.setAttrs({ isCloned: undefined }); + nodeTarget.setAttrs({ isCloneOrigin: undefined }); + } + + originalPosition = null; + if (!this.didMove) { return; } @@ -421,6 +455,12 @@ export abstract class WeaveNode implements WeaveNodeBase { const realNodeTarget: Konva.Node = this.getRealSelectedNode(nodeTarget); + if (nodeTarget.getAttrs().isCloneOrigin) { + nodeTarget.setAttrs({ isCloned: undefined }); + nodeTarget.setAttrs({ isCloneOrigin: undefined }); + return; + } + if ( this.isSelecting() && this.getSelectionPlugin()?.getSelectedNodes().length === 1 @@ -452,11 +492,7 @@ export abstract class WeaveNode implements WeaveNodeBase { } let moved = false; - if ( - containerToMove && - !hasFrames(node) && - !realNodeTarget.getAttrs().isCloned - ) { + if (containerToMove && !hasFrames(node)) { moved = moveNodeToContainer( this.instance, realNodeTarget, diff --git a/code/packages/sdk/src/plugins/nodes-selection/nodes-selection.ts b/code/packages/sdk/src/plugins/nodes-selection/nodes-selection.ts index c4d73fa64..6ef2be15f 100644 --- a/code/packages/sdk/src/plugins/nodes-selection/nodes-selection.ts +++ b/code/packages/sdk/src/plugins/nodes-selection/nodes-selection.ts @@ -292,8 +292,18 @@ export class WeaveNodesSelectionPlugin extends WeavePlugin { this.triggerSelectedNodesEvent(); }); + const nodesOriginalPositions: Record = {}; let initialPos: Vector2d | null = null; + tr.on('mousemove', () => { + const selectedNodes = tr.nodes(); + for (let i = 0; i < selectedNodes.length; i++) { + const node = selectedNodes[i]; + nodesOriginalPositions[node.getAttrs().id ?? ''] = node.position(); + node.updatePosition(node.getAbsolutePosition()); + } + }); + tr.on('dragstart', (e) => { initialPos = { x: e.target.x(), y: e.target.y() }; @@ -317,8 +327,6 @@ export class WeaveNodesSelectionPlugin extends WeavePlugin { if (e.evt?.altKey) { tr.stopDrag(e.evt); - - e.cancelBubble = true; } tr.forceUpdate(); diff --git a/docs/content/docs/main/changelog/prerelease/0.74.1.mdx b/docs/content/docs/main/changelog/prerelease/0.74.1.mdx index 824d1520a..5722e8f3a 100644 --- a/docs/content/docs/main/changelog/prerelease/0.74.1.mdx +++ b/docs/content/docs/main/changelog/prerelease/0.74.1.mdx @@ -1,12 +1,13 @@ --- title: v0.74.1 -description: Minor bugfixed +description: Minor bugfixes --- ## Metadata -- **Release date**: 2025-10-09 +- **Release date**: 2025-10-10 ### Fixed - [#701](https://github.com/InditexTech/weavejs/issues/701) Fix Video node TS types issues and rotation +- [#705](https://github.com/InditexTech/weavejs/issues/705) When ctrl + alt and drag, original node is moved a delta, but when reload its OK diff --git a/docs/content/docs/main/changelog/prerelease/meta.json b/docs/content/docs/main/changelog/prerelease/meta.json index bc64b9990..bd98d8ffb 100644 --- a/docs/content/docs/main/changelog/prerelease/meta.json +++ b/docs/content/docs/main/changelog/prerelease/meta.json @@ -2,6 +2,7 @@ "title": "Prerelease versions", "description": "Detailed changelog for Weave.js pre-release versions", "pages": [ + "0.74.1", "0.74.0", "0.73.1", "0.73.0", From bfa2bf9176b318652d6f8ed827956ebb8f3da54f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesus=20Manuel=20Pi=C3=B1eiro=20Cid?= Date: Fri, 10 Oct 2025 09:40:42 +0200 Subject: [PATCH 3/5] fix: more polished click + alt drag cloning --- code/packages/sdk/src/nodes/node.ts | 57 +++++++++---------- .../nodes-selection/nodes-selection.ts | 23 +------- 2 files changed, 28 insertions(+), 52 deletions(-) diff --git a/code/packages/sdk/src/nodes/node.ts b/code/packages/sdk/src/nodes/node.ts index fb88c53c1..0a6d17fb8 100644 --- a/code/packages/sdk/src/nodes/node.ts +++ b/code/packages/sdk/src/nodes/node.ts @@ -287,15 +287,24 @@ export abstract class WeaveNode implements WeaveNodeBase { let originalPosition: Vector2d | null = null; + this.instance.addEventListener('onSelectionState', (state) => { + const nodesSelectionPlugin = this.getSelectionPlugin(); + const selectedNodes = nodesSelectionPlugin?.getSelectedNodes() ?? []; + + if ( + !state && + selectedNodes && + selectedNodes.some((n) => n.getAttrs().id === node.getAttrs().id) + ) { + originalPosition = node.getAbsolutePosition(); + } + }); + node.on('mousedown', (e) => { const nodeTarget = e.target; originalPosition = nodeTarget.getAbsolutePosition(); }); - node.on('mouseup', () => { - originalPosition = null; - }); - node.on('dragstart', (e) => { const nodeTarget = e.target; @@ -348,17 +357,7 @@ export abstract class WeaveNode implements WeaveNodeBase { const nodesSelectionPlugin = this.getNodesSelectionPlugin(); nodesSelectionPlugin?.setSelectedNodes([]); - if (originalPosition) { - nodeTarget.setAbsolutePosition(originalPosition); - originalPosition = null; - } - requestAnimationFrame(() => { - if (originalPosition) { - nodeTarget.setAbsolutePosition(originalPosition); - originalPosition = null; - } - nodesSelectionPlugin?.setSelectedNodes( this.instance.getCloningManager().getClones() ); @@ -396,9 +395,9 @@ export abstract class WeaveNode implements WeaveNodeBase { const realNodeTarget: Konva.Node = this.getRealSelectedNode(nodeTarget); - if (nodeTarget.getAttrs().isCloneOrigin && originalPosition) { - nodeTarget.setAbsolutePosition(originalPosition); - } + // if (nodeTarget.getAttrs().isCloneOrigin && originalPosition) { + // nodeTarget.setAbsolutePosition(originalPosition); + // } if ( this.isSelecting() && @@ -431,15 +430,12 @@ export abstract class WeaveNode implements WeaveNodeBase { if (nodeTarget.getAttrs().isCloneOrigin && originalPosition) { nodeTarget.setAbsolutePosition(originalPosition); - } - - if (nodeTarget.getAttrs().isCloneOrigin) { - nodeTarget.setAttrs({ isCloned: undefined }); nodeTarget.setAttrs({ isCloneOrigin: undefined }); + nodeTarget.setAttrs({ isCloned: undefined }); + originalPosition = null; + return; } - originalPosition = null; - if (!this.didMove) { return; } @@ -455,12 +451,6 @@ export abstract class WeaveNode implements WeaveNodeBase { const realNodeTarget: Konva.Node = this.getRealSelectedNode(nodeTarget); - if (nodeTarget.getAttrs().isCloneOrigin) { - nodeTarget.setAttrs({ isCloned: undefined }); - nodeTarget.setAttrs({ isCloneOrigin: undefined }); - return; - } - if ( this.isSelecting() && this.getSelectionPlugin()?.getSelectedNodes().length === 1 @@ -502,10 +492,9 @@ export abstract class WeaveNode implements WeaveNodeBase { if (realNodeTarget.getAttrs().isCloned) { this.instance.getCloningManager().removeClone(realNodeTarget); + originalPosition = realNodeTarget.getAbsolutePosition(); } - realNodeTarget?.setAttrs({ isCloned: undefined }); - if (containerToMove) { containerToMove.fire(WEAVE_NODE_CUSTOM_EVENTS.onTargetLeave, { bubbles: true, @@ -518,6 +507,12 @@ export abstract class WeaveNode implements WeaveNodeBase { ); } } + + nodeTarget.setAttrs({ isCloned: undefined }); + nodeTarget.setAttrs({ isCloneOrigin: undefined }); + realNodeTarget.setAttrs({ isCloned: undefined }); + realNodeTarget.setAttrs({ isCloneOrigin: undefined }); + originalPosition = realNodeTarget.getAbsolutePosition(); }); node.handleMouseover = () => { diff --git a/code/packages/sdk/src/plugins/nodes-selection/nodes-selection.ts b/code/packages/sdk/src/plugins/nodes-selection/nodes-selection.ts index 6ef2be15f..9f06538b7 100644 --- a/code/packages/sdk/src/plugins/nodes-selection/nodes-selection.ts +++ b/code/packages/sdk/src/plugins/nodes-selection/nodes-selection.ts @@ -292,18 +292,8 @@ export class WeaveNodesSelectionPlugin extends WeavePlugin { this.triggerSelectedNodesEvent(); }); - const nodesOriginalPositions: Record = {}; let initialPos: Vector2d | null = null; - tr.on('mousemove', () => { - const selectedNodes = tr.nodes(); - for (let i = 0; i < selectedNodes.length; i++) { - const node = selectedNodes[i]; - nodesOriginalPositions[node.getAttrs().id ?? ''] = node.position(); - node.updatePosition(node.getAbsolutePosition()); - } - }); - tr.on('dragstart', (e) => { initialPos = { x: e.target.x(), y: e.target.y() }; @@ -319,16 +309,6 @@ export class WeaveNodesSelectionPlugin extends WeavePlugin { e.cancelBubble = true; - const selectedNodes = tr.nodes(); - for (let i = 0; i < selectedNodes.length; i++) { - const node = selectedNodes[i]; - node.updatePosition(node.getAbsolutePosition()); - } - - if (e.evt?.altKey) { - tr.stopDrag(e.evt); - } - tr.forceUpdate(); }); @@ -398,7 +378,6 @@ export class WeaveNodesSelectionPlugin extends WeavePlugin { const node = selectedNodes[i]; selectionContainsFrames = selectionContainsFrames || hasFrames(node); node.updatePosition(node.getAbsolutePosition()); - node.setAttrs({ isCloned: undefined }); } if (this.isSelecting() && tr.nodes().length > 1) { @@ -472,6 +451,8 @@ export class WeaveNodesSelectionPlugin extends WeavePlugin { selectedNodes[i].getAttrs().nodeType ); + selectedNodes[i].setAttrs({ isCloned: undefined }); + if (nodeHandler) { this.instance.updateNode( nodeHandler.serialize(selectedNodes[i] as WeaveElementInstance) From 330271bebbb1aeab2809a7086754ac19583b2b75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesus=20Manuel=20Pi=C3=B1eiro=20Cid?= Date: Fri, 10 Oct 2025 10:04:36 +0200 Subject: [PATCH 4/5] fix: image and video on drag over a container (frame) now on right position --- .../sdk/src/actions/image-tool/image-tool.ts | 17 +++++---------- .../sdk/src/actions/image-tool/types.ts | 5 ++++- .../sdk/src/actions/video-tool/video-tool.ts | 4 +++- code/packages/sdk/src/utils.ts | 21 +++++++++++++++++++ 4 files changed, 33 insertions(+), 14 deletions(-) diff --git a/code/packages/sdk/src/actions/image-tool/image-tool.ts b/code/packages/sdk/src/actions/image-tool/image-tool.ts index 054ff6fdc..be71026e5 100644 --- a/code/packages/sdk/src/actions/image-tool/image-tool.ts +++ b/code/packages/sdk/src/actions/image-tool/image-tool.ts @@ -6,7 +6,6 @@ import { v4 as uuidv4 } from 'uuid'; import { WeaveAction } from '@/actions/action'; import { type Vector2d } from 'konva/lib/types'; import { - type ImageOptions, type WeaveImageToolActionTriggerParams, type WeaveImageToolActionState, type WeaveImageToolActionTriggerReturn, @@ -20,6 +19,7 @@ import { WeaveNodesSelectionPlugin } from '@/plugins/nodes-selection/nodes-selec import Konva from 'konva'; import type { WeaveImageNode } from '@/nodes/image/image'; import { SELECTION_TOOL_ACTION_NAME } from '../selection-tool/constants'; +import { getPositionRelativeToContainerOnPosition } from '@/utils'; export class WeaveImageToolAction extends WeaveAction { protected initialized: boolean = false; @@ -69,7 +69,8 @@ export class WeaveImageToolAction extends WeaveAction { this.instance.addEventListener('onStageDrop', (e) => { if (window.weaveDragImageURL) { this.instance.getStage().setPointersPositions(e); - const position = this.instance.getStage().getRelativePointerPosition(); + const position: Vector2d | null | undefined = + getPositionRelativeToContainerOnPosition(this.instance); this.instance.triggerAction(IMAGE_TOOL_ACTION_NAME, { imageURL: window.weaveDragImageURL, @@ -164,11 +165,7 @@ export class WeaveImageToolAction extends WeaveAction { this.state = state; } - private loadImage( - imageURL: string, - options?: ImageOptions, - position?: Vector2d - ) { + private loadImage(imageURL: string, position?: Vector2d) { this.setCursor(); this.setFocusStage(); @@ -380,11 +377,7 @@ export class WeaveImageToolAction extends WeaveAction { } if (params?.imageURL) { - this.loadImage( - params.imageURL, - params?.options ?? undefined, - params?.position ?? undefined - ); + this.loadImage(params.imageURL, params?.position ?? undefined); return; } diff --git a/code/packages/sdk/src/actions/image-tool/types.ts b/code/packages/sdk/src/actions/image-tool/types.ts index 152d614b8..30cfa6c39 100644 --- a/code/packages/sdk/src/actions/image-tool/types.ts +++ b/code/packages/sdk/src/actions/image-tool/types.ts @@ -32,6 +32,9 @@ export type ImageOptions = { export type WeaveImageToolActionTriggerReturn = | { - finishUploadCallback: (imageURL: string, options?: ImageOptions) => void; + finishUploadCallback: ( + imageURL: string, + position?: Vector2d | undefined + ) => void; } | undefined; diff --git a/code/packages/sdk/src/actions/video-tool/video-tool.ts b/code/packages/sdk/src/actions/video-tool/video-tool.ts index 8454c0b0b..daacab1c7 100644 --- a/code/packages/sdk/src/actions/video-tool/video-tool.ts +++ b/code/packages/sdk/src/actions/video-tool/video-tool.ts @@ -18,6 +18,7 @@ import { WeaveNodesSelectionPlugin } from '@/plugins/nodes-selection/nodes-selec import Konva from 'konva'; import { SELECTION_TOOL_ACTION_NAME } from '../selection-tool/constants'; import type { WeaveVideoNode } from '@/nodes/video/video'; +import { getPositionRelativeToContainerOnPosition } from '@/utils'; export class WeaveVideoToolAction extends WeaveAction { protected initialized: boolean = false; @@ -73,7 +74,8 @@ export class WeaveVideoToolAction extends WeaveAction { this.instance.addEventListener('onStageDrop', (e) => { if (window.weaveDragVideoId && window.weaveDragVideoParams) { this.instance.getStage().setPointersPositions(e); - const position = this.instance.getStage().getRelativePointerPosition(); + const position: Vector2d | null | undefined = + getPositionRelativeToContainerOnPosition(this.instance); this.instance.triggerAction(VIDEO_TOOL_ACTION_NAME, { videoId: window.weaveDragVideoId, diff --git a/code/packages/sdk/src/utils.ts b/code/packages/sdk/src/utils.ts index c85fcde39..600bbf7a6 100644 --- a/code/packages/sdk/src/utils.ts +++ b/code/packages/sdk/src/utils.ts @@ -568,3 +568,24 @@ export function isIOS() { } export const isServer = () => typeof window === 'undefined'; + +export const getPositionRelativeToContainerOnPosition = ( + instance: Weave +): Vector2d | null | undefined => { + let position: Vector2d | null | undefined = instance + .getStage() + .getRelativePointerPosition(); + + if (!position) { + return position; + } + + const container = containerOverCursor(instance, [], position); + position = container?.getRelativePointerPosition(); + + if (!position) { + return position; + } + + return position; +}; From 4d5d7505151974fabcfb6046e6a590d02bc6ff09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesus=20Manuel=20Pi=C3=B1eiro=20Cid?= Date: Fri, 10 Oct 2025 10:07:20 +0200 Subject: [PATCH 5/5] chore: sonar qube issues fixing --- code/packages/sdk/src/nodes/node.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/code/packages/sdk/src/nodes/node.ts b/code/packages/sdk/src/nodes/node.ts index 0a6d17fb8..b0673db06 100644 --- a/code/packages/sdk/src/nodes/node.ts +++ b/code/packages/sdk/src/nodes/node.ts @@ -293,8 +293,7 @@ export abstract class WeaveNode implements WeaveNodeBase { if ( !state && - selectedNodes && - selectedNodes.some((n) => n.getAttrs().id === node.getAttrs().id) + selectedNodes?.some((n) => n.getAttrs().id === node.getAttrs().id) ) { originalPosition = node.getAbsolutePosition(); } @@ -395,10 +394,6 @@ export abstract class WeaveNode implements WeaveNodeBase { const realNodeTarget: Konva.Node = this.getRealSelectedNode(nodeTarget); - // if (nodeTarget.getAttrs().isCloneOrigin && originalPosition) { - // nodeTarget.setAbsolutePosition(originalPosition); - // } - if ( this.isSelecting() && this.getSelectionPlugin()?.getSelectedNodes().length === 1