fixed errors but still WIP
This commit is contained in:
@@ -24,6 +24,12 @@ export type Node<
|
||||
focusable?: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
* The node data structure that gets used for internal nodes.
|
||||
* There are some data structures added under node.internal
|
||||
* that are needed for tracking some properties
|
||||
* @public
|
||||
*/
|
||||
export type InternalNode<NodeType extends Node = Node> = InternalNodeBase<NodeType>;
|
||||
|
||||
export type NodeMouseHandler<NodeType extends Node = Node> = (event: ReactMouseEvent, node: NodeType) => void;
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
const {
|
||||
connectionMode,
|
||||
domNode,
|
||||
nodes,
|
||||
nodeLookup,
|
||||
connectionRadius,
|
||||
viewport,
|
||||
isValidConnection,
|
||||
@@ -72,7 +72,7 @@
|
||||
isTarget,
|
||||
connectionRadius: $connectionRadius,
|
||||
domNode: $domNode,
|
||||
nodes: $nodes,
|
||||
nodeLookup: $nodeLookup,
|
||||
connectionMode: $connectionMode,
|
||||
lib: $lib,
|
||||
autoPanOnConnect: $autoPanOnConnect,
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
$: selectedNodes = $nodes.filter((n) => n.selected);
|
||||
$: bounds = getNodesBounds(selectedNodes);
|
||||
|
||||
$: console.log($nodes);
|
||||
|
||||
function onContextMenu(event: MouseEvent | TouchEvent) {
|
||||
dispatch('selectioncontextmenu', { nodes: selectedNodes, event });
|
||||
}
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { onDestroy } from 'svelte';
|
||||
import {
|
||||
internalsSymbol,
|
||||
getPositionWithOrigin,
|
||||
getNodeDimensions,
|
||||
nodeHasDimensions
|
||||
} from '@xyflow/system';
|
||||
import { getPositionWithOrigin, getNodeDimensions, nodeHasDimensions } from '@xyflow/system';
|
||||
|
||||
import { NodeWrapper } from '$lib/components/NodeWrapper';
|
||||
import { useStore } from '$lib/store';
|
||||
@@ -46,8 +41,8 @@
|
||||
{#each $visibleNodes as node (node.id)}
|
||||
{@const nodeDimesions = getNodeDimensions(node)}
|
||||
{@const posOrigin = getPositionWithOrigin({
|
||||
x: node.computed?.positionAbsolute?.x ?? 0,
|
||||
y: node.computed?.positionAbsolute?.y ?? 0,
|
||||
x: node.internals.positionAbsolute.x ?? 0,
|
||||
y: node.internals.positionAbsolute.y ?? 0,
|
||||
...nodeDimesions,
|
||||
origin: node.origin
|
||||
})}
|
||||
@@ -66,26 +61,26 @@
|
||||
node.connectable ||
|
||||
($nodesConnectable && typeof node.connectable === 'undefined')
|
||||
)}
|
||||
positionX={node.computed?.positionAbsolute?.x ?? 0}
|
||||
positionY={node.computed?.positionAbsolute?.y ?? 0}
|
||||
positionX={node.internals.positionAbsolute?.x ?? 0}
|
||||
positionY={node.internals.positionAbsolute?.y ?? 0}
|
||||
positionOriginX={posOrigin.x ?? 0}
|
||||
positionOriginY={posOrigin.y ?? 0}
|
||||
isParent={!!node[internalsSymbol]?.isParent}
|
||||
isParent={!!node.internals.isParent}
|
||||
style={node.style}
|
||||
class={node.class}
|
||||
type={node.type ?? 'default'}
|
||||
sourcePosition={node.sourcePosition}
|
||||
targetPosition={node.targetPosition}
|
||||
dragging={node.dragging}
|
||||
zIndex={node[internalsSymbol]?.z ?? 0}
|
||||
zIndex={node.internals.z ?? 0}
|
||||
dragHandle={node.dragHandle}
|
||||
initialized={nodeHasDimensions(node)}
|
||||
width={node.width}
|
||||
height={node.height}
|
||||
initialWidth={node.initialWidth}
|
||||
initialHeight={node.initialHeight}
|
||||
computedWidth={node.computed?.width}
|
||||
computedHeight={node.computed?.height}
|
||||
computedWidth={node.measured.width}
|
||||
computedHeight={node.measured.height}
|
||||
{resizeObserver}
|
||||
on:nodeclick
|
||||
on:nodemouseenter
|
||||
|
||||
@@ -17,10 +17,7 @@
|
||||
const isSelected = ids.includes(item.id);
|
||||
|
||||
if (item.selected !== isSelected) {
|
||||
return {
|
||||
...item,
|
||||
selected: isSelected
|
||||
};
|
||||
item.selected = isSelected;
|
||||
}
|
||||
|
||||
return item;
|
||||
@@ -56,6 +53,7 @@
|
||||
}>();
|
||||
const {
|
||||
nodes,
|
||||
nodeLookup,
|
||||
edges,
|
||||
viewport,
|
||||
dragging,
|
||||
@@ -130,8 +128,8 @@
|
||||
const prevSelectedNodeIds = selectedNodes.map((n) => n.id);
|
||||
const prevSelectedEdgeIds = getConnectedEdges(selectedNodes, $edges).map((e) => e.id);
|
||||
|
||||
selectedNodes = getNodesInside<Node>(
|
||||
$nodes,
|
||||
selectedNodes = getNodesInside(
|
||||
$nodeLookup,
|
||||
nextUserSelectRect,
|
||||
[$viewport.x, $viewport.y, $viewport.zoom],
|
||||
$selectionMode === SelectionMode.Partial,
|
||||
@@ -172,7 +170,7 @@
|
||||
selectionRect.set(null);
|
||||
|
||||
if (selectedNodes.length > 0) {
|
||||
selectionRectMode.set('nodes');
|
||||
$selectionRectMode = 'nodes';
|
||||
}
|
||||
|
||||
// onSelectionEnd?.(event);
|
||||
|
||||
@@ -331,11 +331,12 @@ export function useSvelteFlow(): {
|
||||
}
|
||||
|
||||
return (nodesToIntersect || get(nodes)).filter((n) => {
|
||||
if (!isRect && (n.id === nodeOrRect.id || !n.computed?.positionAbsolute)) {
|
||||
const internalNode = get(nodeLookup).get(n.id);
|
||||
if (!internalNode || (!isRect && n.id === nodeOrRect.id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const currNodeRect = nodeToRect(n);
|
||||
const currNodeRect = nodeToRect(internalNode);
|
||||
const overlappingArea = getOverlappingArea(currNodeRect, nodeRect);
|
||||
const partiallyVisible = partially && overlappingArea > 0;
|
||||
|
||||
|
||||
@@ -116,6 +116,5 @@ export {
|
||||
getOutgoers,
|
||||
getConnectedEdges,
|
||||
addEdge,
|
||||
updateEdge,
|
||||
internalsSymbol
|
||||
updateEdge
|
||||
} from '@xyflow/system';
|
||||
|
||||
@@ -1,14 +1,8 @@
|
||||
<script lang="ts">
|
||||
import { getContext } from 'svelte';
|
||||
import {
|
||||
getNodesBounds,
|
||||
Position,
|
||||
type Rect,
|
||||
internalsSymbol,
|
||||
getNodeToolbarTransform
|
||||
} from '@xyflow/system';
|
||||
import { getNodesBounds, Position, type Rect, getNodeToolbarTransform } from '@xyflow/system';
|
||||
import portal from '$lib/actions/portal';
|
||||
import type { Node } from '$lib/types';
|
||||
import type { InternalNode } from '$lib/types';
|
||||
import { useStore } from '$lib/store';
|
||||
|
||||
import type { NodeToolbarProps } from './types';
|
||||
@@ -25,26 +19,26 @@
|
||||
const contextNodeId = getContext<string>('svelteflow__node_id');
|
||||
|
||||
let transform: string;
|
||||
let toolbarNodes: Node[] = [];
|
||||
let toolbarNodes: InternalNode[] = [];
|
||||
let _offset = offset !== undefined ? offset : 10;
|
||||
let _position = position !== undefined ? position : Position.Top;
|
||||
let _align = align !== undefined ? align : 'center';
|
||||
|
||||
$: {
|
||||
// $nodes only needed to trigger updates, $nodeLookup is just a helper that does not trigger any updates
|
||||
if ($nodes) {
|
||||
const nodeIds = Array.isArray(nodeId) ? nodeId : [nodeId || contextNodeId];
|
||||
// nly needed to trigger updates, $nodeLookup is just a helper that does not trigger any updates
|
||||
$nodes;
|
||||
|
||||
toolbarNodes = nodeIds.reduce<Node[]>((res, nodeId) => {
|
||||
const node = $nodeLookup.get(nodeId);
|
||||
const nodeIds = Array.isArray(nodeId) ? nodeId : [nodeId || contextNodeId];
|
||||
|
||||
if (node) {
|
||||
res.push(node);
|
||||
}
|
||||
toolbarNodes = nodeIds.reduce<InternalNode[]>((res, nodeId) => {
|
||||
const node = $nodeLookup.get(nodeId);
|
||||
|
||||
return res;
|
||||
}, []);
|
||||
}
|
||||
if (node) {
|
||||
res.push(node);
|
||||
}
|
||||
|
||||
return res;
|
||||
}, []);
|
||||
}
|
||||
|
||||
$: {
|
||||
@@ -54,8 +48,8 @@
|
||||
const toolbarNode = toolbarNodes[0];
|
||||
nodeRect = {
|
||||
...toolbarNode.position,
|
||||
width: toolbarNode.computed?.width ?? toolbarNode.width ?? 0,
|
||||
height: toolbarNode.computed?.height ?? toolbarNode.height ?? 0
|
||||
width: toolbarNode.measured.width ?? toolbarNode.width ?? 0,
|
||||
height: toolbarNode.measured.height ?? toolbarNode.height ?? 0
|
||||
};
|
||||
} else if (toolbarNodes.length > 1) {
|
||||
nodeRect = getNodesBounds(toolbarNodes, { nodeOrigin: $nodeOrigin });
|
||||
@@ -69,7 +63,7 @@
|
||||
$: zIndex =
|
||||
toolbarNodes.length === 0
|
||||
? 1
|
||||
: Math.max(...toolbarNodes.map((node) => (node[internalsSymbol]?.z || 5) + 1));
|
||||
: Math.max(...toolbarNodes.map((node) => (node.internals.z || 5) + 1));
|
||||
|
||||
//FIXME: Possible performance bottleneck
|
||||
$: selectedNodesCount = $nodes.filter((node) => node.selected).length;
|
||||
|
||||
@@ -6,7 +6,6 @@ import {
|
||||
ConnectionLineType,
|
||||
ConnectionMode,
|
||||
Position,
|
||||
internalsSymbol,
|
||||
type HandleElement
|
||||
} from '@xyflow/system';
|
||||
|
||||
@@ -65,8 +64,9 @@ export function getDerivedConnectionProps(
|
||||
return initConnectionProps;
|
||||
}
|
||||
|
||||
// TODO: it should bail out if the node is not found
|
||||
const fromNode = nodeLookup.get(connection.connectionStartHandle?.nodeId);
|
||||
const fromHandleBounds = fromNode?.[internalsSymbol]?.handleBounds;
|
||||
const fromHandleBounds = fromNode?.internals.handleBounds;
|
||||
const handleBoundsStrict =
|
||||
fromHandleBounds?.[connection.connectionStartHandle.type || 'source'] || [];
|
||||
const handleBoundsLoose: HandleElement[] | undefined | null = handleBoundsStrict
|
||||
@@ -81,12 +81,12 @@ export function getDerivedConnectionProps(
|
||||
: handleBounds?.[0];
|
||||
const fromHandleX = fromHandle
|
||||
? fromHandle.x + fromHandle.width / 2
|
||||
: (fromNode?.computed?.width ?? 0) / 2;
|
||||
: (fromNode?.measured.width ?? 0) / 2;
|
||||
const fromHandleY = fromHandle
|
||||
? fromHandle.y + fromHandle.height / 2
|
||||
: fromNode?.computed?.height ?? 0;
|
||||
const fromX = (fromNode?.computed?.positionAbsolute?.x ?? 0) + fromHandleX;
|
||||
const fromY = (fromNode?.computed?.positionAbsolute?.y ?? 0) + fromHandleY;
|
||||
: fromNode?.measured.height ?? 0;
|
||||
const fromX = (fromNode?.internals.positionAbsolute.x ?? 0) + fromHandleX;
|
||||
const fromY = (fromNode?.internals.positionAbsolute.y ?? 0) + fromHandleY;
|
||||
const fromPosition = fromHandle?.position;
|
||||
const toPosition = fromPosition ? oppositePosition[fromPosition] : undefined;
|
||||
|
||||
|
||||
@@ -64,52 +64,72 @@ export function createStore({
|
||||
const updateNodePositions: UpdateNodePositions = (nodeDragItems, dragging = false) => {
|
||||
const nodeLookup = get(store.nodeLookup);
|
||||
|
||||
nodeDragItems.forEach((nodeDragItem) => {
|
||||
for (const nodeDragItem of nodeDragItems) {
|
||||
const node = nodeLookup.get(nodeDragItem.id);
|
||||
|
||||
if (node) {
|
||||
node.position = nodeDragItem.position;
|
||||
node.dragging = dragging;
|
||||
node.computed = {
|
||||
...node.computed,
|
||||
positionAbsolute: nodeDragItem.computed?.positionAbsolute
|
||||
};
|
||||
if (!node) {
|
||||
continue;
|
||||
}
|
||||
});
|
||||
|
||||
const userNode = node.internals.userNode;
|
||||
userNode.position = nodeDragItem.position;
|
||||
userNode.dragging = dragging;
|
||||
// node.internals.positionAbsolute = nodeDragItem.internals.positionAbsolute;
|
||||
}
|
||||
|
||||
store.nodes.set(get(store.nodes));
|
||||
//$nodes = $nodes
|
||||
};
|
||||
|
||||
function updateNodeDimensions(updates: Map<string, NodeDimensionUpdate>) {
|
||||
const nextNodes = updateNodeDimensionsSystem(
|
||||
const nodeLookup = get(store.nodeLookup);
|
||||
const nodeUpdates = updateNodeDimensionsSystem(
|
||||
updates,
|
||||
get(store.nodes),
|
||||
get(store.nodeLookup),
|
||||
nodeLookup,
|
||||
get(store.domNode),
|
||||
get(store.nodeOrigin)
|
||||
);
|
||||
|
||||
if (!nextNodes) {
|
||||
if (!nodeUpdates) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!get(store.fitViewOnInitDone) && get(store.fitViewOnInit)) {
|
||||
const fitViewOptions = get(store.fitViewOptions);
|
||||
const fitViewOnInitDone = fitView(nextNodes, {
|
||||
const fitViewOnInitDone = fitView({
|
||||
...fitViewOptions,
|
||||
nodes: fitViewOptions?.nodes || nextNodes
|
||||
nodes: fitViewOptions?.nodes
|
||||
});
|
||||
store.fitViewOnInitDone.set(fitViewOnInitDone);
|
||||
}
|
||||
|
||||
store.nodes.set(nextNodes);
|
||||
for (const nodeUpdate of nodeUpdates) {
|
||||
const node = nodeLookup.get(nodeUpdate.id)?.internals.userNode;
|
||||
|
||||
if (!node) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (nodeUpdate.type) {
|
||||
case 'dimensions':
|
||||
node.width = nodeUpdate.dimensions?.width ?? node.width;
|
||||
node.height = nodeUpdate.dimensions?.height ?? node.height;
|
||||
// TODO: do we need measured here?
|
||||
break;
|
||||
case 'position':
|
||||
node.position = nodeUpdate.position ?? node.position;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
store.nodes.set(get(store.nodes));
|
||||
|
||||
if (!get(store.nodesInitialized)) {
|
||||
store.nodesInitialized.set(true);
|
||||
}
|
||||
}
|
||||
|
||||
function fitView(nodes: Node[], options?: FitViewOptions) {
|
||||
function fitView(options?: FitViewOptions) {
|
||||
const panZoom = get(store.panZoom);
|
||||
|
||||
if (!panZoom) {
|
||||
@@ -118,7 +138,7 @@ export function createStore({
|
||||
|
||||
return fitViewUtil(
|
||||
{
|
||||
nodes,
|
||||
nodeLookup: get(store.nodeLookup),
|
||||
width: get(store.width),
|
||||
height: get(store.height),
|
||||
minZoom: get(store.minZoom),
|
||||
@@ -384,7 +404,7 @@ export function createStore({
|
||||
updateNodeDimensions,
|
||||
zoomIn,
|
||||
zoomOut,
|
||||
fitView: (options?: FitViewOptions) => fitView(get(store.nodes), options),
|
||||
fitView: (options?: FitViewOptions) => fitView(options),
|
||||
setMinZoom,
|
||||
setMaxZoom,
|
||||
setTranslateExtent,
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
ConnectionMode,
|
||||
ConnectionLineType,
|
||||
devWarn,
|
||||
adoptUserProvidedNodes,
|
||||
adoptUserNodes,
|
||||
getNodesBounds,
|
||||
getViewportForBounds,
|
||||
updateConnectionLookup,
|
||||
@@ -47,7 +47,8 @@ import type {
|
||||
OnDelete,
|
||||
OnEdgeCreate,
|
||||
OnBeforeDelete,
|
||||
IsValidConnection
|
||||
IsValidConnection,
|
||||
InternalNode
|
||||
} from '$lib/types';
|
||||
import { createNodesStore, createEdgesStore } from './utils';
|
||||
import { initConnectionProps, type ConnectionProps } from './derived-connection-props';
|
||||
@@ -80,9 +81,10 @@ export const getInitialStore = ({
|
||||
fitView?: boolean;
|
||||
}) => {
|
||||
const nodeLookup: NodeLookup = new Map();
|
||||
const nextNodes = adoptUserProvidedNodes(nodes, nodeLookup, {
|
||||
adoptUserNodes(nodes, nodeLookup, {
|
||||
nodeOrigin: [0, 0],
|
||||
elevateNodesOnSelect: false
|
||||
elevateNodesOnSelect: false,
|
||||
checkEquality: false
|
||||
});
|
||||
const connectionLookup = new Map();
|
||||
const edgeLookup = new Map();
|
||||
@@ -91,9 +93,10 @@ export const getInitialStore = ({
|
||||
let viewport: Viewport = { x: 0, y: 0, zoom: 1 };
|
||||
|
||||
if (fitView && width && height) {
|
||||
const nodesWithDimensions = nextNodes.filter(
|
||||
const nodesWithDimensions = Array.from(nodeLookup.values()).filter(
|
||||
(node) => (node.width && node.height) || (node.initialWidth && node.initialHeight)
|
||||
);
|
||||
|
||||
// @todo users nodeOrigin should be used here
|
||||
const bounds = getNodesBounds(nodesWithDimensions, { nodeOrigin: [0, 0] });
|
||||
viewport = getViewportForBounds(bounds, width, height, 0.5, 2, 0.1);
|
||||
@@ -101,10 +104,10 @@ export const getInitialStore = ({
|
||||
|
||||
return {
|
||||
flowId: writable<string | null>(null),
|
||||
nodes: createNodesStore(nextNodes, nodeLookup),
|
||||
nodeLookup: readable<NodeLookup<Node>>(nodeLookup),
|
||||
nodes: createNodesStore(nodes, nodeLookup),
|
||||
nodeLookup: readable<NodeLookup<InternalNode>>(nodeLookup),
|
||||
edgeLookup: readable<EdgeLookup<Edge>>(edgeLookup),
|
||||
visibleNodes: readable<Node[]>([]),
|
||||
visibleNodes: readable<InternalNode[]>([]),
|
||||
edges: createEdgesStore(edges, connectionLookup, edgeLookup),
|
||||
visibleEdges: readable<EdgeLayouted[]>([]),
|
||||
connectionLookup: readable<ConnectionLookup>(connectionLookup),
|
||||
|
||||
@@ -16,7 +16,7 @@ import {
|
||||
type NodeLookup
|
||||
} from '@xyflow/system';
|
||||
|
||||
import type { DefaultEdgeOptions, DefaultNodeOptions, Edge, Node } from '$lib/types';
|
||||
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).
|
||||
@@ -127,7 +127,7 @@ export type NodeStoreOptions = {
|
||||
// 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<Node>
|
||||
nodeLookup: NodeLookup<InternalNode>
|
||||
): {
|
||||
subscribe: (this: void, run: Subscriber<Node[]>) => Unsubscriber;
|
||||
update: (this: void, updater: Updater<Node[]>) => void;
|
||||
@@ -141,12 +141,13 @@ export const createNodesStore = (
|
||||
let elevateNodesOnSelect = true;
|
||||
|
||||
const _set = (nds: Node[]): Node[] => {
|
||||
const nextNodes = adoptUserNodes(nds, nodeLookup, {
|
||||
adoptUserNodes(nds, nodeLookup, {
|
||||
elevateNodesOnSelect,
|
||||
defaults
|
||||
defaults,
|
||||
checkEquality: false
|
||||
});
|
||||
|
||||
value = nextNodes;
|
||||
value = nodes;
|
||||
|
||||
set(value);
|
||||
|
||||
|
||||
@@ -1,18 +1,23 @@
|
||||
import { derived } from 'svelte/store';
|
||||
import { getNodesInside, type Transform } from '@xyflow/system';
|
||||
|
||||
import type { Node } from '$lib/types';
|
||||
import type { SvelteFlowStoreState } from './types';
|
||||
|
||||
export function getVisibleNodes(store: SvelteFlowStoreState) {
|
||||
return derived(
|
||||
[store.nodes, store.onlyRenderVisibleElements, store.width, store.height, store.viewport],
|
||||
([nodes, onlyRenderVisibleElements, width, height, viewport]) => {
|
||||
[
|
||||
store.nodes,
|
||||
store.nodeLookup,
|
||||
store.onlyRenderVisibleElements,
|
||||
store.width,
|
||||
store.height,
|
||||
store.viewport
|
||||
],
|
||||
([_, nodeLookup, onlyRenderVisibleElements, width, height, viewport]) => {
|
||||
const transform: Transform = [viewport.x, viewport.y, viewport.zoom];
|
||||
|
||||
return onlyRenderVisibleElements
|
||||
? getNodesInside<Node>(nodes, { x: 0, y: 0, width, height }, transform, true)
|
||||
: nodes;
|
||||
? getNodesInside(nodeLookup, { x: 0, y: 0, width, height }, transform, true)
|
||||
: Array.from(nodeLookup.values());
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
import type { ComponentType, SvelteComponent } from 'svelte';
|
||||
import type { NodeBase, NodeProps as NodePropsBase } from '@xyflow/system';
|
||||
import type { InternalNodeBase, NodeBase, NodeProps as NodePropsBase } from '@xyflow/system';
|
||||
|
||||
/**
|
||||
* The node data structure that gets used for internal nodes.
|
||||
* There are some data structures added under node.internal
|
||||
* that are needed for tracking some properties
|
||||
* @public
|
||||
*/
|
||||
export type InternalNode<NodeType extends Node = Node> = InternalNodeBase<NodeType>;
|
||||
|
||||
/**
|
||||
* The node data structure that gets used for the nodes prop.
|
||||
|
||||
@@ -230,14 +230,14 @@ export const getNodesInside = <NodeType extends NodeBase = NodeBase>(
|
||||
// set excludeNonSelectableNodes if you want to pay attention to the nodes "selectable" attribute
|
||||
excludeNonSelectableNodes = false,
|
||||
nodeOrigin: NodeOrigin = [0, 0]
|
||||
): NodeType[] => {
|
||||
): InternalNodeBase<NodeType>[] => {
|
||||
const paneRect = {
|
||||
...pointToRendererPoint(rect, [tx, ty, tScale]),
|
||||
width: rect.width / tScale,
|
||||
height: rect.height / tScale,
|
||||
};
|
||||
|
||||
const visibleNodes: NodeType[] = [];
|
||||
const visibleNodes: InternalNodeBase<NodeType>[] = [];
|
||||
|
||||
for (const [, node] of nodeLookup) {
|
||||
const { measured, selectable = true, hidden = false } = node;
|
||||
@@ -290,6 +290,7 @@ export function fitView<Params extends FitViewParamsBase<NodeBase>, Options exte
|
||||
nodeLookup.forEach((n) => {
|
||||
const isVisible = n.measured.width && n.measured.height && (options?.includeHiddenNodes || !n.hidden);
|
||||
|
||||
// TODO: this remove options.nodes.some with a Set
|
||||
if (
|
||||
isVisible &&
|
||||
(!options?.nodes || (options?.nodes.length && options?.nodes.some((optionNode) => optionNode.id === n.id)))
|
||||
|
||||
@@ -14,6 +14,8 @@ import {
|
||||
NodeChange,
|
||||
NodeLookup,
|
||||
Rect,
|
||||
NodeDimensionChange,
|
||||
NodePositionChange,
|
||||
} from '../types';
|
||||
import { getDimensions, getHandleBounds } from './dom';
|
||||
import { getBoundsOfRects, getNodeDimensions, isNumeric, nodeToRect } from './general';
|
||||
@@ -68,6 +70,7 @@ type UpdateNodesOptions<NodeType extends NodeBase> = {
|
||||
nodeOrigin?: NodeOrigin;
|
||||
elevateNodesOnSelect?: boolean;
|
||||
defaults?: Partial<NodeType>;
|
||||
checkEquality?: boolean;
|
||||
};
|
||||
|
||||
export function adoptUserNodes<NodeType extends NodeBase>(
|
||||
@@ -77,6 +80,7 @@ export function adoptUserNodes<NodeType extends NodeBase>(
|
||||
nodeOrigin: [0, 0] as NodeOrigin,
|
||||
elevateNodesOnSelect: true,
|
||||
defaults: {},
|
||||
checkEquality: true,
|
||||
}
|
||||
) {
|
||||
const tmpLookup = new Map(nodeLookup);
|
||||
@@ -91,7 +95,7 @@ export function adoptUserNodes<NodeType extends NodeBase>(
|
||||
parentNodeIds.add(userNode.parentId);
|
||||
}
|
||||
|
||||
if (userNode === currentStoreNode?.internals.userNode) {
|
||||
if (options.checkEquality && userNode === currentStoreNode?.internals.userNode) {
|
||||
nodeLookup.set(userNode.id, currentStoreNode);
|
||||
} else {
|
||||
nodeLookup.set(userNode.id, {
|
||||
@@ -142,8 +146,11 @@ function calculateXYZPosition<NodeType extends NodeBase>(
|
||||
);
|
||||
}
|
||||
|
||||
export function handleParentExpand(nodes: InternalNodeBase[], nodeLookup: NodeLookup): NodeChange[] {
|
||||
const changes: NodeChange[] = [];
|
||||
export function handleParentExpand(
|
||||
nodes: InternalNodeBase[],
|
||||
nodeLookup: NodeLookup
|
||||
): (NodeDimensionChange | NodePositionChange)[] {
|
||||
const changes: (NodeDimensionChange | NodePositionChange)[] = [];
|
||||
const chilNodeRects = new Map<string, Rect>();
|
||||
|
||||
nodes.forEach((node) => {
|
||||
@@ -211,14 +218,14 @@ export function updateNodeDimensions<NodeType extends InternalNodeBase>(
|
||||
nodeLookup: Map<string, NodeType>,
|
||||
domNode: HTMLElement | null,
|
||||
nodeOrigin?: NodeOrigin
|
||||
): NodeChange[] {
|
||||
): (NodeDimensionChange | NodePositionChange)[] {
|
||||
const viewportNode = domNode?.querySelector('.xyflow__viewport');
|
||||
|
||||
if (!viewportNode) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const changes: NodeChange[] = [];
|
||||
const changes: (NodeDimensionChange | NodePositionChange)[] = [];
|
||||
const style = window.getComputedStyle(viewportNode);
|
||||
const { m22: zoom } = new window.DOMMatrixReadOnly(style.transform);
|
||||
// in this array we collect nodes, that might trigger changes (like expanding parent)
|
||||
|
||||
Reference in New Issue
Block a user