diff --git a/packages/react/src/hooks/useColorModeClass.ts b/packages/react/src/hooks/useColorModeClass.ts index b66f8cea..bcf8c6af 100644 --- a/packages/react/src/hooks/useColorModeClass.ts +++ b/packages/react/src/hooks/useColorModeClass.ts @@ -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( colorMode === 'system' ? null : colorMode diff --git a/packages/react/src/hooks/useDrag.ts b/packages/react/src/hooks/useDrag.ts index 3b332d8a..8a4fab65 100644 --- a/packages/react/src/hooks/useDrag.ts +++ b/packages/react/src/hooks/useDrag.ts @@ -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(false); diff --git a/packages/react/src/hooks/useEdges.ts b/packages/react/src/hooks/useEdges.ts index 194f8805..94445ce4 100644 --- a/packages/react/src/hooks/useEdges.ts +++ b/packages/react/src/hooks/useEdges.ts @@ -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(): Edge[] { const edges = useStore(edgesSelector, shallow); diff --git a/packages/react/src/hooks/useGlobalKeyHandler.ts b/packages/react/src/hooks/useGlobalKeyHandler.ts index c243298d..786ed870 100644 --- a/packages/react/src/hooks/useGlobalKeyHandler.ts +++ b/packages/react/src/hooks/useGlobalKeyHandler.ts @@ -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, diff --git a/packages/react/src/hooks/useKeyPress.ts b/packages/react/src/hooks/useKeyPress.ts index f897a6c4..98d460d0 100644 --- a/packages/react/src/hooks/useKeyPress.ts +++ b/packages/react/src/hooks/useKeyPress.ts @@ -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 => { diff --git a/packages/react/src/hooks/useNodes.ts b/packages/react/src/hooks/useNodes.ts index 1ccd1d85..bb54865d 100644 --- a/packages/react/src/hooks/useNodes.ts +++ b/packages/react/src/hooks/useNodes.ts @@ -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[] { const nodes = useStore(nodesSelector, shallow) as NodeType[]; diff --git a/packages/react/src/hooks/useNodesData.ts b/packages/react/src/hooks/useNodesData.ts index 4c242ad3..e209df22 100644 --- a/packages/react/src/hooks/useNodesData.ts +++ b/packages/react/src/hooks/useNodesData.ts @@ -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(nodeId: string): NodeType['data'] | null; export function useNodesData(nodeIds: string[]): NodeType['data'][]; export function useNodesData( diff --git a/packages/react/src/hooks/useNodesEdgesState.ts b/packages/react/src/hooks/useNodesEdgesState.ts index 5255c7dd..b0976b57 100644 --- a/packages/react/src/hooks/useNodesEdgesState.ts +++ b/packages/react/src/hooks/useNodesEdgesState.ts @@ -7,8 +7,6 @@ import type { Node, NodeChange, Edge, EdgeChange } from '../types'; type ApplyChanges = (changes: ChangesType[], items: ItemType[]) => ItemType[]; type OnChange = (changes: ChangesType[]) => void; -// returns a hook that can be used liked this: -// const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes); function createUseItemsState( applyChanges: ApplyChanges ): ( @@ -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); diff --git a/packages/react/src/hooks/useNodesInitialized.ts b/packages/react/src/hooks/useNodesInitialized.ts index 3e869873..5a330706 100644 --- a/packages/react/src/hooks/useNodesInitialized.ts +++ b/packages/react/src/hooks/useNodesInitialized.ts @@ -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)); diff --git a/packages/react/src/hooks/useOnInitHandler.ts b/packages/react/src/hooks/useOnInitHandler.ts index 27de912b..e08e3b4c 100644 --- a/packages/react/src/hooks/useOnInitHandler.ts +++ b/packages/react/src/hooks/useOnInitHandler.ts @@ -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(false); diff --git a/packages/react/src/hooks/useOnSelectionChange.ts b/packages/react/src/hooks/useOnSelectionChange.ts index 51df3ddb..bd3541d9 100644 --- a/packages/react/src/hooks/useOnSelectionChange.ts +++ b/packages/react/src/hooks/useOnSelectionChange.ts @@ -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(); diff --git a/packages/react/src/hooks/useOnViewportChange.ts b/packages/react/src/hooks/useOnViewportChange.ts index 00ac15a7..13209d62 100644 --- a/packages/react/src/hooks/useOnViewportChange.ts +++ b/packages/react/src/hooks/useOnViewportChange.ts @@ -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(); diff --git a/packages/react/src/hooks/useReactFlow.ts b/packages/react/src/hooks/useReactFlow.ts index dfe399c6..aa043e99 100644 --- a/packages/react/src/hooks/useReactFlow.ts +++ b/packages/react/src/hooks/useReactFlow.ts @@ -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((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((node) => { - const { nodes, edges } = store.getState(); - - if (typeof node === 'string') { - return getIncomersBase({ id: node }, nodes, edges); - } - - return getIncomersBase(node, nodes, edges); - }, []); - - const getOutgoers = useCallback((node) => { - const { nodes, edges } = store.getState(); - - if (typeof node == 'string') { - return getOutgoersBase({ id: node }, nodes, edges); - } - - return getOutgoersBase(node, nodes, edges); - }, []); - - const updateNode = useCallback( + const updateNode = useCallback>( (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( + const updateNodeData = useCallback>( (id, dataUpdate, options = { replace: false }) => { updateNode( id, @@ -318,9 +275,6 @@ export default function useReactFlow): void { const store = useStoreApi(); diff --git a/packages/react/src/hooks/useStore.ts b/packages/react/src/hooks/useStore.ts index eb075d00..96587161 100644 --- a/packages/react/src/hooks/useStore.ts +++ b/packages/react/src/hooks/useStore.ts @@ -10,6 +10,14 @@ const zustandErrorMessage = errorMessages['error001'](); type ExtractState = StoreApi 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( selector: (state: ReactFlowState) => StateSlice, equalityFn?: (a: StateSlice, b: StateSlice) => boolean diff --git a/packages/react/src/hooks/useUpdateNodeInternals.ts b/packages/react/src/hooks/useUpdateNodeInternals.ts index d14f35f3..ced202da 100644 --- a/packages/react/src/hooks/useUpdateNodeInternals.ts +++ b/packages/react/src/hooks/useUpdateNodeInternals.ts @@ -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(); diff --git a/packages/react/src/hooks/useUpdateNodePositions.ts b/packages/react/src/hooks/useUpdateNodePositions.ts index 06577601..77def71f 100644 --- a/packages/react/src/hooks/useUpdateNodePositions.ts +++ b/packages/react/src/hooks/useUpdateNodePositions.ts @@ -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(); diff --git a/packages/react/src/hooks/useViewport.ts b/packages/react/src/hooks/useViewport.ts index c7153fac..4d48cf5c 100644 --- a/packages/react/src/hooks/useViewport.ts +++ b/packages/react/src/hooks/useViewport.ts @@ -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); diff --git a/packages/react/src/hooks/useViewportHelper.ts b/packages/react/src/hooks/useViewportHelper.ts index f1099b43..481bae15 100644 --- a/packages/react/src/hooks/useViewportHelper.ts +++ b/packages/react/src/hooks/useViewportHelper.ts @@ -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); diff --git a/packages/react/src/hooks/useViewportSync.ts b/packages/react/src/hooks/useViewportSync.ts index a34cdcd5..f0a1a31e 100644 --- a/packages/react/src/hooks/useViewportSync.ts +++ b/packages/react/src/hooks/useViewportSync.ts @@ -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(); diff --git a/packages/react/src/hooks/useVisibleEdgeIds.ts b/packages/react/src/hooks/useVisibleEdgeIds.ts index eaa4eb2d..ceb40f31 100644 --- a/packages/react/src/hooks/useVisibleEdgeIds.ts +++ b/packages/react/src/hooks/useVisibleEdgeIds.ts @@ -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( diff --git a/packages/react/src/hooks/useVisibleNodeIds.ts b/packages/react/src/hooks/useVisibleNodeIds.ts index 23b29096..803fde6d 100644 --- a/packages/react/src/hooks/useVisibleNodeIds.ts +++ b/packages/react/src/hooks/useVisibleNodeIds.ts @@ -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); diff --git a/packages/react/src/types/changes.ts b/packages/react/src/types/changes.ts index 440a4c6b..f1282574 100644 --- a/packages/react/src/types/changes.ts +++ b/packages/react/src/types/changes.ts @@ -40,6 +40,10 @@ export type NodeResetChange = { type: 'reset'; }; +/** + * Union type of all possible node changes. + * @public + */ export type NodeChange = | NodeDimensionChange | NodePositionChange diff --git a/packages/react/src/types/component-props.ts b/packages/react/src/types/component-props.ts index 09f9a582..43dc5e90 100644 --- a/packages/react/src/types/component-props.ts +++ b/packages/react/src/types/component-props.ts @@ -45,6 +45,10 @@ import type { EdgeMouseHandler, } from '.'; +/** + * ReactFlow component props. + * @public + */ export type ReactFlowProps = Omit, 'onError'> & { nodes?: Node[]; edges?: Edge[]; diff --git a/packages/react/src/types/edges.ts b/packages/react/src/types/edges.ts index ec48db9d..faae7501 100644 --- a/packages/react/src/types/edges.ts +++ b/packages/react/src/types/edges.ts @@ -54,7 +54,8 @@ type StepEdgeType = DefaultEdge & { }; /** - * 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 = DefaultEdge | SmoothStepEdgeType | BezierEdgeType | StepEdgeType; @@ -92,7 +93,8 @@ export type EdgeTextProps = HTMLAttributes & }; /** - * Custom edge component props. + * Custom edge component props + * @public */ export type EdgeProps = Pick< Edge, @@ -110,7 +112,8 @@ export type EdgeProps = 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 = EdgeComponentProps & { /** * BezierEdge component props + * @public */ export type BezierEdgeProps = EdgeComponentWithPathOptions; /** * SmoothStepEdge component props + * @public */ export type SmoothStepEdgeProps = EdgeComponentWithPathOptions; /** * StepEdge component props + * @public */ export type StepEdgeProps = EdgeComponentWithPathOptions; /** * StraightEdge component props + * @public */ export type StraightEdgeProps = Omit; /** * SimpleBezier component props + * @public */ export type SimpleBezierEdgeProps = EdgeComponentProps; diff --git a/packages/react/src/types/instance.ts b/packages/react/src/types/instance.ts index 05eb1d4b..878e85a8 100644 --- a/packages/react/src/types/instance.ts +++ b/packages/react/src/types/instance.ts @@ -51,7 +51,7 @@ export namespace Instance { export type UpdateNode = ( id: string, - dataUpdate: Partial | ((node: NodeType) => Partial), + nodeUpdate: Partial | ((node: NodeType) => Partial), options?: { replace: boolean } ) => void; export type UpdateNodeData = (