Skip to content

Commit 553a2b6

Browse files
committed
fix: improve Vue nodes mode canvas layout and drawing compatibility
- Add prepareVueCompatCanvasDraw to handle canvas resizing, pixel ratio, and height scheduling before widget draw in Vue compat mode - Track and restore additional layout state in updateVueCompatCanvasLayout/ teardownVueCompatCanvasLayout, including body position, canvas host minHeight, badge visibility, and full slots positioning - Switch slots to absolute positioning instead of negative margin to prevent layout overlap issues in Vue nodes mode - Hide badge element during canvas draw to avoid visual conflicts
1 parent 188ba43 commit 553a2b6

1 file changed

Lines changed: 86 additions & 3 deletions

File tree

js/node/resolution_master_node_lifecycle.js

Lines changed: 86 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,47 @@ export const nodeLifecycleMethods = {
122122
widget.triggerDraw?.();
123123
},
124124

125+
prepareVueCompatCanvasDraw(ctx, width, height, widget) {
126+
if (!this.isVueNodesMode() || !this.collapsedSections?.extraControls) {
127+
return { ctx, height };
128+
}
129+
130+
const canvasElement = ctx?.canvas;
131+
const canvasHost = canvasElement?.parentElement;
132+
if (!canvasElement || !canvasHost) return { ctx, height };
133+
134+
const releaseHostMinimum = () => {
135+
if (canvasHost.isConnected !== false) {
136+
canvasHost.style.minHeight = "0px";
137+
}
138+
};
139+
releaseHostMinimum();
140+
if (typeof queueMicrotask === "function") {
141+
queueMicrotask(releaseHostMinimum);
142+
}
143+
144+
const minimumHeight = this.getVueCompatWidgetHeight();
145+
const hostHeight = Math.floor(Number(canvasHost.clientHeight) || 0);
146+
const targetHeight = Math.max(minimumHeight, hostHeight);
147+
const currentHeight = Number(height) || minimumHeight;
148+
if (!Number.isFinite(targetHeight) || Math.abs(targetHeight - currentHeight) <= 1) {
149+
return { ctx, height: currentHeight };
150+
}
151+
152+
widget.computedHeight = targetHeight;
153+
const pixelRatio = Math.max(
154+
1,
155+
Number(canvasElement.width) / Math.max(1, Number(width) || canvasElement.clientWidth || 1)
156+
);
157+
canvasElement.height = Math.max(1, Math.ceil((targetHeight + 2) * pixelRatio));
158+
const resizedContext = canvasElement.getContext?.("2d");
159+
if (!resizedContext) return { ctx, height: currentHeight };
160+
161+
resizedContext.scale(pixelRatio, pixelRatio);
162+
this.scheduleVueCompatHeightRedraw();
163+
return { ctx: resizedContext, height: targetHeight };
164+
},
165+
125166
normalizeVueCompatPointerEvent(e, pos = null) {
126167
if (!e || !this.isVueNodesMode()) return e;
127168

@@ -150,30 +191,56 @@ export const nodeLifecycleMethods = {
150191
updateVueCompatCanvasLayout(canvasElement) {
151192
const widgetsGrid = canvasElement?.closest?.('[data-testid="node-widgets"]');
152193
const slotsElement = widgetsGrid?.previousElementSibling;
153-
if (!widgetsGrid || !slotsElement) return;
194+
const bodyElement = widgetsGrid?.parentElement;
195+
if (!widgetsGrid || !slotsElement || !bodyElement) return;
154196

155197
if (this._vueCompatLayout?.widgetsGrid !== widgetsGrid) {
156198
this.teardownVueCompatCanvasLayout();
199+
const canvasHost = canvasElement.parentElement;
200+
const badgeElement = Array.from(bodyElement.children).find(element =>
201+
element !== slotsElement
202+
&& element !== widgetsGrid
203+
&& element.classList?.contains('h-5')
204+
&& element.classList?.contains('text-muted-foreground')
205+
) || null;
157206
this._vueCompatLayout = {
207+
bodyElement,
158208
widgetsGrid,
159209
slotsElement,
210+
canvasHost,
211+
badgeElement,
212+
bodyPosition: bodyElement.style.position,
213+
canvasHostMinHeight: canvasHost?.style.minHeight ?? '',
160214
gridMarginTop: widgetsGrid.style.marginTop,
161215
gridPosition: widgetsGrid.style.position,
162216
gridZIndex: widgetsGrid.style.zIndex,
163217
slotsPosition: slotsElement.style.position,
218+
slotsTop: slotsElement.style.top,
219+
slotsLeft: slotsElement.style.left,
220+
slotsRight: slotsElement.style.right,
221+
slotsWidth: slotsElement.style.width,
164222
slotsZIndex: slotsElement.style.zIndex,
165223
slotsPointerEvents: slotsElement.style.pointerEvents,
224+
badgeDisplay: badgeElement?.style.display ?? '',
166225
slotDotPointerEvents: new Map()
167226
};
168227
}
169228

170229
const slotHeight = Math.max(0, Number(slotsElement.offsetHeight) || 0);
171-
widgetsGrid.style.marginTop = slotHeight > 0 ? `-${slotHeight}px` : "";
230+
bodyElement.style.position = "relative";
231+
widgetsGrid.style.marginTop = "";
172232
widgetsGrid.style.position = "relative";
173233
widgetsGrid.style.zIndex = "1";
174-
slotsElement.style.position = "relative";
234+
slotsElement.style.position = "absolute";
235+
slotsElement.style.top = "0";
236+
slotsElement.style.left = "0";
237+
slotsElement.style.right = "0";
238+
slotsElement.style.width = "100%";
175239
slotsElement.style.zIndex = "2";
176240
slotsElement.style.pointerEvents = "none";
241+
if (this._vueCompatLayout.badgeElement) {
242+
this._vueCompatLayout.badgeElement.style.display = "none";
243+
}
177244
for (const slotDot of slotsElement.querySelectorAll?.('[data-testid="slot-connection-dot"]') || []) {
178245
if (!this._vueCompatLayout.slotDotPointerEvents.has(slotDot)) {
179246
this._vueCompatLayout.slotDotPointerEvents.set(slotDot, slotDot.style.pointerEvents);
@@ -311,12 +378,25 @@ export const nodeLifecycleMethods = {
311378
teardownVueCompatCanvasLayout() {
312379
const layout = this._vueCompatLayout;
313380
if (layout) {
381+
if (layout.bodyElement) {
382+
layout.bodyElement.style.position = layout.bodyPosition ?? "";
383+
}
384+
if (layout.canvasHost) {
385+
layout.canvasHost.style.minHeight = layout.canvasHostMinHeight ?? "";
386+
}
314387
layout.widgetsGrid.style.marginTop = layout.gridMarginTop;
315388
layout.widgetsGrid.style.position = layout.gridPosition;
316389
layout.widgetsGrid.style.zIndex = layout.gridZIndex;
317390
layout.slotsElement.style.position = layout.slotsPosition;
391+
layout.slotsElement.style.top = layout.slotsTop ?? "";
392+
layout.slotsElement.style.left = layout.slotsLeft ?? "";
393+
layout.slotsElement.style.right = layout.slotsRight ?? "";
394+
layout.slotsElement.style.width = layout.slotsWidth ?? "";
318395
layout.slotsElement.style.zIndex = layout.slotsZIndex;
319396
layout.slotsElement.style.pointerEvents = layout.slotsPointerEvents;
397+
if (layout.badgeElement) {
398+
layout.badgeElement.style.display = layout.badgeDisplay;
399+
}
320400
for (const [slotDot, pointerEvents] of layout.slotDotPointerEvents) {
321401
slotDot.style.pointerEvents = pointerEvents;
322402
}
@@ -400,6 +480,9 @@ export const nodeLifecycleMethods = {
400480
self._vueCompatWidgetWidth = width;
401481
self.bindVueCompatCanvasEvents(ctx.canvas);
402482
self.updateVueCompatCanvasLayout(ctx.canvas);
483+
const preparedDraw = self.prepareVueCompatCanvasDraw(ctx, width, height, widget);
484+
ctx = preparedDraw.ctx;
485+
height = preparedDraw.height;
403486
const minimumHeight = self.getVueCompatWidgetHeight();
404487
const renderedCanvasHeight = Number(height)
405488
|| Number(widget.computedHeight)

0 commit comments

Comments
 (0)