diff --git a/browser_tests/tests/vueNodes/nodeStates/colors.spec.ts-snapshots/vue-node-custom-colors-dark-all-colors-chromium-linux.png b/browser_tests/tests/vueNodes/nodeStates/colors.spec.ts-snapshots/vue-node-custom-colors-dark-all-colors-chromium-linux.png index 6f0ec83aad..878321d708 100644 Binary files a/browser_tests/tests/vueNodes/nodeStates/colors.spec.ts-snapshots/vue-node-custom-colors-dark-all-colors-chromium-linux.png and b/browser_tests/tests/vueNodes/nodeStates/colors.spec.ts-snapshots/vue-node-custom-colors-dark-all-colors-chromium-linux.png differ diff --git a/browser_tests/tests/vueNodes/nodeStates/colors.spec.ts-snapshots/vue-node-custom-colors-light-all-colors-chromium-linux.png b/browser_tests/tests/vueNodes/nodeStates/colors.spec.ts-snapshots/vue-node-custom-colors-light-all-colors-chromium-linux.png index d8b3ca38df..fc8d3eca8d 100644 Binary files a/browser_tests/tests/vueNodes/nodeStates/colors.spec.ts-snapshots/vue-node-custom-colors-light-all-colors-chromium-linux.png and b/browser_tests/tests/vueNodes/nodeStates/colors.spec.ts-snapshots/vue-node-custom-colors-light-all-colors-chromium-linux.png differ diff --git a/src/renderer/extensions/vueNodes/components/LGraphNode.vue b/src/renderer/extensions/vueNodes/components/LGraphNode.vue index bbb3ff9093..109d0c5629 100644 --- a/src/renderer/extensions/vueNodes/components/LGraphNode.vue +++ b/src/renderer/extensions/vueNodes/components/LGraphNode.vue @@ -117,17 +117,14 @@ - - - - + +
@@ -150,7 +147,6 @@ import { useTelemetry } from '@/platform/telemetry' import { useCanvasStore } from '@/renderer/core/canvas/canvasStore' import { useCanvasInteractions } from '@/renderer/core/canvas/useCanvasInteractions' import { layoutStore } from '@/renderer/core/layout/store/layoutStore' -import { useTransformState } from '@/renderer/core/layout/transform/useTransformState' import SlotConnectionDot from '@/renderer/extensions/vueNodes/components/SlotConnectionDot.vue' import { useNodeEventHandlers } from '@/renderer/extensions/vueNodes/composables/useNodeEventHandlers' import { useNodePointerInteractions } from '@/renderer/extensions/vueNodes/composables/useNodePointerInteractions' @@ -172,7 +168,6 @@ import { } from '@/utils/graphTraversalUtil' import { cn } from '@/utils/tailwindUtil' -import type { ResizeHandleDirection } from '../interactions/resize/resizeMath' import { useNodeResize } from '../interactions/resize/useNodeResize' import LivePreview from './LivePreview.vue' import NodeContent from './NodeContent.vue' @@ -197,13 +192,6 @@ const { bringNodeToFront } = useNodeZIndex() useVueElementTracking(() => nodeData.id, 'node') -const transformState = useTransformState() -if (!transformState) { - throw new Error( - 'TransformState must be provided for node resize functionality' - ) -} - const { selectedNodeIds } = storeToRefs(useCanvasStore()) const isSelected = computed(() => { return selectedNodeIds.value.has(nodeData.id) @@ -271,7 +259,7 @@ onErrorCaptured((error) => { return false // Prevent error propagation }) -const { position, size, zIndex, moveNodeTo } = useNodeLayout(() => nodeData.id) +const { position, size, zIndex } = useNodeLayout(() => nodeData.id) const { pointerHandlers } = useNodePointerInteractions(() => nodeData.id) const { onPointerdown, ...remainingPointerHandlers } = pointerHandlers const { startDrag } = useNodeDrag() @@ -322,74 +310,23 @@ onMounted(() => { const baseResizeHandleClasses = 'absolute h-3 w-3 opacity-0 pointer-events-auto focus-visible:outline focus-visible:outline-2 focus-visible:outline-white/40' -const POSITION_EPSILON = 0.01 - -type CornerResizeHandle = { - id: string - direction: ResizeHandleDirection - classes: string - ariaLabel: string -} - -const cornerResizeHandles: CornerResizeHandle[] = [ - { - id: 'se', - direction: { horizontal: 'right', vertical: 'bottom' }, - classes: 'right-0 bottom-0 cursor-se-resize', - ariaLabel: t('g.resizeFromBottomRight') - }, - { - id: 'ne', - direction: { horizontal: 'right', vertical: 'top' }, - classes: 'right-0 top-0 cursor-ne-resize', - ariaLabel: t('g.resizeFromTopRight') - }, - { - id: 'sw', - direction: { horizontal: 'left', vertical: 'bottom' }, - classes: 'left-0 bottom-0 cursor-sw-resize', - ariaLabel: t('g.resizeFromBottomLeft') - }, - { - id: 'nw', - direction: { horizontal: 'left', vertical: 'top' }, - classes: 'left-0 top-0 cursor-nw-resize', - ariaLabel: t('g.resizeFromTopLeft') - } -] const MIN_NODE_WIDTH = 225 -const { startResize } = useNodeResize( - (result, element) => { - if (isCollapsed.value) return +const { startResize } = useNodeResize((result, element) => { + if (isCollapsed.value) return - // Clamp width to minimum to avoid conflicts with CSS min-width - const clampedWidth = Math.max(result.size.width, MIN_NODE_WIDTH) + // Clamp width to minimum to avoid conflicts with CSS min-width + const clampedWidth = Math.max(result.size.width, MIN_NODE_WIDTH) - // Apply size directly to DOM element - ResizeObserver will pick this up - element.style.setProperty('--node-width', `${clampedWidth}px`) - element.style.setProperty('--node-height', `${result.size.height}px`) - - const currentPosition = position.value - const deltaX = Math.abs(result.position.x - currentPosition.x) - const deltaY = Math.abs(result.position.y - currentPosition.y) - - if (deltaX > POSITION_EPSILON || deltaY > POSITION_EPSILON) { - moveNodeTo(result.position) - } - }, - { - transformState - } -) - -const handleResizePointerDown = (direction: ResizeHandleDirection) => { - return (event: PointerEvent) => { - if (nodeData.flags?.pinned) return + // Apply size directly to DOM element - ResizeObserver will pick this up + element.style.setProperty('--node-width', `${clampedWidth}px`) + element.style.setProperty('--node-height', `${result.size.height}px`) +}) - startResize(event, direction, { ...position.value }) - } +const handleResizePointerDown = (event: PointerEvent) => { + if (nodeData.flags?.pinned) return + startResize(event) } watch(isCollapsed, (collapsed) => { diff --git a/src/renderer/extensions/vueNodes/interactions/resize/resizeMath.ts b/src/renderer/extensions/vueNodes/interactions/resize/resizeMath.ts deleted file mode 100644 index a837d59c58..0000000000 --- a/src/renderer/extensions/vueNodes/interactions/resize/resizeMath.ts +++ /dev/null @@ -1,104 +0,0 @@ -import type { Point, Size } from '@/renderer/core/layout/types' - -export type ResizeHandleDirection = { - horizontal: 'left' | 'right' - vertical: 'top' | 'bottom' -} - -function applyHandleDelta( - startSize: Size, - delta: Point, - handle: ResizeHandleDirection -): Size { - const horizontalMultiplier = handle.horizontal === 'right' ? 1 : -1 - const verticalMultiplier = handle.vertical === 'bottom' ? 1 : -1 - - return { - width: startSize.width + delta.x * horizontalMultiplier, - height: startSize.height + delta.y * verticalMultiplier - } -} - -function computeAdjustedPosition( - startPosition: Point, - startSize: Size, - nextSize: Size, - handle: ResizeHandleDirection -): Point { - const widthDelta = startSize.width - nextSize.width - const heightDelta = startSize.height - nextSize.height - - return { - x: - handle.horizontal === 'left' - ? startPosition.x + widthDelta - : startPosition.x, - y: - handle.vertical === 'top' - ? startPosition.y + heightDelta - : startPosition.y - } -} - -/** - * Computes the resulting size and position of a node given pointer movement - * and handle orientation. - */ -export function computeResizeOutcome({ - startSize, - startPosition, - delta, - handle, - snapFn -}: { - startSize: Size - startPosition: Point - delta: Point - handle: ResizeHandleDirection - snapFn?: (size: Size) => Size -}): { size: Size; position: Point } { - const resized = applyHandleDelta(startSize, delta, handle) - const snapped = snapFn?.(resized) ?? resized - const position = computeAdjustedPosition( - startPosition, - startSize, - snapped, - handle - ) - - return { - size: snapped, - position - } -} - -export function createResizeSession(config: { - startSize: Size - startPosition: Point - handle: ResizeHandleDirection -}) { - const startSize = { ...config.startSize } - const startPosition = { ...config.startPosition } - const handle = config.handle - - return (delta: Point, snapFn?: (size: Size) => Size) => - computeResizeOutcome({ - startSize, - startPosition, - handle, - delta, - snapFn - }) -} - -export function toCanvasDelta( - startPointer: Point, - currentPointer: Point, - scale: number -): Point { - const safeScale = scale === 0 ? 1 : scale - return { - x: (currentPointer.x - startPointer.x) / safeScale, - y: (currentPointer.y - startPointer.y) / safeScale - } -} diff --git a/src/renderer/extensions/vueNodes/interactions/resize/useNodeResize.ts b/src/renderer/extensions/vueNodes/interactions/resize/useNodeResize.ts index 823ffefbf4..ebc8a3f015 100644 --- a/src/renderer/extensions/vueNodes/interactions/resize/useNodeResize.ts +++ b/src/renderer/extensions/vueNodes/interactions/resize/useNodeResize.ts @@ -4,48 +4,26 @@ import { ref } from 'vue' 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 type { ResizeHandleDirection } from './resizeMath' -import { createResizeSession, toCanvasDelta } from './resizeMath' -import type { useTransformState } from '@/renderer/core/layout/transform/useTransformState' - -interface UseNodeResizeOptions { - /** Transform state for coordinate conversion */ - transformState: ReturnType