refactor(Graph.svelte): use snippets for ports

This commit is contained in:
Smit 2025-07-06 16:43:39 +05:30
parent abce214ced
commit d0c34e0ca9
2 changed files with 39 additions and 121 deletions

View file

@ -5,7 +5,7 @@
import type { Editor } from "@graphite/editor"; import type { Editor } from "@graphite/editor";
import type { Node } from "@graphite/messages.svelte"; import type { Node } from "@graphite/messages.svelte";
import type { FrontendNode, FrontendGraphInput, FrontendGraphOutput } from "@graphite/messages.svelte"; import { type FrontendNode, type FrontendGraphInput, FrontendGraphOutput, } from "@graphite/messages.svelte";
import type { NodeGraphState } from "@graphite/state-providers/node-graph"; import type { NodeGraphState } from "@graphite/state-providers/node-graph";
import type { IconName } from "@graphite/utility-functions/icons"; import type { IconName } from "@graphite/utility-functions/icons";
@ -230,6 +230,7 @@
$effect.pre(() => { $effect.pre(() => {
nodeValues = Array.from($nodeGraph.nodes.values()); nodeValues = Array.from($nodeGraph.nodes.values());
}); });
// Key value is node id + input/output index // Key value is node id + input/output index
// Imports/Export are stored at a key value of 0 // Imports/Export are stored at a key value of 0
@ -340,25 +341,7 @@
<!-- Import and Export ports --> <!-- Import and Export ports -->
<div class="imports-and-exports" style:transform-origin={`0 0`} style:transform={`translate(${$nodeGraph.transform.x}px, ${$nodeGraph.transform.y}px) scale(${$nodeGraph.transform.scale})`}> <div class="imports-and-exports" style:transform-origin={`0 0`} style:transform={`translate(${$nodeGraph.transform.x}px, ${$nodeGraph.transform.y}px) scale(${$nodeGraph.transform.scale})`}>
{#each $nodeGraph.imports as { outputMetadata, position }, index} {#each $nodeGraph.imports as { outputMetadata, position }, index}
<svg {@render port("port", "output", outputMetadata, position.x / 24, position.y / 24)}
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 8 8"
class="port"
data-port="output"
data-datatype={outputMetadata.dataType}
style:--data-color={`var(--color-data-${outputMetadata.dataType.toLowerCase()})`}
style:--data-color-dim={`var(--color-data-${outputMetadata.dataType.toLowerCase()}-dim)`}
style:--offset-left={position.x / 24}
style:--offset-top={position.y / 24}
>
<title>{`${dataTypeTooltip(outputMetadata)}\n\n${outputConnectedToText(outputMetadata)}`}</title>
{#if outputMetadata.connectedTo !== undefined}
<path d="M0,6.306A1.474,1.474,0,0,0,2.356,7.724L7.028,5.248c1.3-.687,1.3-1.809,0-2.5L2.356.276A1.474,1.474,0,0,0,0,1.694Z" fill="var(--data-color)" />
{:else}
<path d="M0,6.306A1.474,1.474,0,0,0,2.356,7.724L7.028,5.248c1.3-.687,1.3-1.809,0-2.5L2.356.276A1.474,1.474,0,0,0,0,1.694Z" fill="var(--data-color-dim)" />
{/if}
</svg>
<div <div
class="edit-import-export import" class="edit-import-export import"
onpointerenter={() => (hoveringImportIndex = index)} onpointerenter={() => (hoveringImportIndex = index)}
@ -414,24 +397,7 @@
</div> </div>
{/if} {/if}
{#each $nodeGraph.exports as { inputMetadata, position }, index} {#each $nodeGraph.exports as { inputMetadata, position }, index}
<svg {@render port("port", "input", inputMetadata, position.x / 24, position.y / 24)}
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 8 8"
class="port"
data-port="input"
data-datatype={inputMetadata.dataType}
style:--data-color={`var(--color-data-${inputMetadata.dataType.toLowerCase()})`}
style:--data-color-dim={`var(--color-data-${inputMetadata.dataType.toLowerCase()}-dim)`}
style:--offset-left={position.x / 24}
style:--offset-top={position.y / 24}
>
<title>{`${dataTypeTooltip(inputMetadata)}\n\n${inputConnectedToText(inputMetadata)}`}</title>
{#if inputMetadata.connectedTo !== undefined}
<path d="M0,6.306A1.474,1.474,0,0,0,2.356,7.724L7.028,5.248c1.3-.687,1.3-1.809,0-2.5L2.356.276A1.474,1.474,0,0,0,0,1.694Z" fill="var(--data-color)" />
{:else}
<path d="M0,6.306A1.474,1.474,0,0,0,2.356,7.724L7.028,5.248c1.3-.687,1.3-1.809,0-2.5L2.356.276A1.474,1.474,0,0,0,0,1.694Z" fill="var(--data-color-dim)" />
{/if}
</svg>
<div <div
class="edit-import-export export" class="edit-import-export export"
onpointerenter={() => (hoveringExportIndex = index)} onpointerenter={() => (hoveringExportIndex = index)}
@ -570,22 +536,7 @@
<!-- Layer input port (from left) --> <!-- Layer input port (from left) -->
{#if node.exposedInputs.length > 0} {#if node.exposedInputs.length > 0}
<div class="input ports"> <div class="input ports">
<svg {@render port("port", "input", stackDataInput)}
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 8 8"
class="port"
data-port="input"
data-datatype={stackDataInput.dataType}
style:--data-color={`var(--color-data-${stackDataInput.dataType.toLowerCase()})`}
style:--data-color-dim={`var(--color-data-${stackDataInput.dataType.toLowerCase()}-dim)`}
>
<title>{`${dataTypeTooltip(stackDataInput)}\n\n${validTypesText(stackDataInput)}\n\n${inputConnectedToText(stackDataInput)}`}</title>
{#if stackDataInput.connectedTo !== undefined}
<path d="M0,6.306A1.474,1.474,0,0,0,2.356,7.724L7.028,5.248c1.3-.687,1.3-1.809,0-2.5L2.356.276A1.474,1.474,0,0,0,0,1.694Z" fill="var(--data-color)" />
{:else}
<path d="M0,6.306A1.474,1.474,0,0,0,2.356,7.724L7.028,5.248c1.3-.687,1.3-1.809,0-2.5L2.356.276A1.474,1.474,0,0,0,0,1.694Z" fill="var(--data-color-dim)" />
{/if}
</svg>
</div> </div>
{/if} {/if}
<div class="details"> <div class="details">
@ -688,81 +639,19 @@
<!-- Input ports --> <!-- Input ports -->
<div class="input ports"> <div class="input ports">
{#if node.primaryInput?.dataType} {#if node.primaryInput?.dataType}
<svg {@render port("port primary-port", "input", node.primaryInput)}
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 8 8"
class="port primary-port"
data-port="input"
data-datatype={node.primaryInput?.dataType}
style:--data-color={`var(--color-data-${node.primaryInput.dataType.toLowerCase()})`}
style:--data-color-dim={`var(--color-data-${node.primaryInput.dataType.toLowerCase()}-dim)`}
>
<title>{`${dataTypeTooltip(node.primaryInput)}\n\n${validTypesText(node.primaryInput)}\n\n${inputConnectedToText(node.primaryInput)}`}</title>
{#if node.primaryInput.connectedTo !== undefined}
<path d="M0,6.306A1.474,1.474,0,0,0,2.356,7.724L7.028,5.248c1.3-.687,1.3-1.809,0-2.5L2.356.276A1.474,1.474,0,0,0,0,1.694Z" fill="var(--data-color)" />
{:else}
<path d="M0,6.306A1.474,1.474,0,0,0,2.356,7.724L7.028,5.248c1.3-.687,1.3-1.809,0-2.5L2.356.276A1.474,1.474,0,0,0,0,1.694Z" fill="var(--data-color-dim)" />
{/if}
</svg>
{/if} {/if}
{#each node.exposedInputs as secondary, index} {#each node.exposedInputs as secondary, index}
{#if index < node.exposedInputs.length} {#if index < node.exposedInputs.length}
<svg {@render port("port", "input", secondary)}
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 8 8"
class="port"
data-port="input"
data-datatype={secondary.dataType}
style:--data-color={`var(--color-data-${secondary.dataType.toLowerCase()})`}
style:--data-color-dim={`var(--color-data-${secondary.dataType.toLowerCase()}-dim)`}
>
<title>{`${dataTypeTooltip(secondary)}\n\n${validTypesText(secondary)}\n\n${inputConnectedToText(secondary)}`}</title>
{#if secondary.connectedTo !== undefined}
<path d="M0,6.306A1.474,1.474,0,0,0,2.356,7.724L7.028,5.248c1.3-.687,1.3-1.809,0-2.5L2.356.276A1.474,1.474,0,0,0,0,1.694Z" fill="var(--data-color)" />
{:else}
<path d="M0,6.306A1.474,1.474,0,0,0,2.356,7.724L7.028,5.248c1.3-.687,1.3-1.809,0-2.5L2.356.276A1.474,1.474,0,0,0,0,1.694Z" fill="var(--data-color-dim)" />
{/if}
</svg>
{/if} {/if}
{/each} {/each}
</div> </div>
<!-- Output ports --> <!-- Output ports -->
<div class="output ports"> <div class="output ports">
{#if node.primaryOutput} {@render port("port primary-port", "output", node.primaryOutput)}
<svg {#each node.exposedOutputs as secondary, outputIndex}
xmlns="http://www.w3.org/2000/svg" {@render port("port", "output", secondary)}
viewBox="0 0 8 8"
class="port primary-port"
data-port="output"
data-datatype={node.primaryOutput.dataType}
style:--data-color={`var(--color-data-${node.primaryOutput.dataType.toLowerCase()})`}
style:--data-color-dim={`var(--color-data-${node.primaryOutput.dataType.toLowerCase()}-dim)`}
>
<title>{`${dataTypeTooltip(node.primaryOutput)}\n\n${outputConnectedToText(node.primaryOutput)}`}</title>
{#if node.primaryOutput.connectedTo !== undefined}
<path d="M0,6.306A1.474,1.474,0,0,0,2.356,7.724L7.028,5.248c1.3-.687,1.3-1.809,0-2.5L2.356.276A1.474,1.474,0,0,0,0,1.694Z" fill="var(--data-color)" />
{:else}
<path d="M0,6.306A1.474,1.474,0,0,0,2.356,7.724L7.028,5.248c1.3-.687,1.3-1.809,0-2.5L2.356.276A1.474,1.474,0,0,0,0,1.694Z" fill="var(--data-color-dim)" />
{/if}
</svg>
{/if}
{#each node.exposedOutputs as secondary}
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 8 8"
class="port"
data-port="output"
data-datatype={secondary.dataType}
style:--data-color={`var(--color-data-${secondary.dataType.toLowerCase()})`}
style:--data-color-dim={`var(--color-data-${secondary.dataType.toLowerCase()}-dim)`}
>
<title>{`${dataTypeTooltip(secondary)}\n\n${outputConnectedToText(secondary)}`}</title>
{#if secondary.connectedTo !== undefined}
<path d="M0,6.306A1.474,1.474,0,0,0,2.356,7.724L7.028,5.248c1.3-.687,1.3-1.809,0-2.5L2.356.276A1.474,1.474,0,0,0,0,1.694Z" fill="var(--data-color)" />
{:else}
<path d="M0,6.306A1.474,1.474,0,0,0,2.356,7.724L7.028,5.248c1.3-.687,1.3-1.809,0-2.5L2.356.276A1.474,1.474,0,0,0,0,1.694Z" fill="var(--data-color-dim)" />
{/if}
</svg>
{/each} {/each}
</div> </div>
<svg class="border-mask" width="0" height="0"> <svg class="border-mask" width="0" height="0">
@ -792,6 +681,34 @@
></div> ></div>
{/if} {/if}
{#snippet port(className: string, dataPort: string, node?: FrontendGraphInput | FrontendGraphOutput, offsetLeft?: number, offsetTop?: number)}
{#if node}
{@const color = node.dataType.toLowerCase()}
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 8 8"
class={className}
data-port={dataPort}
data-datatype={node.dataType}
style:--data-color={`var(--color-data-${color})`}
style:--data-color-dim={`var(--color-data-${color}-dim)`}
style:--offset-left={offsetLeft}
style:--offset-top={offsetTop}
>
{#if node instanceof FrontendGraphOutput}
<title>{`${dataTypeTooltip(node)}\n\n${outputConnectedToText(node)}`}</title>
{:else}
<title>{`${dataTypeTooltip(node)}\n\n${validTypesText(node)}\n\n${inputConnectedToText(node)}`}</title>
{/if}
{#if node.connectedTo !== undefined}
<path d="M0,6.306A1.474,1.474,0,0,0,2.356,7.724L7.028,5.248c1.3-.687,1.3-1.809,0-2.5L2.356.276A1.474,1.474,0,0,0,0,1.694Z" fill="var(--data-color)" />
{:else}
<path d="M0,6.306A1.474,1.474,0,0,0,2.356,7.724L7.028,5.248c1.3-.687,1.3-1.809,0-2.5L2.356.276A1.474,1.474,0,0,0,0,1.694Z" fill="var(--data-color-dim)" />
{/if}
</svg>
{/if}
{/snippet}
<style lang="scss" global> <style lang="scss" global>
.graph { .graph {
position: relative; position: relative;

View file

@ -128,6 +128,7 @@ export function createNodeGraphState(editor: Editor) {
}); });
editor.subscriptions.subscribeJsMessage(UpdateVisibleNodes, (updateVisibleNodes) => { editor.subscriptions.subscribeJsMessage(UpdateVisibleNodes, (updateVisibleNodes) => {
update((state) => { update((state) => {
console.log("🚀 ~ update ~ state:", state);
state.visibleNodes = new Set<bigint>(updateVisibleNodes.nodes); state.visibleNodes = new Set<bigint>(updateVisibleNodes.nodes);
return state; return state;
}); });