port more updates

This commit is contained in:
peterkogo
2024-12-17 17:37:26 +01:00
parent 72d3e014b7
commit 39930e705d
14 changed files with 68 additions and 57 deletions
@@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import { NodeToolbar, useNodes } from '@xyflow/svelte'; import { NodeToolbar, useNodes } from '@xyflow/svelte';
const nodes = useNodes(); let nodes = useNodes();
let selectedNodeIds = $derived( let selectedNodeIds = $derived(
nodes.current.filter((node) => node.selected).map((node) => node.id) nodes.current.filter((node) => node.selected).map((node) => node.id)
@@ -1,11 +1,10 @@
<script lang="ts"> <script lang="ts">
import { writable } from 'svelte/store';
import { SvelteFlow, Controls, Background, MiniMap, type Node, type Edge } from '@xyflow/svelte'; import { SvelteFlow, Controls, Background, MiniMap, type Node, type Edge } from '@xyflow/svelte';
import '@xyflow/svelte/dist/style.css'; import '@xyflow/svelte/dist/style.css';
const nodes = writable<Node[]>([]); let nodes = $state.raw<Node[]>([]);
const edges = writable<Edge[]>([]); let edges = $state.raw<Edge[]>([]);
const resetNodesArray = () => { const resetNodesArray = () => {
const node1: Node = { const node1: Node = {
@@ -20,14 +19,14 @@
position: { x: 100, y: 0 } position: { x: 100, y: 0 }
}; };
$nodes = [node1, node2]; nodes = [node1, node2];
}; };
</script> </script>
<button onclick={resetNodesArray}> Reset </button> <button onclick={resetNodesArray}> Reset </button>
<div style:height="100vh"> <div style:height="100vh">
<SvelteFlow {nodes} {edges} fitView> <SvelteFlow bind:nodes bind:edges fitView>
<Controls /> <Controls />
<Background /> <Background />
<MiniMap /> <MiniMap />
@@ -1,5 +1,4 @@
<script lang="ts"> <script lang="ts">
import { writable } from 'svelte/store';
import { import {
SvelteFlow, SvelteFlow,
Controls, Controls,
@@ -1,12 +1,11 @@
<script lang="ts"> <script lang="ts">
import { writable } from 'svelte/store';
import { SvelteFlow, Controls, Background, BackgroundVariant, MiniMap } from '@xyflow/svelte'; import { SvelteFlow, Controls, Background, BackgroundVariant, MiniMap } from '@xyflow/svelte';
import Sidebar from './Sidebar.svelte'; import Sidebar from './Sidebar.svelte';
import '@xyflow/svelte/dist/style.css'; import '@xyflow/svelte/dist/style.css';
const nodes = writable([ let nodes = $state.raw([
{ {
id: '1', id: '1',
type: 'input', type: 'input',
@@ -27,7 +26,7 @@
} }
]); ]);
const edges = writable([ let edges = $state.raw([
{ {
id: '1-2', id: '1-2',
type: 'default', type: 'default',
@@ -45,7 +44,7 @@
</script> </script>
<main> <main>
<SvelteFlow {nodes} {edges} fitView> <SvelteFlow bind:nodes bind:edges fitView>
<Controls /> <Controls />
<Background variant={BackgroundVariant.Dots} /> <Background variant={BackgroundVariant.Dots} />
<MiniMap /> <MiniMap />
@@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { useEdges, useNodes, useSvelteFlow } from '@xyflow/svelte'; import { useEdges, useNodes, useSvelteFlow, useViewport } from '@xyflow/svelte';
const { const {
zoomIn, zoomIn,
@@ -9,17 +9,18 @@
setCenter, setCenter,
setViewport, setViewport,
getViewport, getViewport,
viewport,
toObject, toObject,
deleteElements deleteElements
} = useSvelteFlow(); } = useSvelteFlow();
const nodes = useNodes(); let nodes = useNodes();
const edges = useEdges(); let edges = useEdges();
let viewport = useViewport();
const deleteNode = () => { const deleteNode = () => {
$nodes.shift(); //TODO: do we really want to allow this?
$nodes = $nodes; // nodes.shift();
// nodes = nodes;
}; };
</script> </script>
@@ -33,11 +34,13 @@
<button onclick={() => setViewport({ x: 100, y: 100, zoom: 2 })}>setViewport</button> <button onclick={() => setViewport({ x: 100, y: 100, zoom: 2 })}>setViewport</button>
<button onclick={() => console.log(getViewport())}>getViewport</button> <button onclick={() => console.log(getViewport())}>getViewport</button>
<button onclick={() => deleteElements({ edges: $edges.map((edge) => ({ id: edge.id })) })} <button onclick={() => deleteElements({ edges: edges.current.map((edge) => ({ id: edge.id })) })}
>delete edges</button >delete edges</button
> >
<button onclick={() => deleteElements({ nodes: [{ id: $nodes[0].id }] })}>delete node</button> <button onclick={() => deleteElements({ nodes: [{ id: nodes.current[0].id }] })}
<button onclick={() => deleteElements({ nodes: $nodes.map((node) => ({ id: node.id })) })} >delete node</button
>
<button onclick={() => deleteElements({ nodes: nodes.current.map((node) => ({ id: node.id })) })}
>deleteElements</button >deleteElements</button
> >
<button onclick={() => deleteNode()}>delete via store</button> <button onclick={() => deleteNode()}>delete via store</button>
@@ -49,13 +52,15 @@
> >
<div class="label">Nodes:</div> <div class="label">Nodes:</div>
{#each $nodes as node (node.id)} {#each nodes.current as node (node.id)}
<div>id: {node.id} | x: {node.position.x.toFixed(1)} y: {node.position.y.toFixed(1)}</div> <div>id: {node.id} | x: {node.position.x.toFixed(1)} y: {node.position.y.toFixed(1)}</div>
{/each} {/each}
<div class="label">Viewport:</div> <div class="label">Viewport:</div>
<div> <div>
x: {$viewport.x.toFixed(1)} y: {$viewport.y.toFixed(1)} zoom: {$viewport.zoom.toFixed(1)} x: {viewport.current.x.toFixed(1)} y: {viewport.current.y.toFixed(1)} zoom: {viewport.current.zoom.toFixed(
1
)}
</div> </div>
</aside> </aside>
@@ -1,5 +1,4 @@
<script lang="ts"> <script lang="ts">
import { writable } from 'svelte/store';
import { import {
SvelteFlow, SvelteFlow,
Controls, Controls,
@@ -19,7 +18,7 @@
custom: CustomNode custom: CustomNode
}; };
const nodes = writable([ const nodes = $state.raw([
{ {
id: '1', id: '1',
type: 'custom', type: 'custom',
@@ -40,7 +39,7 @@
} }
]); ]);
const edges = writable([ const edges = $state.raw([
{ {
id: '1-2', id: '1-2',
source: '1', source: '1',
@@ -53,7 +52,7 @@
} }
]); ]);
const { updateNode } = useSvelteFlow(); const { updateNode } = $derived(useSvelteFlow());
const updateNodePosition = () => { const updateNodePosition = () => {
updateNode('1', (node) => ({ position: { x: node.position.x + 10, y: node.position.y } })); updateNode('1', (node) => ({ position: { x: node.position.x + 10, y: node.position.y } }));
@@ -19,6 +19,8 @@
onedgemouseleave onedgemouseleave
}: { store: SvelteFlowStore; edge: EdgeLayouted } & EdgeEvents = $props(); }: { store: SvelteFlowStore; edge: EdgeLayouted } & EdgeEvents = $props();
$inspect(edge);
let { let {
source, source,
target, target,
@@ -36,7 +36,7 @@
const previous = previousLayoutedEdges.get(edge.id); const previous = previousLayoutedEdges.get(edge.id);
if ( if (
previous && previous &&
edge == previous.edge && edge === previous.edge &&
sourceNode == previous.sourceNode && sourceNode == previous.sourceNode &&
targetNode == previous.targetNode targetNode == previous.targetNode
) { ) {
@@ -4,7 +4,7 @@ import { useStore } from '$lib/store';
* Hook for getting the current nodes from the store. * Hook for getting the current nodes from the store.
* *
* @public * @public
* @returns store with an array of nodes * @returns reactive signal of the current edges
*/ */
export function useNodes() { export function useNodes() {
const { nodes } = $derived(useStore()); const { nodes } = $derived(useStore());
@@ -19,7 +19,7 @@ export function useNodes() {
* Hook for getting the current edges from the store. * Hook for getting the current edges from the store.
* *
* @public * @public
* @returns store with an array of edges * @returns reactive signal of the current edges
*/ */
export function useEdges() { export function useEdges() {
const { edges } = $derived(useStore()); const { edges } = $derived(useStore());
@@ -29,3 +29,18 @@ export function useEdges() {
} }
}; };
} }
/**
* Hook for getting the current viewport from the store.
*
* @public
* @returns reactive signal of the current viewport
*/
export function useViewport() {
const { viewport } = $derived(useStore());
return {
get current() {
return viewport;
}
};
}
@@ -370,7 +370,7 @@ export function useSvelteFlow(): {
return Promise.resolve(true); return Promise.resolve(true);
}, },
getViewport: () => store.viewport, getViewport: () => $state.snapshot(store.viewport),
setCenter: async (x, y, options) => { setCenter: async (x, y, options) => {
const nextZoom = typeof options?.zoom !== 'undefined' ? options.zoom : store.maxZoom; const nextZoom = typeof options?.zoom !== 'undefined' ? options.zoom : store.maxZoom;
const currentPanZoom = store.panZoom; const currentPanZoom = store.panZoom;
@@ -1,4 +1,3 @@
import { get } from 'svelte/store';
import type { UpdateNodeInternals } from '@xyflow/system'; import type { UpdateNodeInternals } from '@xyflow/system';
import { useStore } from '$lib/store'; import { useStore } from '$lib/store';
@@ -10,7 +9,7 @@ import { useStore } from '$lib/store';
* @returns function for updating node internals * @returns function for updating node internals
*/ */
export function useUpdateNodeInternals(): UpdateNodeInternals { export function useUpdateNodeInternals(): UpdateNodeInternals {
const { domNode, updateNodeInternals } = useStore(); const { domNode, updateNodeInternals } = $derived(useStore());
// @todo: do we want to add this to system? // @todo: do we want to add this to system?
const updateInternals = (id: string | string[]) => { const updateInternals = (id: string | string[]) => {
@@ -18,7 +17,7 @@ export function useUpdateNodeInternals(): UpdateNodeInternals {
const updates = new Map(); const updates = new Map();
updateIds.forEach((updateId) => { updateIds.forEach((updateId) => {
const nodeElement = get(domNode)?.querySelector( const nodeElement = domNode?.querySelector(
`.svelte-flow__node[data-id="${updateId}"]` `.svelte-flow__node[data-id="${updateId}"]`
) as HTMLDivElement; ) as HTMLDivElement;
+3 -3
View File
@@ -31,10 +31,10 @@ export { useStore } from '$lib/store';
export * from '$lib/utils'; export * from '$lib/utils';
//hooks //hooks
export * from '$lib/hooks/useSvelteFlow'; export * from '$lib/hooks/useSvelteFlow.svelte';
export * from '$lib/hooks/useUpdateNodeInternals'; export * from '$lib/hooks/useUpdateNodeInternals.svelte';
export * from '$lib/hooks/useConnection.svelte'; export * from '$lib/hooks/useConnection.svelte';
export * from '$lib/hooks/useNodesEdges.svelte'; export * from '$lib/hooks/useNodesEdgesViewport.svelte';
export * from '$lib/hooks/useHandleConnections.svelte'; export * from '$lib/hooks/useHandleConnections.svelte';
export * from '$lib/hooks/useNodesData'; export * from '$lib/hooks/useNodesData';
export * from '$lib/hooks/useInternalNode'; export * from '$lib/hooks/useInternalNode';
@@ -11,7 +11,7 @@
type XYResizerChildChange type XYResizerChildChange
} from '@xyflow/system'; } from '@xyflow/system';
import type { ResizeControlProps } from './types'; import type { ResizeControlProps } from './types';
import { get } from 'svelte/store'; import { useSvelteFlow } from '$lib/hooks/useSvelteFlow.svelte';
let { let {
nodeId, nodeId,
@@ -34,6 +34,8 @@
const store = useStore(); const store = useStore();
const { updateNode } = useSvelteFlow();
let id = $derived( let id = $derived(
typeof nodeId === 'string' ? nodeId : getContext<string>('svelteflow__node_id') typeof nodeId === 'string' ? nodeId : getContext<string>('svelteflow__node_id')
); );
@@ -72,28 +74,20 @@
}; };
}, },
onChange: (change: XYResizerChange, childChanges: XYResizerChildChange[]) => { onChange: (change: XYResizerChange, childChanges: XYResizerChildChange[]) => {
const node = store.nodeLookup.get(id)?.internals.userNode; updateNode(id, (node) => ({
if (!node) { ...node,
return; position: { x: change.x ?? node.position.x, y: change.y ?? node.position.y },
} width: change.width ?? node.width,
height: change.height ?? node.height
if (change.x !== undefined && change.y !== undefined) { }));
node.position = { x: change.x, y: change.y };
}
if (change.width !== undefined && change.height !== undefined) {
node.width = change.width;
node.height = change.height;
}
// TODO: performance?
for (const childChange of childChanges) { for (const childChange of childChanges) {
const childNode = store.nodeLookup.get(childChange.id)?.internals.userNode; updateNode(childChange.id, (node) => ({
if (childNode) { ...node,
childNode.position = childChange.position; position: childChange.position
} }));
} }
// store.nodes.set(get(store.nodes));
} }
}); });
} }
@@ -4,7 +4,7 @@
import portal from '$lib/actions/portal'; import portal from '$lib/actions/portal';
import { useStore } from '$lib/store'; import { useStore } from '$lib/store';
import { useSvelteFlow } from '$lib/hooks/useSvelteFlow'; import { useSvelteFlow } from '$lib/hooks/useSvelteFlow.svelte';
import type { InternalNode } from '$lib/types'; import type { InternalNode } from '$lib/types';
import type { NodeToolbarProps } from './types'; import type { NodeToolbarProps } from './types';