From 1bc1ae855d087fd23ec980f92f2c689e205226ef Mon Sep 17 00:00:00 2001 From: moklick Date: Mon, 15 Jan 2024 17:32:30 +0100 Subject: [PATCH 1/4] refactor(util-functions): cleanup types so that node/edge types get infered --- packages/react/src/index.ts | 7 +- packages/react/src/utils/changes.ts | 2 +- packages/react/src/utils/general.ts | 64 ++----------------- packages/svelte/CHANGELOG.md | 2 + packages/svelte/src/lib/index.ts | 4 ++ .../svelte/src/lib/store/initial-store.ts | 2 +- packages/svelte/src/lib/utils/index.ts | 64 ++----------------- packages/system/src/utils/edges/general.ts | 4 +- packages/system/src/utils/graph.ts | 8 +-- 9 files changed, 30 insertions(+), 127 deletions(-) diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts index 20573392..3cabb813 100644 --- a/packages/react/src/index.ts +++ b/packages/react/src/index.ts @@ -29,7 +29,7 @@ export { useConnection } from './hooks/useConnection'; export { useNodeId } from './contexts/NodeIdContext'; export { applyNodeChanges, applyEdgeChanges, handleParentExpand } from './utils/changes'; -export { isNode, isEdge, getIncomers, getOutgoers, addEdge, updateEdge, getConnectedEdges } from './utils/general'; +export { isNode, isEdge } from './utils/general'; export * from './additional-components'; @@ -102,5 +102,10 @@ export { getStraightPath, getViewportForBounds, getNodesBounds, + getIncomers, + getOutgoers, + addEdge, + updateEdge, + getConnectedEdges, internalsSymbol, } from '@xyflow/system'; diff --git a/packages/react/src/utils/changes.ts b/packages/react/src/utils/changes.ts index 91a7a004..6bcddabd 100644 --- a/packages/react/src/utils/changes.ts +++ b/packages/react/src/utils/changes.ts @@ -267,7 +267,7 @@ export function getElementsDiffChanges({ lookup, }: { items: Node[] | undefined; - lookup: NodeLookup; + lookup: NodeLookup; }): NodeChange[]; export function getElementsDiffChanges({ items, diff --git a/packages/react/src/utils/general.ts b/packages/react/src/utils/general.ts index 5de3c3b2..2c2387fc 100644 --- a/packages/react/src/utils/general.ts +++ b/packages/react/src/utils/general.ts @@ -1,12 +1,4 @@ -import { - isNodeBase, - isEdgeBase, - addEdgeBase, - getOutgoersBase, - getIncomersBase, - updateEdgeBase, - getConnectedEdgesBase, -} from '@xyflow/system'; +import { isNodeBase, isEdgeBase } from '@xyflow/system'; import type { Edge, Node } from '../types'; @@ -17,7 +9,8 @@ import type { Edge, Node } from '../types'; * @param element - The element to test * @returns A boolean indicating whether the element is an Node */ -export const isNode = isNodeBase; +export const isNode = (element: unknown): element is NodeType => + isNodeBase(element); /** * Test whether an object is useable as an Edge @@ -26,52 +19,5 @@ export const isNode = isNodeBase; * @param element - The element to test * @returns A boolean indicating whether the element is an Edge */ -export const isEdge = isEdgeBase; - -/** - * Pass in a node, and get connected nodes where edge.source === node.id - * @public - * @param node - The node to get the connected nodes from - * @param nodes - The array of all nodes - * @param edges - The array of all edges - * @returns An array of nodes that are connected over eges where the source is the given node - */ -export const getOutgoers = getOutgoersBase; - -/** - * Pass in a node, and get connected nodes where edge.target === node.id - * @public - * @param node - The node to get the connected nodes from - * @param nodes - The array of all nodes - * @param edges - The array of all edges - * @returns An array of nodes that are connected over eges where the target is the given node - */ -export const getIncomers = getIncomersBase; - -/** - * This util is a convenience function to add a new Edge to an array of edges - * @remarks It also performs some validation to make sure you don't add an invalid edge or duplicate an existing one. - * @public - * @param edgeParams - Either an Edge or a Connection you want to add - * @param edges - The array of all current edges - * @returns A new array of edges with the new edge added - */ -export const addEdge = addEdgeBase; - -/** - * A handy utility to update an existing Edge with new properties - * @param oldEdge - The edge you want to update - * @param newConnection - The new connection you want to update the edge with - * @param edges - The array of all current edges - * @param options.shouldReplaceId - should the id of the old edge be replaced with the new connection id - * @returns the updated edges array - */ -export const updateEdge = updateEdgeBase; - -/** - * Get all connecting edges for a given set of nodes - * @param nodes - Nodes you want to get the connected edges for - * @param edges - All edges - * @returns Array of edges that connect any of the given nodes with each other - */ -export const getConnectedEdges = getConnectedEdgesBase; +export const isEdge = (element: unknown): element is EdgeType => + isEdgeBase(element); diff --git a/packages/svelte/CHANGELOG.md b/packages/svelte/CHANGELOG.md index 96044f85..23164fb0 100644 --- a/packages/svelte/CHANGELOG.md +++ b/packages/svelte/CHANGELOG.md @@ -5,6 +5,8 @@ ## Minor changes - add second option param to `screenToFlowPosition` for configuring if `snapToGrid` should be used +- add slot to `Controls` +- cleanup `ControlButton` types ## 0.0.33 diff --git a/packages/svelte/src/lib/index.ts b/packages/svelte/src/lib/index.ts index 9a706959..357b241a 100644 --- a/packages/svelte/src/lib/index.ts +++ b/packages/svelte/src/lib/index.ts @@ -112,5 +112,9 @@ export { getStraightPath, getViewportForBounds, getNodesBounds, + getIncomers, + getOutgoers, + getConnectedEdges, + addEdge, internalsSymbol } from '@xyflow/system'; diff --git a/packages/svelte/src/lib/store/initial-store.ts b/packages/svelte/src/lib/store/initial-store.ts index 90c59b2d..26c57c86 100644 --- a/packages/svelte/src/lib/store/initial-store.ts +++ b/packages/svelte/src/lib/store/initial-store.ts @@ -99,7 +99,7 @@ export const getInitialStore = ({ return { flowId: writable(null), nodes: createNodesStore(nextNodes, nodeLookup), - nodeLookup: readable(nodeLookup), + nodeLookup: readable>(nodeLookup), edgeLookup: readable(edgeLookup), visibleNodes: readable([]), edges: createEdgesStore(edges, connectionLookup, edgeLookup), diff --git a/packages/svelte/src/lib/utils/index.ts b/packages/svelte/src/lib/utils/index.ts index bad572dc..10f205ca 100644 --- a/packages/svelte/src/lib/utils/index.ts +++ b/packages/svelte/src/lib/utils/index.ts @@ -1,12 +1,4 @@ -import { - isNodeBase, - isEdgeBase, - addEdgeBase, - getOutgoersBase, - getIncomersBase, - updateEdgeBase, - getConnectedEdgesBase -} from '@xyflow/system'; +import { isNodeBase, isEdgeBase } from '@xyflow/system'; import type { Edge, Node } from '$lib/types'; @@ -17,7 +9,8 @@ import type { Edge, Node } from '$lib/types'; * @param element - The element to test * @returns A boolean indicating whether the element is an Node */ -export const isNode = isNodeBase; +export const isNode = (element: unknown): element is NodeType => + isNodeBase(element); /** * Test whether an object is useable as an Edge @@ -26,52 +19,5 @@ export const isNode = isNodeBase; * @param element - The element to test * @returns A boolean indicating whether the element is an Edge */ -export const isEdge = isEdgeBase; - -/** - * Pass in a node, and get connected nodes where edge.source === node.id - * @public - * @param node - The node to get the connected nodes from - * @param nodes - The array of all nodes - * @param edges - The array of all edges - * @returns An array of nodes that are connected over eges where the source is the given node - */ -export const getOutgoers = getOutgoersBase; - -/** - * Pass in a node, and get connected nodes where edge.target === node.id - * @public - * @param node - The node to get the connected nodes from - * @param nodes - The array of all nodes - * @param edges - The array of all edges - * @returns An array of nodes that are connected over eges where the target is the given node - */ -export const getIncomers = getIncomersBase; - -/** - * This util is a convenience function to add a new Edge to an array of edges - * @remarks It also performs some validation to make sure you don't add an invalid edge or duplicate an existing one. - * @public - * @param edgeParams - Either an Edge or a Connection you want to add - * @param edges - The array of all current edges - * @returns A new array of edges with the new edge added - */ -export const addEdge = addEdgeBase; - -/** - * A handy utility to update an existing Edge with new properties - * @param oldEdge - The edge you want to update - * @param newConnection - The new connection you want to update the edge with - * @param edges - The array of all current edges - * @param options.shouldReplaceId - should the id of the old edge be replaced with the new connection id - * @returns the updated edges array - */ -export const updateEdge = updateEdgeBase; - -/** - * Get all connecting edges for a given set of nodes - * @param nodes - Nodes you want to get the connected edges for - * @param edges - All edges - * @returns Array of edges that connect any of the given nodes with each other - */ -export const getConnectedEdges = getConnectedEdgesBase; +export const isEdge = (element: unknown): element is EdgeType => + isEdgeBase(element); diff --git a/packages/system/src/utils/edges/general.ts b/packages/system/src/utils/edges/general.ts index 14e73318..f53db23a 100644 --- a/packages/system/src/utils/edges/general.ts +++ b/packages/system/src/utils/edges/general.ts @@ -98,7 +98,7 @@ const connectionExists = (edge: EdgeBase, edges: EdgeBase[]) => { * @param edges - The array of all current edges * @returns A new array of edges with the new edge added */ -export const addEdgeBase = ( +export const addEdge = ( edgeParams: EdgeType | Connection, edges: EdgeType[] ): EdgeType[] => { @@ -145,7 +145,7 @@ export type UpdateEdgeOptions = { * @param options.shouldReplaceId - should the id of the old edge be replaced with the new connection id * @returns the updated edges array */ -export const updateEdgeBase = ( +export const updateEdge = ( oldEdge: EdgeType, newConnection: Connection, edges: EdgeType[], diff --git a/packages/system/src/utils/graph.ts b/packages/system/src/utils/graph.ts index 6d341e5e..fa56a987 100644 --- a/packages/system/src/utils/graph.ts +++ b/packages/system/src/utils/graph.ts @@ -54,7 +54,7 @@ export const isNodeBase = (element: any): * @param edges - The array of all edges * @returns An array of nodes that are connected over eges where the source is the given node */ -export const getOutgoersBase = ( +export const getOutgoers = ( node: NodeType | { id: string }, nodes: NodeType[], edges: EdgeType[] @@ -81,7 +81,7 @@ export const getOutgoersBase = ( +export const getIncomers = ( node: NodeType | { id: string }, nodes: NodeType[], edges: EdgeType[] @@ -212,7 +212,7 @@ export const getNodesInside = ( * @param edges - All edges * @returns Array of edges that connect any of the given nodes with each other */ -export const getConnectedEdgesBase = ( +export const getConnectedEdges = ( nodes: NodeType[], edges: EdgeType[] ): EdgeType[] => { @@ -370,7 +370,7 @@ export async function getElementsToRemove edge.id); const deletableEdges = edges.filter((edge) => edge.deletable !== false); - const connectedEdges = getConnectedEdgesBase(matchingNodes, deletableEdges); + const connectedEdges = getConnectedEdges(matchingNodes, deletableEdges); const matchingEdges: EdgeType[] = connectedEdges; for (const edge of deletableEdges) { From 37f76275eb00127adef868fabad7286ff3a48dcb Mon Sep 17 00:00:00 2001 From: moklick Date: Mon, 15 Jan 2024 17:35:08 +0100 Subject: [PATCH 2/4] chore(libs): update changelogs --- packages/react/CHANGELOG.md | 1 + packages/svelte/CHANGELOG.md | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/react/CHANGELOG.md b/packages/react/CHANGELOG.md index 951f4895..66a7b055 100644 --- a/packages/react/CHANGELOG.md +++ b/packages/react/CHANGELOG.md @@ -7,6 +7,7 @@ - pass Node/Edge types to changes thanks @FelipeEmos - use position instead of positionAbsolute for `getNodesBounds` - add second option param to `screenToFlowPosition` for configuring if `snapToGrid` should be used +- infer types for `getIncomers`, `getOutgoers`, `updateEdge`, `addEdge` and `getConnectedEdges` thanks @joeyballentine ## 12.0.0-next.6 diff --git a/packages/svelte/CHANGELOG.md b/packages/svelte/CHANGELOG.md index 23164fb0..ffc72eeb 100644 --- a/packages/svelte/CHANGELOG.md +++ b/packages/svelte/CHANGELOG.md @@ -7,6 +7,7 @@ - add second option param to `screenToFlowPosition` for configuring if `snapToGrid` should be used - add slot to `Controls` - cleanup `ControlButton` types +- infer types for `getIncomers`, `getOutgoers`, `updateEdge`, `addEdge` and `getConnectedEdges` thanks @joeyballentine ## 0.0.33 From e23cf8256a624af787817fdd202bd43fcd57f153 Mon Sep 17 00:00:00 2001 From: moklick Date: Mon, 15 Jan 2024 17:37:18 +0100 Subject: [PATCH 3/4] chore(svelte): export updateEdge --- packages/svelte/src/lib/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/svelte/src/lib/index.ts b/packages/svelte/src/lib/index.ts index 357b241a..4c3737ea 100644 --- a/packages/svelte/src/lib/index.ts +++ b/packages/svelte/src/lib/index.ts @@ -116,5 +116,6 @@ export { getOutgoers, getConnectedEdges, addEdge, + updateEdge, internalsSymbol } from '@xyflow/system'; From f32a92ecca1abf8d9bd351c50307d4ea268f1684 Mon Sep 17 00:00:00 2001 From: moklick Date: Mon, 15 Jan 2024 17:44:29 +0100 Subject: [PATCH 4/4] refactor(utils): use utils from system package --- packages/react/src/components/Handle/index.tsx | 2 +- packages/react/src/hooks/useNodesEdgesState.ts | 14 ++++++++++---- packages/react/src/types/instance.ts | 3 --- packages/svelte/src/lib/container/Pane/Pane.svelte | 8 ++++++-- packages/svelte/src/lib/store/index.ts | 2 +- 5 files changed, 18 insertions(+), 11 deletions(-) diff --git a/packages/react/src/components/Handle/index.tsx b/packages/react/src/components/Handle/index.tsx index 41bf492c..86f8da2a 100644 --- a/packages/react/src/components/Handle/index.tsx +++ b/packages/react/src/components/Handle/index.tsx @@ -12,6 +12,7 @@ import { XYHandle, getHostForElement, isMouseEvent, + addEdge, type HandleProps, type Connection, type HandleType, @@ -19,7 +20,6 @@ import { import { useStore, useStoreApi } from '../../hooks/useStore'; import { useNodeId } from '../../contexts/NodeIdContext'; -import { addEdge } from '../../utils/'; import { type ReactFlowState } from '../../types'; export type HandleComponentProps = HandleProps & Omit, 'id'>; diff --git a/packages/react/src/hooks/useNodesEdgesState.ts b/packages/react/src/hooks/useNodesEdgesState.ts index c134472b..766ee049 100644 --- a/packages/react/src/hooks/useNodesEdgesState.ts +++ b/packages/react/src/hooks/useNodesEdgesState.ts @@ -12,9 +12,12 @@ import type { Node, NodeChange, Edge, EdgeChange } from '../types'; */ export function useNodesState( initialNodes: NodeType[] -): [NodeType[], Dispatch>, (changes: NodeChange[]) => void] { +): [NodeType[], Dispatch>, (changes: NodeChange[]) => void] { const [nodes, setNodes] = useState(initialNodes); - const onNodesChange = useCallback((changes: NodeChange[]) => setNodes((nds) => applyNodeChanges(changes, nds)), []); + const onNodesChange = useCallback( + (changes: NodeChange[]) => setNodes((nds) => applyNodeChanges(changes, nds)), + [] + ); return [nodes, setNodes, onNodesChange]; } @@ -28,9 +31,12 @@ export function useNodesState( */ export function useEdgesState( initialEdges: EdgeType[] -): [EdgeType[], Dispatch>, (changes: EdgeChange[]) => void] { +): [EdgeType[], Dispatch>, (changes: EdgeChange[]) => void] { const [edges, setEdges] = useState(initialEdges); - const onEdgesChange = useCallback((changes: EdgeChange[]) => setEdges((eds) => applyEdgeChanges(changes, eds)), []); + const onEdgesChange = useCallback( + (changes: EdgeChange[]) => setEdges((eds) => applyEdgeChanges(changes, eds)), + [] + ); return [edges, setEdges, onEdgesChange]; } diff --git a/packages/react/src/types/instance.ts b/packages/react/src/types/instance.ts index 0bf01b20..6b37fd14 100644 --- a/packages/react/src/types/instance.ts +++ b/packages/react/src/types/instance.ts @@ -45,9 +45,6 @@ export namespace Instance { area: Rect, partially?: boolean ) => boolean; - export type getConnectedEdges = (id: string | (Node | { id: Node['id'] })[]) => Edge[]; - export type getIncomers = (node: string | Node | { id: Node['id'] }) => Node[]; - export type getOutgoers = (node: string | Node | { id: Node['id'] }) => Node[]; export type UpdateNode = ( id: string, diff --git a/packages/svelte/src/lib/container/Pane/Pane.svelte b/packages/svelte/src/lib/container/Pane/Pane.svelte index 21ed2a61..cce95636 100644 --- a/packages/svelte/src/lib/container/Pane/Pane.svelte +++ b/packages/svelte/src/lib/container/Pane/Pane.svelte @@ -30,10 +30,14 @@