diff --git a/examples/react/src/examples/Basic/index.tsx b/examples/react/src/examples/Basic/index.tsx index 8d9c7dfd..f454b313 100644 --- a/examples/react/src/examples/Basic/index.tsx +++ b/examples/react/src/examples/Basic/index.tsx @@ -10,9 +10,10 @@ import { Edge, useReactFlow, Panel, + OnNodeDrag, } from '@xyflow/react'; -const onNodeDrag = (_: MouseEvent, node: Node) => console.log('drag', node); +const onNodeDrag: OnNodeDrag = (_, node) => console.log('drag', node); const onNodeDragStop = (_: MouseEvent, node: Node) => console.log('drag stop', node); const onNodeClick = (_: MouseEvent, node: Node) => console.log('click', node); diff --git a/examples/react/src/examples/CustomNode/ColorSelectorNode.tsx b/examples/react/src/examples/CustomNode/ColorSelectorNode.tsx index 6857e1ac..72255e27 100644 --- a/examples/react/src/examples/CustomNode/ColorSelectorNode.tsx +++ b/examples/react/src/examples/CustomNode/ColorSelectorNode.tsx @@ -1,6 +1,8 @@ -import React, { memo, FC, CSSProperties, useCallback, useEffect } from 'react'; +import React, { memo, FC, CSSProperties, useCallback } from 'react'; import { Handle, Position, NodeProps, Connection, Edge, useOnViewportChange, Viewport } from '@xyflow/react'; +import type { ColorSelectorNode } from '.'; + const targetHandleStyle: CSSProperties = { background: '#555' }; const sourceHandleStyleA: CSSProperties = { ...targetHandleStyle, top: 10 }; const sourceHandleStyleB: CSSProperties = { @@ -11,7 +13,7 @@ const sourceHandleStyleB: CSSProperties = { const onConnect = (params: Connection | Edge) => console.log('handle onConnect', params); -const ColorSelectorNode: FC = ({ data, isConnectable }) => { +const ColorSelectorNode: FC> = ({ data, isConnectable }) => { const onStart = useCallback((viewport: Viewport) => console.log('onStart', viewport), []); const onChange = useCallback((viewport: Viewport) => console.log('onChange', viewport), []); const onEnd = useCallback((viewport: Viewport) => console.log('onEnd', viewport), []); diff --git a/examples/react/src/examples/CustomNode/index.tsx b/examples/react/src/examples/CustomNode/index.tsx index ce7d0f62..22433db0 100644 --- a/examples/react/src/examples/CustomNode/index.tsx +++ b/examples/react/src/examples/CustomNode/index.tsx @@ -5,24 +5,32 @@ import { Controls, addEdge, Node, - ReactFlowInstance, Position, SnapGrid, - Connection, - useNodesState, useEdgesState, Background, Edge, + OnNodeDrag, + OnInit, + applyNodeChanges, + OnNodesChange, + OnConnect, } from '@xyflow/react'; import ColorSelectorNode from './ColorSelectorNode'; -const onInit = (reactFlowInstance: ReactFlowInstance) => { +export type ColorSelectorNode = Node< + { color: string; onChange: (event: ChangeEvent) => void }, + 'selectorNode' +>; +export type MyNode = Node | ColorSelectorNode; + +const onInit: OnInit = (reactFlowInstance) => { console.log('flow loaded:', reactFlowInstance); }; -const onNodeDragStop = (_: MouseEvent, node: Node) => console.log('drag stop', node); -const onNodeClick = (_: MouseEvent, node: Node) => console.log('click', node); +const onNodeDragStop: OnNodeDrag = (_, node) => console.log('drag stop', node); +const onNodeClick = (_: MouseEvent, node: MyNode) => console.log('click', node); const initBgColor = '#1A192B'; @@ -34,7 +42,16 @@ const nodeTypes = { }; const CustomNodeFlow = () => { - const [nodes, setNodes, onNodesChange] = useNodesState([]); + const [nodes, setNodes] = useState([]); + const onNodesChange: OnNodesChange = useCallback( + (changes) => + setNodes((nds) => { + const nextNodes = applyNodeChanges(changes, nds); + return nextNodes; + }), + [setNodes] + ); + const [edges, setEdges, onEdgesChange] = useEdgesState([]); const [bgColor, setBgColor] = useState(initBgColor); @@ -120,9 +137,8 @@ const CustomNodeFlow = () => { ]); }, []); - const onConnect = useCallback( - (connection: Connection) => - setEdges((eds) => addEdge({ ...connection, animated: true, style: { stroke: '#fff' } }, eds)), + const onConnect: OnConnect = useCallback( + (connection) => setEdges((eds) => addEdge({ ...connection, animated: true, style: { stroke: '#fff' } }, eds)), [setEdges] ); @@ -145,14 +161,14 @@ const CustomNodeFlow = () => { maxZoom={2} > { + nodeStrokeColor={(n: MyNode): string => { if (n.type === 'input') return '#0041d0'; if (n.type === 'selectorNode') return bgColor; if (n.type === 'output') return '#ff0072'; return '#eee'; }} - nodeColor={(n: Node): string => { + nodeColor={(n: MyNode): string => { if (n.type === 'selectorNode') return bgColor; return '#fff'; diff --git a/examples/svelte/src/routes/examples/handle-connect/MultiHandleNode.svelte b/examples/svelte/src/routes/examples/handle-connect/MultiHandleNode.svelte index ebc85c74..f411fc44 100644 --- a/examples/svelte/src/routes/examples/handle-connect/MultiHandleNode.svelte +++ b/examples/svelte/src/routes/examples/handle-connect/MultiHandleNode.svelte @@ -43,10 +43,8 @@ export let zIndex: $$Props['zIndex'] = undefined; export let dragging: $$Props['dragging'] = false; export let dragHandle: $$Props['dragHandle'] = undefined; - export let positionAbsolute: $$Props['positionAbsolute'] = { - x: 0, - y: 0 - }; + export let positionAbsoluteX: $$Props['positionAbsoluteX'] = 0; + export let positionAbsoluteY: $$Props['positionAbsoluteY'] = 0; export let isConnectable: $$Props['isConnectable'] = undefined; data; @@ -59,7 +57,8 @@ zIndex; dragging; dragHandle; - positionAbsolute; + positionAbsoluteX; + positionAbsoluteY; isConnectable; diff --git a/packages/react/CHANGELOG.md b/packages/react/CHANGELOG.md index 2dd4e593..70a3de11 100644 --- a/packages/react/CHANGELOG.md +++ b/packages/react/CHANGELOG.md @@ -1,19 +1,28 @@ # @xyflow/react +## 12.0.0-next.8 + +### Patch changes + +- fix `OnNodeDrag` type + ## 12.0.0-next.7 ## Minor changes -- 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 + +### Patch changes + +- pass `Node`/ `Edge` types to changes thanks @FelipeEmos +- use position instead of positionAbsolute for `getNodesBounds` - infer types for `getIncomers`, `getOutgoers`, `updateEdge`, `addEdge` and `getConnectedEdges` thanks @joeyballentine - refactor handles: prefix with flow id for handling nested flows - add comments for types like `ReactFlowProps` or `Node` for a better developer experience ## 12.0.0-next.6 -### Minor changes +### Patch changes - fix `deleteElements` - refactor internal `applyChanges` diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts index 3cabb813..8ad67000 100644 --- a/packages/react/src/index.ts +++ b/packages/react/src/index.ts @@ -67,7 +67,6 @@ export { type OnError, type NodeProps, type NodeOrigin, - type OnNodeDrag, type OnSelectionDrag, Position, type XYPosition, diff --git a/packages/react/src/types/component-props.ts b/packages/react/src/types/component-props.ts index 50f07303..f8bc8dfd 100644 --- a/packages/react/src/types/component-props.ts +++ b/packages/react/src/types/component-props.ts @@ -40,10 +40,10 @@ import type { OnDelete, OnNodesChange, OnEdgesChange, - NodeDragHandler, NodeMouseHandler, SelectionDragHandler, EdgeMouseHandler, + OnNodeDrag, } from '.'; /** @@ -111,11 +111,11 @@ export interface ReactFlowProps extends Omit, 'on /** This event handler is called when a user right clicks on a node */ onNodeContextMenu?: NodeMouseHandler; /** This event handler is called when a user starts to drag a node */ - onNodeDragStart?: NodeDragHandler; + onNodeDragStart?: OnNodeDrag; /** This event handler is called when a user drags a node */ - onNodeDrag?: NodeDragHandler; + onNodeDrag?: OnNodeDrag; /** This event handler is called when a user stops dragging a node */ - onNodeDragStop?: NodeDragHandler; + onNodeDragStop?: OnNodeDrag; /** This event handler is called when a user clicks on an edge */ onEdgeClick?: (event: ReactMouseEvent, edge: Edge) => void; /** This event handler is called when a user right clicks on an edge */ diff --git a/packages/react/src/types/general.ts b/packages/react/src/types/general.ts index 9a36e41f..1a7462ad 100644 --- a/packages/react/src/types/general.ts +++ b/packages/react/src/types/general.ts @@ -19,7 +19,7 @@ import { ComponentType } from 'react'; export type OnNodesChange = (changes: NodeChange[]) => void; export type OnEdgesChange = (changes: EdgeChange[]) => void; -export type OnNodesDelete = (nodes: Node[]) => void; +export type OnNodesDelete = (nodes: NodeType[]) => void; export type OnEdgesDelete = (edges: Edge[]) => void; export type OnDelete = (params: { nodes: Node[]; edges: Edge[] }) => void; diff --git a/packages/react/src/types/nodes.ts b/packages/react/src/types/nodes.ts index 71bfb685..612c1d50 100644 --- a/packages/react/src/types/nodes.ts +++ b/packages/react/src/types/nodes.ts @@ -3,11 +3,11 @@ import type { CoordinateExtent, NodeBase, NodeOrigin, OnError } from '@xyflow/sy import { NodeTypes } from './general'; -// eslint-disable-next-line @typescript-eslint/no-explicit-any /** * The node data structure that gets used for the nodes prop. * @public */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any export type Node = NodeBase< NodeData, NodeType @@ -18,9 +18,13 @@ export type Node void; -export type NodeDragHandler = (event: ReactMouseEvent, node: Node, nodes: Node[]) => void; -export type SelectionDragHandler = (event: ReactMouseEvent, nodes: Node[]) => void; +export type NodeMouseHandler = (event: ReactMouseEvent, node: NodeType) => void; +export type SelectionDragHandler = (event: ReactMouseEvent, nodes: NodeType[]) => void; +export type OnNodeDrag = ( + event: ReactMouseEvent, + node: NodeType, + nodes: NodeType[] +) => void; export type NodeWrapperProps = { id: string; diff --git a/packages/react/src/types/store.ts b/packages/react/src/types/store.ts index b138fc9d..a0d5f8cc 100644 --- a/packages/react/src/types/store.ts +++ b/packages/react/src/types/store.ts @@ -17,7 +17,6 @@ import { type PanBy, type OnConnectStart, type OnConnectEnd, - type OnNodeDrag, type OnSelectionDrag, type OnMoveStart, type OnMove, @@ -43,6 +42,7 @@ import type { OnSelectionChangeFunc, UnselectNodesAndEdgesParams, OnDelete, + OnNodeDrag, } from '.'; export type ReactFlowStore = { diff --git a/packages/svelte/src/lib/index.ts b/packages/svelte/src/lib/index.ts index 4c3737ea..edaed9ee 100644 --- a/packages/svelte/src/lib/index.ts +++ b/packages/svelte/src/lib/index.ts @@ -79,7 +79,6 @@ export { type OnError, type NodeProps, type NodeOrigin, - type OnNodeDrag, type OnSelectionDrag, Position, type XYPosition, diff --git a/packages/svelte/src/lib/store/index.ts b/packages/svelte/src/lib/store/index.ts index 18941bc6..91160860 100644 --- a/packages/svelte/src/lib/store/index.ts +++ b/packages/svelte/src/lib/store/index.ts @@ -15,7 +15,6 @@ import { type XYPosition, type CoordinateExtent, type UpdateConnection, - type NodeBase, type NodeDragItem, errorMessages } from '@xyflow/system'; @@ -67,7 +66,7 @@ export function createStore({ const updateNodePositions: UpdateNodePositions = (nodeDragItems, dragging = false) => { store.nodes.update((nds) => { return nds.map((node) => { - const nodeDragItem = (nodeDragItems as Array).find( + const nodeDragItem = (nodeDragItems as Array).find( (ndi) => ndi.id === node.id ); diff --git a/packages/system/src/types/nodes.ts b/packages/system/src/types/nodes.ts index 40aa1c16..b75e6d1b 100644 --- a/packages/system/src/types/nodes.ts +++ b/packages/system/src/types/nodes.ts @@ -94,9 +94,9 @@ export type NodeProps = { positionAbsoluteY: number; width?: number; height?: number; - dragging: boolean; - targetPosition?: Position; - sourcePosition?: Position; + dragging: NodeBase['dragging']; + sourcePosition?: NodeBase['sourcePosition']; + targetPosition?: NodeBase['targetPosition']; }; export type NodeHandleBounds = { @@ -134,8 +134,6 @@ export type NodeDragItem = { export type NodeOrigin = [number, number]; -export type OnNodeDrag = (event: MouseEvent, node: NodeBase, nodes: NodeBase[]) => void; - export type OnSelectionDrag = (event: MouseEvent, nodes: NodeBase[]) => void; export type NodeHandle = Optional; diff --git a/packages/system/src/xydrag/XYDrag.ts b/packages/system/src/xydrag/XYDrag.ts index 79a0823a..40d1aa4b 100644 --- a/packages/system/src/xydrag/XYDrag.ts +++ b/packages/system/src/xydrag/XYDrag.ts @@ -23,7 +23,6 @@ import type { SnapGrid, Transform, PanBy, - OnNodeDrag, OnSelectionDrag, UpdateNodePositions, Box, @@ -31,7 +30,7 @@ import type { export type OnDrag = (event: MouseEvent, dragItems: NodeDragItem[], node: NodeBase, nodes: NodeBase[]) => void; -type StoreItems = { +type StoreItems = { nodes: NodeBase[]; nodeLookup: Map; edges: EdgeBase[]; @@ -58,9 +57,9 @@ type StoreItems = { updateNodePositions: UpdateNodePositions; }; -export type XYDragParams = { +export type XYDragParams = { domNode: Element; - getStoreItems: () => StoreItems; + getStoreItems: () => StoreItems; onDragStart?: OnDrag; onDrag?: OnDrag; onDragStop?: OnDrag; @@ -80,14 +79,15 @@ export type DragUpdateParams = { domNode: Element; }; -export function XYDrag({ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export function XYDrag void | undefined>({ domNode, onNodeMouseDown, getStoreItems, onDragStart, onDrag, onDragStop, -}: XYDragParams): XYDragInstance { +}: XYDragParams): XYDragInstance { let lastPos: { x: number | null; y: number | null } = { x: null, y: null }; let autoPanId = 0; let dragItems: NodeDragItem[] = [];