feat(svelte): add updateNodeInternals
This commit is contained in:
@@ -1,46 +1,47 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { goto } from '$app/navigation';
|
import { goto } from '$app/navigation';
|
||||||
import { page } from '$app/stores';
|
import { page } from '$app/stores';
|
||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
'customnode',
|
'customnode',
|
||||||
'drag-n-drop',
|
'drag-n-drop',
|
||||||
'edges',
|
'edges',
|
||||||
'figma',
|
'figma',
|
||||||
'interaction',
|
'interaction',
|
||||||
'overview',
|
'overview',
|
||||||
'stress',
|
'stress',
|
||||||
'subflows',
|
'subflows',
|
||||||
'usesvelteflow',
|
'usesvelteflow',
|
||||||
'validation'
|
'useupdatenodeinternals',
|
||||||
];
|
'validation'
|
||||||
|
];
|
||||||
|
|
||||||
const onChange = (event: Event) => {
|
const onChange = (event: Event) => {
|
||||||
const route = (event.target as HTMLSelectElement).value;
|
const route = (event.target as HTMLSelectElement).value;
|
||||||
goto(route);
|
goto(route);
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<header>
|
<header>
|
||||||
<div class="logo">Svelte Flow</div>
|
<div class="logo">Svelte Flow</div>
|
||||||
<select on:change={onChange} value={$page.route.id}>
|
<select on:change={onChange} value={$page.route.id}>
|
||||||
{#each routes as route}
|
{#each routes as route}
|
||||||
<option value={`/${route}`}>{route}</option>
|
<option value={`/${route}`}>{route}</option>
|
||||||
{/each}
|
{/each}
|
||||||
</select>
|
</select>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
header {
|
header {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
border-bottom: 1px solid #eee;
|
border-bottom: 1px solid #eee;
|
||||||
display: flex;
|
display: flex;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
color: #111;
|
color: #111;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo {
|
.logo {
|
||||||
margin-right: 1rem;
|
margin-right: 1rem;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { SvelteFlowProvider } from '@xyflow/svelte';
|
||||||
|
|
||||||
|
import Flow from './Flow.svelte';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<SvelteFlowProvider>
|
||||||
|
<Flow />
|
||||||
|
</SvelteFlowProvider>
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Handle, Position, type NodeProps, useUpdateNodeInternals } from '@xyflow/svelte';
|
||||||
|
|
||||||
|
type $$Props = NodeProps;
|
||||||
|
|
||||||
|
export let id: $$Props['id'];
|
||||||
|
|
||||||
|
const updateNodeInternals = useUpdateNodeInternals();
|
||||||
|
|
||||||
|
$: handleCount = 1;
|
||||||
|
|
||||||
|
const onClick = () => {
|
||||||
|
handleCount += 1;
|
||||||
|
updateNodeInternals(id);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Handle type="target" position={Position.Top} on:connect />
|
||||||
|
<button on:click={onClick}>add handle</button>
|
||||||
|
|
||||||
|
{#each Array.from({ length: handleCount }) as handle, i}
|
||||||
|
<Handle
|
||||||
|
type="source"
|
||||||
|
position={Position.Bottom}
|
||||||
|
id={`${i}`}
|
||||||
|
style={`left: ${i * 10}px;`}
|
||||||
|
on:connect
|
||||||
|
/>
|
||||||
|
{/each}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { writable } from 'svelte/store';
|
||||||
|
import {
|
||||||
|
SvelteFlow,
|
||||||
|
Controls,
|
||||||
|
Background,
|
||||||
|
BackgroundVariant,
|
||||||
|
MiniMap,
|
||||||
|
type NodeTypes
|
||||||
|
} from '@xyflow/svelte';
|
||||||
|
|
||||||
|
import CustomNode from './CustomNode.svelte';
|
||||||
|
|
||||||
|
import '@xyflow/svelte/dist/style.css';
|
||||||
|
|
||||||
|
const nodeTypes: NodeTypes = {
|
||||||
|
custom: CustomNode
|
||||||
|
};
|
||||||
|
|
||||||
|
const nodes = writable([
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
type: 'custom',
|
||||||
|
data: { label: 'Input Node' },
|
||||||
|
position: { x: 150, y: 0 }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
type: 'default',
|
||||||
|
data: { label: 'Node' },
|
||||||
|
position: { x: 0, y: 150 }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '3',
|
||||||
|
type: 'output',
|
||||||
|
data: { label: 'Output Node' },
|
||||||
|
position: { x: 300, y: 150 }
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
const edges = writable([
|
||||||
|
{
|
||||||
|
id: '1-2',
|
||||||
|
source: '1',
|
||||||
|
target: '2'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '1-3',
|
||||||
|
source: '1',
|
||||||
|
target: '3'
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<SvelteFlow {nodes} {edges} {nodeTypes} fitView>
|
||||||
|
<Controls />
|
||||||
|
<Background variant={BackgroundVariant.Dots} />
|
||||||
|
<MiniMap />
|
||||||
|
</SvelteFlow>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
main {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@xyflow/svelte",
|
"name": "@xyflow/svelte",
|
||||||
"version": "0.0.18",
|
"version": "0.0.19",
|
||||||
"description": "Svelte Flow - A highly customizable Svelte library for building node-based editors, workflow systems, diagrams and more.",
|
"description": "Svelte Flow - A highly customizable Svelte library for building node-based editors, workflow systems, diagrams and more.",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"svelte",
|
"svelte",
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ export function useSvelteFlow(): {
|
|||||||
nodes: SvelteFlowStore['nodes'];
|
nodes: SvelteFlowStore['nodes'];
|
||||||
edges: SvelteFlowStore['edges'];
|
edges: SvelteFlowStore['edges'];
|
||||||
} {
|
} {
|
||||||
// how to get the new context here? fit view doesn't work, because the store is not updated (uses old nodes store)
|
|
||||||
const {
|
const {
|
||||||
zoomIn,
|
zoomIn,
|
||||||
zoomOut,
|
zoomOut,
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import { get } from 'svelte/store';
|
||||||
|
import type { UpdateNodeInternals, NodeDimensionUpdate } from '@xyflow/system';
|
||||||
|
|
||||||
|
import { useStore } from '$lib/store';
|
||||||
|
|
||||||
|
export function useUpdateNodeInternals(): UpdateNodeInternals {
|
||||||
|
const { domNode, updateNodeDimensions } = useStore();
|
||||||
|
|
||||||
|
// @todo: do we want to add this to system?
|
||||||
|
const updateInternals = (id: string | string[]) => {
|
||||||
|
const updateIds = Array.isArray(id) ? id : [id];
|
||||||
|
const updates = updateIds.reduce<NodeDimensionUpdate[]>((res, updateId) => {
|
||||||
|
const nodeElement = get(domNode)?.querySelector(
|
||||||
|
`.svelte-flow__node[data-id="${updateId}"]`
|
||||||
|
) as HTMLDivElement;
|
||||||
|
|
||||||
|
if (nodeElement) {
|
||||||
|
res.push({ id: updateId, nodeElement, forceUpdate: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
requestAnimationFrame(() => updateNodeDimensions(updates));
|
||||||
|
};
|
||||||
|
|
||||||
|
return updateInternals;
|
||||||
|
}
|
||||||
@@ -20,6 +20,7 @@ export { useStore } from '$lib/store';
|
|||||||
// utils
|
// utils
|
||||||
export * from '$lib/utils';
|
export * from '$lib/utils';
|
||||||
export * from '$lib/hooks/useSvelteFlow';
|
export * from '$lib/hooks/useSvelteFlow';
|
||||||
|
export * from '$lib/hooks/useUpdateNodeInternals';
|
||||||
|
|
||||||
// types
|
// types
|
||||||
export type { Edge, EdgeProps, EdgeTypes, DefaultEdgeOptions } from '$lib/types/edges';
|
export type { Edge, EdgeProps, EdgeTypes, DefaultEdgeOptions } from '$lib/types/edges';
|
||||||
|
|||||||
Reference in New Issue
Block a user