diff --git a/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-dragging-link-chromium-linux.png b/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-dragging-link-chromium-linux.png index df8f56cb42..e9a11910a2 100644 Binary files a/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-dragging-link-chromium-linux.png and b/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-dragging-link-chromium-linux.png differ diff --git a/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-input-drag-ctrl-alt-chromium-linux.png b/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-input-drag-ctrl-alt-chromium-linux.png index ebfe67a8de..66b808e342 100644 Binary files a/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-input-drag-ctrl-alt-chromium-linux.png and b/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-input-drag-ctrl-alt-chromium-linux.png differ diff --git a/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-input-drag-reuses-origin-chromium-linux.png b/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-input-drag-reuses-origin-chromium-linux.png index cbbb023308..5fa283cee0 100644 Binary files a/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-input-drag-reuses-origin-chromium-linux.png and b/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-input-drag-reuses-origin-chromium-linux.png differ diff --git a/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-reroute-input-drag-chromium-linux.png b/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-reroute-input-drag-chromium-linux.png index 38d93e7178..5c08aded80 100644 Binary files a/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-reroute-input-drag-chromium-linux.png and b/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-reroute-input-drag-chromium-linux.png differ diff --git a/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-reroute-output-shift-drag-chromium-linux.png b/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-reroute-output-shift-drag-chromium-linux.png index 9740334b8e..76946cbc04 100644 Binary files a/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-reroute-output-shift-drag-chromium-linux.png and b/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-reroute-output-shift-drag-chromium-linux.png differ diff --git a/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-shift-output-multi-link-chromium-linux.png b/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-shift-output-multi-link-chromium-linux.png index 5df3a9f421..6a39534a22 100644 Binary files a/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-shift-output-multi-link-chromium-linux.png and b/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-shift-output-multi-link-chromium-linux.png differ diff --git a/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-snap-to-node-chromium-linux.png b/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-snap-to-node-chromium-linux.png index c8d2db1f44..0b51591e7c 100644 Binary files a/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-snap-to-node-chromium-linux.png and b/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-snap-to-node-chromium-linux.png differ diff --git a/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-snap-to-slot-chromium-linux.png b/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-snap-to-slot-chromium-linux.png index ead82b036d..a12651973e 100644 Binary files a/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-snap-to-slot-chromium-linux.png and b/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-snap-to-slot-chromium-linux.png differ diff --git a/browser_tests/tests/vueNodes/widgets/load/uploadWidgets.spec.ts-snapshots/vue-nodes-upload-widgets-chromium-linux.png b/browser_tests/tests/vueNodes/widgets/load/uploadWidgets.spec.ts-snapshots/vue-nodes-upload-widgets-chromium-linux.png index ec764bd4bb..8318ff97bc 100644 Binary files a/browser_tests/tests/vueNodes/widgets/load/uploadWidgets.spec.ts-snapshots/vue-nodes-upload-widgets-chromium-linux.png and b/browser_tests/tests/vueNodes/widgets/load/uploadWidgets.spec.ts-snapshots/vue-nodes-upload-widgets-chromium-linux.png differ diff --git a/src/renderer/extensions/vueNodes/components/LGraphNode.vue b/src/renderer/extensions/vueNodes/components/LGraphNode.vue index a3ed81cb57..72d0641345 100644 --- a/src/renderer/extensions/vueNodes/components/LGraphNode.vue +++ b/src/renderer/extensions/vueNodes/components/LGraphNode.vue @@ -8,8 +8,9 @@ :data-node-id="nodeData.id" :class=" cn( - 'bg-node-component-surface', - 'lg-node absolute rounded-2xl touch-none flex flex-col', + 'bg-node-component-surface lg-node absolute', + 'min-h-min min-w-min contain-style contain-layout', + 'rounded-2xl touch-none flex flex-col', 'border-1 border-solid border-node-component-border', // hover (only when node should handle events) shouldHandleNodePointerEvents && @@ -83,7 +84,7 @@
@@ -150,7 +151,6 @@ import { cn } from '@/utils/tailwindUtil' import type { ResizeHandleDirection } from '../interactions/resize/resizeMath' import { useNodeResize } from '../interactions/resize/useNodeResize' -import { calculateIntrinsicSize } from '../utils/calculateIntrinsicSize' import LivePreview from './LivePreview.vue' import NodeContent from './NodeContent.vue' import NodeHeader from './NodeHeader.vue' @@ -269,18 +269,9 @@ const handleContextMenu = (event: MouseEvent) => { onMounted(() => { // Set initial DOM size from layout store, but respect intrinsic content minimum - if (size.value && nodeContainerRef.value && transformState) { - const intrinsicMin = calculateIntrinsicSize( - nodeContainerRef.value, - transformState.camera.z - ) - - // Use the larger of stored size or intrinsic minimum - const finalWidth = Math.max(size.value.width, intrinsicMin.width) - const finalHeight = Math.max(size.value.height, intrinsicMin.height) - - nodeContainerRef.value.style.width = `${finalWidth}px` - nodeContainerRef.value.style.height = `${finalHeight}px` + if (size.value && nodeContainerRef.value) { + nodeContainerRef.value.style.width = `${size.value.width}px` + nodeContainerRef.value.style.height = `${size.value.height}px` } }) diff --git a/src/renderer/extensions/vueNodes/components/NodeHeader.vue b/src/renderer/extensions/vueNodes/components/NodeHeader.vue index efee5b1c17..decfd63f0b 100644 --- a/src/renderer/extensions/vueNodes/components/NodeHeader.vue +++ b/src/renderer/extensions/vueNodes/components/NodeHeader.vue @@ -6,7 +6,8 @@ v-else :class=" cn( - 'lg-node-header p-4 rounded-t-2xl w-full bg-node-component-header-surface text-node-component-header', + 'lg-node-header p-4 rounded-t-2xl w-full min-w-50', + 'bg-node-component-header-surface text-node-component-header', collapsed && 'rounded-2xl' ) " diff --git a/src/renderer/extensions/vueNodes/interactions/resize/resizeMath.ts b/src/renderer/extensions/vueNodes/interactions/resize/resizeMath.ts index c58b0db6f8..a837d59c58 100644 --- a/src/renderer/extensions/vueNodes/interactions/resize/resizeMath.ts +++ b/src/renderer/extensions/vueNodes/interactions/resize/resizeMath.ts @@ -19,26 +19,6 @@ function applyHandleDelta( } } -function clampToMinSize(size: Size, minSize: Size): Size { - return { - width: Math.max(size.width, minSize.width), - height: Math.max(size.height, minSize.height) - } -} - -function snapSize( - size: Size, - minSize: Size, - snapFn?: (size: Size) => Size -): Size { - if (!snapFn) return size - const snapped = snapFn(size) - return { - width: Math.max(minSize.width, snapped.width), - height: Math.max(minSize.height, snapped.height) - } -} - function computeAdjustedPosition( startPosition: Point, startSize: Size, @@ -68,20 +48,17 @@ export function computeResizeOutcome({ startSize, startPosition, delta, - minSize, handle, snapFn }: { startSize: Size startPosition: Point delta: Point - minSize: Size handle: ResizeHandleDirection snapFn?: (size: Size) => Size }): { size: Size; position: Point } { const resized = applyHandleDelta(startSize, delta, handle) - const clamped = clampToMinSize(resized, minSize) - const snapped = snapSize(clamped, minSize, snapFn) + const snapped = snapFn?.(resized) ?? resized const position = computeAdjustedPosition( startPosition, startSize, @@ -98,19 +75,16 @@ export function computeResizeOutcome({ export function createResizeSession(config: { startSize: Size startPosition: Point - minSize: Size handle: ResizeHandleDirection }) { const startSize = { ...config.startSize } const startPosition = { ...config.startPosition } - const minSize = { ...config.minSize } const handle = config.handle return (delta: Point, snapFn?: (size: Size) => Size) => computeResizeOutcome({ startSize, startPosition, - minSize, handle, delta, snapFn diff --git a/src/renderer/extensions/vueNodes/interactions/resize/useNodeResize.ts b/src/renderer/extensions/vueNodes/interactions/resize/useNodeResize.ts index 2566fe41b6..39d745073c 100644 --- a/src/renderer/extensions/vueNodes/interactions/resize/useNodeResize.ts +++ b/src/renderer/extensions/vueNodes/interactions/resize/useNodeResize.ts @@ -5,7 +5,6 @@ import type { TransformState } from '@/renderer/core/layout/injectionKeys' import type { Point, Size } from '@/renderer/core/layout/types' import { useNodeSnap } from '@/renderer/extensions/vueNodes/composables/useNodeSnap' import { useShiftKeySync } from '@/renderer/extensions/vueNodes/composables/useShiftKeySync' -import { calculateIntrinsicSize } from '@/renderer/extensions/vueNodes/utils/calculateIntrinsicSize' import type { ResizeHandleDirection } from './resizeMath' import { createResizeSession, toCanvasDelta } from './resizeMath' @@ -76,8 +75,6 @@ export function useNodeResize( height: rect.height / scale } - const minSize = calculateIntrinsicSize(nodeElement, scale) - // Track shift key state and sync to canvas for snap preview const stopShiftSync = trackShiftKey(event) @@ -89,7 +86,6 @@ export function useNodeResize( resizeSession.value = createResizeSession({ startSize, startPosition: { ...startPosition }, - minSize, handle }) diff --git a/src/renderer/extensions/vueNodes/utils/calculateIntrinsicSize.test.ts b/src/renderer/extensions/vueNodes/utils/calculateIntrinsicSize.test.ts deleted file mode 100644 index cd34f8a3fb..0000000000 --- a/src/renderer/extensions/vueNodes/utils/calculateIntrinsicSize.test.ts +++ /dev/null @@ -1,138 +0,0 @@ -import { afterEach, beforeEach, describe, expect, it } from 'vitest' - -import { calculateIntrinsicSize } from './calculateIntrinsicSize' - -describe('calculateIntrinsicSize', () => { - let element: HTMLElement - - beforeEach(() => { - // Create a test element - element = document.createElement('div') - element.style.width = '200px' - element.style.height = '100px' - document.body.appendChild(element) - }) - - afterEach(() => { - document.body.removeChild(element) - }) - - it('should calculate intrinsic size and convert to canvas coordinates', () => { - // Mock getBoundingClientRect to return specific dimensions - const originalGetBoundingClientRect = element.getBoundingClientRect - element.getBoundingClientRect = () => ({ - width: 300, - height: 150, - top: 0, - left: 0, - bottom: 150, - right: 300, - x: 0, - y: 0, - toJSON: () => ({}) - }) - - const scale = 2 - const result = calculateIntrinsicSize(element, scale) - - // Should divide by scale to convert from screen to canvas coordinates - expect(result).toEqual({ - width: 150, // 300 / 2 - height: 75 // 150 / 2 - }) - - element.getBoundingClientRect = originalGetBoundingClientRect - }) - - it('should restore original size after measuring', () => { - const originalWidth = element.style.width - const originalHeight = element.style.height - - element.getBoundingClientRect = () => ({ - width: 300, - height: 150, - top: 0, - left: 0, - bottom: 150, - right: 300, - x: 0, - y: 0, - toJSON: () => ({}) - }) - - calculateIntrinsicSize(element, 1) - - // Should restore original styles - expect(element.style.width).toBe(originalWidth) - expect(element.style.height).toBe(originalHeight) - }) - - it('should handle scale of 1 correctly', () => { - element.getBoundingClientRect = () => ({ - width: 400, - height: 200, - top: 0, - left: 0, - bottom: 200, - right: 400, - x: 0, - y: 0, - toJSON: () => ({}) - }) - - const result = calculateIntrinsicSize(element, 1) - - expect(result).toEqual({ - width: 400, - height: 200 - }) - }) - - it('should handle fractional scales', () => { - element.getBoundingClientRect = () => ({ - width: 300, - height: 150, - top: 0, - left: 0, - bottom: 150, - right: 300, - x: 0, - y: 0, - toJSON: () => ({}) - }) - - const result = calculateIntrinsicSize(element, 0.5) - - expect(result).toEqual({ - width: 600, // 300 / 0.5 - height: 300 // 150 / 0.5 - }) - }) - - it('should temporarily set width and height to auto during measurement', () => { - let widthDuringMeasurement = '' - let heightDuringMeasurement = '' - - element.getBoundingClientRect = function (this: HTMLElement) { - widthDuringMeasurement = this.style.width - heightDuringMeasurement = this.style.height - return { - width: 300, - height: 150, - top: 0, - left: 0, - bottom: 150, - right: 300, - x: 0, - y: 0, - toJSON: () => ({}) - } - } - - calculateIntrinsicSize(element, 1) - - // During measurement, styles should be set to 'auto' - expect(widthDuringMeasurement).toBe('auto') - expect(heightDuringMeasurement).toBe('auto') - }) -}) diff --git a/src/renderer/extensions/vueNodes/utils/calculateIntrinsicSize.ts b/src/renderer/extensions/vueNodes/utils/calculateIntrinsicSize.ts deleted file mode 100644 index 36da7cd827..0000000000 --- a/src/renderer/extensions/vueNodes/utils/calculateIntrinsicSize.ts +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Calculate the intrinsic (minimum content-based) size of a node element - * - * Temporarily sets the element to auto-size to measure its natural content dimensions, - * then converts from screen coordinates to canvas coordinates using the camera scale. - * - * @param element - The node element to measure - * @param scale - Camera zoom scale for coordinate conversion - * @returns The intrinsic minimum size in canvas coordinates - */ -export function calculateIntrinsicSize( - element: HTMLElement, - scale: number -): { width: number; height: number } { - // Store original size to restore later - const originalWidth = element.style.width - const originalHeight = element.style.height - - // Temporarily set to auto to measure natural content size - element.style.width = 'auto' - element.style.height = 'auto' - - const intrinsicRect = element.getBoundingClientRect() - - // Restore original size - element.style.width = originalWidth - element.style.height = originalHeight - - // Convert from screen coordinates to canvas coordinates - return { - width: intrinsicRect.width / scale, - height: intrinsicRect.height / scale - } -} diff --git a/src/renderer/extensions/vueNodes/widgets/components/layout/WidgetLayoutField.vue b/src/renderer/extensions/vueNodes/widgets/components/layout/WidgetLayoutField.vue index e596ba290e..24411c9cc0 100644 --- a/src/renderer/extensions/vueNodes/widgets/components/layout/WidgetLayoutField.vue +++ b/src/renderer/extensions/vueNodes/widgets/components/layout/WidgetLayoutField.vue @@ -12,20 +12,20 @@ defineProps<{