first working version with using $state for nodes & edges
This commit is contained in:
@@ -14,11 +14,11 @@
|
||||
onedgemouseleave
|
||||
}: { store: SvelteFlowStore } & EdgeEvents = $props();
|
||||
|
||||
const { edges, nodes } = store;
|
||||
// const { edges, nodes } = store;
|
||||
|
||||
let layoutedEdges = $derived.by(() => {
|
||||
$nodes;
|
||||
const layoutedEdges = $edges.reduce<EdgeLayouted[]>((res, edge) => {
|
||||
store.nodes;
|
||||
const layoutedEdges = store.edges.reduce<EdgeLayouted[]>((res, edge) => {
|
||||
const sourceNode = store.nodeLookup.get(edge.source);
|
||||
const targetNode = store.nodeLookup.get(edge.target);
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import { onDestroy } from 'svelte';
|
||||
import { nodeHasDimensions } from '@xyflow/system';
|
||||
|
||||
import type { NodeEvents } from '$lib/types';
|
||||
import type { Node, NodeEvents } from '$lib/types';
|
||||
import { NodeWrapper } from '$lib/components/NodeWrapper';
|
||||
import type { SvelteFlowStore } from '$lib/store/types';
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
onnodedragstop
|
||||
}: { store: SvelteFlowStore; nodeClickDistance?: number } & NodeEvents = $props();
|
||||
|
||||
const { nodes } = store;
|
||||
// const { nodes } = store;
|
||||
|
||||
const resizeObserver: ResizeObserver | null =
|
||||
typeof ResizeObserver === 'undefined'
|
||||
@@ -43,10 +43,19 @@
|
||||
onDestroy(() => {
|
||||
resizeObserver?.disconnect();
|
||||
});
|
||||
|
||||
function give(node: Node) {
|
||||
const internalNode = store.nodeLookup.get(node.id);
|
||||
// console.log('this reruns most definitely', internalNode);
|
||||
console.log(internalNode?.position);
|
||||
return internalNode;
|
||||
}
|
||||
|
||||
// $inspect(store.nodes).with(console.trace);
|
||||
</script>
|
||||
|
||||
<div class="svelte-flow__nodes">
|
||||
{#each $nodes as node (node.id)}
|
||||
{#each store.nodes as node (node.id)}
|
||||
{@const internalNode = store.nodeLookup.get(node.id)}
|
||||
<NodeWrapper
|
||||
{store}
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
children
|
||||
}: PaneProps = $props();
|
||||
|
||||
const { nodes, edges } = store;
|
||||
// const { nodes, edges } = store;
|
||||
|
||||
// svelte-ignore non_reactive_update
|
||||
let container: HTMLDivElement;
|
||||
@@ -126,7 +126,7 @@
|
||||
height: Math.abs(mousePos.y - startY)
|
||||
};
|
||||
const prevSelectedNodeIds = selectedNodes.map((n) => n.id);
|
||||
const prevSelectedEdgeIds = getConnectedEdges(selectedNodes, $edges).map((e) => e.id);
|
||||
const prevSelectedEdgeIds = getConnectedEdges(selectedNodes, store.edges).map((e) => e.id);
|
||||
|
||||
selectedNodes = getNodesInside(
|
||||
store.nodeLookup,
|
||||
@@ -135,7 +135,7 @@
|
||||
store.selectionMode === SelectionMode.Partial,
|
||||
true
|
||||
);
|
||||
const selectedEdgeIds = getConnectedEdges(selectedNodes, $edges).map((e) => e.id);
|
||||
const selectedEdgeIds = getConnectedEdges(selectedNodes, store.edges).map((e) => e.id);
|
||||
const selectedNodeIds = selectedNodes.map((n) => n.id);
|
||||
|
||||
// this prevents unnecessary updates while updating the selection rectangle
|
||||
@@ -143,14 +143,14 @@
|
||||
prevSelectedNodeIds.length !== selectedNodeIds.length ||
|
||||
selectedNodeIds.some((id) => !prevSelectedNodeIds.includes(id))
|
||||
) {
|
||||
nodes.update((nodes) => nodes.map(toggleSelected(selectedNodeIds)));
|
||||
// store.nodes.update((nodes) => nodes.map(toggleSelected(selectedNodeIds)));
|
||||
}
|
||||
|
||||
if (
|
||||
prevSelectedEdgeIds.length !== selectedEdgeIds.length ||
|
||||
selectedEdgeIds.some((id) => !prevSelectedEdgeIds.includes(id))
|
||||
) {
|
||||
edges.update((edges) => edges.map(toggleSelected(selectedEdgeIds)));
|
||||
// store.edges.update((edges) => edges.map(toggleSelected(selectedEdgeIds)));
|
||||
}
|
||||
|
||||
store.selectionRectMode = 'user';
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<!-- TODO: why is this neccessary for types to work?? -->
|
||||
<svelte:options runes={true} />
|
||||
|
||||
<script lang="ts">
|
||||
import { onMount, getContext, setContext } from 'svelte';
|
||||
import { getContext, setContext, onDestroy } from 'svelte';
|
||||
import cc from 'classcat';
|
||||
import { PanOnScrollMode } from '@xyflow/system';
|
||||
|
||||
@@ -64,28 +67,45 @@
|
||||
connectionLineStyle = '',
|
||||
attributionPosition,
|
||||
children,
|
||||
nodes = $bindable([]),
|
||||
edges = $bindable([]),
|
||||
...props
|
||||
}: SvelteFlowProps = $props();
|
||||
|
||||
// svelte-ignore perf_avoid_inline_class
|
||||
const container: ContainerSignals = new (class {
|
||||
domNode = $state<HTMLDivElement>();
|
||||
width = $state<number | undefined>(width);
|
||||
height = $state<number | undefined>(height);
|
||||
})();
|
||||
let domNode = $state<HTMLDivElement>();
|
||||
let clientWidth = $state<number | undefined>(width);
|
||||
let clientHeight = $state<number | undefined>(height);
|
||||
|
||||
const store = createStore({
|
||||
props,
|
||||
container
|
||||
get domNode() {
|
||||
return domNode;
|
||||
},
|
||||
get width() {
|
||||
return clientWidth;
|
||||
},
|
||||
get height() {
|
||||
return clientHeight;
|
||||
},
|
||||
get nodes() {
|
||||
return nodes;
|
||||
},
|
||||
set nodes(newNodes) {
|
||||
nodes = newNodes;
|
||||
},
|
||||
get edges() {
|
||||
return edges;
|
||||
},
|
||||
set edges(newEdges) {
|
||||
edges = newEdges;
|
||||
}
|
||||
});
|
||||
|
||||
store.syncNodeStores(props.nodes);
|
||||
store.syncEdgeStores(props.edges);
|
||||
|
||||
const providerContext = getContext<ProviderContext>(key);
|
||||
if (providerContext) {
|
||||
providerContext.setStore(store);
|
||||
}
|
||||
|
||||
setContext(key, {
|
||||
provider: false,
|
||||
getStore() {
|
||||
@@ -93,93 +113,94 @@
|
||||
}
|
||||
} satisfies StoreContext);
|
||||
|
||||
onMount(() => {
|
||||
return () => {
|
||||
store.reset();
|
||||
};
|
||||
onDestroy(() => {
|
||||
store.reset();
|
||||
});
|
||||
|
||||
let colorModeClass = $derived(useColorModeClass(store.colorMode));
|
||||
</script>
|
||||
|
||||
<div
|
||||
bind:this={container.domNode}
|
||||
bind:clientWidth={container.width}
|
||||
bind:clientHeight={container.height}
|
||||
style:width
|
||||
style:height
|
||||
{style}
|
||||
class={cc(['svelte-flow', className, $colorModeClass])}
|
||||
data-testid="svelte-flow__wrapper"
|
||||
{...props}
|
||||
role="application"
|
||||
>
|
||||
<KeyHandler
|
||||
{store}
|
||||
{selectionKey}
|
||||
{deleteKey}
|
||||
{panActivationKey}
|
||||
{multiSelectionKey}
|
||||
{zoomActivationKey}
|
||||
/>
|
||||
<Zoom
|
||||
{store}
|
||||
{onMoveStart}
|
||||
{onMove}
|
||||
{onMoveEnd}
|
||||
{panOnScrollMode}
|
||||
{preventScrolling}
|
||||
{zoomOnScroll}
|
||||
{zoomOnDoubleClick}
|
||||
{zoomOnPinch}
|
||||
{panOnScroll}
|
||||
{panOnDrag}
|
||||
{paneClickDistance}
|
||||
<!-- TODO: this is the only hack in the library so far. Can we get rid of it? -->
|
||||
{#if store.adoptNodes && store.adoptEdges}
|
||||
<div
|
||||
bind:this={domNode}
|
||||
bind:clientWidth
|
||||
bind:clientHeight
|
||||
style:width
|
||||
style:height
|
||||
{style}
|
||||
class={cc(['svelte-flow', className, $colorModeClass])}
|
||||
data-testid="svelte-flow__wrapper"
|
||||
{...props}
|
||||
role="application"
|
||||
>
|
||||
<Pane {store} {onpaneclick} {onpanecontextmenu} {panOnDrag} {selectionOnDrag}>
|
||||
<ViewportComponent {store}>
|
||||
<EdgeRenderer
|
||||
{store}
|
||||
{onedgeclick}
|
||||
{onedgecontextmenu}
|
||||
{onedgemouseenter}
|
||||
{onedgemouseleave}
|
||||
/>
|
||||
<ConnectionLine
|
||||
{store}
|
||||
containerStyle={connectionLineContainerStyle}
|
||||
style={connectionLineStyle}
|
||||
{connectionLine}
|
||||
/>
|
||||
<div class="svelte-flow__edgelabel-renderer"></div>
|
||||
<div class="svelte-flow__viewport-portal"></div>
|
||||
<NodeRenderer
|
||||
{store}
|
||||
{nodeClickDistance}
|
||||
{onnodeclick}
|
||||
{onnodecontextmenu}
|
||||
{onnodemouseenter}
|
||||
{onnodemousemove}
|
||||
{onnodemouseleave}
|
||||
{onnodedrag}
|
||||
{onnodedragstart}
|
||||
{onnodedragstop}
|
||||
/>
|
||||
<NodeSelection
|
||||
{store}
|
||||
{onselectionclick}
|
||||
{onselectioncontextmenu}
|
||||
{onnodedrag}
|
||||
{onnodedragstart}
|
||||
{onnodedragstop}
|
||||
/>
|
||||
</ViewportComponent>
|
||||
<UserSelection />
|
||||
</Pane>
|
||||
</Zoom>
|
||||
<Attribution {proOptions} position={attributionPosition} />
|
||||
{@render children?.()}
|
||||
</div>
|
||||
<KeyHandler
|
||||
{store}
|
||||
{selectionKey}
|
||||
{deleteKey}
|
||||
{panActivationKey}
|
||||
{multiSelectionKey}
|
||||
{zoomActivationKey}
|
||||
/>
|
||||
<Zoom
|
||||
{store}
|
||||
{onMoveStart}
|
||||
{onMove}
|
||||
{onMoveEnd}
|
||||
{panOnScrollMode}
|
||||
{preventScrolling}
|
||||
{zoomOnScroll}
|
||||
{zoomOnDoubleClick}
|
||||
{zoomOnPinch}
|
||||
{panOnScroll}
|
||||
{panOnDrag}
|
||||
{paneClickDistance}
|
||||
>
|
||||
<Pane {store} {onpaneclick} {onpanecontextmenu} {panOnDrag} {selectionOnDrag}>
|
||||
<ViewportComponent {store}>
|
||||
<EdgeRenderer
|
||||
{store}
|
||||
{onedgeclick}
|
||||
{onedgecontextmenu}
|
||||
{onedgemouseenter}
|
||||
{onedgemouseleave}
|
||||
/>
|
||||
<ConnectionLine
|
||||
{store}
|
||||
containerStyle={connectionLineContainerStyle}
|
||||
style={connectionLineStyle}
|
||||
{connectionLine}
|
||||
/>
|
||||
<div class="svelte-flow__edgelabel-renderer"></div>
|
||||
<div class="svelte-flow__viewport-portal"></div>
|
||||
<NodeRenderer
|
||||
{store}
|
||||
{nodeClickDistance}
|
||||
{onnodeclick}
|
||||
{onnodecontextmenu}
|
||||
{onnodemouseenter}
|
||||
{onnodemousemove}
|
||||
{onnodemouseleave}
|
||||
{onnodedrag}
|
||||
{onnodedragstart}
|
||||
{onnodedragstop}
|
||||
/>
|
||||
<NodeSelection
|
||||
{store}
|
||||
{onselectionclick}
|
||||
{onselectioncontextmenu}
|
||||
{onnodedrag}
|
||||
{onnodedragstart}
|
||||
{onnodedragstop}
|
||||
/>
|
||||
</ViewportComponent>
|
||||
<UserSelection />
|
||||
</Pane>
|
||||
</Zoom>
|
||||
<Attribution {proOptions} position={attributionPosition} />
|
||||
{@render children?.()}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
.svelte-flow {
|
||||
|
||||
@@ -59,7 +59,7 @@ export type SvelteFlowProps = NodeEvents &
|
||||
* }
|
||||
* ]);
|
||||
*/
|
||||
nodes: Writable<Node[]>;
|
||||
nodes: Node[];
|
||||
/** An array of edges to render in a controlled flow.
|
||||
* @example
|
||||
* const edges = writable([
|
||||
@@ -70,7 +70,7 @@ export type SvelteFlowProps = NodeEvents &
|
||||
* }
|
||||
* ]);
|
||||
*/
|
||||
edges: Writable<Edge[]>;
|
||||
edges: Edge[];
|
||||
/** Custom node types to be available in a flow.
|
||||
*
|
||||
* Svelte Flow matches a node's type to a component in the nodeTypes object.
|
||||
@@ -191,7 +191,7 @@ export type SvelteFlowProps = NodeEvents &
|
||||
/**
|
||||
* Controls if nodes should be automatically selected when being dragged
|
||||
*/
|
||||
selectNodesOnDrag: boolean;
|
||||
selectNodesOnDrag?: boolean;
|
||||
/** Grid all nodes will snap to
|
||||
* @example [20, 20]
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user