refactor(svelte): cleanup useSvelteFlow, add functions (#3474)

* chore(svelte) removed nodes, edges from useSvelteFlow

* feat(svelte) added deleteElements to useSvelteFlow

* fix(svelte) parent div gets resized correctly, got rid of getBoundingClient Rect

* feat(svelte) added screenToFlowCoordinate

* feat(svelte) added flowToScreenCoordinate to useSvelteFlow

* chore(svelte) removed project from useSvelteFlow

* Delete examples/svelte/src/routes/add-node-on-drop/+server.ts

---------

Co-authored-by: Moritz Klack <info@moritzklack.com>
This commit is contained in:
peterkogo
2023-10-05 18:53:57 +02:00
committed by GitHub
co-authored by Moritz Klack
parent 86516d3ddd
commit cdf1c4c3a6
5 changed files with 235 additions and 18 deletions
@@ -71,13 +71,14 @@
export { className as class };
let domNode: HTMLDivElement;
let clientWidth: number;
let clientHeight: number;
const store = hasContext(key) ? useStore() : createStoreContext();
onMount(() => {
const { width, height } = domNode.getBoundingClientRect();
store.width.set(width);
store.height.set(height);
store.width.set(clientWidth);
store.height.set(clientHeight);
store.domNode.set(domNode);
store.syncNodeStores(nodes);
@@ -141,6 +142,8 @@
<div
bind:this={domNode}
bind:clientWidth
bind:clientHeight
{style}
class={cc(['svelte-flow', className])}
data-testid="svelte-flow__wrapper"
+103 -14
View File
@@ -1,17 +1,20 @@
import { get, type Writable } from 'svelte/store';
import {
pointToRendererPoint,
type Project,
type FitBoundsOptions,
type SetCenterOptions,
type Viewport,
type ViewportHelperFunctionOptions,
type XYPosition,
type ZoomInOut
type ZoomInOut,
type Rect,
getTransformForBounds,
getElementsToRemove,
rendererPointToPoint
} from '@xyflow/system';
import { useStore } from '$lib/store';
import type { FitViewOptions } from '$lib/types';
import type { SvelteFlowStore } from '$lib/store/types';
import type { Edge, FitViewOptions, Node } from '$lib/types';
export function useSvelteFlow(): {
zoomIn: ZoomInOut;
@@ -22,10 +25,14 @@ export function useSvelteFlow(): {
setViewport: (viewport: Viewport, options?: ViewportHelperFunctionOptions) => void;
getViewport: () => Viewport;
fitView: (options?: FitViewOptions) => void;
project: Project;
fitBounds: (bounds: Rect, options?: FitBoundsOptions) => void;
deleteElements: (
nodesToRemove?: Partial<Node> & { id: string }[],
edgesToRemove?: Partial<Edge> & { id: string }[]
) => { deletedNodes: Node[]; deletedEdges: Edge[] };
screenToFlowCoordinate: (position: XYPosition) => XYPosition;
flowToScreenCoordinate: (position: XYPosition) => XYPosition;
viewport: Writable<Viewport>;
nodes: SvelteFlowStore['nodes'];
edges: SvelteFlowStore['edges'];
} {
const {
zoomIn,
@@ -35,10 +42,12 @@ export function useSvelteFlow(): {
viewport,
width,
height,
minZoom,
maxZoom,
panZoom,
nodes,
edges
edges,
domNode
} = useStore();
return {
@@ -78,14 +87,94 @@ export function useSvelteFlow(): {
);
},
fitView,
project: (position: XYPosition) => {
const _snapGrid = get(snapGrid);
const { x, y, zoom } = get(viewport);
fitBounds: (bounds: Rect, options?: FitBoundsOptions) => {
const _width = get(width);
const _height = get(height);
const _maxZoom = get(maxZoom);
const _minZoom = get(minZoom);
return pointToRendererPoint(position, [x, y, zoom], _snapGrid !== null, _snapGrid || [1, 1]);
const [x, y, zoom] = getTransformForBounds(
bounds,
_width,
_height,
_minZoom,
_maxZoom,
options?.padding ?? 0.1
);
get(panZoom)?.setViewport(
{
x,
y,
zoom
},
{ duration: options?.duration }
);
},
deleteElements: (
nodesToRemove: Partial<Node> & { id: string }[] = [],
edgesToRemove: Partial<Edge> & { id: string }[] = []
) => {
const _nodes = get(nodes);
const _edges = get(edges);
const { matchingNodes, matchingEdges } = getElementsToRemove<Node, Edge>({
nodesToRemove,
edgesToRemove,
nodes: _nodes,
edges: _edges
});
if (matchingNodes) {
nodes.set(_nodes.filter((node) => !matchingNodes.some(({ id }) => id === node.id)));
}
if (matchingEdges) {
edges.set(_edges.filter((edge) => !matchingEdges.some(({ id }) => id === edge.id)));
}
return {
deletedNodes: matchingNodes,
deletedEdges: matchingEdges
};
},
screenToFlowCoordinate: (position: XYPosition) => {
const _domNode = get(domNode);
if (_domNode) {
const _snapGrid = get(snapGrid);
const { x, y, zoom } = get(viewport);
const { x: domX, y: domY } = _domNode.getBoundingClientRect();
const correctedPosition = {
x: position.x - domX,
y: position.y - domY
};
return pointToRendererPoint(
correctedPosition,
[x, y, zoom],
_snapGrid !== null,
_snapGrid || [1, 1]
);
}
return { x: 0, y: 0 };
},
flowToScreenCoordinate: (position: XYPosition) => {
const _domNode = get(domNode);
if (_domNode) {
const { x, y, zoom } = get(viewport);
const { x: domX, y: domY } = _domNode.getBoundingClientRect();
const rendererPosition = rendererPointToPoint(position, [x, y, zoom]);
return {
x: rendererPosition.x + domX,
y: rendererPosition.y + domY
};
}
return { x: 0, y: 0 };
},
nodes,
edges,
viewport: viewport
};
}