diff --git a/frontend/src/CustomNode.jsx b/frontend/src/CustomNode.jsx index 6f3c5cb..a6202d5 100644 --- a/frontend/src/CustomNode.jsx +++ b/frontend/src/CustomNode.jsx @@ -1075,7 +1075,7 @@ function CustomNode({ id, data }) { } if (opts?.hidden) { hiddenWidgets.add(name); - } else if (isDataSocketSpec(spec)) { + } else if (isDataSocketSpec(spec) || opts?.socket_only) { dataInputs.push({ name, type, label: formatUiLabel(opts?.label || name) }); visibleInputNames.add(name); } else { @@ -1267,7 +1267,7 @@ function CustomNode({ id, data }) {
{data.warning}
)} - {scalarDisplay && ( + {scalarDisplay && !standaloneWidgets.some((w) => w.opts?.text_input) && (
{scalarDisplay.valueText} diff --git a/frontend/src/nodeClipboard.js b/frontend/src/nodeClipboard.js index eff750e..77eca2f 100644 --- a/frontend/src/nodeClipboard.js +++ b/frontend/src/nodeClipboard.js @@ -177,16 +177,26 @@ export function buildNodeClipboardPayloadForIds( )) : []; + const snapDim = (v) => { + const n = Math.round(Number(v)); + return Number.isFinite(n) && n > 0 ? n : undefined; + }; + return { kind: NODE_CLIPBOARD_KIND, version: 1, - nodes: selectedNodes.map((node) => ({ + nodes: selectedNodes.map((node) => { + const width = snapDim(node.measured?.width ?? node.width); + const height = snapDim(node.measured?.height ?? node.height); + return { id: String(node.id), type: node.type || 'custom', position: { x: Number(node.position?.x) || 0, y: Number(node.position?.y) || 0, }, + ...(width != null ? { width } : {}), + ...(height != null ? { height } : {}), ...(node.className ? { className: node.className } : {}), ...(node.parentId ? { parentId: String(node.parentId) } : {}), ...(node.extent ? { extent: node.extent } : {}), @@ -200,7 +210,8 @@ export function buildNodeClipboardPayloadForIds( runtimeValues: clonePlainObject(node.data?.runtimeValues), extraData: clonePlainObject(extractExtraData(node.data)), }, - })), + }; + }), edges: capturedEdges.map((edge) => ({ source: String(edge.source), sourceHandle: edge.sourceHandle, @@ -267,6 +278,8 @@ export function instantiateNodeClipboardPayload( x: (Number(node.position?.x) || 0) + (Number(offset?.x) || 0), y: (Number(node.position?.y) || 0) + (Number(offset?.y) || 0), }, + ...(node.width != null ? { width: node.width } : {}), + ...(node.height != null ? { height: node.height } : {}), ...(node.parentId ? { parentId: idMap.get(String(node.parentId)) || String(node.parentId) } : {}), ...(node.extent ? { extent: node.extent } : {}), ...(node.hidden ? { hidden: true } : {}), diff --git a/frontend/src/workflowSerialization.js b/frontend/src/workflowSerialization.js index 5c64a3a..09beea5 100644 --- a/frontend/src/workflowSerialization.js +++ b/frontend/src/workflowSerialization.js @@ -26,14 +26,23 @@ export function serializeWorkflowState(nodes, edges) { sanitizeRuntimeValuesForPersistence(node.data?.className, node.data?.runtimeValues), ); + const snapDim = (v) => { + const n = Math.round(Number(v)); + return Number.isFinite(n) && n > 0 ? n : undefined; + }; + return { version: 1, nodes: nodes.map((node) => { const runtimeValues = getRuntimeValues(node); + const width = snapDim(node.measured?.width ?? node.width); + const height = snapDim(node.measured?.height ?? node.height); return { id: node.id, type: node.type || 'custom', position: node.position, + ...(width != null ? { width } : {}), + ...(height != null ? { height } : {}), ...(node.className ? { className: node.className } : {}), ...(node.parentId ? { parentId: node.parentId } : {}), ...(node.extent ? { extent: node.extent } : {}),