chore(react/hooks): add docs
This commit is contained in:
@@ -9,6 +9,12 @@ function getMediaQuery() {
|
||||
return window.matchMedia('(prefers-color-scheme: dark)');
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook for receiving the current color mode class 'dark' or 'light'.
|
||||
*
|
||||
* @internal
|
||||
* @param colorMode - The color mode to use ('dark', 'light' or 'system')
|
||||
*/
|
||||
export default function useColorModeClass(colorMode: ColorMode): ColorModeClass {
|
||||
const [colorModeClass, setColorModeClass] = useState<ColorModeClass | null>(
|
||||
colorMode === 'system' ? null : colorMode
|
||||
|
||||
@@ -13,6 +13,11 @@ type UseDragParams = {
|
||||
isSelectable?: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
* Hook for calling XYDrag helper from @xyflow/system.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
function useDrag({ nodeRef, disabled = false, noDragClassName, handleSelector, nodeId, isSelectable }: UseDragParams) {
|
||||
const store = useStoreApi();
|
||||
const [dragging, setDragging] = useState<boolean>(false);
|
||||
|
||||
@@ -5,6 +5,12 @@ import type { Edge, ReactFlowState } from '../types';
|
||||
|
||||
const edgesSelector = (state: ReactFlowState) => state.edges;
|
||||
|
||||
/**
|
||||
* Hook for getting the current edges from the store.
|
||||
*
|
||||
* @public
|
||||
* @returns An array of edges
|
||||
*/
|
||||
function useEdges<EdgeData>(): Edge<EdgeData>[] {
|
||||
const edges = useStore(edgesSelector, shallow);
|
||||
|
||||
|
||||
@@ -10,6 +10,11 @@ const selected = (item: Node | Edge) => item.selected;
|
||||
|
||||
const deleteKeyOptions: UseKeyPressOptions = { actInsideInputWithModifier: false };
|
||||
|
||||
/**
|
||||
* Hook for handling global key events.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
export default ({
|
||||
deleteKeyCode,
|
||||
multiSelectionKeyCode,
|
||||
|
||||
@@ -12,11 +12,19 @@ export type UseKeyPressOptions = {
|
||||
|
||||
const defaultDoc = typeof document !== 'undefined' ? document : null;
|
||||
|
||||
// the keycode can be a string 'a' or an array of strings ['a', 'a+d']
|
||||
// a string means a single key 'a' or a combination when '+' is used 'a+d'
|
||||
// an array means different possibilites. Explainer: ['a', 'd+s'] here the
|
||||
// user can use the single key 'a' or the combination 'd' + 's'
|
||||
/**
|
||||
* Hook for handling key events.
|
||||
*
|
||||
* @public
|
||||
* @param param.keyCode - The key code (string or array of strings) to use
|
||||
* @param param.options - Options
|
||||
* @returns boolean
|
||||
*/
|
||||
export default (
|
||||
// the keycode can be a string 'a' or an array of strings ['a', 'a+d']
|
||||
// a string means a single key 'a' or a combination when '+' is used 'a+d'
|
||||
// an array means different possibilites. Explainer: ['a', 'd+s'] here the
|
||||
// user can use the single key 'a' or the combination 'd' + 's'
|
||||
keyCode: KeyCode | null = null,
|
||||
options: UseKeyPressOptions = { target: defaultDoc, actInsideInputWithModifier: true }
|
||||
): boolean => {
|
||||
|
||||
@@ -5,6 +5,12 @@ import type { Node, ReactFlowState } from '../types';
|
||||
|
||||
const nodesSelector = (state: ReactFlowState) => state.nodes;
|
||||
|
||||
/**
|
||||
* Hook for getting the current nodes from the store.
|
||||
*
|
||||
* @public
|
||||
* @returns An array of nodes
|
||||
*/
|
||||
function useNodes<NodeType extends Node = Node>(): NodeType[] {
|
||||
const nodes = useStore(nodesSelector, shallow) as NodeType[];
|
||||
|
||||
|
||||
@@ -4,6 +4,14 @@ import { shallow } from 'zustand/shallow';
|
||||
import { useStore } from '../hooks/useStore';
|
||||
import type { Node } from '../types';
|
||||
|
||||
/**
|
||||
* Hook for receiving data of one or multiple nodes
|
||||
*
|
||||
* @public
|
||||
* @param nodeId - The id (or ids) of the node to get the data from
|
||||
* @param guard - Optional guard function to narrow down the node type
|
||||
* @returns An array data objects
|
||||
*/
|
||||
export function useNodesData<NodeType extends Node = Node>(nodeId: string): NodeType['data'] | null;
|
||||
export function useNodesData<NodeType extends Node = Node>(nodeIds: string[]): NodeType['data'][];
|
||||
export function useNodesData<NodeType extends Node = Node>(
|
||||
|
||||
@@ -7,8 +7,6 @@ import type { Node, NodeChange, Edge, EdgeChange } from '../types';
|
||||
type ApplyChanges<ItemType, ChangesType> = (changes: ChangesType[], items: ItemType[]) => ItemType[];
|
||||
type OnChange<ChangesType> = (changes: ChangesType[]) => void;
|
||||
|
||||
// returns a hook that can be used liked this:
|
||||
// const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
|
||||
function createUseItemsState(
|
||||
applyChanges: ApplyChanges<Node, NodeChange>
|
||||
): <NodeType extends Node = Node>(
|
||||
@@ -31,5 +29,20 @@ function createUseItemsState(
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook for managing the state of nodes - should only be used for prototyping / simple use cases.
|
||||
*
|
||||
* @public
|
||||
* @param initialNodes
|
||||
* @returns an array [nodes, setNodes, onNodesChange]
|
||||
*/
|
||||
export const useNodesState = createUseItemsState(applyNodeChanges);
|
||||
|
||||
/**
|
||||
* Hook for managing the state of edges - should only be used for prototyping / simple use cases.
|
||||
*
|
||||
* @public
|
||||
* @param initialEdges
|
||||
* @returns an array [edges, setEdges, onEdgesChange]
|
||||
*/
|
||||
export const useEdgesState = createUseItemsState(applyEdgeChanges);
|
||||
|
||||
@@ -21,6 +21,13 @@ const defaultOptions = {
|
||||
includeHiddenNodes: false,
|
||||
};
|
||||
|
||||
/**
|
||||
* Hook which returns true when all nodes are initialized.
|
||||
*
|
||||
* @public
|
||||
* @param options.includeHiddenNodes - defaults to false
|
||||
* @returns boolean indicating whether all nodes are initialized
|
||||
*/
|
||||
function useNodesInitialized(options: UseNodesInitializedOptions = defaultOptions): boolean {
|
||||
const initialized = useStore(selector(options));
|
||||
|
||||
|
||||
@@ -3,6 +3,11 @@ import { useEffect, useRef } from 'react';
|
||||
import useReactFlow from './useReactFlow';
|
||||
import type { OnInit } from '../types';
|
||||
|
||||
/**
|
||||
* Hook for calling onInit handler.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
function useOnInitHandler(onInit: OnInit | undefined) {
|
||||
const rfInstance = useReactFlow();
|
||||
const isInitialized = useRef<boolean>(false);
|
||||
|
||||
@@ -7,6 +7,12 @@ export type UseOnSelectionChangeOptions = {
|
||||
onChange: OnSelectionChangeFunc;
|
||||
};
|
||||
|
||||
/**
|
||||
* Hook for registering an onSelectionChange handler.
|
||||
*
|
||||
* @public
|
||||
* @params params.onChange - The handler to register
|
||||
*/
|
||||
function useOnSelectionChange({ onChange }: UseOnSelectionChangeOptions) {
|
||||
const store = useStoreApi();
|
||||
|
||||
|
||||
@@ -9,6 +9,14 @@ export type UseOnViewportChangeOptions = {
|
||||
onEnd?: OnViewportChange;
|
||||
};
|
||||
|
||||
/**
|
||||
* Hook for registering an onViewportChange handler.
|
||||
*
|
||||
* @public
|
||||
* @param params.onStart - gets called when the viewport starts changing
|
||||
* @param params.onChange - gets called when the viewport changes
|
||||
* @param params.onEnd - gets called when the viewport stops changing
|
||||
*/
|
||||
function useOnViewportChange({ onStart, onChange, onEnd }: UseOnViewportChangeOptions) {
|
||||
const store = useStoreApi();
|
||||
|
||||
|
||||
@@ -1,13 +1,5 @@
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import {
|
||||
getElementsToRemove,
|
||||
getIncomersBase,
|
||||
getOutgoersBase,
|
||||
getOverlappingArea,
|
||||
isRectObject,
|
||||
nodeToRect,
|
||||
type Rect,
|
||||
} from '@xyflow/system';
|
||||
import { getElementsToRemove, getOverlappingArea, isRectObject, nodeToRect, type Rect } from '@xyflow/system';
|
||||
|
||||
import useViewportHelper from './useViewportHelper';
|
||||
import { useStoreApi } from './useStore';
|
||||
@@ -238,48 +230,13 @@ export default function useReactFlow<NodeType extends Node = Node, EdgeType exte
|
||||
[]
|
||||
);
|
||||
|
||||
const getConnectedEdges = useCallback<Instance.getConnectedEdges>((node) => {
|
||||
const { edges } = store.getState();
|
||||
|
||||
const nodeIds = new Set();
|
||||
if (typeof node === 'string') {
|
||||
nodeIds.add(node);
|
||||
} else if (node.length >= 1) {
|
||||
node.forEach((n) => {
|
||||
nodeIds.add(n.id);
|
||||
});
|
||||
}
|
||||
|
||||
return edges.filter((edge) => nodeIds.has(edge.source) || nodeIds.has(edge.target));
|
||||
}, []);
|
||||
|
||||
const getIncomers = useCallback<Instance.getIncomers>((node) => {
|
||||
const { nodes, edges } = store.getState();
|
||||
|
||||
if (typeof node === 'string') {
|
||||
return getIncomersBase({ id: node }, nodes, edges);
|
||||
}
|
||||
|
||||
return getIncomersBase(node, nodes, edges);
|
||||
}, []);
|
||||
|
||||
const getOutgoers = useCallback<Instance.getOutgoers>((node) => {
|
||||
const { nodes, edges } = store.getState();
|
||||
|
||||
if (typeof node == 'string') {
|
||||
return getOutgoersBase({ id: node }, nodes, edges);
|
||||
}
|
||||
|
||||
return getOutgoersBase(node, nodes, edges);
|
||||
}, []);
|
||||
|
||||
const updateNode = useCallback<Instance.UpdateNode>(
|
||||
const updateNode = useCallback<Instance.UpdateNode<NodeType>>(
|
||||
(id, nodeUpdate, options = { replace: true }) => {
|
||||
setNodes((prevNodes) =>
|
||||
prevNodes.map((node) => {
|
||||
if (node.id === id) {
|
||||
const nextNode = typeof nodeUpdate === 'function' ? nodeUpdate(node as Node) : nodeUpdate;
|
||||
return options.replace && isNode(nextNode) ? nextNode : { ...node, ...nextNode };
|
||||
const nextNode = typeof nodeUpdate === 'function' ? nodeUpdate(node as NodeType) : nodeUpdate;
|
||||
return options.replace && isNode(nextNode) ? (nextNode as NodeType) : { ...node, ...nextNode };
|
||||
}
|
||||
|
||||
return node;
|
||||
@@ -289,7 +246,7 @@ export default function useReactFlow<NodeType extends Node = Node, EdgeType exte
|
||||
[setNodes]
|
||||
);
|
||||
|
||||
const updateNodeData = useCallback<Instance.UpdateNodeData>(
|
||||
const updateNodeData = useCallback<Instance.UpdateNodeData<NodeType>>(
|
||||
(id, dataUpdate, options = { replace: false }) => {
|
||||
updateNode(
|
||||
id,
|
||||
@@ -318,9 +275,6 @@ export default function useReactFlow<NodeType extends Node = Node, EdgeType exte
|
||||
deleteElements,
|
||||
getIntersectingNodes,
|
||||
isNodeIntersecting,
|
||||
getConnectedEdges,
|
||||
getIncomers,
|
||||
getOutgoers,
|
||||
updateNode,
|
||||
updateNodeData,
|
||||
};
|
||||
@@ -338,8 +292,7 @@ export default function useReactFlow<NodeType extends Node = Node, EdgeType exte
|
||||
deleteElements,
|
||||
getIntersectingNodes,
|
||||
isNodeIntersecting,
|
||||
getConnectedEdges,
|
||||
getIncomers,
|
||||
getOutgoers,
|
||||
updateNode,
|
||||
updateNodeData,
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,11 @@ import { errorMessages, getDimensions } from '@xyflow/system';
|
||||
|
||||
import { useStoreApi } from '../hooks/useStore';
|
||||
|
||||
/**
|
||||
* Hook for handling resize events.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
function useResizeHandler(domNode: MutableRefObject<HTMLDivElement | null>): void {
|
||||
const store = useStoreApi();
|
||||
|
||||
|
||||
@@ -10,6 +10,14 @@ const zustandErrorMessage = errorMessages['error001']();
|
||||
|
||||
type ExtractState = StoreApi<ReactFlowState> extends { getState: () => infer T } ? T : never;
|
||||
|
||||
/**
|
||||
* Hook for accessing the internal store. Should only be used in rare cases.
|
||||
*
|
||||
* @public
|
||||
* @param selector
|
||||
* @param equalityFn
|
||||
* @returns The selected state slice
|
||||
*/
|
||||
function useStore<StateSlice = ExtractState>(
|
||||
selector: (state: ReactFlowState) => StateSlice,
|
||||
equalityFn?: (a: StateSlice, b: StateSlice) => boolean
|
||||
|
||||
@@ -3,6 +3,12 @@ import type { UpdateNodeInternals, NodeDimensionUpdate } from '@xyflow/system';
|
||||
|
||||
import { useStoreApi } from '../hooks/useStore';
|
||||
|
||||
/**
|
||||
* Hook for updating node internals.
|
||||
*
|
||||
* @public
|
||||
* @returns function for updating node internals
|
||||
*/
|
||||
function useUpdateNodeInternals(): UpdateNodeInternals {
|
||||
const store = useStoreApi();
|
||||
|
||||
|
||||
@@ -7,6 +7,12 @@ import { useStoreApi } from '../hooks/useStore';
|
||||
const selectedAndDraggable = (nodesDraggable: boolean) => (n: Node) =>
|
||||
n.selected && (n.draggable || (nodesDraggable && typeof n.draggable === 'undefined'));
|
||||
|
||||
/**
|
||||
* Hook for updating node positions.
|
||||
*
|
||||
* @internal
|
||||
* @returns function for updating node positions
|
||||
*/
|
||||
function useUpdateNodePositions() {
|
||||
const store = useStoreApi();
|
||||
|
||||
|
||||
@@ -10,6 +10,12 @@ const viewportSelector = (state: ReactFlowState) => ({
|
||||
zoom: state.transform[2],
|
||||
});
|
||||
|
||||
/**
|
||||
* Hook for getting the current viewport from the store.
|
||||
*
|
||||
* @public
|
||||
* @returns The current viewport
|
||||
*/
|
||||
function useViewport(): Viewport {
|
||||
const viewport = useStore(viewportSelector, shallow);
|
||||
|
||||
|
||||
@@ -12,6 +12,12 @@ import type { ViewportHelperFunctions, ReactFlowState } from '../types';
|
||||
|
||||
const selector = (s: ReactFlowState) => !!s.panZoom;
|
||||
|
||||
/**
|
||||
* Hook for getting viewport helper functions.
|
||||
*
|
||||
* @internal
|
||||
* @returns viewport helper functions
|
||||
*/
|
||||
const useViewportHelper = (): ViewportHelperFunctions => {
|
||||
const store = useStoreApi();
|
||||
const panZoomInitialized = useStore(selector);
|
||||
|
||||
@@ -6,6 +6,12 @@ import type { ReactFlowState } from '../types';
|
||||
|
||||
const selector = (state: ReactFlowState) => state.panZoom?.syncViewport;
|
||||
|
||||
/**
|
||||
* Hook for syncing the viewport with the panzoom instance.
|
||||
*
|
||||
* @internal
|
||||
* @param viewport
|
||||
*/
|
||||
export default function useViewportSync(viewport?: Viewport) {
|
||||
const syncViewport = useStore(selector);
|
||||
const store = useStoreApi();
|
||||
|
||||
@@ -5,6 +5,13 @@ import { isEdgeVisible } from '@xyflow/system';
|
||||
import { useStore } from './useStore';
|
||||
import { type ReactFlowState } from '../types';
|
||||
|
||||
/**
|
||||
* Hook for getting the visible edge ids from the store.
|
||||
*
|
||||
* @internal
|
||||
* @param onlyRenderVisible
|
||||
* @returns array with visible edge ids
|
||||
*/
|
||||
function useVisibleEdgeIds(onlyRenderVisible: boolean): string[] {
|
||||
const edgeIds = useStore(
|
||||
useCallback(
|
||||
|
||||
@@ -13,6 +13,13 @@ const selector = (onlyRenderVisible: boolean) => (s: ReactFlowState) => {
|
||||
: Array.from(s.nodeLookup.keys());
|
||||
};
|
||||
|
||||
/**
|
||||
* Hook for getting the visible node ids from the store.
|
||||
*
|
||||
* @internal
|
||||
* @param onlyRenderVisible
|
||||
* @returns array with visible node ids
|
||||
*/
|
||||
function useVisibleNodeIds(onlyRenderVisible: boolean) {
|
||||
const nodeIds = useStore(useCallback(selector(onlyRenderVisible), [onlyRenderVisible]), shallow);
|
||||
|
||||
|
||||
@@ -40,6 +40,10 @@ export type NodeResetChange<NodeType extends Node = Node> = {
|
||||
type: 'reset';
|
||||
};
|
||||
|
||||
/**
|
||||
* Union type of all possible node changes.
|
||||
* @public
|
||||
*/
|
||||
export type NodeChange =
|
||||
| NodeDimensionChange
|
||||
| NodePositionChange
|
||||
|
||||
@@ -45,6 +45,10 @@ import type {
|
||||
EdgeMouseHandler,
|
||||
} from '.';
|
||||
|
||||
/**
|
||||
* ReactFlow component props.
|
||||
* @public
|
||||
*/
|
||||
export type ReactFlowProps = Omit<HTMLAttributes<HTMLDivElement>, 'onError'> & {
|
||||
nodes?: Node[];
|
||||
edges?: Edge[];
|
||||
|
||||
@@ -54,7 +54,8 @@ type StepEdgeType<T> = DefaultEdge<T> & {
|
||||
};
|
||||
|
||||
/**
|
||||
* The Edge type is mainly used for the `edges` that get passed to the ReactFlow component.
|
||||
* The Edge type is mainly used for the `edges` that get passed to the ReactFlow component
|
||||
* @public
|
||||
*/
|
||||
export type Edge<T = any> = DefaultEdge<T> | SmoothStepEdgeType<T> | BezierEdgeType<T> | StepEdgeType<T>;
|
||||
|
||||
@@ -92,7 +93,8 @@ export type EdgeTextProps = HTMLAttributes<SVGElement> &
|
||||
};
|
||||
|
||||
/**
|
||||
* Custom edge component props.
|
||||
* Custom edge component props
|
||||
* @public
|
||||
*/
|
||||
export type EdgeProps<T = any> = Pick<
|
||||
Edge<T>,
|
||||
@@ -110,7 +112,8 @@ export type EdgeProps<T = any> = Pick<
|
||||
};
|
||||
|
||||
/**
|
||||
* BaseEdge component props.
|
||||
* BaseEdge component props
|
||||
* @public
|
||||
*/
|
||||
export type BaseEdgeProps = EdgeLabelOptions & {
|
||||
id?: string;
|
||||
@@ -124,7 +127,8 @@ export type BaseEdgeProps = EdgeLabelOptions & {
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper type for edge components that get exported by the library.
|
||||
* Helper type for edge components that get exported by the library
|
||||
* @public
|
||||
*/
|
||||
export type EdgeComponentProps = EdgePosition &
|
||||
EdgeLabelOptions & {
|
||||
@@ -143,26 +147,31 @@ export type EdgeComponentWithPathOptions<PathOptions> = EdgeComponentProps & {
|
||||
|
||||
/**
|
||||
* BezierEdge component props
|
||||
* @public
|
||||
*/
|
||||
export type BezierEdgeProps = EdgeComponentWithPathOptions<BezierPathOptions>;
|
||||
|
||||
/**
|
||||
* SmoothStepEdge component props
|
||||
* @public
|
||||
*/
|
||||
export type SmoothStepEdgeProps = EdgeComponentWithPathOptions<SmoothStepPathOptions>;
|
||||
|
||||
/**
|
||||
* StepEdge component props
|
||||
* @public
|
||||
*/
|
||||
export type StepEdgeProps = EdgeComponentWithPathOptions<StepPathOptions>;
|
||||
|
||||
/**
|
||||
* StraightEdge component props
|
||||
* @public
|
||||
*/
|
||||
export type StraightEdgeProps = Omit<EdgeComponentProps, 'sourcePosition' | 'targetPosition'>;
|
||||
|
||||
/**
|
||||
* SimpleBezier component props
|
||||
* @public
|
||||
*/
|
||||
export type SimpleBezierEdgeProps = EdgeComponentProps;
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ export namespace Instance {
|
||||
|
||||
export type UpdateNode<NodeType extends Node = Node> = (
|
||||
id: string,
|
||||
dataUpdate: Partial<NodeType> | ((node: NodeType) => Partial<NodeType>),
|
||||
nodeUpdate: Partial<NodeType> | ((node: NodeType) => Partial<NodeType>),
|
||||
options?: { replace: boolean }
|
||||
) => void;
|
||||
export type UpdateNodeData<NodeType extends Node = Node> = (
|
||||
|
||||
Reference in New Issue
Block a user