feat(svelte): reactive nodes

This commit is contained in:
moklick
2023-02-22 18:06:26 +01:00
parent f91ec399a7
commit 658366e67f
9 changed files with 88 additions and 35 deletions
@@ -1,7 +1,7 @@
<script lang="ts">
import Handle from '$lib/components/Handle/index.svelte';
import { Position } from '@reactflow/system';
export let data: { label: string } = { label: 'Node' };
export let xPos: number = 0;
export let yPos: number = 0;
@@ -16,7 +16,7 @@
export let positionAbsolute: XYPosition = { x: 0, y: 0 };
export let position: XYPosition = { x: 0, y: 0 };
export let dragging: boolean = false;
export let resizeObserver: WrapNodeProps['resizeObserver'] = undefined;
export let resizeObserver: WrapNodeProps['resizeObserver'] = null;
export let style: WrapNodeProps['style'] = undefined;
export let width: WrapNodeProps['width'] = undefined;
export let height: WrapNodeProps['height'] = undefined;
@@ -30,7 +30,7 @@
let nodeRef: HTMLDivElement;
const { nodesStore, transformStore, updateNodePositions, nodeTypesStore } = useStore();
const nodeComponent: typeof SvelteComponentTyped<NodeProps> = $nodeTypesStore[type] || DefaultNode;
const nodeComponent: typeof SvelteComponentTyped<Partial<NodeProps>> = $nodeTypesStore[type] || DefaultNode;
setContext('rf_nodeid', id);
+7
View File
@@ -0,0 +1,7 @@
import type { PanelPosition } from '@reactflow/system';
export type PanelProps = {
position?: PanelPosition;
style?: string;
class?: string;
};
@@ -1,11 +1,12 @@
<script lang="ts">
import type { PanelPosition } from '@reactflow/system';
import cc from 'classcat';
import type { PanelProps } from './Panel';
export let position: PanelPosition = 'top-right';
export let style: string = '';
interface $$Props extends PanelProps {}
let className: string;
export let position: $$Props['position'] = 'top-right';
export let style: $$Props['style'] = '';
let className: $$Props['class'] = undefined;
export { className as class }
$: positionClasses = `${position}`.split('-');
@@ -11,21 +11,21 @@
import UserSelection from '$lib/components/UserSelection/index.svelte';
import NodeSelection from '$lib/components/NodeSelection/index.svelte';
import KeyHandler from '$lib/components/KeyHandler/index.svelte';
import type { NodeTypes, Node, Edge } from '$lib/types';
import type { SvelteFlowProps } from '$lib/types';
export let id: string = '1';
export let nodes: Node[] = [];
export let edges: Edge[] = [];
export let fitView: boolean = false;
export let nodeTypes: NodeTypes;
let className: string = '';
interface $$Props extends SvelteFlowProps {}
export let id: $$Props['id'] = '1';
export let nodes: $$Props['nodes'] = [];
export let edges: $$Props['edges'] = [];
export let fitView: $$Props['fitView'] = undefined;
export let nodeTypes: $$Props['nodeTypes'] = undefined;
let className: $$Props['class'] = undefined;
export { className as class };
let domNode: Element;
const store = createStore({
nodes,
edges,
fitView,
nodeTypes
});
@@ -38,7 +38,20 @@
const { width, height } = domNode.getBoundingClientRect();
store.widthStore.set(width);
store.heightStore.set(height);
})
// @todo: is this a svelte way for two way binding?
store.nodesStore.subscribe((ns) => {
nodes = ns;
});
});
$: {
store.setNodes(nodes);
}
$: {
store.setEdges(edges);
}
</script>
<div
+29 -10
View File
@@ -34,9 +34,7 @@ import SmoothStepEdge from '$lib/components/edges/SmoothStepEdge.svelte';
export const key = Symbol();
type CreateStoreProps = {
nodes: Node[];
edges: Edge[];
fitView: boolean;
fitView?: boolean;
nodeOrigin?: NodeOrigin;
transform?: Transform;
nodeTypes?: NodeTypes;
@@ -50,8 +48,8 @@ export type EdgeWithData = EdgePosition & {
};
type SvelteFlowStore = {
nodesStore: Writable<CreateStoreProps['nodes']>;
edgesStore: Writable<CreateStoreProps['edges']>;
nodesStore: Writable<Node[]>;
edgesStore: Writable<Edge[]>;
heightStore: Writable<number>;
widthStore: Writable<number>;
d3Store: Writable<{
@@ -69,6 +67,8 @@ type SvelteFlowStore = {
selectionKeyPressedStore: Writable<boolean>;
nodeTypesStore: Writable<NodeTypes>;
edgeTypesStore: Writable<EdgeTypes>;
setNodes: (nodes: Node[]) => void;
setEdges: (edges: Edge[]) => void;
zoomIn: (options?: ViewportHelperFunctionOptions) => void;
zoomOut: (options?: ViewportHelperFunctionOptions) => void;
fitView: (options?: ViewportHelperFunctionOptions) => boolean;
@@ -82,8 +82,6 @@ type SvelteFlowStore = {
};
export function createStore({
nodes = [],
edges = [],
transform = [0, 0, 1],
nodeOrigin = [0, 0],
fitView: fitViewOnInit = false,
@@ -91,8 +89,8 @@ export function createStore({
edgeTypes = {},
id = '1'
}: CreateStoreProps): SvelteFlowStore {
const nodesStore = writable(nodes.map((n) => ({ ...n, positionAbsolute: n.position })));
const edgesStore = writable(edges);
const nodesStore = writable([] as Node[]);
const edgesStore = writable([] as Edge[]);
const heightStore = writable(500);
const widthStore = writable(500);
const nodeOriginStore = writable(nodeOrigin);
@@ -119,6 +117,7 @@ export function createStore({
smoothstep: edgeTypes.smoothstep || SmoothStepEdge,
default: edgeTypes.default || BezierEdge
});
const transformStore = writable(transform);
let fitViewOnInitDone = false;
@@ -171,7 +170,25 @@ export function createStore({
.filter((e) => e !== null) as EdgeWithData[];
});
const transformStore = writable(transform);
function setEdges(edges: Edge[]) {
edgesStore.set(edges);
}
function setNodes(nodes: Node[]) {
nodesStore.update((currentNodes) => {
const nextNodes = nodes.map((n) => {
const currentNode = currentNodes.find((cn) => cn.id === n.id) || {};
return {
...currentNode,
...n,
positionAbsolute: n.position
};
});
return nextNodes;
});
}
function updateNodePositions(nodeDragItems: NodeDragItem[], dragging = false) {
nodesStore.update((nds) => {
@@ -310,6 +327,8 @@ export function createStore({
selectionMode,
nodeTypesStore,
edgeTypesStore,
setNodes,
setEdges,
updateNodePositions,
updateNodeDimensions,
zoomIn,
+1
View File
@@ -8,4 +8,5 @@ export type SvelteFlowProps = {
fitView?: boolean;
class?: string;
style?: string;
id?: string;
};
+3 -2
View File
@@ -9,6 +9,7 @@ export type Node<NodeData = any> = {
position: XYPosition;
sourcePosition?: Position;
targetPosition?: Position;
positionAbsolute?: XYPosition;
width?: number;
height?: number;
@@ -35,7 +36,7 @@ export type NodeProps<NodeData = any> = Pick<
};
export type WrapNodeProps = Node & {
resizeObserver?: ResizeObserver;
resizeObserver?: ResizeObserver | null;
};
export type NodeTypes = Record<string, typeof SvelteComponentTyped<NodeProps>>;
export type NodeTypes = Record<string, typeof SvelteComponentTyped<Partial<NodeProps>>>;
+17 -6
View File
@@ -1,9 +1,9 @@
<script lang="ts">
import type { Node, Edge } from '../lib/types';
import SvelteFlow, { Controls, Background, BackgroundVariant, Minimap } from '../lib/index';
import type { Node, Edge, NodeTypes } from '../lib/types';
import SvelteFlow, { Controls, Background, BackgroundVariant, Minimap, Panel } from '../lib/index';
import CustomNode from '../customnodes/Custom.svelte';
const nodeTypes = {
const nodeTypes: NodeTypes = {
custom: CustomNode,
};
@@ -43,7 +43,7 @@
// }
// }
const nodes: Node<{ label: string }>[] = [{
let nodes: Node<{ label: string }>[] = [{
id: '1',
type: 'input',
data: { label: 'Input Node' },
@@ -79,7 +79,7 @@
position: { x: 150, y: 300 },
}];
const edges: Edge[] = [{
let edges: Edge[] = [{
id: '1-2',
type: 'default',
source: '1',
@@ -95,12 +95,23 @@
source: '2',
target: '4'
}];
function updateNode() {
nodes[0].position = { x: nodes[0].position.x + 20, y: nodes[0].position.y };
}
// $: {
// console.log('nodes changed', nodes)
// }
</script>
<SvelteFlow {nodes} {edges} {nodeTypes} fitView>
<SvelteFlow bind:nodes bind:edges {nodeTypes} fitView>
<Controls />
<Background variant={BackgroundVariant.Dots} />
<Minimap />
<Panel position="top-right">
<button on:click={updateNode}>update node pos</button>
</Panel>
</SvelteFlow>
<style>