Skip to content

Commit 6b1abb1

Browse files
committed
Use min-dimensions with calc-based port positioning
1 parent c653454 commit 6b1abb1

1 file changed

Lines changed: 25 additions & 28 deletions

File tree

src/lib/components/nodes/BaseNode.svelte

Lines changed: 25 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@
1111
import { showTooltip, hideTooltip } from '$lib/components/Tooltip.svelte';
1212
import { paramInput } from '$lib/actions/paramInput';
1313
import { plotDataStore } from '$lib/plotting/processing/plotDataStore';
14-
import { NODE, calculatePortPosition, snapTo2G } from '$lib/constants/dimensions';
15-
import { G } from '$lib/constants/grid';
14+
import { NODE, snapTo2G } from '$lib/constants/dimensions';
1615
import PlotPreview from './PlotPreview.svelte';
1716
1817
interface Props {
@@ -136,32 +135,34 @@
136135
137136
const maxPortsOnSide = $derived(Math.max(data.inputs.length, data.outputs.length));
138137
139-
// Calculate content height for pinned params (each param row ~24px)
140-
const pinnedParamCount = $derived(validPinnedParams().length);
141-
const contentExtraHeight = $derived(
142-
pinnedParamCount > 0
143-
? 4 + pinnedParamCount * 24 + 6 // border + rows + padding
144-
: 0
145-
);
146-
147-
// Node dimensions: always multiples of 2G (20px) for symmetric expansion from center
148-
// Ports require: maxPorts * portSpacing
138+
// Minimum node dimensions based on port count (grid-aligned to 2G)
139+
// Content can expand beyond these minimums
149140
const minPortDimension = $derived(Math.max(1, maxPortsOnSide) * NODE.portSpacing);
150-
const nodeHeight = $derived(
141+
const minNodeHeight = $derived(
151142
isVertical
152-
? snapTo2G(Math.max(NODE.baseHeight, NODE.baseHeight + contentExtraHeight))
153-
: snapTo2G(Math.max(NODE.baseHeight, minPortDimension, NODE.baseHeight + contentExtraHeight))
143+
? snapTo2G(NODE.baseHeight)
144+
: snapTo2G(Math.max(NODE.baseHeight, minPortDimension))
154145
);
155-
const nodeWidth = $derived(
146+
const minNodeWidth = $derived(
156147
isVertical
157148
? snapTo2G(Math.max(NODE.baseWidth, minPortDimension))
158149
: snapTo2G(NODE.baseWidth)
159150
);
160151
161-
// Calculate port position in pixels (grid-aligned)
162-
function getPortPositionPx(index: number, total: number, edgeLength: number): string {
163-
const position = calculatePortPosition(index, total, edgeLength);
164-
return `${position}px`;
152+
// Calculate port position as offset from center (using calc for CSS)
153+
// This ensures ports stay grid-aligned regardless of actual node dimensions
154+
// because the node center is at a grid-aligned position
155+
function getPortPositionCalc(index: number, total: number): string {
156+
if (total <= 0 || total === 1) {
157+
return '50%'; // Single port at center
158+
}
159+
// For N ports with spacing S: span = (N-1)*S, offset from center = -span/2 + i*S
160+
const span = (total - 1) * NODE.portSpacing;
161+
const offsetFromCenter = -span / 2 + index * NODE.portSpacing;
162+
if (offsetFromCenter === 0) {
163+
return '50%';
164+
}
165+
return `calc(50% + ${offsetFromCenter}px)`;
165166
}
166167
167168
// Check if this is a Subsystem or Interface node (using shapes utility)
@@ -300,7 +301,7 @@
300301
class:preview-hovered={showPreview}
301302
class:subsystem-type={isSubsystemType}
302303
data-rotation={rotation}
303-
style="width: {nodeWidth}px; height: {nodeHeight}px; --node-color: {nodeColor};"
304+
style="min-width: {minNodeWidth}px; min-height: {minNodeHeight}px; --node-color: {nodeColor};"
304305
ondblclick={handleDoubleClick}
305306
onmouseenter={handleMouseEnter}
306307
onmouseleave={handleMouseLeave}
@@ -379,7 +380,7 @@
379380
type="target"
380381
position={inputPosition()}
381382
id={port.id}
382-
style={isVertical ? `left: ${getPortPositionPx(i, data.inputs.length, nodeWidth)};` : `top: ${getPortPositionPx(i, data.inputs.length, nodeHeight)};`}
383+
style={isVertical ? `left: ${getPortPositionCalc(i, data.inputs.length)};` : `top: ${getPortPositionCalc(i, data.inputs.length)};`}
383384
class="handle handle-input"
384385
onmouseenter={(e) => handleInputMouseEnter(e, port)}
385386
onmouseleave={() => handleInputMouseLeave(port)}
@@ -394,7 +395,7 @@
394395
type="source"
395396
position={outputPosition()}
396397
id={port.id}
397-
style={isVertical ? `left: ${getPortPositionPx(i, data.outputs.length, nodeWidth)};` : `top: ${getPortPositionPx(i, data.outputs.length, nodeHeight)};`}
398+
style={isVertical ? `left: ${getPortPositionCalc(i, data.outputs.length)};` : `top: ${getPortPositionCalc(i, data.outputs.length)};`}
398399
class="handle handle-output"
399400
onmouseenter={(e) => handleOutputMouseEnter(e, port)}
400401
onmouseleave={() => handleOutputMouseLeave(port)}
@@ -468,12 +469,8 @@
468469
z-index: 1000 !important;
469470
}
470471
471-
/* Inner wrapper - uses flexbox to center content vertically */
472+
/* Inner wrapper for content */
472473
.node-inner {
473-
flex: 1;
474-
display: flex;
475-
flex-direction: column;
476-
justify-content: center;
477474
border-radius: inherit;
478475
overflow: hidden;
479476
}

0 commit comments

Comments
 (0)