From d094ef0581fa743410c211d1ea73941ac83e02d0 Mon Sep 17 00:00:00 2001 From: moklick Date: Sun, 23 Feb 2025 18:32:43 +0100 Subject: [PATCH 1/3] fix(OnSelectionChangeFunc): pass node and edge type generics #5023 --- packages/react/src/hooks/useOnSelectionChange.ts | 12 +++++++----- packages/react/src/types/component-props.ts | 4 ++-- packages/react/src/types/general.ts | 16 +++++++++------- packages/react/src/types/store.ts | 4 ++-- 4 files changed, 20 insertions(+), 16 deletions(-) diff --git a/packages/react/src/hooks/useOnSelectionChange.ts b/packages/react/src/hooks/useOnSelectionChange.ts index 65cad6fd..17232895 100644 --- a/packages/react/src/hooks/useOnSelectionChange.ts +++ b/packages/react/src/hooks/useOnSelectionChange.ts @@ -1,10 +1,10 @@ import { useEffect } from 'react'; import { useStoreApi } from './useStore'; -import type { OnSelectionChangeFunc } from '../types'; +import type { OnSelectionChangeFunc, Node, Edge } from '../types'; -export type UseOnSelectionChangeOptions = { - onChange: OnSelectionChangeFunc; +export type UseOnSelectionChangeOptions = { + onChange: OnSelectionChangeFunc; }; /** @@ -45,8 +45,10 @@ export type UseOnSelectionChangeOptions = { * * @remarks You need to memoize the passed `onChange` handler, otherwise the hook will not work correctly. */ -export function useOnSelectionChange({ onChange }: UseOnSelectionChangeOptions) { - const store = useStoreApi(); +export function useOnSelectionChange({ + onChange, +}: UseOnSelectionChangeOptions) { + const store = useStoreApi(); useEffect(() => { const nextOnSelectionChangeHandlers = [...store.getState().onSelectionChangeHandlers, onChange]; diff --git a/packages/react/src/types/component-props.ts b/packages/react/src/types/component-props.ts index b7c414f1..d558bc47 100644 --- a/packages/react/src/types/component-props.ts +++ b/packages/react/src/types/component-props.ts @@ -216,7 +216,7 @@ export interface ReactFlowProps; /** This event handler gets called when user scroll inside the pane */ onPaneScroll?: (event?: WheelEvent) => void; /** This event handler gets called when user clicks inside the pane */ @@ -316,7 +316,7 @@ export interface ReactFlowProps >; -export type UnselectNodesAndEdgesParams = { - nodes?: Node[]; - edges?: Edge[]; +export type UnselectNodesAndEdgesParams = { + nodes?: NodeType[]; + edges?: EdgeType[]; }; -export type OnSelectionChangeParams = { - nodes: Node[]; - edges: Edge[]; +export type OnSelectionChangeParams = { + nodes: NodeType[]; + edges: EdgeType[]; }; -export type OnSelectionChangeFunc = (params: OnSelectionChangeParams) => void; +export type OnSelectionChangeFunc = ( + params: OnSelectionChangeParams +) => void; export type FitViewParams = FitViewParamsBase; diff --git a/packages/react/src/types/store.ts b/packages/react/src/types/store.ts index b060be36..e0ec76fa 100644 --- a/packages/react/src/types/store.ts +++ b/packages/react/src/types/store.ts @@ -134,7 +134,7 @@ export type ReactFlowStore; - onSelectionChangeHandlers: OnSelectionChangeFunc[]; + onSelectionChangeHandlers: OnSelectionChangeFunc[]; ariaLiveMessage: string; autoPanOnConnect: boolean; @@ -155,7 +155,7 @@ export type ReactFlowActions = { updateNodeInternals: (updates: Map, params?: { triggerFitView: boolean }) => void; updateNodePositions: UpdateNodePositions; resetSelectedElements: () => void; - unselectNodesAndEdges: (params?: UnselectNodesAndEdgesParams) => void; + unselectNodesAndEdges: (params?: UnselectNodesAndEdgesParams) => void; addSelectedNodes: (nodeIds: string[]) => void; addSelectedEdges: (edgeIds: string[]) => void; setMinZoom: (minZoom: number) => void; From b3bf5693c659069cea90bf1cb215ae65d06c5509 Mon Sep 17 00:00:00 2001 From: moklick Date: Sun, 23 Feb 2025 18:33:28 +0100 Subject: [PATCH 2/3] chore(changeset): add --- .changeset/old-moles-push.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/old-moles-push.md diff --git a/.changeset/old-moles-push.md b/.changeset/old-moles-push.md new file mode 100644 index 00000000..ea79bbba --- /dev/null +++ b/.changeset/old-moles-push.md @@ -0,0 +1,5 @@ +--- +'@xyflow/react': patch +--- + +Pass generics to OnSelectionChangeFunc so that users can type it correctly From 27df80b6a60c05678b22eae48160f0e137b6eedc Mon Sep 17 00:00:00 2001 From: moklick Date: Mon, 24 Feb 2025 08:58:24 +0100 Subject: [PATCH 3/3] fix(selection-listener): pass generics --- .../src/components/SelectionListener/index.tsx | 18 +++++++++++------- .../react/src/container/ReactFlow/index.tsx | 2 +- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/packages/react/src/components/SelectionListener/index.tsx b/packages/react/src/components/SelectionListener/index.tsx index 6a9a03a6..89ed2c26 100644 --- a/packages/react/src/components/SelectionListener/index.tsx +++ b/packages/react/src/components/SelectionListener/index.tsx @@ -10,8 +10,8 @@ import { shallow } from 'zustand/shallow'; import { useStore, useStoreApi } from '../../hooks/useStore'; import type { ReactFlowState, OnSelectionChangeFunc, Node, Edge } from '../../types'; -type SelectionListenerProps = { - onSelectionChange?: OnSelectionChangeFunc; +type SelectionListenerProps = { + onSelectionChange?: OnSelectionChangeFunc; }; const selector = (s: ReactFlowState) => { @@ -44,12 +44,14 @@ function areEqual(a: SelectorSlice, b: SelectorSlice) { ); } -function SelectionListenerInner({ onSelectionChange }: SelectionListenerProps) { - const store = useStoreApi(); +function SelectionListenerInner({ + onSelectionChange, +}: SelectionListenerProps) { + const store = useStoreApi(); const { selectedNodes, selectedEdges } = useStore(selector, areEqual); useEffect(() => { - const params = { nodes: selectedNodes, edges: selectedEdges }; + const params = { nodes: selectedNodes as NodeType[], edges: selectedEdges as EdgeType[] }; onSelectionChange?.(params); store.getState().onSelectionChangeHandlers.forEach((fn) => fn(params)); @@ -60,11 +62,13 @@ function SelectionListenerInner({ onSelectionChange }: SelectionListenerProps) { const changeSelector = (s: ReactFlowState) => !!s.onSelectionChangeHandlers; -export function SelectionListener({ onSelectionChange }: SelectionListenerProps) { +export function SelectionListener({ + onSelectionChange, +}: SelectionListenerProps) { const storeHasSelectionChangeHandlers = useStore(changeSelector); if (onSelectionChange || storeHasSelectionChangeHandlers) { - return ; + return onSelectionChange={onSelectionChange} />; } return null; diff --git a/packages/react/src/container/ReactFlow/index.tsx b/packages/react/src/container/ReactFlow/index.tsx index cfc4f40c..31389887 100644 --- a/packages/react/src/container/ReactFlow/index.tsx +++ b/packages/react/src/container/ReactFlow/index.tsx @@ -303,7 +303,7 @@ function ReactFlow( paneClickDistance={paneClickDistance} debug={debug} /> - + onSelectionChange={onSelectionChange} /> {children}