Thomas G. Lopes
images upload
d7d2be5
raw
history blame
2.38 kB
<script lang="ts">
import "@xyflow/svelte/dist/style.css";
import type { Node } from "@xyflow/svelte";
import { Background, Controls, MiniMap, SvelteFlow } from "@xyflow/svelte";
import "@xyflow/svelte/dist/style.css";
import { useDebounce } from "runed";
import IconAdd from "~icons/lucide/plus";
import ChatNode from "./chat-node.svelte";
import { edges, nodes } from "./state.js";
import { models } from "$lib/state/models.svelte";
import ImgPreview from "$lib/components/inference-playground/img-preview.svelte";
const nodeTypes = { chat: ChatNode } as const;
// Make edges non-editable with clean styling
const edgeOptions = {
deletable: false,
selectable: false,
style: "stroke: #9ca3af; stroke-width: 2px;",
};
function addNewNode() {
const newNode: Node = {
id: crypto.randomUUID(),
position: { x: Math.random() * 500, y: Math.random() * 300 },
data: { query: "", response: "", modelId: undefined },
type: "chat",
width: undefined,
height: undefined,
};
nodes.current.push(newNode);
}
let derivedNodes = $derived(nodes.current);
const throttledSave = useDebounce((n: Node[]) => {
nodes.current = n;
}, 100);
await models.load();
</script>
<div class="h-screen w-screen bg-gray-50">
<!-- Header -->
<header class="absolute top-6 left-6 z-50 flex items-center gap-4">
<div
class="flex items-center gap-3 rounded-xl border border-gray-200/80 bg-white/95 px-6
py-3 shadow-sm backdrop-blur-md"
>
<h1 class="text-lg font-medium text-gray-900">Canvas</h1>
</div>
<button
onclick={addNewNode}
class="flex items-center gap-2 rounded-xl bg-black px-5 py-3 text-sm
font-medium text-white shadow-sm transition-all hover:scale-[1.02] hover:bg-gray-900
focus:ring-2 focus:ring-gray-900/20 focus:outline-hidden active:scale-[0.98]"
>
<IconAdd class="h-4 w-4" />
Add Node
</button>
</header>
{#if models.ready}
<SvelteFlow
bind:nodes={
() => derivedNodes,
v => {
derivedNodes = v;
throttledSave(v);
}
}
bind:edges={edges.current}
fitView
{nodeTypes}
defaultEdgeOptions={edgeOptions}
>
<MiniMap pannable zoomable class="rounded-xl border border-gray-200 bg-white shadow-sm" />
<Controls class="rounded-xl border border-gray-200 bg-white shadow-sm" />
<Background gap={20} size={1} />
</SvelteFlow>
{/if}
</div>
<ImgPreview />