diff --git a/packages/react/CHANGELOG.md b/packages/react/CHANGELOG.md index 4f04aa2b..cb1deb41 100644 --- a/packages/react/CHANGELOG.md +++ b/packages/react/CHANGELOG.md @@ -1,5 +1,12 @@ # @xyflow/react +## 12.0.0-next.4 + +### Minor changes + +- fix applyChanges: handle empty flows + addNodes/addEdges closes +- cleanup hook exports + ## 12.0.0-next.3 ### Minor changes diff --git a/packages/react/src/additional-components/Controls/Controls.tsx b/packages/react/src/additional-components/Controls/Controls.tsx index 29fcb268..0604186b 100644 --- a/packages/react/src/additional-components/Controls/Controls.tsx +++ b/packages/react/src/additional-components/Controls/Controls.tsx @@ -3,7 +3,7 @@ import cc from 'classcat'; import { shallow } from 'zustand/shallow'; import { useStore, useStoreApi } from '../../hooks/useStore'; -import useReactFlow from '../../hooks/useReactFlow'; +import { useReactFlow } from '../../hooks/useReactFlow'; import Panel from '../../components/Panel'; import { type ReactFlowState } from '../../types'; diff --git a/packages/react/src/components/NodeWrapper/index.tsx b/packages/react/src/components/NodeWrapper/index.tsx index cc593439..461abf5a 100644 --- a/packages/react/src/components/NodeWrapper/index.tsx +++ b/packages/react/src/components/NodeWrapper/index.tsx @@ -1,5 +1,6 @@ import { useEffect, useRef, memo, type MouseEvent, type KeyboardEvent } from 'react'; import cc from 'classcat'; +import { shallow } from 'zustand/shallow'; import { clampPosition, elementSelectionKeys, @@ -12,12 +13,11 @@ import { import { useStore, useStoreApi } from '../../hooks/useStore'; import { Provider } from '../../contexts/NodeIdContext'; import { ARIA_NODE_DESC_KEY } from '../A11yDescriptions'; -import useDrag from '../../hooks/useDrag'; -import useUpdateNodePositions from '../../hooks/useUpdateNodePositions'; +import { useDrag } from '../../hooks/useDrag'; +import { useUpdateNodePositions } from '../../hooks/useUpdateNodePositions'; import { handleNodeClick } from '../Nodes/utils'; -import type { NodeWrapperProps } from '../../types'; import { arrowKeyDiffs, builtinNodeTypes } from './utils'; -import { shallow } from 'zustand/shallow'; +import type { NodeWrapperProps } from '../../types'; const NodeWrapper = ({ id, diff --git a/packages/react/src/components/NodesSelection/index.tsx b/packages/react/src/components/NodesSelection/index.tsx index e79ed782..c485d65c 100644 --- a/packages/react/src/components/NodesSelection/index.tsx +++ b/packages/react/src/components/NodesSelection/index.tsx @@ -9,10 +9,10 @@ import { shallow } from 'zustand/shallow'; import { getNodesBounds } from '@xyflow/system'; import { useStore, useStoreApi } from '../../hooks/useStore'; -import useDrag from '../../hooks/useDrag'; -import useUpdateNodePositions from '../../hooks/useUpdateNodePositions'; -import type { Node, ReactFlowState } from '../../types'; +import { useDrag } from '../../hooks/useDrag'; +import { useUpdateNodePositions } from '../../hooks/useUpdateNodePositions'; import { arrowKeyDiffs } from '../NodeWrapper/utils'; +import type { Node, ReactFlowState } from '../../types'; export type NodesSelectionProps = { onSelectionContextMenu?: (event: MouseEvent, nodes: Node[]) => void; diff --git a/packages/react/src/container/FlowRenderer/index.tsx b/packages/react/src/container/FlowRenderer/index.tsx index bb92f66a..04604ec9 100644 --- a/packages/react/src/container/FlowRenderer/index.tsx +++ b/packages/react/src/container/FlowRenderer/index.tsx @@ -1,8 +1,8 @@ import { memo, type ReactNode } from 'react'; import { useStore } from '../../hooks/useStore'; -import useGlobalKeyHandler from '../../hooks/useGlobalKeyHandler'; -import useKeyPress from '../../hooks/useKeyPress'; +import { useGlobalKeyHandler } from '../../hooks/useGlobalKeyHandler'; +import { useKeyPress } from '../../hooks/useKeyPress'; import { GraphViewProps } from '../GraphView'; import ZoomPane from '../ZoomPane'; import Pane from '../Pane'; diff --git a/packages/react/src/container/GraphView/index.tsx b/packages/react/src/container/GraphView/index.tsx index 8ff19028..ae67d6b4 100644 --- a/packages/react/src/container/GraphView/index.tsx +++ b/packages/react/src/container/GraphView/index.tsx @@ -4,11 +4,11 @@ import FlowRenderer from '../FlowRenderer'; import NodeRenderer from '../NodeRenderer'; import EdgeRenderer from '../EdgeRenderer'; import ViewportWrapper from '../Viewport'; -import useOnInitHandler from '../../hooks/useOnInitHandler'; -import useViewportSync from '../../hooks/useViewportSync'; +import { useOnInitHandler } from '../../hooks/useOnInitHandler'; +import { useViewportSync } from '../../hooks/useViewportSync'; import ConnectionLine from '../../components/ConnectionLine'; import type { ReactFlowProps } from '../../types'; -import useNodeOrEdgeTypesWarning from './useNodeOrEdgeTypesWarning'; +import { useNodeOrEdgeTypesWarning } from './useNodeOrEdgeTypesWarning'; export type GraphViewProps = Omit< ReactFlowProps, diff --git a/packages/react/src/container/GraphView/useNodeOrEdgeTypesWarning.ts b/packages/react/src/container/GraphView/useNodeOrEdgeTypesWarning.ts index e842018c..1c2ef365 100644 --- a/packages/react/src/container/GraphView/useNodeOrEdgeTypesWarning.ts +++ b/packages/react/src/container/GraphView/useNodeOrEdgeTypesWarning.ts @@ -12,7 +12,7 @@ const emptyTypes = {}; export function useNodeOrEdgeTypesWarning(nodeOrEdgeTypes?: NodeTypes): void; export function useNodeOrEdgeTypesWarning(nodeOrEdgeTypes?: EdgeTypes): void; // eslint-disable-next-line @typescript-eslint/no-explicit-any -export default function useNodeOrEdgeTypesWarning(nodeOrEdgeTypes: any = emptyTypes): any { +export function useNodeOrEdgeTypesWarning(nodeOrEdgeTypes: any = emptyTypes): any { const updateCount = useRef(0); const store = useStoreApi(); diff --git a/packages/react/src/container/ReactFlow/index.tsx b/packages/react/src/container/ReactFlow/index.tsx index bfe3530c..5f1f2628 100644 --- a/packages/react/src/container/ReactFlow/index.tsx +++ b/packages/react/src/container/ReactFlow/index.tsx @@ -15,10 +15,10 @@ import Attribution from '../../components/Attribution'; import SelectionListener from '../../components/SelectionListener'; import StoreUpdater from '../../components/StoreUpdater'; import A11yDescriptions from '../../components/A11yDescriptions'; +import { useColorModeClass } from '../../hooks/useColorModeClass'; import GraphView from '../GraphView'; import Wrapper from './Wrapper'; import type { ReactFlowProps, ReactFlowRefType } from '../../types'; -import useColorModeClass from '../../hooks/useColorModeClass'; export const initNodeOrigin: NodeOrigin = [0, 0]; const initDefaultViewport: Viewport = { x: 0, y: 0, zoom: 1 }; diff --git a/packages/react/src/container/ZoomPane/index.tsx b/packages/react/src/container/ZoomPane/index.tsx index aee6ac87..f79e5c29 100644 --- a/packages/react/src/container/ZoomPane/index.tsx +++ b/packages/react/src/container/ZoomPane/index.tsx @@ -3,8 +3,8 @@ import { useEffect, useRef } from 'react'; import { shallow } from 'zustand/shallow'; import { XYPanZoom, PanOnScrollMode, type Transform, type PanZoomInstance } from '@xyflow/system'; -import useKeyPress from '../../hooks/useKeyPress'; -import useResizeHandler from '../../hooks/useResizeHandler'; +import { useKeyPress } from '../../hooks/useKeyPress'; +import { useResizeHandler } from '../../hooks/useResizeHandler'; import { useStore, useStoreApi } from '../../hooks/useStore'; import { containerStyle } from '../../styles/utils'; import type { FlowRendererProps } from '../FlowRenderer'; diff --git a/packages/react/src/hooks/useColorModeClass.ts b/packages/react/src/hooks/useColorModeClass.ts index bcf8c6af..ec60d6dc 100644 --- a/packages/react/src/hooks/useColorModeClass.ts +++ b/packages/react/src/hooks/useColorModeClass.ts @@ -15,7 +15,7 @@ function getMediaQuery() { * @internal * @param colorMode - The color mode to use ('dark', 'light' or 'system') */ -export default function useColorModeClass(colorMode: ColorMode): ColorModeClass { +export 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 8a4fab65..f632d732 100644 --- a/packages/react/src/hooks/useDrag.ts +++ b/packages/react/src/hooks/useDrag.ts @@ -18,7 +18,14 @@ type UseDragParams = { * * @internal */ -function useDrag({ nodeRef, disabled = false, noDragClassName, handleSelector, nodeId, isSelectable }: UseDragParams) { +export function useDrag({ + nodeRef, + disabled = false, + noDragClassName, + handleSelector, + nodeId, + isSelectable, +}: UseDragParams) { const store = useStoreApi(); const [dragging, setDragging] = useState(false); const xyDrag = useRef(); @@ -64,5 +71,3 @@ function useDrag({ nodeRef, disabled = false, noDragClassName, handleSelector, n return dragging; } - -export default useDrag; diff --git a/packages/react/src/hooks/useEdges.ts b/packages/react/src/hooks/useEdges.ts index 94445ce4..bd748abb 100644 --- a/packages/react/src/hooks/useEdges.ts +++ b/packages/react/src/hooks/useEdges.ts @@ -11,10 +11,8 @@ const edgesSelector = (state: ReactFlowState) => state.edges; * @public * @returns An array of edges */ -function useEdges(): Edge[] { +export function useEdges(): Edge[] { const edges = useStore(edgesSelector, shallow); return edges; } - -export default useEdges; diff --git a/packages/react/src/hooks/useGlobalKeyHandler.ts b/packages/react/src/hooks/useGlobalKeyHandler.ts index 2409558f..f85826c7 100644 --- a/packages/react/src/hooks/useGlobalKeyHandler.ts +++ b/packages/react/src/hooks/useGlobalKeyHandler.ts @@ -2,8 +2,8 @@ import { useEffect } from 'react'; import type { KeyCode } from '@xyflow/system'; import { useStoreApi } from '../hooks/useStore'; -import useKeyPress, { UseKeyPressOptions } from './useKeyPress'; -import useReactFlow from './useReactFlow'; +import { useKeyPress, UseKeyPressOptions } from './useKeyPress'; +import { useReactFlow } from './useReactFlow'; import { Edge, Node } from '../types'; const selected = (item: Node | Edge) => item.selected; @@ -15,13 +15,13 @@ const deleteKeyOptions: UseKeyPressOptions = { actInsideInputWithModifier: false * * @internal */ -export default ({ +export function useGlobalKeyHandler({ deleteKeyCode, multiSelectionKeyCode, }: { deleteKeyCode: KeyCode | null; multiSelectionKeyCode: KeyCode | null; -}): void => { +}): void { const store = useStoreApi(); const { deleteElements } = useReactFlow(); @@ -39,4 +39,4 @@ export default ({ useEffect(() => { store.setState({ multiSelectionActive: multiSelectionKeyPressed }); }, [multiSelectionKeyPressed]); -}; +} diff --git a/packages/react/src/hooks/useKeyPress.ts b/packages/react/src/hooks/useKeyPress.ts index 98d460d0..77966207 100644 --- a/packages/react/src/hooks/useKeyPress.ts +++ b/packages/react/src/hooks/useKeyPress.ts @@ -20,14 +20,14 @@ const defaultDoc = typeof document !== 'undefined' ? document : null; * @param param.options - Options * @returns boolean */ -export default ( +export function useKeyPress( // 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 => { +): boolean { const [keyPressed, setKeyPressed] = useState(false); // we need to remember if a modifier key is pressed in order to track it @@ -113,7 +113,7 @@ export default ( }, [keyCode, setKeyPressed]); return keyPressed; -}; +} // utils diff --git a/packages/react/src/hooks/useNodes.ts b/packages/react/src/hooks/useNodes.ts index bb54865d..5e558e90 100644 --- a/packages/react/src/hooks/useNodes.ts +++ b/packages/react/src/hooks/useNodes.ts @@ -11,10 +11,8 @@ const nodesSelector = (state: ReactFlowState) => state.nodes; * @public * @returns An array of nodes */ -function useNodes(): NodeType[] { +export function useNodes(): NodeType[] { const nodes = useStore(nodesSelector, shallow) as NodeType[]; return nodes; } - -export default useNodes; diff --git a/packages/react/src/hooks/useNodesInitialized.ts b/packages/react/src/hooks/useNodesInitialized.ts index 5a330706..e70ba7cd 100644 --- a/packages/react/src/hooks/useNodesInitialized.ts +++ b/packages/react/src/hooks/useNodesInitialized.ts @@ -28,10 +28,8 @@ const defaultOptions = { * @param options.includeHiddenNodes - defaults to false * @returns boolean indicating whether all nodes are initialized */ -function useNodesInitialized(options: UseNodesInitializedOptions = defaultOptions): boolean { +export function useNodesInitialized(options: UseNodesInitializedOptions = defaultOptions): boolean { const initialized = useStore(selector(options)); return initialized; } - -export default useNodesInitialized; diff --git a/packages/react/src/hooks/useOnInitHandler.ts b/packages/react/src/hooks/useOnInitHandler.ts index e08e3b4c..5b677c1a 100644 --- a/packages/react/src/hooks/useOnInitHandler.ts +++ b/packages/react/src/hooks/useOnInitHandler.ts @@ -1,6 +1,6 @@ import { useEffect, useRef } from 'react'; -import useReactFlow from './useReactFlow'; +import { useReactFlow } from './useReactFlow'; import type { OnInit } from '../types'; /** @@ -8,7 +8,7 @@ import type { OnInit } from '../types'; * * @internal */ -function useOnInitHandler(onInit: OnInit | undefined) { +export function useOnInitHandler(onInit: OnInit | undefined) { const rfInstance = useReactFlow(); const isInitialized = useRef(false); @@ -19,5 +19,3 @@ function useOnInitHandler(onInit: OnInit | undefined) { } }, [onInit, rfInstance.viewportInitialized]); } - -export default useOnInitHandler; diff --git a/packages/react/src/hooks/useOnSelectionChange.ts b/packages/react/src/hooks/useOnSelectionChange.ts index bd3541d9..53c48891 100644 --- a/packages/react/src/hooks/useOnSelectionChange.ts +++ b/packages/react/src/hooks/useOnSelectionChange.ts @@ -13,7 +13,7 @@ export type UseOnSelectionChangeOptions = { * @public * @params params.onChange - The handler to register */ -function useOnSelectionChange({ onChange }: UseOnSelectionChangeOptions) { +export function useOnSelectionChange({ onChange }: UseOnSelectionChangeOptions) { const store = useStoreApi(); useEffect(() => { @@ -26,5 +26,3 @@ function useOnSelectionChange({ onChange }: UseOnSelectionChangeOptions) { }; }, [onChange]); } - -export default useOnSelectionChange; diff --git a/packages/react/src/hooks/useOnViewportChange.ts b/packages/react/src/hooks/useOnViewportChange.ts index 13209d62..61e4d64f 100644 --- a/packages/react/src/hooks/useOnViewportChange.ts +++ b/packages/react/src/hooks/useOnViewportChange.ts @@ -17,7 +17,7 @@ export type UseOnViewportChangeOptions = { * @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) { +export function useOnViewportChange({ onStart, onChange, onEnd }: UseOnViewportChangeOptions) { const store = useStoreApi(); useEffect(() => { @@ -32,5 +32,3 @@ function useOnViewportChange({ onStart, onChange, onEnd }: UseOnViewportChangeOp store.setState({ onViewportChangeEnd: onEnd }); }, [onEnd]); } - -export default useOnViewportChange; diff --git a/packages/react/src/hooks/useReactFlow.ts b/packages/react/src/hooks/useReactFlow.ts index eb07cc6a..198599d5 100644 --- a/packages/react/src/hooks/useReactFlow.ts +++ b/packages/react/src/hooks/useReactFlow.ts @@ -23,7 +23,7 @@ import { isNode } from '../utils'; * @public * @returns ReactFlowInstance */ -export default function useReactFlow(): ReactFlowInstance< +export function useReactFlow(): ReactFlowInstance< NodeType, EdgeType > { diff --git a/packages/react/src/hooks/useResizeHandler.ts b/packages/react/src/hooks/useResizeHandler.ts index 1b3dc6ce..2db37499 100644 --- a/packages/react/src/hooks/useResizeHandler.ts +++ b/packages/react/src/hooks/useResizeHandler.ts @@ -8,7 +8,7 @@ import { useStoreApi } from '../hooks/useStore'; * * @internal */ -function useResizeHandler(domNode: MutableRefObject): void { +export function useResizeHandler(domNode: MutableRefObject): void { const store = useStoreApi(); useEffect(() => { @@ -42,5 +42,3 @@ function useResizeHandler(domNode: MutableRefObject): voi } }, []); } - -export default useResizeHandler; diff --git a/packages/react/src/hooks/useUpdateNodeInternals.ts b/packages/react/src/hooks/useUpdateNodeInternals.ts index ced202da..1d7cc681 100644 --- a/packages/react/src/hooks/useUpdateNodeInternals.ts +++ b/packages/react/src/hooks/useUpdateNodeInternals.ts @@ -9,7 +9,7 @@ import { useStoreApi } from '../hooks/useStore'; * @public * @returns function for updating node internals */ -function useUpdateNodeInternals(): UpdateNodeInternals { +export function useUpdateNodeInternals(): UpdateNodeInternals { const store = useStoreApi(); return useCallback((id: string | string[]) => { @@ -28,5 +28,3 @@ function useUpdateNodeInternals(): UpdateNodeInternals { requestAnimationFrame(() => updateNodeDimensions(updates)); }, []); } - -export default useUpdateNodeInternals; diff --git a/packages/react/src/hooks/useUpdateNodePositions.ts b/packages/react/src/hooks/useUpdateNodePositions.ts index 77def71f..1ca0d4ee 100644 --- a/packages/react/src/hooks/useUpdateNodePositions.ts +++ b/packages/react/src/hooks/useUpdateNodePositions.ts @@ -13,7 +13,7 @@ const selectedAndDraggable = (nodesDraggable: boolean) => (n: Node) => * @internal * @returns function for updating node positions */ -function useUpdateNodePositions() { +export function useUpdateNodePositions() { const store = useStoreApi(); const updatePositions = useCallback((params: { x: number; y: number; isShiftPressed: boolean }) => { @@ -63,5 +63,3 @@ function useUpdateNodePositions() { return updatePositions; } - -export default useUpdateNodePositions; diff --git a/packages/react/src/hooks/useViewport.ts b/packages/react/src/hooks/useViewport.ts index 4d48cf5c..0b9758c1 100644 --- a/packages/react/src/hooks/useViewport.ts +++ b/packages/react/src/hooks/useViewport.ts @@ -16,10 +16,8 @@ const viewportSelector = (state: ReactFlowState) => ({ * @public * @returns The current viewport */ -function useViewport(): Viewport { +export function useViewport(): Viewport { const viewport = useStore(viewportSelector, shallow); return viewport; } - -export default useViewport; diff --git a/packages/react/src/hooks/useViewportSync.ts b/packages/react/src/hooks/useViewportSync.ts index f0a1a31e..00fae17a 100644 --- a/packages/react/src/hooks/useViewportSync.ts +++ b/packages/react/src/hooks/useViewportSync.ts @@ -12,7 +12,7 @@ const selector = (state: ReactFlowState) => state.panZoom?.syncViewport; * @internal * @param viewport */ -export default function useViewportSync(viewport?: Viewport) { +export function useViewportSync(viewport?: Viewport) { const syncViewport = useStore(selector); const store = useStoreApi(); diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts index 771c7d86..3d419470 100644 --- a/packages/react/src/index.ts +++ b/packages/react/src/index.ts @@ -12,17 +12,17 @@ export { default as Panel, type PanelProps } from './components/Panel'; export { default as EdgeLabelRenderer } from './components/EdgeLabelRenderer'; export { default as ViewportPortal } from './components/ViewportPortal'; -export { default as useReactFlow } from './hooks/useReactFlow'; -export { default as useUpdateNodeInternals } from './hooks/useUpdateNodeInternals'; -export { default as useNodes } from './hooks/useNodes'; -export { default as useEdges } from './hooks/useEdges'; -export { default as useViewport } from './hooks/useViewport'; -export { default as useKeyPress } from './hooks/useKeyPress'; -export * from './hooks/useNodesEdgesState'; +export { useReactFlow } from './hooks/useReactFlow'; +export { useUpdateNodeInternals } from './hooks/useUpdateNodeInternals'; +export { useNodes } from './hooks/useNodes'; +export { useEdges } from './hooks/useEdges'; +export { useViewport } from './hooks/useViewport'; +export { useKeyPress } from './hooks/useKeyPress'; +export { useNodesState, useEdgesState } from './hooks/useNodesEdgesState'; export { useStore, useStoreApi } from './hooks/useStore'; -export { default as useOnViewportChange, type UseOnViewportChangeOptions } from './hooks/useOnViewportChange'; -export { default as useOnSelectionChange, type UseOnSelectionChangeOptions } from './hooks/useOnSelectionChange'; -export { default as useNodesInitialized, type UseNodesInitializedOptions } from './hooks/useNodesInitialized'; +export { useOnViewportChange, type UseOnViewportChangeOptions } from './hooks/useOnViewportChange'; +export { useOnSelectionChange, type UseOnSelectionChangeOptions } from './hooks/useOnSelectionChange'; +export { useNodesInitialized, type UseNodesInitializedOptions } from './hooks/useNodesInitialized'; export { useHandleConnections } from './hooks/useHandleConnections'; export { useNodesData } from './hooks/useNodesData'; export { useConnection } from './hooks/useConnection';