Skip to content

Commit 52757d5

Browse files
committed
Refactor pinned params SVG rendering to read positions from DOM
1 parent df44d33 commit 52757d5

1 file changed

Lines changed: 40 additions & 34 deletions

File tree

src/lib/export/svg/renderer.ts

Lines changed: 40 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
import { get } from 'svelte/store';
1212
import { graphStore } from '$lib/stores/graph';
1313
import { eventStore } from '$lib/stores/events';
14-
import { nodeRegistry } from '$lib/nodes';
1514
import { getThemeColors } from '$lib/constants/theme';
1615
import { NODE, EVENT } from '$lib/constants/dimensions';
1716
import { getHandlePath } from '$lib/constants/handlePaths';
@@ -172,22 +171,22 @@ function renderNode(node: NodeInstance, ctx: RenderContext): string {
172171
`<rect x="${x}" y="${y}" width="${width}" height="${height}" rx="${borderRadius}" fill="none" stroke="${ctx.theme.edge}" stroke-width="1"${strokeDasharray}/>`
173172
);
174173

175-
// Get pinned params info
176-
const typeDef = nodeRegistry.get(node.type);
177-
const validPinnedParams = node.pinnedParams?.filter(
178-
(name) => typeDef?.params.some((p) => p.name === name)
179-
) || [];
180-
const hasPinnedParams = validPinnedParams.length > 0;
174+
// Check for pinned params section in DOM
175+
const pinnedParamsEl = nodeEl.querySelector('.pinned-params') as HTMLElement;
176+
const zoom = getZoom();
177+
const nodeRect = wrapper.getBoundingClientRect();
181178

182-
// Calculate content area height (excluding pinned params)
183-
// Pinned params: 7px top padding + 24px per row
184-
const pinnedParamsHeight = hasPinnedParams ? 7 + 24 * validPinnedParams.length : 0;
185-
const contentHeight = height - pinnedParamsHeight;
179+
// Calculate content center (above pinned params if present)
180+
let contentCenterY = y + height / 2;
181+
if (pinnedParamsEl) {
182+
const pinnedRect = pinnedParamsEl.getBoundingClientRect();
183+
const pinnedTop = (pinnedRect.top - nodeRect.top) / zoom;
184+
contentCenterY = y + pinnedTop / 2;
185+
}
186186

