Merge pull request #5047 from xyflow/fix/on-selection-change-generics
fix(OnSelectionChangeFunc): pass node and edge type generics
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@xyflow/react': patch
|
||||
---
|
||||
|
||||
Pass generics to OnSelectionChangeFunc so that users can type it correctly
|
||||
@@ -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<NodeType extends Node = Node, EdgeType extends Edge = Edge> = {
|
||||
onSelectionChange?: OnSelectionChangeFunc<NodeType, EdgeType>;
|
||||
};
|
||||
|
||||
const selector = (s: ReactFlowState) => {
|
||||
@@ -44,12 +44,14 @@ function areEqual(a: SelectorSlice, b: SelectorSlice) {
|
||||
);
|
||||
}
|
||||
|
||||
function SelectionListenerInner({ onSelectionChange }: SelectionListenerProps) {
|
||||
const store = useStoreApi();
|
||||
function SelectionListenerInner<NodeType extends Node = Node, EdgeType extends Edge = Edge>({
|
||||
onSelectionChange,
|
||||
}: SelectionListenerProps<NodeType, EdgeType>) {
|
||||
const store = useStoreApi<NodeType, EdgeType>();
|
||||
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<NodeType extends Node = Node, EdgeType extends Edge = Edge>({
|
||||
onSelectionChange,
|
||||
}: SelectionListenerProps<NodeType, EdgeType>) {
|
||||
const storeHasSelectionChangeHandlers = useStore(changeSelector);
|
||||
|
||||
if (onSelectionChange || storeHasSelectionChangeHandlers) {
|
||||
return <SelectionListenerInner onSelectionChange={onSelectionChange} />;
|
||||
return <SelectionListenerInner<NodeType, EdgeType> onSelectionChange={onSelectionChange} />;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -303,7 +303,7 @@ function ReactFlow<NodeType extends Node = Node, EdgeType extends Edge = Edge>(
|
||||
paneClickDistance={paneClickDistance}
|
||||
debug={debug}
|
||||
/>
|
||||
<SelectionListener onSelectionChange={onSelectionChange} />
|
||||
<SelectionListener<NodeType, EdgeType> onSelectionChange={onSelectionChange} />
|
||||
{children}
|
||||
<Attribution proOptions={proOptions} position={attributionPosition} />
|
||||
<A11yDescriptions rfId={rfId} disableKeyboardA11y={disableKeyboardA11y} />
|
||||
|
||||
@@ -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<NodeType extends Node = Node, EdgeType extends Edge = Edge> = {
|
||||
onChange: OnSelectionChangeFunc<NodeType, EdgeType>;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -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<NodeType extends Node = Node, EdgeType extends Edge = Edge>({
|
||||
onChange,
|
||||
}: UseOnSelectionChangeOptions<NodeType, EdgeType>) {
|
||||
const store = useStoreApi<NodeType, EdgeType>();
|
||||
|
||||
useEffect(() => {
|
||||
const nextOnSelectionChangeHandlers = [...store.getState().onSelectionChangeHandlers, onChange];
|
||||
|
||||
@@ -216,7 +216,7 @@ export interface ReactFlowProps<NodeType extends Node = Node, EdgeType extends E
|
||||
/** This event handler gets called when a user stops panning or zooming the viewport */
|
||||
onMoveEnd?: OnMoveEnd;
|
||||
/** This event handler gets called when a user changes group of selected elements in the flow */
|
||||
onSelectionChange?: OnSelectionChangeFunc;
|
||||
onSelectionChange?: OnSelectionChangeFunc<NodeType, EdgeType>;
|
||||
/** 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<NodeType extends Node = Node, EdgeType extends E
|
||||
*
|
||||
* By setting this prop to null you can disable this functionality.
|
||||
* @default 'Meta' for macOS, "Ctrl" for other systems
|
||||
*
|
||||
*
|
||||
*/
|
||||
zoomActivationKeyCode?: KeyCode | null;
|
||||
/** Set this prop to make the flow snap to the grid */
|
||||
|
||||
@@ -85,17 +85,19 @@ export type EdgeTypes = Record<
|
||||
>
|
||||
>;
|
||||
|
||||
export type UnselectNodesAndEdgesParams = {
|
||||
nodes?: Node[];
|
||||
edges?: Edge[];
|
||||
export type UnselectNodesAndEdgesParams<NodeType extends Node = Node, EdgeType extends Edge = Edge> = {
|
||||
nodes?: NodeType[];
|
||||
edges?: EdgeType[];
|
||||
};
|
||||
|
||||
export type OnSelectionChangeParams = {
|
||||
nodes: Node[];
|
||||
edges: Edge[];
|
||||
export type OnSelectionChangeParams<NodeType extends Node = Node, EdgeType extends Edge = Edge> = {
|
||||
nodes: NodeType[];
|
||||
edges: EdgeType[];
|
||||
};
|
||||
|
||||
export type OnSelectionChangeFunc = (params: OnSelectionChangeParams) => void;
|
||||
export type OnSelectionChangeFunc<NodeType extends Node = Node, EdgeType extends Edge = Edge> = (
|
||||
params: OnSelectionChangeParams<NodeType, EdgeType>
|
||||
) => void;
|
||||
|
||||
export type FitViewParams<NodeType extends Node = Node> = FitViewParamsBase<NodeType>;
|
||||
|
||||
|
||||
@@ -134,7 +134,7 @@ export type ReactFlowStore<NodeType extends Node = Node, EdgeType extends Edge =
|
||||
onViewportChangeEnd?: OnViewportChange;
|
||||
onBeforeDelete?: OnBeforeDelete<NodeType, EdgeType>;
|
||||
|
||||
onSelectionChangeHandlers: OnSelectionChangeFunc[];
|
||||
onSelectionChangeHandlers: OnSelectionChangeFunc<NodeType, EdgeType>[];
|
||||
|
||||
ariaLiveMessage: string;
|
||||
autoPanOnConnect: boolean;
|
||||
@@ -155,7 +155,7 @@ export type ReactFlowActions<NodeType extends Node, EdgeType extends Edge> = {
|
||||
updateNodeInternals: (updates: Map<string, InternalNodeUpdate>, params?: { triggerFitView: boolean }) => void;
|
||||
updateNodePositions: UpdateNodePositions;
|
||||
resetSelectedElements: () => void;
|
||||
unselectNodesAndEdges: (params?: UnselectNodesAndEdgesParams) => void;
|
||||
unselectNodesAndEdges: (params?: UnselectNodesAndEdgesParams<NodeType, EdgeType>) => void;
|
||||
addSelectedNodes: (nodeIds: string[]) => void;
|
||||
addSelectedEdges: (edgeIds: string[]) => void;
|
||||
setMinZoom: (minZoom: number) => void;
|
||||
|
||||
Reference in New Issue
Block a user