feat(react/svelte): controlled viewport (#3461)

* feat(react): controlled viewport

* refactor(react): cleanup viewport

* feat(svelte): two way data binding for viewport, cleanup transform <> viewport stuff

* refactor(svelte): viewport stuff
This commit is contained in:
Moritz Klack
2023-09-28 16:19:03 +02:00
committed by GitHub
parent 2215b68438
commit ae33cba887
35 changed files with 351 additions and 95 deletions
@@ -26,15 +26,15 @@
let className: $$Props['class'] = '';
export { className as class };
const { transform, flowId } = useStore();
const { viewport, flowId } = useStore();
const patternSize = size || defaultSize[variant!];
const isDots = variant === BackgroundVariant.Dots;
const isCross = variant === BackgroundVariant.Cross;
const gapXY: number[] = Array.isArray(gap!) ? gap! : [gap!, gap!];
$: patternId = `background-pattern-${$flowId}`;
$: scaledGap = [gapXY[0] * $transform[2] || 1, gapXY[1] * $transform[2] || 1];
$: scaledSize = patternSize * $transform[2];
$: scaledGap = [gapXY[0] * $viewport.zoom || 1, gapXY[1] * $viewport.zoom || 1];
$: scaledSize = patternSize * $viewport.zoom;
$: patternDimensions = (isCross ? [scaledSize, scaledSize] : scaledGap) as [number, number];
$: patternOffset = isDots
? [scaledSize / 2, scaledSize / 2]
@@ -49,8 +49,8 @@
>
<pattern
id={patternId}
x={$transform[0] % scaledGap[0]}
y={$transform[1] % scaledGap[1]}
x={$viewport.x % scaledGap[0]}
y={$viewport.y % scaledGap[1]}
width={scaledGap[0]}
height={scaledGap[1]}
patternUnits="userSpaceOnUse"
@@ -26,7 +26,7 @@
zoomIn,
zoomOut,
fitView,
transform,
viewport,
minZoom,
maxZoom,
nodesDraggable,
@@ -43,8 +43,8 @@
};
$: isInteractive = $nodesDraggable || $nodesConnectable || $elementsSelectable;
$: minZoomReached = $transform[2] <= $minZoom;
$: maxZoomReached = $transform[2] >= $maxZoom;
$: minZoomReached = $viewport.zoom <= $minZoom;
$: maxZoomReached = $viewport.zoom >= $maxZoom;
const onZoomInHandler = () => {
zoomIn();
@@ -43,7 +43,7 @@
const defaultHeight = 150;
const {
nodes,
transform,
viewport,
width: containerWidth,
height: containerHeight,
flowId,
@@ -59,10 +59,10 @@
const labelledBy = `svelte-flow__minimap-desc-${$flowId}`;
$: viewBB = {
x: -$transform[0] / $transform[2],
y: -$transform[1] / $transform[2],
width: $containerWidth / $transform[2],
height: $containerHeight / $transform[2]
x: -$viewport.x / $viewport.zoom,
y: -$viewport.y / $viewport.zoom,
width: $containerWidth / $viewport.zoom,
height: $containerHeight / $viewport.zoom
};
$: boundingRect = $nodes.length > 0 ? getBoundsOfRects(getRectOfNodes($nodes), viewBB) : viewBB;
$: elementWidth = width ?? defaultWidth;
@@ -100,7 +100,7 @@
style:--minimap-mask-stroke-width-props={maskStrokeWidth}
use:interactive={{
panZoom: $panZoom,
transform,
viewport,
getViewScale,
translateExtent: $translateExtent,
width: $containerWidth,
@@ -2,13 +2,13 @@ import { get, type Writable } from 'svelte/store';
import {
XYMinimap,
type PanZoomInstance,
type Transform,
type Viewport,
type XYMinimapUpdate
} from '@xyflow/system';
export type UseInteractiveParams = {
panZoom: PanZoomInstance;
transform: Writable<Transform>;
viewport: Writable<Viewport>;
getViewScale: () => number;
} & XYMinimapUpdate;
@@ -16,7 +16,10 @@ export default function interactive(domNode: Element, params: UseInteractivePara
const minimap = XYMinimap({
domNode,
panZoom: params.panZoom,
getTransform: () => get(params.transform),
getTransform: () => {
const viewport = get(params.viewport);
return [viewport.x, viewport.y, viewport.zoom];
},
getViewScale: params.getViewScale
});