cleaning up Svelte 4 leftovers
This commit is contained in:
@@ -124,16 +124,22 @@
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
function updateNode() {
|
function updateNode() {
|
||||||
nodes[0].position.x += 20;
|
// We might as well just use updateNode() here
|
||||||
// nodes = $nodes;
|
// this is just to show what is required to update a node
|
||||||
|
const newNode = { ...nodes[0] };
|
||||||
|
newNode.position.x += 20;
|
||||||
|
nodes[0] = newNode;
|
||||||
|
nodes = [...nodes];
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateEdge() {
|
function updateEdge() {
|
||||||
edges[0].type = edges[0].type === 'default' ? 'smoothstep' : 'default';
|
// We might as well just use updateEdge() here
|
||||||
// edges = $edges;
|
// this is just to show what is required to update an edge
|
||||||
|
const newEdge = { ...edges[0] };
|
||||||
|
newEdge.type = newEdge.type === 'default' ? 'smoothstep' : 'default';
|
||||||
|
edges[0] = newEdge;
|
||||||
|
edges = [...edges];
|
||||||
}
|
}
|
||||||
|
|
||||||
// $inspect(nodes);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<SvelteFlow
|
<SvelteFlow
|
||||||
@@ -152,38 +158,38 @@
|
|||||||
initialViewport={{ x: 100, y: 100, zoom: 2 }}
|
initialViewport={{ x: 100, y: 100, zoom: 2 }}
|
||||||
snapGrid={[25, 25]}
|
snapGrid={[25, 25]}
|
||||||
oninit={() => console.log('on init')}
|
oninit={() => console.log('on init')}
|
||||||
on:nodeclick={(event) => console.log('on node click', event)}
|
onnodeclick={(event) => console.log('on node click', event)}
|
||||||
on:nodemouseenter={(event) => console.log('on node enter', event)}
|
onnodemouseenter={(event) => console.log('on node enter', event)}
|
||||||
on:nodemouseleave={(event) => console.log('on node leave', event)}
|
onnodemouseleave={(event) => console.log('on node leave', event)}
|
||||||
on:edgeclick={(event) => console.log('edge click', event)}
|
onedgeclick={(event) => console.log('edge click', event)}
|
||||||
on:edgemouseenter={(event) => console.log('edge enter', event)}
|
onedgemouseenter={(event) => console.log('edge enter', event)}
|
||||||
on:edgemouseleave={(event) => console.log('edge leave', event)}
|
onedgemouseleave={(event) => console.log('edge leave', event)}
|
||||||
onconnectstart={(event) => console.log('on connect start', event)}
|
onconnectstart={(event) => console.log('on connect start', event)}
|
||||||
onconnect={(event) => console.log('on connect', event)}
|
onconnect={(event) => console.log('on connect', event)}
|
||||||
onconnectend={(event) => console.log('on connect end', event)}
|
onconnectend={(event) => console.log('on connect end', event)}
|
||||||
on:paneclick={(event) => console.log('on pane click', event)}
|
onpaneclick={(event) => console.log('on pane click', event)}
|
||||||
on:panecontextmenu={(event) => {
|
onpanecontextmenu={(event) => {
|
||||||
console.log('on pane contextmenu', event);
|
console.log('on pane contextmenu', event);
|
||||||
}}
|
}}
|
||||||
on:nodedrag={(event) => {
|
onnodedrag={(event) => {
|
||||||
console.log('on node drag', event);
|
console.log('on node drag', event);
|
||||||
}}
|
}}
|
||||||
on:nodedragstart={(event) => {
|
onnodedragstart={(event) => {
|
||||||
console.log('on node drag start', event);
|
console.log('on node drag start', event);
|
||||||
}}
|
}}
|
||||||
on:nodedragstop={(event) => {
|
onnodedragstop={({ event }) => {
|
||||||
console.log('on node drag stop', event);
|
console.log('on node drag stop', event);
|
||||||
}}
|
}}
|
||||||
on:nodecontextmenu={(event) => {
|
onnodecontextmenu={({ event }) => {
|
||||||
event.detail.event.preventDefault();
|
event.preventDefault();
|
||||||
console.log('on node contextmenu', event);
|
console.log('on node contextmenu', event);
|
||||||
}}
|
}}
|
||||||
on:edgecontextmenu={({ detail: { event, edge } }) => {
|
onedgecontextmenu={({ event, edge }) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
console.log('on edge contextmenu', edge);
|
console.log('on edge contextmenu', edge);
|
||||||
}}
|
}}
|
||||||
on:selectionclick={(event) => console.log('on selection click', event)}
|
onselectionclick={(event) => console.log('on selection click', event)}
|
||||||
on:selectioncontextmenu={(event) => console.log('on selection contextmenu', event)}
|
onselectioncontextmenu={(event) => console.log('on selection contextmenu', event)}
|
||||||
onbeforedelete={async ({ nodes, edges }) => {
|
onbeforedelete={async ({ nodes, edges }) => {
|
||||||
console.log('on before delete', nodes, edges);
|
console.log('on before delete', nodes, edges);
|
||||||
const deleteElements = confirm('Are you sure you want to delete the selected elements?');
|
const deleteElements = confirm('Are you sure you want to delete the selected elements?');
|
||||||
@@ -199,8 +205,7 @@
|
|||||||
{#snippet before()}
|
{#snippet before()}
|
||||||
<ControlButton>xy</ControlButton>
|
<ControlButton>xy</ControlButton>
|
||||||
{/snippet}
|
{/snippet}
|
||||||
<ControlButton aria-label="log" on:click={() => console.log('control button')}
|
<ControlButton aria-label="log" onclick={() => console.log('control button')}>log</ControlButton
|
||||||
>log</ControlButton
|
|
||||||
>
|
>
|
||||||
</Controls>
|
</Controls>
|
||||||
<Background variant={BackgroundVariant.Dots} />
|
<Background variant={BackgroundVariant.Dots} />
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
|
|||||||
const config = {
|
const config = {
|
||||||
// Consult https://kit.svelte.dev/docs/integrations#preprocessors
|
// Consult https://kit.svelte.dev/docs/integrations#preprocessors
|
||||||
// for more information about preprocessors
|
// for more information about preprocessors
|
||||||
preprocess: vitePreprocess(),
|
preprocess: vitePreprocess({ script: true }),
|
||||||
compilerOptions: {
|
compilerOptions: {
|
||||||
runes: true
|
runes: true
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -8,7 +8,10 @@
|
|||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"strict": true
|
"strict": true,
|
||||||
|
"target": "ES2022",
|
||||||
|
"verbatimModuleSyntax": true,
|
||||||
|
"isolatedModules": true
|
||||||
}
|
}
|
||||||
// Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
|
// Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -83,13 +83,13 @@
|
|||||||
"typescript": "^5.5.0"
|
"typescript": "^5.5.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"svelte": "^3.0.0 || ^4.0.0 || ^5.0.0"
|
"svelte": "^5.0.0"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist"
|
"dist"
|
||||||
],
|
],
|
||||||
"typesVersions": {
|
"typesVersions": {
|
||||||
">4.0": {
|
">5.0": {
|
||||||
"index": [
|
"index": [
|
||||||
"./dist/lib/index.d.ts"
|
"./dist/lib/index.d.ts"
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
if (event.target !== container) {
|
if (event.target !== container) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
handler?.(event);
|
handler?.(event);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -17,7 +16,7 @@
|
|||||||
const isSelected = ids.includes(item.id);
|
const isSelected = ids.includes(item.id);
|
||||||
|
|
||||||
if (item.selected !== isSelected) {
|
if (item.selected !== isSelected) {
|
||||||
item.selected = isSelected;
|
return { ...item, selected: isSelected };
|
||||||
}
|
}
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
@@ -33,7 +32,6 @@
|
|||||||
getConnectedEdges
|
getConnectedEdges
|
||||||
} from '@xyflow/system';
|
} from '@xyflow/system';
|
||||||
|
|
||||||
import { useStore } from '$lib/store';
|
|
||||||
import type { Node, Edge, InternalNode } from '$lib/types';
|
import type { Node, Edge, InternalNode } from '$lib/types';
|
||||||
import type { PaneProps } from './types';
|
import type { PaneProps } from './types';
|
||||||
let {
|
let {
|
||||||
@@ -45,8 +43,6 @@
|
|||||||
children
|
children
|
||||||
}: PaneProps = $props();
|
}: PaneProps = $props();
|
||||||
|
|
||||||
// const { nodes, edges } = store;
|
|
||||||
|
|
||||||
// svelte-ignore non_reactive_update
|
// svelte-ignore non_reactive_update
|
||||||
let container: HTMLDivElement;
|
let container: HTMLDivElement;
|
||||||
let containerBounds: DOMRect | null = null;
|
let containerBounds: DOMRect | null = null;
|
||||||
@@ -143,14 +139,14 @@
|
|||||||
prevSelectedNodeIds.length !== selectedNodeIds.length ||
|
prevSelectedNodeIds.length !== selectedNodeIds.length ||
|
||||||
selectedNodeIds.some((id) => !prevSelectedNodeIds.includes(id))
|
selectedNodeIds.some((id) => !prevSelectedNodeIds.includes(id))
|
||||||
) {
|
) {
|
||||||
// store.nodes.update((nodes) => nodes.map(toggleSelected(selectedNodeIds)));
|
store.nodes = store.nodes.map(toggleSelected(selectedNodeIds));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
prevSelectedEdgeIds.length !== selectedEdgeIds.length ||
|
prevSelectedEdgeIds.length !== selectedEdgeIds.length ||
|
||||||
selectedEdgeIds.some((id) => !prevSelectedEdgeIds.includes(id))
|
selectedEdgeIds.some((id) => !prevSelectedEdgeIds.includes(id))
|
||||||
) {
|
) {
|
||||||
// store.edges.update((edges) => edges.map(toggleSelected(selectedEdgeIds)));
|
store.edges = store.edges.map(toggleSelected(selectedEdgeIds));
|
||||||
}
|
}
|
||||||
|
|
||||||
store.selectionRectMode = 'user';
|
store.selectionRectMode = 'user';
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
<!-- TODO: why is this neccessary for types to work?? -->
|
|
||||||
<svelte:options runes={true} />
|
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { getContext, setContext, onDestroy } from 'svelte';
|
import { getContext, setContext, onDestroy } from 'svelte';
|
||||||
import cc from 'classcat';
|
import cc from 'classcat';
|
||||||
@@ -19,7 +16,7 @@
|
|||||||
import { key, createStore } from '$lib/store';
|
import { key, createStore } from '$lib/store';
|
||||||
import type { SvelteFlowProps } from './types';
|
import type { SvelteFlowProps } from './types';
|
||||||
import { useColorModeClass } from '$lib/hooks/useColorModeClass';
|
import { useColorModeClass } from '$lib/hooks/useColorModeClass';
|
||||||
import { type ProviderContext, type ContainerSignals, type StoreContext } from '$lib/store/types';
|
import { type ProviderContext, type StoreContext } from '$lib/store/types';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
style,
|
style,
|
||||||
@@ -62,7 +59,6 @@
|
|||||||
panOnScroll = false,
|
panOnScroll = false,
|
||||||
panOnDrag = true,
|
panOnDrag = true,
|
||||||
selectionOnDrag = true,
|
selectionOnDrag = true,
|
||||||
defaultEdgeOptions,
|
|
||||||
connectionLineContainerStyle = '',
|
connectionLineContainerStyle = '',
|
||||||
connectionLineStyle = '',
|
connectionLineStyle = '',
|
||||||
attributionPosition,
|
attributionPosition,
|
||||||
@@ -101,11 +97,13 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Set store for provider context
|
||||||
const providerContext = getContext<ProviderContext>(key);
|
const providerContext = getContext<ProviderContext>(key);
|
||||||
if (providerContext) {
|
if (providerContext) {
|
||||||
providerContext.setStore(store);
|
providerContext.setStore(store);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Overwrite store context to give children direct access
|
||||||
setContext(key, {
|
setContext(key, {
|
||||||
provider: false,
|
provider: false,
|
||||||
getStore() {
|
getStore() {
|
||||||
|
|||||||
@@ -31,7 +31,8 @@ import type {
|
|||||||
OnDelete,
|
OnDelete,
|
||||||
OnEdgeCreate,
|
OnEdgeCreate,
|
||||||
OnBeforeDelete,
|
OnBeforeDelete,
|
||||||
IsValidConnection
|
IsValidConnection,
|
||||||
|
DefaultNodeOptions
|
||||||
} from '$lib/types';
|
} from '$lib/types';
|
||||||
import type { Writable } from 'svelte/store';
|
import type { Writable } from 'svelte/store';
|
||||||
import type { Snippet } from 'svelte';
|
import type { Snippet } from 'svelte';
|
||||||
@@ -301,6 +302,22 @@ export type SvelteFlowProps = NodeEvents &
|
|||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
defaultEdgeOptions?: DefaultEdgeOptions;
|
defaultEdgeOptions?: DefaultEdgeOptions;
|
||||||
|
/** Defaults to be applied to all new nodes that are added to the flow.
|
||||||
|
*
|
||||||
|
* Properties on a new nodes will override these defaults if they exist.
|
||||||
|
* @example
|
||||||
|
* const defaultNodeOptions = {
|
||||||
|
* type: 'customNodeType',
|
||||||
|
* position: {x: 0, y: 0}
|
||||||
|
* data: { label: 'custom label' },
|
||||||
|
* hidden: false,
|
||||||
|
* deletable: true,
|
||||||
|
* selected: false,
|
||||||
|
* focusable: true,
|
||||||
|
* zIndex: 12,
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
defaultNodeOptions?: DefaultNodeOptions;
|
||||||
/** Sets a fixed width for the flow */
|
/** Sets a fixed width for the flow */
|
||||||
width?: number;
|
width?: number;
|
||||||
/** Sets a fixed height for the flow */
|
/** Sets a fixed height for the flow */
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
import { getContext } from 'svelte';
|
|
||||||
import type { StoreContext, SvelteFlowStore } from './types';
|
|
||||||
|
|
||||||
import { key } from './';
|
|
||||||
|
|
||||||
export function useStore(): SvelteFlowStore {
|
|
||||||
const storeContext = getContext<StoreContext>(key);
|
|
||||||
|
|
||||||
if (!storeContext) {
|
|
||||||
throw new Error(
|
|
||||||
'In order to use useStore you need to wrap your component in a <SvelteFlowProvider />'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (process.env.NODE_ENV === 'development') {
|
|
||||||
if (storeContext.provider && !$effect.tracking()) {
|
|
||||||
console.warn(
|
|
||||||
'Use $derived(useStore()), when not calling inside a child of the <SvelteFlow /> component.'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return storeContext.getStore();
|
|
||||||
}
|
|
||||||
@@ -21,14 +21,12 @@ import {
|
|||||||
import type { EdgeTypes, NodeTypes, Node, Edge, FitViewOptions } from '$lib/types';
|
import type { EdgeTypes, NodeTypes, Node, Edge, FitViewOptions } from '$lib/types';
|
||||||
import { initialEdgeTypes, initialNodeTypes, getInitialStore } from './initial-store.svelte';
|
import { initialEdgeTypes, initialNodeTypes, getInitialStore } from './initial-store.svelte';
|
||||||
import { type StoreSignals, type SvelteFlowStore, type SvelteFlowStoreActions } from './types';
|
import { type StoreSignals, type SvelteFlowStore, type SvelteFlowStoreActions } from './types';
|
||||||
import { syncNodeStores, syncEdgeStores } from './utils';
|
|
||||||
import drag from '$lib/actions/drag';
|
|
||||||
// import { getVisibleEdges } from './visible-edges';
|
// import { getVisibleEdges } from './visible-edges';
|
||||||
// import { getVisibleNodes } from './visible-nodes';
|
// import { getVisibleNodes } from './visible-nodes';
|
||||||
|
|
||||||
export const key = Symbol();
|
export const key = Symbol();
|
||||||
|
|
||||||
export { useStore } from './hook.svelte';
|
export { useStore } from '../hooks/useStore';
|
||||||
|
|
||||||
export function createStore(signals: StoreSignals): SvelteFlowStore {
|
export function createStore(signals: StoreSignals): SvelteFlowStore {
|
||||||
const store = getInitialStore(signals);
|
const store = getInitialStore(signals);
|
||||||
@@ -82,7 +80,9 @@ export function createStore(signals: StoreSignals): SvelteFlowStore {
|
|||||||
...store.fitViewOptions,
|
...store.fitViewOptions,
|
||||||
nodes: store.fitViewOptions?.nodes
|
nodes: store.fitViewOptions?.nodes
|
||||||
});
|
});
|
||||||
store.fitViewOnInitDone = fitViewOnInitDone;
|
if (fitViewOnInitDone) {
|
||||||
|
store.fitViewOnInitDone = fitViewOnInitDone;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const newNodes = new Map<string, Node>();
|
const newNodes = new Map<string, Node>();
|
||||||
@@ -115,9 +115,7 @@ export function createStore(signals: StoreSignals): SvelteFlowStore {
|
|||||||
newNodes.set(change.id, node);
|
newNodes.set(change.id, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
// store.nodes.update((nds) => nds);
|
|
||||||
store.nodes = store.nodes.map((node) => newNodes.get(node.id) ?? node);
|
store.nodes = store.nodes.map((node) => newNodes.get(node.id) ?? node);
|
||||||
// signals.updateNodes((node) => newNodes.get(node.id) ?? node);
|
|
||||||
|
|
||||||
if (!store.nodesInitialized) {
|
if (!store.nodesInitialized) {
|
||||||
store.nodesInitialized = true;
|
store.nodesInitialized = true;
|
||||||
@@ -244,24 +242,23 @@ export function createStore(signals: StoreSignals): SvelteFlowStore {
|
|||||||
const isMultiSelection = store.multiselectionKeyPressed;
|
const isMultiSelection = store.multiselectionKeyPressed;
|
||||||
|
|
||||||
// store.nodes.update((ns) =>
|
// store.nodes.update((ns) =>
|
||||||
store.nodes.forEach((node) => {
|
store.nodes = store.nodes.map((node) => {
|
||||||
const nodeWillBeSelected = ids.includes(node.id);
|
const nodeWillBeSelected = ids.includes(node.id);
|
||||||
const selected = isMultiSelection ? node.selected || nodeWillBeSelected : nodeWillBeSelected;
|
const selected = isMultiSelection ? node.selected || nodeWillBeSelected : nodeWillBeSelected;
|
||||||
|
|
||||||
// we need to mutate the node here in order to have the correct selected state in the drag handler
|
if (node.selected !== selected) {
|
||||||
node.selected = selected;
|
// we need to mutate the node here in order to have the correct selected state in the drag handler
|
||||||
|
node.selected = selected;
|
||||||
|
return { ...node };
|
||||||
|
}
|
||||||
|
|
||||||
// return node;
|
return node;
|
||||||
});
|
});
|
||||||
// );
|
|
||||||
|
|
||||||
if (!isMultiSelection) {
|
if (!isMultiSelection) {
|
||||||
// store.edges.forEach((es) =>
|
store.edges = store.edges.map((edge) => {
|
||||||
store.edges.forEach((edge) => {
|
return edge.selected ? { ...edge, selected: false } : edge;
|
||||||
edge.selected = false;
|
|
||||||
// return edge;
|
|
||||||
});
|
});
|
||||||
// );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -319,7 +316,6 @@ export function createStore(signals: StoreSignals): SvelteFlowStore {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// const _connection = writable<ConnectionState>(initialConnection);
|
|
||||||
const updateConnection: UpdateConnection = (newConnection: ConnectionState) => {
|
const updateConnection: UpdateConnection = (newConnection: ConnectionState) => {
|
||||||
store.rawConnection = { ...newConnection };
|
store.rawConnection = { ...newConnection };
|
||||||
};
|
};
|
||||||
@@ -338,9 +334,6 @@ export function createStore(signals: StoreSignals): SvelteFlowStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const storeWithActions = Object.assign(store, {
|
const storeWithActions = Object.assign(store, {
|
||||||
// syncNodeStores: (nodes) => syncNodeStores(store.nodes, nodes),
|
|
||||||
// syncEdgeStores: (edges) => syncEdgeStores(store.edges, edges),
|
|
||||||
// syncViewport: (viewport) => syncViewportStores(store.panZoom, store.viewport, viewport),
|
|
||||||
setNodeTypes,
|
setNodeTypes,
|
||||||
setEdgeTypes,
|
setEdgeTypes,
|
||||||
addEdge,
|
addEdge,
|
||||||
|
|||||||
@@ -49,7 +49,9 @@ import type {
|
|||||||
OnDelete,
|
OnDelete,
|
||||||
OnEdgeCreate,
|
OnEdgeCreate,
|
||||||
OnBeforeDelete,
|
OnBeforeDelete,
|
||||||
IsValidConnection
|
IsValidConnection,
|
||||||
|
Edge,
|
||||||
|
Node
|
||||||
} from '$lib/types';
|
} from '$lib/types';
|
||||||
|
|
||||||
import type { StoreSignals } from './types';
|
import type { StoreSignals } from './types';
|
||||||
@@ -69,6 +71,8 @@ export const initialEdgeTypes = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const getInitialStore = (signals: StoreSignals) => {
|
export const getInitialStore = (signals: StoreSignals) => {
|
||||||
|
// We use a class here, because Svelte adds getters & setter for us.
|
||||||
|
// Inline classes have some performance implications but we just call it once.
|
||||||
class SvelteFlowStore {
|
class SvelteFlowStore {
|
||||||
get nodes() {
|
get nodes() {
|
||||||
return signals.nodes;
|
return signals.nodes;
|
||||||
@@ -86,6 +90,7 @@ export const getInitialStore = (signals: StoreSignals) => {
|
|||||||
parentLookup: ParentLookup = new Map();
|
parentLookup: ParentLookup = new Map();
|
||||||
connectionLookup: ConnectionLookup = new Map();
|
connectionLookup: ConnectionLookup = new Map();
|
||||||
edgeLookup: EdgeLookup = new Map();
|
edgeLookup: EdgeLookup = new Map();
|
||||||
|
|
||||||
adoptNodes: true = $derived.by(() => {
|
adoptNodes: true = $derived.by(() => {
|
||||||
adoptUserNodes(signals.nodes, this.nodeLookup, this.parentLookup, {
|
adoptUserNodes(signals.nodes, this.nodeLookup, this.parentLookup, {
|
||||||
nodeExtent: this.nodeExtent,
|
nodeExtent: this.nodeExtent,
|
||||||
@@ -100,7 +105,7 @@ export const getInitialStore = (signals: StoreSignals) => {
|
|||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
domNode: HTMLDivElement | null = $derived(signals.domNode ?? signals.props.domNode ?? null);
|
domNode: HTMLDivElement | null = $derived(signals.domNode ?? signals.domNode ?? null);
|
||||||
width: number = $derived(signals.width ?? signals.props.width ?? 0);
|
width: number = $derived(signals.width ?? signals.props.width ?? 0);
|
||||||
height: number = $derived(signals.height ?? signals.props.height ?? 0);
|
height: number = $derived(signals.height ?? signals.props.height ?? 0);
|
||||||
|
|
||||||
@@ -112,6 +117,9 @@ export const getInitialStore = (signals: StoreSignals) => {
|
|||||||
nodeExtent: CoordinateExtent = $derived(signals.props.nodeExtent ?? infiniteExtent);
|
nodeExtent: CoordinateExtent = $derived(signals.props.nodeExtent ?? infiniteExtent);
|
||||||
translateExtent: CoordinateExtent = $derived(signals.props.translateExtent ?? infiniteExtent);
|
translateExtent: CoordinateExtent = $derived(signals.props.translateExtent ?? infiniteExtent);
|
||||||
|
|
||||||
|
defaultEdgeOptions: Partial<Edge> = $derived(signals.props.defaultEdgeOptions ?? {});
|
||||||
|
defaultNodeOptions: Partial<Node> = $derived(signals.props.defaultNodeOptions ?? {});
|
||||||
|
|
||||||
nodeDragThreshold: number = $derived(signals.props.nodeDragThreshold ?? 1);
|
nodeDragThreshold: number = $derived(signals.props.nodeDragThreshold ?? 1);
|
||||||
autoPanOnNodeDrag: boolean = $derived(signals.props.autoPanOnNodeDrag ?? true);
|
autoPanOnNodeDrag: boolean = $derived(signals.props.autoPanOnNodeDrag ?? true);
|
||||||
autoPanOnConnect: boolean = $derived(signals.props.autoPanOnConnect ?? true);
|
autoPanOnConnect: boolean = $derived(signals.props.autoPanOnConnect ?? true);
|
||||||
@@ -207,6 +215,7 @@ export const getInitialStore = (signals: StoreSignals) => {
|
|||||||
colorMode: ColorMode = $derived(signals.props.colorMode ?? 'light');
|
colorMode: ColorMode = $derived(signals.props.colorMode ?? 'light');
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
|
// Process intial fitView here
|
||||||
if (signals.props.fitView && !signals.props.initialViewport && this.width && this.height) {
|
if (signals.props.fitView && !signals.props.initialViewport && this.width && this.height) {
|
||||||
const bounds = getInternalNodesBounds(this.nodeLookup, {
|
const bounds = getInternalNodesBounds(this.nodeLookup, {
|
||||||
filter: (node) =>
|
filter: (node) =>
|
||||||
@@ -221,95 +230,4 @@ export const getInitialStore = (signals: StoreSignals) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new SvelteFlowStore();
|
return new SvelteFlowStore();
|
||||||
|
|
||||||
// return new Store();
|
|
||||||
// const nodeLookup: NodeLookup = new Map();
|
|
||||||
// const parentLookup = new Map();
|
|
||||||
// const connectionLookup = new Map();
|
|
||||||
// const edgeLookup = new Map();
|
|
||||||
|
|
||||||
// const storeNodeOrigin = nodeOrigin ?? [0, 0];
|
|
||||||
// const storeNodeExtent = nodeExtent ?? infiniteExtent;
|
|
||||||
|
|
||||||
// adoptUserNodes(nodes, nodeLookup, parentLookup, {
|
|
||||||
// nodeExtent: storeNodeExtent,
|
|
||||||
// nodeOrigin: storeNodeOrigin,
|
|
||||||
// elevateNodesOnSelect: false,
|
|
||||||
// checkEquality: false
|
|
||||||
// });
|
|
||||||
|
|
||||||
// updateConnectionLookup(connectionLookup, edgeLookup, edges);
|
|
||||||
|
|
||||||
// let viewport: Viewport = { x: 0, y: 0, zoom: 1 };
|
|
||||||
|
|
||||||
// if (fitView && width && height) {
|
|
||||||
// const bounds = getInternalNodesBounds(nodeLookup, {
|
|
||||||
// filter: (node) => !!((node.width || node.initialWidth) && (node.height || node.initialHeight))
|
|
||||||
// });
|
|
||||||
// viewport = getViewportForBounds(bounds, width, height, 0.5, 2, 0.1);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return {
|
|
||||||
// flowId: writable<string | null>(null),
|
|
||||||
// nodes: createNodesStore(nodes, nodeLookup, parentLookup, storeNodeOrigin, storeNodeExtent),
|
|
||||||
// nodeLookup: readable<NodeLookup<InternalNode>>(nodeLookup),
|
|
||||||
// parentLookup: readable<ParentLookup<InternalNode>>(parentLookup),
|
|
||||||
// edgeLookup: readable<EdgeLookup<Edge>>(edgeLookup),
|
|
||||||
// visibleNodes: readable<InternalNode[]>([]),
|
|
||||||
// edges: createEdgesStore(edges, connectionLookup, edgeLookup),
|
|
||||||
// visibleEdges: readable<EdgeLayouted[]>([]),
|
|
||||||
// connectionLookup: readable<ConnectionLookup>(connectionLookup),
|
|
||||||
// height: writable<number>(500),
|
|
||||||
// width: writable<number>(500),
|
|
||||||
// minZoom: writable<number>(0.5),
|
|
||||||
// maxZoom: writable<number>(2),
|
|
||||||
// nodeOrigin: writable<NodeOrigin>(storeNodeOrigin),
|
|
||||||
// nodeDragThreshold: writable<number>(1),
|
|
||||||
// nodeExtent: writable<CoordinateExtent>(storeNodeExtent),
|
|
||||||
// translateExtent: writable<CoordinateExtent>(infiniteExtent),
|
|
||||||
// autoPanOnNodeDrag: writable<boolean>(true),
|
|
||||||
// autoPanOnConnect: writable<boolean>(true),
|
|
||||||
// fitViewOnInit: writable<boolean>(false),
|
|
||||||
// fitViewOnInitDone: writable<boolean>(false),
|
|
||||||
// fitViewOptions: writable<FitViewOptions>(undefined),
|
|
||||||
// panZoom: writable<PanZoomInstance | null>(null),
|
|
||||||
// snapGrid: writable<SnapGrid | null>(null),
|
|
||||||
// dragging: writable<boolean>(false),
|
|
||||||
// selectionRect: writable<SelectionRect | null>(null),
|
|
||||||
// selectionKeyPressed: writable<boolean>(false),
|
|
||||||
// multiselectionKeyPressed: writable<boolean>(false),
|
|
||||||
// deleteKeyPressed: writable<boolean>(false),
|
|
||||||
// panActivationKeyPressed: writable<boolean>(false),
|
|
||||||
// zoomActivationKeyPressed: writable<boolean>(false),
|
|
||||||
// selectionRectMode: writable<string | null>(null),
|
|
||||||
// selectionMode: writable<SelectionMode>(SelectionMode.Partial),
|
|
||||||
// nodeTypes: writable<NodeTypes>(initialNodeTypes),
|
|
||||||
// edgeTypes: writable<EdgeTypes>(initialEdgeTypes),
|
|
||||||
// viewport: writable<Viewport>(viewport),
|
|
||||||
// connectionMode: writable<ConnectionMode>(ConnectionMode.Strict),
|
|
||||||
// domNode: writable<HTMLDivElement | null>(null),
|
|
||||||
// connection: readable<ConnectionState>(initialConnection),
|
|
||||||
// connectionLineType: writable<ConnectionLineType>(ConnectionLineType.Bezier),
|
|
||||||
// connectionRadius: writable<number>(20),
|
|
||||||
// isValidConnection: writable<IsValidConnection>(() => true),
|
|
||||||
// nodesDraggable: writable<boolean>(true),
|
|
||||||
// nodesConnectable: writable<boolean>(true),
|
|
||||||
// elementsSelectable: writable<boolean>(true),
|
|
||||||
// selectNodesOnDrag: writable<boolean>(true),
|
|
||||||
// markers: readable<MarkerProps[]>([]),
|
|
||||||
// defaultMarkerColor: writable<string>('#b1b1b7'),
|
|
||||||
// lib: readable<string>('svelte'),
|
|
||||||
// onlyRenderVisibleElements: writable<boolean>(false),
|
|
||||||
// onerror: writable<OnError>(devWarn),
|
|
||||||
// ondelete: writable<OnDelete>(undefined),
|
|
||||||
// onedgecreate: writable<OnEdgeCreate>(undefined),
|
|
||||||
// onconnect: writable<OnConnect>(undefined),
|
|
||||||
// onconnectstart: writable<OnConnectStart>(undefined),
|
|
||||||
// onconnectend: writable<OnConnectEnd>(undefined),
|
|
||||||
// onbeforedelete: writable<OnBeforeDelete>(undefined),
|
|
||||||
// nodesInitialized: writable<boolean>(false),
|
|
||||||
// edgesInitialized: writable<boolean>(false),
|
|
||||||
// viewportInitialized: writable<boolean>(false),
|
|
||||||
// initialized: readable<boolean>(false)
|
|
||||||
// };
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,178 +0,0 @@
|
|||||||
import { readable, writable } from 'svelte/store';
|
|
||||||
import {
|
|
||||||
infiniteExtent,
|
|
||||||
SelectionMode,
|
|
||||||
ConnectionMode,
|
|
||||||
ConnectionLineType,
|
|
||||||
devWarn,
|
|
||||||
adoptUserNodes,
|
|
||||||
getViewportForBounds,
|
|
||||||
updateConnectionLookup,
|
|
||||||
initialConnection,
|
|
||||||
type SelectionRect,
|
|
||||||
type SnapGrid,
|
|
||||||
type MarkerProps,
|
|
||||||
type PanZoomInstance,
|
|
||||||
type CoordinateExtent,
|
|
||||||
type NodeOrigin,
|
|
||||||
type OnError,
|
|
||||||
type Viewport,
|
|
||||||
type ConnectionLookup,
|
|
||||||
type OnConnect,
|
|
||||||
type OnConnectStart,
|
|
||||||
type OnConnectEnd,
|
|
||||||
type NodeLookup,
|
|
||||||
type EdgeLookup,
|
|
||||||
type ConnectionState,
|
|
||||||
type ParentLookup,
|
|
||||||
getInternalNodesBounds
|
|
||||||
} from '@xyflow/system';
|
|
||||||
|
|
||||||
import DefaultNode from '$lib/components/nodes/DefaultNode.svelte';
|
|
||||||
import InputNode from '$lib/components/nodes/InputNode.svelte';
|
|
||||||
import OutputNode from '$lib/components/nodes/OutputNode.svelte';
|
|
||||||
import GroupNode from '$lib/components/nodes/GroupNode.svelte';
|
|
||||||
|
|
||||||
import {
|
|
||||||
BezierEdgeInternal,
|
|
||||||
SmoothStepEdgeInternal,
|
|
||||||
StraightEdgeInternal,
|
|
||||||
StepEdgeInternal
|
|
||||||
} from '$lib/components/edges';
|
|
||||||
|
|
||||||
import type {
|
|
||||||
NodeTypes,
|
|
||||||
EdgeTypes,
|
|
||||||
EdgeLayouted,
|
|
||||||
Node,
|
|
||||||
Edge,
|
|
||||||
FitViewOptions,
|
|
||||||
OnDelete,
|
|
||||||
OnEdgeCreate,
|
|
||||||
OnBeforeDelete,
|
|
||||||
IsValidConnection,
|
|
||||||
InternalNode
|
|
||||||
} from '$lib/types';
|
|
||||||
import { createNodesStore, createEdgesStore } from './utils';
|
|
||||||
|
|
||||||
export const initialNodeTypes = {
|
|
||||||
input: InputNode,
|
|
||||||
output: OutputNode,
|
|
||||||
default: DefaultNode,
|
|
||||||
group: GroupNode
|
|
||||||
};
|
|
||||||
|
|
||||||
export const initialEdgeTypes = {
|
|
||||||
straight: StraightEdgeInternal,
|
|
||||||
smoothstep: SmoothStepEdgeInternal,
|
|
||||||
default: BezierEdgeInternal,
|
|
||||||
step: StepEdgeInternal
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getInitialStore = ({
|
|
||||||
nodes = [],
|
|
||||||
edges = [],
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
fitView,
|
|
||||||
nodeOrigin,
|
|
||||||
nodeExtent
|
|
||||||
}: {
|
|
||||||
nodes?: Node[];
|
|
||||||
edges?: Edge[];
|
|
||||||
width?: number;
|
|
||||||
height?: number;
|
|
||||||
fitView?: boolean;
|
|
||||||
nodeOrigin?: NodeOrigin;
|
|
||||||
nodeExtent?: CoordinateExtent;
|
|
||||||
}) => {
|
|
||||||
const nodeLookup: NodeLookup = new Map();
|
|
||||||
const parentLookup = new Map();
|
|
||||||
const connectionLookup = new Map();
|
|
||||||
const edgeLookup = new Map();
|
|
||||||
|
|
||||||
const storeNodeOrigin = nodeOrigin ?? [0, 0];
|
|
||||||
const storeNodeExtent = nodeExtent ?? infiniteExtent;
|
|
||||||
|
|
||||||
adoptUserNodes(nodes, nodeLookup, parentLookup, {
|
|
||||||
nodeExtent: storeNodeExtent,
|
|
||||||
nodeOrigin: storeNodeOrigin,
|
|
||||||
elevateNodesOnSelect: false,
|
|
||||||
checkEquality: false
|
|
||||||
});
|
|
||||||
|
|
||||||
updateConnectionLookup(connectionLookup, edgeLookup, edges);
|
|
||||||
|
|
||||||
let viewport: Viewport = { x: 0, y: 0, zoom: 1 };
|
|
||||||
|
|
||||||
if (fitView && width && height) {
|
|
||||||
const bounds = getInternalNodesBounds(nodeLookup, {
|
|
||||||
filter: (node) => !!((node.width || node.initialWidth) && (node.height || node.initialHeight))
|
|
||||||
});
|
|
||||||
viewport = getViewportForBounds(bounds, width, height, 0.5, 2, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
flowId: writable<string | null>(null),
|
|
||||||
nodes: createNodesStore(nodes, nodeLookup, parentLookup, storeNodeOrigin, storeNodeExtent),
|
|
||||||
nodeLookup: readable<NodeLookup<InternalNode>>(nodeLookup),
|
|
||||||
parentLookup: readable<ParentLookup<InternalNode>>(parentLookup),
|
|
||||||
edgeLookup: readable<EdgeLookup<Edge>>(edgeLookup),
|
|
||||||
visibleNodes: readable<InternalNode[]>([]),
|
|
||||||
edges: createEdgesStore(edges, connectionLookup, edgeLookup),
|
|
||||||
visibleEdges: readable<EdgeLayouted[]>([]),
|
|
||||||
connectionLookup: readable<ConnectionLookup>(connectionLookup),
|
|
||||||
height: writable<number>(500),
|
|
||||||
width: writable<number>(500),
|
|
||||||
minZoom: writable<number>(0.5),
|
|
||||||
maxZoom: writable<number>(2),
|
|
||||||
nodeOrigin: writable<NodeOrigin>(storeNodeOrigin),
|
|
||||||
nodeDragThreshold: writable<number>(1),
|
|
||||||
nodeExtent: writable<CoordinateExtent>(storeNodeExtent),
|
|
||||||
translateExtent: writable<CoordinateExtent>(infiniteExtent),
|
|
||||||
autoPanOnNodeDrag: writable<boolean>(true),
|
|
||||||
autoPanOnConnect: writable<boolean>(true),
|
|
||||||
fitViewOnInit: writable<boolean>(false),
|
|
||||||
fitViewOnInitDone: writable<boolean>(false),
|
|
||||||
fitViewOptions: writable<FitViewOptions>(undefined),
|
|
||||||
panZoom: writable<PanZoomInstance | null>(null),
|
|
||||||
snapGrid: writable<SnapGrid | null>(null),
|
|
||||||
dragging: writable<boolean>(false),
|
|
||||||
selectionRect: writable<SelectionRect | null>(null),
|
|
||||||
selectionKeyPressed: writable<boolean>(false),
|
|
||||||
multiselectionKeyPressed: writable<boolean>(false),
|
|
||||||
deleteKeyPressed: writable<boolean>(false),
|
|
||||||
panActivationKeyPressed: writable<boolean>(false),
|
|
||||||
zoomActivationKeyPressed: writable<boolean>(false),
|
|
||||||
selectionRectMode: writable<string | null>(null),
|
|
||||||
selectionMode: writable<SelectionMode>(SelectionMode.Partial),
|
|
||||||
nodeTypes: writable<NodeTypes>(initialNodeTypes),
|
|
||||||
edgeTypes: writable<EdgeTypes>(initialEdgeTypes),
|
|
||||||
viewport: writable<Viewport>(viewport),
|
|
||||||
connectionMode: writable<ConnectionMode>(ConnectionMode.Strict),
|
|
||||||
domNode: writable<HTMLDivElement | null>(null),
|
|
||||||
connection: readable<ConnectionState>(initialConnection),
|
|
||||||
connectionLineType: writable<ConnectionLineType>(ConnectionLineType.Bezier),
|
|
||||||
connectionRadius: writable<number>(20),
|
|
||||||
isValidConnection: writable<IsValidConnection>(() => true),
|
|
||||||
nodesDraggable: writable<boolean>(true),
|
|
||||||
nodesConnectable: writable<boolean>(true),
|
|
||||||
elementsSelectable: writable<boolean>(true),
|
|
||||||
selectNodesOnDrag: writable<boolean>(true),
|
|
||||||
markers: readable<MarkerProps[]>([]),
|
|
||||||
defaultMarkerColor: writable<string>('#b1b1b7'),
|
|
||||||
lib: readable<string>('svelte'),
|
|
||||||
onlyRenderVisibleElements: writable<boolean>(false),
|
|
||||||
onerror: writable<OnError>(devWarn),
|
|
||||||
ondelete: writable<OnDelete>(undefined),
|
|
||||||
onedgecreate: writable<OnEdgeCreate>(undefined),
|
|
||||||
onconnect: writable<OnConnect>(undefined),
|
|
||||||
onconnectstart: writable<OnConnectStart>(undefined),
|
|
||||||
onconnectend: writable<OnConnectEnd>(undefined),
|
|
||||||
onbeforedelete: writable<OnBeforeDelete>(undefined),
|
|
||||||
nodesInitialized: writable<boolean>(false),
|
|
||||||
edgesInitialized: writable<boolean>(false),
|
|
||||||
viewportInitialized: writable<boolean>(false),
|
|
||||||
initialized: readable<boolean>(false)
|
|
||||||
};
|
|
||||||
};
|
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
import type { Writable } from 'svelte/store';
|
|
||||||
import type {
|
import type {
|
||||||
InternalNodeUpdate,
|
InternalNodeUpdate,
|
||||||
XYPosition,
|
XYPosition,
|
||||||
@@ -14,9 +13,6 @@ import type { Node, Edge, NodeTypes, EdgeTypes, FitViewOptions } from '$lib/type
|
|||||||
import type { SvelteFlowProps } from '$lib/container/SvelteFlow';
|
import type { SvelteFlowProps } from '$lib/container/SvelteFlow';
|
||||||
|
|
||||||
export type SvelteFlowStoreActions = {
|
export type SvelteFlowStoreActions = {
|
||||||
// syncNodeStores: (nodesStore: Writable<Node[]>) => void;
|
|
||||||
// syncEdgeStores: (edgeStore: Writable<Edge[]>) => void;
|
|
||||||
// syncViewport: (viewportStore?: Writable<Viewport>) => void;
|
|
||||||
setNodeTypes: (nodeTypes: NodeTypes) => void;
|
setNodeTypes: (nodeTypes: NodeTypes) => void;
|
||||||
setEdgeTypes: (edgeTypes: EdgeTypes) => void;
|
setEdgeTypes: (edgeTypes: EdgeTypes) => void;
|
||||||
addEdge: (edge: Edge | Connection) => void;
|
addEdge: (edge: Edge | Connection) => void;
|
||||||
@@ -39,9 +35,8 @@ export type SvelteFlowStoreActions = {
|
|||||||
reset(): void;
|
reset(): void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ContainerSignals = { domNode?: HTMLDivElement | null; width?: number; height?: number };
|
|
||||||
export type StoreSignals = {
|
export type StoreSignals = {
|
||||||
props: Partial<SvelteFlowProps> & ContainerSignals;
|
props: Partial<SvelteFlowProps>;
|
||||||
domNode?: HTMLDivElement;
|
domNode?: HTMLDivElement;
|
||||||
width?: number;
|
width?: number;
|
||||||
height?: number;
|
height?: number;
|
||||||
|
|||||||
@@ -1,222 +0,0 @@
|
|||||||
import {
|
|
||||||
writable,
|
|
||||||
get,
|
|
||||||
type Unsubscriber,
|
|
||||||
type Subscriber,
|
|
||||||
type Updater,
|
|
||||||
type Writable
|
|
||||||
} from 'svelte/store';
|
|
||||||
import {
|
|
||||||
adoptUserNodes,
|
|
||||||
updateConnectionLookup,
|
|
||||||
type Viewport,
|
|
||||||
type PanZoomInstance,
|
|
||||||
type ConnectionLookup,
|
|
||||||
type EdgeLookup,
|
|
||||||
type NodeLookup,
|
|
||||||
type ParentLookup,
|
|
||||||
type NodeOrigin,
|
|
||||||
infiniteExtent,
|
|
||||||
type CoordinateExtent
|
|
||||||
} from '@xyflow/system';
|
|
||||||
|
|
||||||
import type { DefaultEdgeOptions, DefaultNodeOptions, Edge, InternalNode, Node } from '$lib/types';
|
|
||||||
|
|
||||||
// we need to sync the user nodes and the internal nodes so that the user can receive the updates
|
|
||||||
// made by Svelte Flow (like dragging or selecting a node).
|
|
||||||
export function syncNodeStores(
|
|
||||||
nodesStore: ReturnType<typeof createNodesStore>,
|
|
||||||
userNodesStore: Writable<Node[]>
|
|
||||||
) {
|
|
||||||
const nodesStoreSetter = nodesStore.set;
|
|
||||||
const userNodesStoreSetter = userNodesStore.set;
|
|
||||||
const currentNodesStore = get(nodesStore);
|
|
||||||
const currentUserNodesStore = get(userNodesStore);
|
|
||||||
// depending how the user initializes the nodes, we need to decide if we want to use
|
|
||||||
// the user nodes or the internal nodes for initialization. A user can use a SvelteFlowProvider
|
|
||||||
// without providing any nodes, in that case we want to use the nodes passed by the user.
|
|
||||||
// By default we are using the store nodes, because they already have the absolute positions.
|
|
||||||
const initWithUserNodes = currentNodesStore.length === 0 && currentUserNodesStore.length > 0;
|
|
||||||
|
|
||||||
let val = initWithUserNodes ? currentUserNodesStore : currentNodesStore;
|
|
||||||
nodesStore.set(val);
|
|
||||||
|
|
||||||
const _set = (nds: Node[]) => {
|
|
||||||
const updatedNodes = nodesStoreSetter(nds);
|
|
||||||
val = updatedNodes;
|
|
||||||
|
|
||||||
userNodesStoreSetter(val);
|
|
||||||
|
|
||||||
return updatedNodes;
|
|
||||||
};
|
|
||||||
|
|
||||||
nodesStore.set = userNodesStore.set = _set;
|
|
||||||
nodesStore.update = userNodesStore.update = (fn: (nds: Node[]) => Node[]) => _set(fn(val));
|
|
||||||
}
|
|
||||||
|
|
||||||
// same for edges
|
|
||||||
export function syncEdgeStores(
|
|
||||||
edgesStore: ReturnType<typeof createEdgesStore>,
|
|
||||||
userEdgesStore: Writable<Edge[]>
|
|
||||||
) {
|
|
||||||
const nodesStoreSetter = edgesStore.set;
|
|
||||||
const userEdgesStoreSetter = userEdgesStore.set;
|
|
||||||
|
|
||||||
let val = get(userEdgesStore);
|
|
||||||
edgesStore.set(val);
|
|
||||||
|
|
||||||
const _set = (eds: Edge[]) => {
|
|
||||||
nodesStoreSetter(eds);
|
|
||||||
userEdgesStoreSetter(eds);
|
|
||||||
val = eds;
|
|
||||||
};
|
|
||||||
|
|
||||||
edgesStore.set = userEdgesStore.set = _set;
|
|
||||||
edgesStore.update = userEdgesStore.update = (fn: (nds: Edge[]) => Edge[]) => _set(fn(val));
|
|
||||||
}
|
|
||||||
|
|
||||||
// it is possible to pass a viewport store to SvelteFlow for having more control
|
|
||||||
// if that's the case we need to sync the internal viewport with the user viewport
|
|
||||||
export const syncViewportStores = (
|
|
||||||
panZoomStore: PanZoomInstance | null,
|
|
||||||
viewportStore: Writable<Viewport>,
|
|
||||||
userViewportStore?: Writable<Viewport>
|
|
||||||
) => {
|
|
||||||
if (!userViewportStore) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const panZoom = panZoomStore;
|
|
||||||
|
|
||||||
const viewportStoreSetter = viewportStore.set;
|
|
||||||
const userViewportStoreSetter = userViewportStore.set;
|
|
||||||
|
|
||||||
let val = userViewportStore ? get(userViewportStore) : { x: 0, y: 0, zoom: 1 };
|
|
||||||
viewportStore.set(val);
|
|
||||||
|
|
||||||
viewportStore.set = (vp: Viewport) => {
|
|
||||||
viewportStoreSetter(vp);
|
|
||||||
userViewportStoreSetter(vp);
|
|
||||||
|
|
||||||
val = vp;
|
|
||||||
|
|
||||||
return vp;
|
|
||||||
};
|
|
||||||
|
|
||||||
userViewportStore.set = (vp: Viewport) => {
|
|
||||||
panZoom?.syncViewport(vp);
|
|
||||||
|
|
||||||
viewportStoreSetter(vp);
|
|
||||||
userViewportStoreSetter(vp);
|
|
||||||
|
|
||||||
val = vp;
|
|
||||||
|
|
||||||
return vp;
|
|
||||||
};
|
|
||||||
|
|
||||||
viewportStore.update = (fn: (vp: Viewport) => Viewport) => {
|
|
||||||
viewportStore.set(fn(val));
|
|
||||||
};
|
|
||||||
|
|
||||||
userViewportStore.update = (fn: (vp: Viewport) => Viewport) => {
|
|
||||||
userViewportStore.set(fn(val));
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export type NodeStoreOptions = {
|
|
||||||
elevateNodesOnSelect?: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
type Update<T> = Writable<T>['update'];
|
|
||||||
|
|
||||||
// we are creating a custom store for the internals nodes in order to update the zIndex and positionAbsolute.
|
|
||||||
// The user only passes in relative positions, so we need to calculate the absolute positions based on the parent nodes.
|
|
||||||
export const createNodesStore = (
|
|
||||||
nodes: Node[],
|
|
||||||
nodeLookup: NodeLookup<InternalNode>,
|
|
||||||
parentLookup: ParentLookup<InternalNode>,
|
|
||||||
nodeOrigin: NodeOrigin = [0, 0],
|
|
||||||
nodeExtent: CoordinateExtent = infiniteExtent
|
|
||||||
): {
|
|
||||||
subscribe: (this: void, run: Subscriber<Node[]>) => Unsubscriber;
|
|
||||||
update: (this: void, updater: Updater<Node[]>) => void;
|
|
||||||
set: (this: void, value: Node[]) => Node[];
|
|
||||||
setDefaultOptions: (opts: DefaultNodeOptions) => void;
|
|
||||||
setOptions: (opts: NodeStoreOptions) => void;
|
|
||||||
} => {
|
|
||||||
const { subscribe, set } = writable<Node[]>([]);
|
|
||||||
let value = nodes;
|
|
||||||
let defaults = {};
|
|
||||||
let elevateNodesOnSelect = true;
|
|
||||||
|
|
||||||
const _set = (nds: Node[]): Node[] => {
|
|
||||||
adoptUserNodes(nds, nodeLookup, parentLookup, {
|
|
||||||
elevateNodesOnSelect,
|
|
||||||
nodeOrigin,
|
|
||||||
nodeExtent,
|
|
||||||
defaults,
|
|
||||||
checkEquality: false
|
|
||||||
});
|
|
||||||
|
|
||||||
value = nds;
|
|
||||||
|
|
||||||
set(value);
|
|
||||||
|
|
||||||
return value;
|
|
||||||
};
|
|
||||||
|
|
||||||
const _update: Update<Node[]> = (fn: (nds: Node[]) => Node[]) => _set(fn(value));
|
|
||||||
|
|
||||||
const setDefaultOptions = (options: DefaultNodeOptions) => {
|
|
||||||
defaults = options;
|
|
||||||
};
|
|
||||||
|
|
||||||
const setOptions = (options: NodeStoreOptions) => {
|
|
||||||
elevateNodesOnSelect = options.elevateNodesOnSelect ?? elevateNodesOnSelect;
|
|
||||||
};
|
|
||||||
|
|
||||||
_set(value);
|
|
||||||
|
|
||||||
return {
|
|
||||||
subscribe,
|
|
||||||
set: _set,
|
|
||||||
update: _update,
|
|
||||||
setDefaultOptions,
|
|
||||||
setOptions
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export const createEdgesStore = (
|
|
||||||
edges: Edge[],
|
|
||||||
connectionLookup: ConnectionLookup,
|
|
||||||
edgeLookup: EdgeLookup<Edge>,
|
|
||||||
defaultOptions?: DefaultEdgeOptions
|
|
||||||
): Writable<Edge[]> & { setDefaultOptions: (opts: DefaultEdgeOptions) => void } => {
|
|
||||||
const { subscribe, set } = writable<Edge[]>([]);
|
|
||||||
let value = edges;
|
|
||||||
let defaults = defaultOptions || {};
|
|
||||||
|
|
||||||
const _set: typeof set = (eds: Edge[]) => {
|
|
||||||
const nextEdges = defaults ? eds.map((edge) => ({ ...defaults, ...edge })) : eds;
|
|
||||||
|
|
||||||
updateConnectionLookup(connectionLookup, edgeLookup, nextEdges);
|
|
||||||
|
|
||||||
value = nextEdges;
|
|
||||||
set(value);
|
|
||||||
};
|
|
||||||
|
|
||||||
const _update: Update<Edge[]> = (fn: (eds: Edge[]) => Edge[]) => _set(fn(value));
|
|
||||||
|
|
||||||
const setDefaultOptions = (options: DefaultEdgeOptions) => {
|
|
||||||
defaults = options;
|
|
||||||
};
|
|
||||||
|
|
||||||
_set(value);
|
|
||||||
|
|
||||||
return {
|
|
||||||
subscribe,
|
|
||||||
set: _set,
|
|
||||||
update: _update,
|
|
||||||
setDefaultOptions
|
|
||||||
};
|
|
||||||
};
|
|
||||||
@@ -8,8 +8,7 @@
|
|||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"strict": true,
|
"strict": true
|
||||||
"noErrorTruncation": true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
|
// Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
|
||||||
|
|||||||
Reference in New Issue
Block a user