Skip to content

Commit 0a255ab

Browse files
fix: Prevent edit modal opening on grid block resize and re-render after layout change
Two fixes for block grid resize interactions: 1. Drag detection: Track pointerdown position on the preview <a> tag and compare with click position. If the pointer moved >5px or no pointerdown was recorded (resize drag ended over the element), suppress navigation. Keyboard activation is unaffected. 2. Re-render on resize: Detect columnSpan/rowSpan changes in the entry context observer and trigger a debounced (300ms) re-render with updated layout data, so the server-rendered preview reflects the new dimensions. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent df4cc6d commit 0a255ab

4 files changed

Lines changed: 475 additions & 402 deletions

File tree

src/Umbraco.Community.BlockPreview.UI/src/blockEditor/block-grid-preview.custom-view.element.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,9 @@ export class BlockGridPreviewCustomView extends BlockPreviewBaseElement<BlockGri
101101
layout,
102102
layoutAreas
103103
]) => {
104+
const prevColumnSpan = this._blockContext.layout?.columnSpan;
105+
const prevRowSpan = this._blockContext.layout?.rowSpan;
106+
104107
this._blockContext.contentUdi = contentUdi ?? '';
105108
this._blockContext.settingsUdi = settingsUdi ?? '';
106109
this._blockContext.workspaceEditContentPath = workspaceEditContentPath ?? '';
@@ -114,13 +117,29 @@ export class BlockGridPreviewCustomView extends BlockPreviewBaseElement<BlockGri
114117
this.#managerObserved = true;
115118
await this.#observeBlockPropertyValue();
116119
}
120+
121+
// Re-render when layout dimensions change (resize)
122+
if (this._htmlMarkup && layout && (
123+
layout.columnSpan !== prevColumnSpan ||
124+
layout.rowSpan !== prevRowSpan
125+
)) {
126+
this.blockGridValue = {
127+
...this._blockGridValue,
128+
layout: { ['Umbraco.BlockGrid']: this.#filterLayouts() }
129+
};
130+
clearTimeout(this.#layoutResizeTimer);
131+
this.#layoutResizeTimer = setTimeout(() => {
132+
this.renderBlockPreview();
133+
}, 300);
134+
}
117135
}
118136
);
119137
}
120138
});
121139
}
122140

123141
#managerObserved = false;
142+
#layoutResizeTimer?: ReturnType<typeof setTimeout>;
124143

125144
async #observeBlockPropertyValue() {
126145
this.consumeContext(UMB_BLOCK_GRID_MANAGER_CONTEXT, (context) => {

src/Umbraco.Community.BlockPreview.UI/src/blockEditor/block-preview-base.element.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ export abstract class BlockPreviewBaseElement<TContext extends BlockContext = Bl
5858

5959
protected _isConnected: boolean = false;
6060

61+
/** Tracks pointerdown position on the <a> tag to distinguish clicks from drags. */
62+
private _pointerStartPos: { x: number; y: number } | null = null;
63+
6164
/** Subclass provides a concrete block context object with block-type-specific fields. */
6265
protected abstract _blockContext: TContext;
6366

@@ -258,7 +261,34 @@ export abstract class BlockPreviewBaseElement<TContext extends BlockContext = Bl
258261
return match ? match[1] : '';
259262
}
260263

264+
protected _handlePointerDown(event: PointerEvent) {
265+
this._pointerStartPos = { x: event.clientX, y: event.clientY };
266+
}
267+
261268
protected _handleClick(event: PointerEvent) {
269+
// Detect drag/resize interactions: if the pointer moved significantly between
270+
// pointerdown and click, suppress the navigation. This prevents the edit modal
271+
// from opening when the user finishes resizing a grid block.
272+
const pointerType = 'pointerType' in event ? (event as PointerEvent).pointerType : '';
273+
if (pointerType !== '') {
274+
if (!this._pointerStartPos) {
275+
// Pointer click with no corresponding pointerdown on this element —
276+
// likely a resize/drag that ended over our <a> tag.
277+
event.preventDefault();
278+
event.stopPropagation();
279+
return;
280+
}
281+
const dx = Math.abs(event.clientX - this._pointerStartPos.x);
282+
const dy = Math.abs(event.clientY - this._pointerStartPos.y);
283+
this._pointerStartPos = null;
284+
if (dx > 5 || dy > 5) {
285+
event.preventDefault();
286+
event.stopPropagation();
287+
return;
288+
}
289+
}
290+
this._pointerStartPos = null;
291+
262292
const path = event.composedPath();
263293

264294
// Check for clicks on action bars or resize handlers.
@@ -309,6 +339,7 @@ export abstract class BlockPreviewBaseElement<TContext extends BlockContext = Bl
309339
: this._htmlMarkup
310340
? html`<a
311341
href=${ifDefined(this._blockContext.workspaceEditContentPath)}
342+
@pointerdown=${this._handlePointerDown}
312343
@click=${this._handleClick}
313344
aria-label=${this.localize.term('blockPreview_editBlock')}
314345
class="block-preview-edit"

0 commit comments

Comments
 (0)