From 71d0631a6a91672fbf8b1c5dad97105374ee3ffb Mon Sep 17 00:00:00 2001 From: Ryan Peterson Date: Tue, 18 Aug 2026 14:13:49 -0500 Subject: [PATCH 1/4] Set new widget x based on node x and w and calculated p w. --- src/gridstack.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/gridstack.ts b/src/gridstack.ts index b5c9610b5..be3bdaab1 100644 --- a/src/gridstack.ts +++ b/src/gridstack.ts @@ -3084,8 +3084,14 @@ export class GridStack { // for SE/S/E handles the top-left is anchored — recalculating from pixels causes // rounding drift on fine grids where cellWidth/cellHeight are only a few pixels. #385 #1356 if (event.hasMovedX) { - const left = ui.position!.left + mLeft; - p.x = Math.round(left / cellWidth); + // Set the X based on the node properties. + if (node.x != undefined && p.w != undefined && node.w != undefined) { + p.x = node.x - (p.w - node.w); + } + else { + const left = ui.position!.left + mLeft; + p.x = Math.round(left / cellWidth); + } } if (event.hasMovedY) { const top = ui.position!.top + mTop; From 2bb2a3f289e6d4a8c0905d6306ea134103ef396a Mon Sep 17 00:00:00 2001 From: Ryan Peterson Date: Tue, 18 Aug 2026 15:38:34 -0500 Subject: [PATCH 2/4] Made the same adjustment, just for the north handles. --- src/gridstack.ts | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/gridstack.ts b/src/gridstack.ts index be3bdaab1..2be0dab2f 100644 --- a/src/gridstack.ts +++ b/src/gridstack.ts @@ -3084,7 +3084,7 @@ export class GridStack { // for SE/S/E handles the top-left is anchored — recalculating from pixels causes // rounding drift on fine grids where cellWidth/cellHeight are only a few pixels. #385 #1356 if (event.hasMovedX) { - // Set the X based on the node properties. + // Set the X based on already calculated p width and node properties. if (node.x != undefined && p.w != undefined && node.w != undefined) { p.x = node.x - (p.w - node.w); } @@ -3093,9 +3093,21 @@ export class GridStack { p.x = Math.round(left / cellWidth); } } + console.log({ + nodeY: node.y, + nodeH: node.h, + pY: p.y, + pH: p.h + }) if (event.hasMovedY) { - const top = ui.position!.top + mTop; - p.y = Math.round(top / cellHeight); + // Set the Y based on already calculated p height and node properties. + if (node.y != undefined && p.h != undefined && node.h != undefined) { + p.y = node.y - (p.h - node.h); + } + else { + const top = ui.position!.top + mTop; + p.y = Math.round(top / cellHeight); + } } resizing = true; From 23fa8b25073bd3a0f7bafce461babbe397c557fe Mon Sep 17 00:00:00 2001 From: Ryan Peterson Date: Tue, 18 Aug 2026 16:01:59 -0500 Subject: [PATCH 3/4] Removed excessive logging. Fixed a few linting errors. --- src/dd-draggable.ts | 2 +- src/dd-resizable.ts | 4 ++-- src/gridstack.ts | 12 +++--------- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/src/dd-draggable.ts b/src/dd-draggable.ts index 4e26b941c..214baab13 100644 --- a/src/dd-draggable.ts +++ b/src/dd-draggable.ts @@ -461,7 +461,7 @@ export class DDDraggable extends DDBaseImplement implements HTMLElementExtendOpt /** @internal starts or continues auto-scroll when the dragged helper is clipped by the scroll container. * Takes the grid's own element to find the scroll container so external/sidebar drags work too (#2074). */ - public updateScrollPosition(gridEl: HTMLElement): void { + public updateScrollPosition(gridEl: HTMLElement): void { this._autoScrollContainer = Utils.getScrollElement(gridEl); // always use latest active grid const clipping = this._getClipping(this.helper!, this._autoScrollContainer); if (clipping === 0) { diff --git a/src/dd-resizable.ts b/src/dd-resizable.ts index 3488b6083..e315b5169 100644 --- a/src/dd-resizable.ts +++ b/src/dd-resizable.ts @@ -264,8 +264,8 @@ export class DDResizable extends DDBaseImplement implements HTMLElementExtendOpt const offsetX = event.clientX - oEvent.clientX; const offsetY = this.sizeToContent ? 0 : event.clientY - oEvent.clientY; // prevent vert resize - let moveLeft = false; - let moveUp = false; + let moveLeft = false; + let moveUp = false; const isRtl = this.option.rtl; diff --git a/src/gridstack.ts b/src/gridstack.ts index 2be0dab2f..d821c8fbb 100644 --- a/src/gridstack.ts +++ b/src/gridstack.ts @@ -1997,13 +1997,13 @@ export class GridStack { elStyle.width = n.w! > 1 ? `calc(${n.w} * var(--gs-column-width))` : null; elStyle.height = n.h! > 1 ? `calc(${n.h} * var(--gs-cell-height))` : null; } - + // Always inject variables for print CSS grid mapping (since attr() is not fully supported in calc) el.style.setProperty('--gs-x', String(n.x || 0)); el.style.setProperty('--gs-y', String(n.y || 0)); el.style.setProperty('--gs-w', String(n.w || 1)); el.style.setProperty('--gs-h', String(n.h || 1)); - + // NOTE: those are technically not needed anymore (v12+) as we have CSS vars for everything, but some users depends on them to render item size using CSS // ALways write x,y otherwise it could be autoPositioned incorrectly #3181 el.setAttribute('gs-x', String(n.x ?? 0)); @@ -2059,7 +2059,7 @@ export class GridStack { n.noResize = Utils.toBool(el.getAttribute('gs-no-resize')); n.noMove = Utils.toBool(el.getAttribute('gs-no-move')); n.locked = Utils.toBool(el.getAttribute('gs-locked')); - + let pageBreak = el.getAttribute('gs-page-break'); let hide = el.classList.contains('gs-print-hide'); let orientation = el.getAttribute('gs-print-orientation') as 'portrait' | 'landscape'; @@ -3093,12 +3093,6 @@ export class GridStack { p.x = Math.round(left / cellWidth); } } - console.log({ - nodeY: node.y, - nodeH: node.h, - pY: p.y, - pH: p.h - }) if (event.hasMovedY) { // Set the Y based on already calculated p height and node properties. if (node.y != undefined && p.h != undefined && node.h != undefined) { From 488475427015bb38c09f19bec5be2575cd9955a8 Mon Sep 17 00:00:00 2001 From: Ryan Peterson Date: Tue, 18 Aug 2026 17:21:17 -0500 Subject: [PATCH 4/4] Changed to ensure x and y can't be less than 0. --- src/gridstack.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/gridstack.ts b/src/gridstack.ts index d821c8fbb..69c9cd613 100644 --- a/src/gridstack.ts +++ b/src/gridstack.ts @@ -3086,7 +3086,8 @@ export class GridStack { if (event.hasMovedX) { // Set the X based on already calculated p width and node properties. if (node.x != undefined && p.w != undefined && node.w != undefined) { - p.x = node.x - (p.w - node.w); + const calcPX = node.x - (p.w - node.w); + p.x = calcPX < 0 ? 0 : calcPX; } else { const left = ui.position!.left + mLeft; @@ -3096,7 +3097,8 @@ export class GridStack { if (event.hasMovedY) { // Set the Y based on already calculated p height and node properties. if (node.y != undefined && p.h != undefined && node.h != undefined) { - p.y = node.y - (p.h - node.h); + const calcPY = node.y - (p.h - node.h); + p.y = calcPY < 0 ? 0 : calcPY; } else { const top = ui.position!.top + mTop;