Spaces:
Runtime error
Runtime error
| <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 /> | |