187187
// Labels
188188
if (ctx.options.showLabels) {
189189
const centerX = x + width / 2;
190-
const contentCenterY = y + contentHeight / 2;
191190

192191
if (ctx.options.showTypeLabels && nodeType) {
193192
// Name above center
@@ -206,54 +205,61 @@ function renderNode(node: NodeInstance, ctx: RenderContext): string {
206205
}
207206
}
208207

209-
// Pinned parameters
210-
if (hasPinnedParams && typeDef) {
211-
const pinnedY = y + contentHeight;
208+
// Pinned parameters - read positions from DOM
209+
if (pinnedParamsEl) {
210+
const pinnedRect = pinnedParamsEl.getBoundingClientRect();
211+
const pinnedTop = y + (pinnedRect.top - nodeRect.top) / zoom;
212+
const pinnedHeight = pinnedRect.height / zoom;
212213

213214
// Separator line
214215
parts.push(
215-
`<line x1="${x}" y1="${pinnedY}" x2="${x + width}" y2="${pinnedY}" stroke="${ctx.theme.border}" stroke-width="1"/>`
216+
`<line x1="${x}" y1="${pinnedTop}" x2="${x + width}" y2="${pinnedTop}" stroke="${ctx.theme.border}" stroke-width="1"/>`
216217
);
217218

218219
// Background for pinned params area (square top, rounded bottom to match node)
219220
const px = x + 1;
220-
const py = pinnedY + 1;
221+
const py = pinnedTop + 1;
221222
const pw = width - 2;
222-
const ph = pinnedParamsHeight - 2;
223+
const ph = pinnedHeight - 1;
223224
const br = Math.max(0, borderRadius - 1);
224225
// Path: start top-left, go right, down, rounded bottom-right, left, rounded bottom-left, up
225226
parts.push(
226227
`<path d="M${px},${py} h${pw} v${ph - br} a${br},${br} 0 0 1 -${br},${br} h-${pw - 2 * br} a${br},${br} 0 0 1 -${br},-${br} v-${ph - br} z" fill="${ctx.theme.surface}"/>`
227228
);
228229

229-
// Each pinned param row
230-
validPinnedParams.forEach((paramName, index) => {
231-
const paramDef = typeDef.params.find((p) => p.name === paramName);
232-
const value = node.params[paramName];
233-
const displayValue = value !== undefined && value !== '' ? String(value) : (paramDef?.default !== undefined ? String(paramDef.default) : '');
230+
// Each pinned param row - read from DOM
231+
pinnedParamsEl.querySelectorAll('.pinned-param').forEach((paramEl) => {
232+
const labelEl = paramEl.querySelector('label') as HTMLElement;
233+
const inputEl = paramEl.querySelector('input') as HTMLInputElement;
234+
if (!labelEl || !inputEl) return;
235+
236+
const labelRect = labelEl.getBoundingClientRect();
237+
const inputRect = inputEl.getBoundingClientRect();
234238

235-
// Row Y position: 7px top padding + 24px per row, center each row
236-
const rowY = pinnedY + 7 + index * 24 + 10; // +10 for vertical centering in 20px row
239+
// Label position
240+
const labelX = x + (labelRect.left - nodeRect.left) / zoom;
241+
const labelY = y + (labelRect.top + labelRect.height / 2 - nodeRect.top) / zoom;
242+
const labelText = labelEl.textContent || '';
237243

238-
// Label (left side)
239244
parts.push(
240-
`<text x="${x + 10}" y="${rowY}" dominant-baseline="middle" fill="${ctx.theme.textMuted}" font-size="8" font-family="system-ui, -apple-system, sans-serif">${escapeXml(paramName)}</text>`
245+
`<text x="${labelX}" y="${labelY}" dominant-baseline="middle" fill="${ctx.theme.textMuted}" font-size="8" font-family="system-ui, -apple-system, sans-serif">${escapeXml(labelText)}</text>`
241246
);
242247

243-
// Value (right side, in a box)
244-
const inputX = x + 60;
245-
const inputWidth = width - 70;
246-
const inputY = rowY - 10;
247-
const inputHeight = 20;
248+
// Input box position
249+
const inputX = x + (inputRect.left - nodeRect.left) / zoom;
250+
const inputY = y + (inputRect.top - nodeRect.top) / zoom;
251+
const inputW = inputRect.width / zoom;
252+
const inputH = inputRect.height / zoom;
253+
const inputValue = inputEl.value || inputEl.placeholder || '';
248254

249255
// Input background
250256
parts.push(
251-
`<rect x="${inputX}" y="${inputY}" width="${inputWidth}" height="${inputHeight}" rx="4" fill="${ctx.theme.surfaceRaised}" stroke="${ctx.theme.border}" stroke-width="1"/>`
257+
`<rect x="${inputX}" y="${inputY}" width="${inputW}" height="${inputH}" rx="4" fill="${ctx.theme.surfaceRaised}" stroke="${ctx.theme.border}" stroke-width="1"/>`
252258
);
253259

254260
// Input value
255261
parts.push(
256-
`<text x="${inputX + 8}" y="${rowY}" dominant-baseline="middle" fill="${ctx.theme.text}" font-size="9" font-family="ui-monospace, monospace">${escapeXml(displayValue)}</text>`
262+
`<text x="${inputX + 8}" y="${inputY + inputH / 2}" dominant-baseline="middle" fill="${ctx.theme.text}" font-size="9" font-family="ui-monospace, monospace">${escapeXml(inputValue)}</text>`
257263
);
258264
});
259265
}

0 commit comments

Comments
 (0)