ctx.onselect(node.id, e.shiftKey)}
style="
width: {node.width}px;
--accent: {accentColor};
--accent-dim: {accentDim};
"
>
{#if node.kind === "transform"}
{#if node.space_id || node.model_id || node.dataset_id}
{@const itemId = node.space_id ?? node.model_id ?? node.dataset_id ?? ""}
{:else if node.fn}
{node.fn}()
{:else if !readOnly}
{/if}
{/if}
{#if node.space_id}
e.stopPropagation()}
onmousedown={(e) => e.stopPropagation()}
>
{#if node.endpoints && node.endpoints.length > 1}
{:else if !node.endpoints}
{/if}
{/if}
{#if node.inputs.length > 0}
{@const hiddenCount = node.inputs.filter(
(p) =>
p.required === false && !connectedPorts.has(`${node.id}:${p.id}:input`)
).length}
{@const collapsible = hiddenCount > 0}
{#each node.inputs as port}
{@const portConnected = connectedPorts.has(
`${node.id}:${port.id}:input`
)}
{@const visible =
showAllInputs || portConnected || port.required !== false}
{#if visible}
{#if !portConnected && node.kind === "transform" && (port.type === "text" || port.type === "number" || port.type === "boolean" || port.type === "any" || port.type === "json")}
e.stopPropagation()}
>
{#if port.choices && port.choices.length > 0 && port.multiselect}
{@const selected = Array.isArray(node.data?.[port.id])
? (node.data[port.id] as string[])
: []}
{#each port.choices as choice}
{/each}
{:else if port.choices && port.choices.length > 0}
{@const raw = node.data?.[port.id] ?? port.default_value}
{@const current = raw != null ? String(raw) : ""}
{@const hasCurrent = port.choices.includes(current)}
{:else if port.type === "number"}
ctx.ondatachange(
node.id,
port.id,
parseFloat(e.currentTarget.value) || 0
)}
/>
{:else if port.type === "boolean"}
{:else}
ctx.ondatachange(node.id, port.id, e.currentTarget.value)}
/>
{/if}
{/if}
{/if}
{/each}
{#if collapsible}
{/if}
{/if}
{#if hasWidget && widgetPortId && widgetType}
{/if}
{#if node.outputs.length > 0}
{#each node.outputs as port}
{@const portConnected = connectedPorts.has(
`${node.id}:${port.id}:output`
)}
{#if !hasWidget}
{port.type}
{port.label}
{/if}
ctx.onportpointerdown(e, node.id, port.id, port.type, false)}
onclick={(e) => {
if (!readOnly && !portConnected && pending === null) {
e.stopPropagation();
ctx.onpopout(node.id, port.id, port.type, false);
}
}}
>
{/each}
{/if}
{#if status === "error" && error}
{error}
{/if}