From c48bddd71dea16687db33801ef17a66f8bcbba5b Mon Sep 17 00:00:00 2001 From: moklick Date: Thu, 4 Jan 2024 09:07:57 +0100 Subject: [PATCH 1/8] fix(react): multi handles --- packages/react/CHANGELOG.md | 71 ++++++++++--------- .../src/components/EdgeWrapper/index.tsx | 16 ++--- packages/react/src/types/edges.ts | 2 - 3 files changed, 44 insertions(+), 45 deletions(-) diff --git a/packages/react/CHANGELOG.md b/packages/react/CHANGELOG.md index fb1ff106..0ccc2ae0 100644 --- a/packages/react/CHANGELOG.md +++ b/packages/react/CHANGELOG.md @@ -14,54 +14,58 @@ React Flow v12 is coming soon! We worked hard over the past months and tried to 2. **Reactive flows**: new hooks and helper functions to simplify data flows 3. **Dark mode**: a new base style and easy way to switch between built in color modes -Svelte Flow had a big impact on this release as well. While combing through each line of React Flow, we created framework agnostic helpers, found bugs, and made some under the hood improvements. All of these changes are baked into the v12 release as a welcome side-effect of that launch. đŸ™ŒđŸ»Â We also improved the performance for larger flows with the help of Ivan. +Svelte Flow had a big impact on this release as well. While combing through each line of React Flow, we created framework agnostic helpers, found bugs, and made some under the hood improvements. All of these changes are baked into the v12 release as a welcome side-effect of that launch. đŸ™ŒđŸ»Â We also improved the performance for larger flows with the help of Ivan. ### Migrate from 11 to 12 Before you can try out the new features, you need to do some minor updates: - **A new npm package name:** Our name changed from `reactflow` to `@xyflow/react` and the main component is no longer a default, but a named import: - - v11: `import ReactFlow from 'reactflow';` - - v12: `import { ReactFlow } from '@xyflow/react';` + - v11: `import { ReactFlow } from '@xyflow/react';` + - v12: `import { ReactFlow } from '@xyflow/react';` - **Node attribute “computed”:** All computed node values are now stored in `node.computed` - - v11: `node.width`, `node.height` ,`node.positionAbsolute` - - v12: `node.computed.width`, `node.computed.height` and `node.computed.positionAbsolute` . (`node.width`/ `node.height` can now be used for SSG) + - v11: `node.width`, `node.height` ,`node.positionAbsolute` + - v12: `node.computed.width`, `node.computed.height` and `node.computed.positionAbsolute` . (`node.width`/ `node.height` can now be used for SSG) - **Updating nodes:** We are not supporting node updates with object mutations anymore. If you want to update a certain attribute, you need to create a new node. - - v11: - ```js - setNodes(nds => nds.map((node) => { - node.hidden = true; - return node; - })); - ``` - - v12: - ```js - setNodes(nds => nds.map((node) => ({ - ...node, - hidden: true - }))); - ``` + - v11: + ```js + setNodes((nds) => + nds.map((node) => { + node.hidden = true; + return node; + }) + ); + ``` + - v12: + ```js + setNodes((nds) => + nds.map((node) => ({ + ...node, + hidden: true, + })) + ); + ``` - **NodeProps:** `posX`/`posY` is now called `positionAbsoluteX`/`positionAbsoluteY` - **Typescript only:** We simplified types and fixed issues about functions where users could pass a `NodeData` generic. The new way is to define your own node type for the whole app and then only use that one. The big advantage of this is, that you can have multiple node types with different data structures and always be able to distinguish by checking the `node.type` attribute. - - v11: `applyNodeChange` - - v12: `type MyNodeType = Node<{ value: number }, ‘number’> | Node<{ value: string }, ‘text’>; applyNodeChange` - - affected functions: `useNodes`, `useNodesState`, `useEdgesState`, `applyNodeChange`, `onInit`, `applyEdgeChanges` , `MiniMapProps` + - v11: `applyNodeChange` + - v12: `type MyNodeType = Node<{ value: number }, ‘number’> | Node<{ value: string }, ‘text’>; applyNodeChange` + - affected functions: `useNodes`, `useNodesState`, `useEdgesState`, `applyNodeChange`, `onInit`, `applyEdgeChanges` , `MiniMapProps` - **Removal of deprecated functions:** - - `getTransformForBounds` (new name: `getViewportForBounds`), - - `getRectOfNodes` ****(new name: `getNodesBounds`) - - `project` (new name: `screenToFlowPosition`) - - `getMarkerEndId` + - `getTransformForBounds` (new name: `getViewportForBounds`), + - `getRectOfNodes` \*\*\*\*(new name: `getNodesBounds`) + - `project` (new name: `screenToFlowPosition`) + - `getMarkerEndId` ### Main features Now that you successfully migrated to v12, you can use all the fancy features. As mentioned above, the biggest updates for v12 are: - **SSR / SSG**: you can define `width`, `height` and `handles` for the nodes. This makes it possible to render a flow on the server and hydrate on the client: [codesandbox](https://codesandbox.io/p/devbox/reactflow-v12-next-pr66yh) - - Details: In v11, `width` and `height` were set by the library as soon as the nodes got measured. This still happens, but we are now using `computed.width` and `computed.height` to store this information. The `positionAbsolute` attribute also gets stored in `computed` . In the previous versions there was always a lot of confusion about `width` and `height`. It’s hard to understand, that you can’t use it for passing an actual width or height. It’s also not obvious that those attributes get added by the library. We think that the new implementation solves both of the problems: `width` and `height` are optional attributes that can be used to define dimensions and everything that is set by the library, is stored in `computed`. + - Details: In v11, `width` and `height` were set by the library as soon as the nodes got measured. This still happens, but we are now using `computed.width` and `computed.height` to store this information. The `positionAbsolute` attribute also gets stored in `computed` . In the previous versions there was always a lot of confusion about `width` and `height`. It’s hard to understand, that you can’t use it for passing an actual width or height. It’s also not obvious that those attributes get added by the library. We think that the new implementation solves both of the problems: `width` and `height` are optional attributes that can be used to define dimensions and everything that is set by the library, is stored in `computed`. - **Reactive Flows:** The new hooks `useHandleConnections` and `useNodesData` and the new `updateNode` and `updateNodeData` functions can be used for managing the data flow between your nodes: [codesandbox](https://codesandbox.io/p/sandbox/reactflow-reactive-flow-sy93yx) - - Details: Working with reactive flows is super common. You update node A and want to react on those changes in the connected node B. Until now everyone had to come up with a custom solution. With this version we want to change this and give you performant helpers to handle this. If you are excited about this, you can check out this example: + - Details: Working with reactive flows is super common. You update node A and want to react on those changes in the connected node B. Until now everyone had to come up with a custom solution. With this version we want to change this and give you performant helpers to handle this. If you are excited about this, you can check out this example: - **Dark mode and css variables:** React Flow now comes with a built-in dark mode, that can be toggled by using the new `colorMode` prop (”light”, “dark” or “system”): [codesandbox](https://codesandbox.io/p/sandbox/reactflow-dark-mode-256l99) - - Details: With this version we want to make it easier to switch between dark and light modes and give you a better starting point for dark flows. If you pass colorMode=”dark”, we add the class name “dark” to the wrapper and use it to adjust the styling. To make the implementation for this new feature easier on our ends, we switched to CSS variables for most of the styles. These variables can also be used in user land to customize a flow. + - Details: With this version we want to make it easier to switch between dark and light modes and give you a better starting point for dark flows. If you pass colorMode=”dark”, we add the class name “dark” to the wrapper and use it to adjust the styling. To make the implementation for this new feature easier on our ends, we switched to CSS variables for most of the styles. These variables can also be used in user land to customize a flow. ### More features and updates @@ -86,12 +90,11 @@ There is more! Besides the new main features, we added some minor things that we These changes are not really user-facing, but it could be important for folks who are working with the React Flow store: - The biggest internal change is that we created a new package **@xyflow/system with framework agnostic helpers** that can be used be React Flow and Svelte Flow - - **XYDrag** for handling dragging node(s) and selection - - **XYPanZoom** for controlling the viewport panning and zooming - - **XYHandle** for managing new connections + - **XYDrag** for handling dragging node(s) and selection + - **XYPanZoom** for controlling the viewport panning and zooming + - **XYHandle** for managing new connections - We replaced the `nodeInternals` map with a `nodes` array. We added a new `nodeLookup` map that serves as a lookup, but we are not creating a new map object on any change so it’s really only useful as a lookup. - We removed `connectionNodeId`, `connectionHandleId`, `connectionHandleType` from the store and added `connectionStartHandle.nodeId`, `connectionStartHandle.handleId`, 
 - add `data-id` to edges - -__With v12 the `reactflow` package was renamed to `@xyflow/react` - you can find the v11 source and the [`reactflow` changelog](https://github.com/xyflow/xyflow/blob/v11/packages/reactflow/CHANGELOG.md) on the v11 branch.__ +**With v12 the `reactflow` package was renamed to `@xyflow/react` - you can find the v11 source and the [`reactflow` changelog](https://github.com/xyflow/xyflow/blob/v11/packages/reactflow/CHANGELOG.md) on the v11 branch.** diff --git a/packages/react/src/components/EdgeWrapper/index.tsx b/packages/react/src/components/EdgeWrapper/index.tsx index 2a30116b..9d96948c 100644 --- a/packages/react/src/components/EdgeWrapper/index.tsx +++ b/packages/react/src/components/EdgeWrapper/index.tsx @@ -22,8 +22,6 @@ function EdgeWrapper({ elementsSelectable, onClick, onDoubleClick, - sourceHandleId, - targetHandleId, onContextMenu, onMouseEnter, onMouseMove, @@ -78,8 +76,8 @@ function EdgeWrapper({ id, sourceNode, targetNode, - sourceHandle: sourceHandleId || null, - targetHandle: targetHandleId || null, + sourceHandle: edge.sourceHandle || null, + targetHandle: edge.targetHandle || null, connectionMode: store.connectionMode, onError, }); @@ -97,7 +95,7 @@ function EdgeWrapper({ ...(edgePosition || nullPosition), }; }, - [edge.source, edge.target, edge.selected, edge.zIndex] + [edge.source, edge.target, edge.sourceHandle, edge.targetHandle, edge.selected, edge.zIndex] ), shallow ); @@ -228,8 +226,8 @@ function EdgeWrapper({ targetPosition={targetPosition} data={edge.data} style={edge.style} - sourceHandleId={sourceHandleId} - targetHandleId={targetHandleId} + sourceHandleId={edge.sourceHandle} + targetHandleId={edge.targetHandle} markerStart={markerStartUrl} markerEnd={markerEndUrl} pathOptions={'pathOptions' in edge ? edge.pathOptions : undefined} @@ -252,8 +250,8 @@ function EdgeWrapper({ targetPosition={targetPosition} setUpdateHover={setUpdateHover} setUpdating={setUpdating} - sourceHandleId={sourceHandleId} - targetHandleId={targetHandleId} + sourceHandleId={edge.sourceHandle} + targetHandleId={edge.targetHandle} /> )} diff --git a/packages/react/src/types/edges.ts b/packages/react/src/types/edges.ts index dce49193..b65b78c3 100644 --- a/packages/react/src/types/edges.ts +++ b/packages/react/src/types/edges.ts @@ -69,8 +69,6 @@ export type EdgeWrapperProps = { noPanClassName: string; onClick?: EdgeMouseHandler; onDoubleClick?: EdgeMouseHandler; - sourceHandleId?: string | null; - targetHandleId?: string | null; onEdgeUpdate?: OnEdgeUpdateFunc; onContextMenu?: EdgeMouseHandler; onMouseEnter?: EdgeMouseHandler; From 9e0f974525e9ffb82feac39a6e4306939c77fadf Mon Sep 17 00:00:00 2001 From: moklick Date: Thu, 4 Jan 2024 09:19:39 +0100 Subject: [PATCH 2/8] fix(react): connectionline --- .../react/src/components/ConnectionLine/index.tsx | 2 +- .../react/src/container/EdgeRenderer/index.tsx | 2 +- packages/react/src/container/GraphView/index.tsx | 15 +++++++-------- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/packages/react/src/components/ConnectionLine/index.tsx b/packages/react/src/components/ConnectionLine/index.tsx index bdf73089..143ec6ef 100644 --- a/packages/react/src/components/ConnectionLine/index.tsx +++ b/packages/react/src/components/ConnectionLine/index.tsx @@ -155,7 +155,7 @@ function ConnectionLineWrapper({ containerStyle, style, type, component }: Conne style={containerStyle} width={width} height={height} - className="react-flow__edges react-flow__connectionline react-flow__container" + className="react-flow__connectionline react-flow__container" > & { - children: ReactNode; + children?: ReactNode; }; const selector = (s: ReactFlowState) => ({ diff --git a/packages/react/src/container/GraphView/index.tsx b/packages/react/src/container/GraphView/index.tsx index e311bc7f..8ff19028 100644 --- a/packages/react/src/container/GraphView/index.tsx +++ b/packages/react/src/container/GraphView/index.tsx @@ -165,14 +165,13 @@ const GraphView = ({ noPanClassName={noPanClassName} disableKeyboardA11y={disableKeyboardA11y} rfId={rfId} - > - - + /> +
Date: Thu, 4 Jan 2024 13:53:36 +0100 Subject: [PATCH 3/8] fix(react): edge styles --- packages/react/CHANGELOG.md | 13 +++++++++++++ packages/react/package.json | 2 +- .../components/EdgeWrapper/EdgeUpdateAnchors.tsx | 4 ++-- packages/system/src/styles/init.css | 8 +++++++- packages/system/src/styles/style.css | 6 ------ 5 files changed, 23 insertions(+), 10 deletions(-) diff --git a/packages/react/CHANGELOG.md b/packages/react/CHANGELOG.md index 0ccc2ae0..4f04aa2b 100644 --- a/packages/react/CHANGELOG.md +++ b/packages/react/CHANGELOG.md @@ -1,5 +1,18 @@ # @xyflow/react +## 12.0.0-next.3 + +### Minor changes + +- fix edges styles when using base.css + +## 12.0.0-next.2 + +### Minor changes + +- fix connection line rendering +- fix multi handle + ## 12.0.0-next.1 ### Minor changes diff --git a/packages/react/package.json b/packages/react/package.json index fbc80b3b..9bd90350 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -1,6 +1,6 @@ { "name": "@xyflow/react", - "version": "12.0.0-next.1", + "version": "12.0.0-next.3", "description": "React Flow - A highly customizable React library for building node-based editors and interactive flow charts.", "keywords": [ "react", diff --git a/packages/react/src/components/EdgeWrapper/EdgeUpdateAnchors.tsx b/packages/react/src/components/EdgeWrapper/EdgeUpdateAnchors.tsx index 8f6ddfe3..57c81724 100644 --- a/packages/react/src/components/EdgeWrapper/EdgeUpdateAnchors.tsx +++ b/packages/react/src/components/EdgeWrapper/EdgeUpdateAnchors.tsx @@ -9,8 +9,8 @@ type EdgeUpdateAnchorsProps = { edge: Edge; isUpdatable: boolean | 'source' | 'target'; edgeUpdaterRadius: EdgeWrapperProps['edgeUpdaterRadius']; - sourceHandleId: EdgeWrapperProps['sourceHandleId']; - targetHandleId: EdgeWrapperProps['targetHandleId']; + sourceHandleId: Edge['sourceHandle']; + targetHandleId: Edge['targetHandle']; onEdgeUpdate: EdgeWrapperProps['onEdgeUpdate']; onEdgeUpdateStart: EdgeWrapperProps['onEdgeUpdateStart']; onEdgeUpdateEnd: EdgeWrapperProps['onEdgeUpdateEnd']; diff --git a/packages/system/src/styles/init.css b/packages/system/src/styles/init.css index 261d9467..a688f6b9 100644 --- a/packages/system/src/styles/init.css +++ b/packages/system/src/styles/init.css @@ -106,6 +106,12 @@ .xy-flow__edges { position: absolute; + + svg { + overflow: visible; + position: absolute; + pointer-events: none; + } } .xy-flow__edge { @@ -156,7 +162,7 @@ } } -.xy-flow__connectionline { +svg.xy-flow__connectionline { z-index: 1001; overflow: visible; position: absolute; diff --git a/packages/system/src/styles/style.css b/packages/system/src/styles/style.css index 6cd4978d..880ebaf7 100644 --- a/packages/system/src/styles/style.css +++ b/packages/system/src/styles/style.css @@ -43,12 +43,6 @@ --xy-controls-box-shadow-default: 0 0 2px 1px rgba(0, 0, 0, 0.08); } -.xy-flow__edges svg { - overflow: visible; - position: absolute; - pointer-events: none; -} - .xy-flow__edge { &.updating { .xy-flow__edge-path { From 1efd3ee3d53eaacba6a57e07b4b06b9bf941096a Mon Sep 17 00:00:00 2001 From: moklick Date: Mon, 8 Jan 2024 11:35:59 +0100 Subject: [PATCH 4/8] fix(applyChanges): handle empty flows + addNodes/addEdges closes #3770 --- packages/react/src/utils/changes.ts | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/packages/react/src/utils/changes.ts b/packages/react/src/utils/changes.ts index 30d01e47..be9460d0 100644 --- a/packages/react/src/utils/changes.ts +++ b/packages/react/src/utils/changes.ts @@ -54,20 +54,26 @@ function applyChanges(changes: any[], elements: any[]): any[] { return changes.filter((c) => c.type === 'reset').map((c) => c.item); } - let remainingChanges = changes; + let remainingChanges = []; const updatedElements: any[] = []; + for (const change of changes) { + if (change.type === 'add') { + updatedElements.push(change.item); + } else { + remainingChanges.push(change); + } + } + for (const item of elements) { const nextChanges: any[] = []; const _remainingChanges: any[] = []; - for (const c of remainingChanges) { - if (c.type === 'add') { - updatedElements.push(c.item); - } else if (c.id === item.id) { - nextChanges.push(c); + for (const change of remainingChanges) { + if (change.id === item.id) { + nextChanges.push(change); } else { - _remainingChanges.push(c); + _remainingChanges.push(change); } } From 30c975e39fce8905a12d1f32e4e85f5273ceb8c9 Mon Sep 17 00:00:00 2001 From: moklick Date: Mon, 8 Jan 2024 11:59:01 +0100 Subject: [PATCH 5/8] chore(react): cleanup exports --- packages/react/CHANGELOG.md | 7 +++++++ .../Controls/Controls.tsx | 2 +- .../src/components/NodeWrapper/index.tsx | 8 ++++---- .../src/components/NodesSelection/index.tsx | 6 +++--- .../src/container/FlowRenderer/index.tsx | 4 ++-- .../react/src/container/GraphView/index.tsx | 6 +++--- .../GraphView/useNodeOrEdgeTypesWarning.ts | 2 +- .../react/src/container/ReactFlow/index.tsx | 2 +- .../react/src/container/ZoomPane/index.tsx | 4 ++-- packages/react/src/hooks/useColorModeClass.ts | 2 +- packages/react/src/hooks/useDrag.ts | 11 +++++++--- packages/react/src/hooks/useEdges.ts | 4 +--- .../react/src/hooks/useGlobalKeyHandler.ts | 10 +++++----- packages/react/src/hooks/useKeyPress.ts | 6 +++--- packages/react/src/hooks/useNodes.ts | 4 +--- .../react/src/hooks/useNodesInitialized.ts | 4 +--- packages/react/src/hooks/useOnInitHandler.ts | 6 ++---- .../react/src/hooks/useOnSelectionChange.ts | 4 +--- .../react/src/hooks/useOnViewportChange.ts | 4 +--- packages/react/src/hooks/useReactFlow.ts | 2 +- packages/react/src/hooks/useResizeHandler.ts | 4 +--- .../react/src/hooks/useUpdateNodeInternals.ts | 4 +--- .../react/src/hooks/useUpdateNodePositions.ts | 4 +--- packages/react/src/hooks/useViewport.ts | 4 +--- packages/react/src/hooks/useViewportSync.ts | 2 +- packages/react/src/index.ts | 20 +++++++++---------- 26 files changed, 64 insertions(+), 72 deletions(-) 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'; From 61f8e00541c32c0e99e83e171eca230c57a9f92f Mon Sep 17 00:00:00 2001 From: moklick Date: Mon, 8 Jan 2024 13:26:14 +0100 Subject: [PATCH 6/8] chore(react): cleanup exports --- examples/react/src/examples/Stress/index.tsx | 1 - .../Background/Background.tsx | 10 +- .../Background/index.tsx | 4 +- .../Controls/ControlButton.tsx | 17 +- .../Controls/Controls.tsx | 29 +- .../Controls/Icons/FitView.tsx | 4 +- .../Controls/Icons/Lock.tsx | 4 +- .../Controls/Icons/Minus.tsx | 4 +- .../Controls/Icons/Plus.tsx | 4 +- .../Controls/Icons/Unlock.tsx | 4 +- .../additional-components/Controls/index.tsx | 6 +- .../additional-components/Controls/types.ts | 3 +- .../additional-components/MiniMap/MiniMap.tsx | 10 +- .../MiniMap/MiniMapNode.tsx | 4 +- .../MiniMap/MiniMapNodes.tsx | 2 +- .../additional-components/MiniMap/index.tsx | 2 +- .../NodeToolbar/NodeToolbar.tsx | 8 +- .../NodeToolbar/NodeToolbarPortal.tsx | 4 +- .../NodeToolbar/index.tsx | 4 +- .../src/components/A11yDescriptions/index.tsx | 4 +- .../src/components/Attribution/index.tsx | 6 +- .../src/components/ConnectionLine/index.tsx | 4 +- .../components/EdgeLabelRenderer/index.tsx | 4 +- .../EdgeWrapper/EdgeUpdateAnchors.tsx | 4 +- .../src/components/EdgeWrapper/index.tsx | 12 +- .../react/src/components/Edges/BaseEdge.tsx | 16 +- .../react/src/components/Edges/BezierEdge.tsx | 2 +- .../react/src/components/Edges/EdgeAnchor.tsx | 32 +- .../react/src/components/Edges/EdgeText.tsx | 11 +- .../src/components/Edges/SimpleBezierEdge.tsx | 2 +- .../src/components/Edges/SmoothStepEdge.tsx | 2 +- .../src/components/Edges/StraightEdge.tsx | 2 +- .../react/src/components/Handle/index.tsx | 6 +- .../src/components/NodeWrapper/index.tsx | 12 +- .../src/components/NodeWrapper/utils.tsx | 8 +- .../src/components/Nodes/DefaultNode.tsx | 13 +- .../react/src/components/Nodes/GroupNode.tsx | 8 +- .../react/src/components/Nodes/InputNode.tsx | 21 +- .../react/src/components/Nodes/OutputNode.tsx | 21 +- packages/react/src/components/Nodes/utils.ts | 2 +- .../src/components/NodesSelection/index.tsx | 6 +- packages/react/src/components/Panel/index.tsx | 6 +- .../components/ReactFlowProvider/index.tsx | 6 +- .../components/SelectionListener/index.tsx | 14 +- .../src/components/StoreUpdater/index.tsx | 6 +- .../src/components/UserSelection/index.tsx | 4 +- .../src/components/ViewportPortal/index.tsx | 4 +- .../container/EdgeRenderer/MarkerSymbols.tsx | 2 - .../src/container/EdgeRenderer/index.tsx | 16 +- .../src/container/FlowRenderer/index.tsx | 12 +- .../react/src/container/GraphView/index.tsx | 28 +- .../src/container/NodeRenderer/index.tsx | 14 +- .../NodeRenderer/useResizeObserver.ts | 2 +- packages/react/src/container/Pane/index.tsx | 370 +++++++++--------- .../react/src/container/ReactFlow/Wrapper.tsx | 8 +- .../react/src/container/ReactFlow/index.tsx | 15 +- .../react/src/container/Viewport/index.tsx | 2 +- .../react/src/container/ZoomPane/index.tsx | 8 +- packages/react/src/hooks/useVisibleEdgeIds.ts | 4 +- packages/react/src/hooks/useVisibleNodeIds.ts | 4 +- packages/react/src/index.ts | 14 +- 61 files changed, 386 insertions(+), 475 deletions(-) diff --git a/examples/react/src/examples/Stress/index.tsx b/examples/react/src/examples/Stress/index.tsx index 14b56b09..9020ddd6 100644 --- a/examples/react/src/examples/Stress/index.tsx +++ b/examples/react/src/examples/Stress/index.tsx @@ -11,7 +11,6 @@ import { EdgeChange, Controls, Background, - MiniMap, Panel, } from '@xyflow/react'; diff --git a/packages/react/src/additional-components/Background/Background.tsx b/packages/react/src/additional-components/Background/Background.tsx index 3e71d723..738ed699 100644 --- a/packages/react/src/additional-components/Background/Background.tsx +++ b/packages/react/src/additional-components/Background/Background.tsx @@ -3,10 +3,10 @@ import cc from 'classcat'; import { shallow } from 'zustand/shallow'; import { useStore } from '../../hooks/useStore'; -import { type ReactFlowState } from '../../types'; -import { BackgroundProps, BackgroundVariant } from './types'; import { DotPattern, LinePattern } from './Patterns'; import { containerStyle } from '../../styles/utils'; +import { type BackgroundProps, BackgroundVariant } from './types'; +import { type ReactFlowState } from '../../types'; const defaultSize = { [BackgroundVariant.Dots]: 1, @@ -16,7 +16,7 @@ const defaultSize = { const selector = (s: ReactFlowState) => ({ transform: s.transform, patternId: `pattern-${s.rfId}` }); -function Background({ +function BackgroundComponent({ id, variant = BackgroundVariant.Dots, // only used for dots and cross @@ -87,6 +87,6 @@ function Background({ ); } -Background.displayName = 'Background'; +BackgroundComponent.displayName = 'Background'; -export default memo(Background); +export const Background = memo(BackgroundComponent); diff --git a/packages/react/src/additional-components/Background/index.tsx b/packages/react/src/additional-components/Background/index.tsx index c0996179..ad5e1dea 100644 --- a/packages/react/src/additional-components/Background/index.tsx +++ b/packages/react/src/additional-components/Background/index.tsx @@ -1,2 +1,2 @@ -export { default as Background } from './Background'; -export * from './types'; +export { Background } from './Background'; +export { BackgroundVariant, type BackgroundProps } from './types'; diff --git a/packages/react/src/additional-components/Controls/ControlButton.tsx b/packages/react/src/additional-components/Controls/ControlButton.tsx index 9952fde0..744f46d4 100644 --- a/packages/react/src/additional-components/Controls/ControlButton.tsx +++ b/packages/react/src/additional-components/Controls/ControlButton.tsx @@ -1,14 +1,11 @@ -import type { FC, PropsWithChildren } from 'react'; import cc from 'classcat'; import type { ControlButtonProps } from './types'; -const ControlButton: FC> = ({ children, className, ...rest }) => ( - -); - -ControlButton.displayName = 'ControlButton'; - -export default ControlButton; +export function ControlButton({ children, className, ...rest }: ControlButtonProps) { + return ( + + ); +} diff --git a/packages/react/src/additional-components/Controls/Controls.tsx b/packages/react/src/additional-components/Controls/Controls.tsx index 0604186b..3a38790d 100644 --- a/packages/react/src/additional-components/Controls/Controls.tsx +++ b/packages/react/src/additional-components/Controls/Controls.tsx @@ -1,19 +1,18 @@ -import { memo, type FC, type PropsWithChildren } from 'react'; +import { memo } from 'react'; import cc from 'classcat'; import { shallow } from 'zustand/shallow'; import { useStore, useStoreApi } from '../../hooks/useStore'; import { useReactFlow } from '../../hooks/useReactFlow'; -import Panel from '../../components/Panel'; +import { Panel } from '../../components/Panel'; import { type ReactFlowState } from '../../types'; -import PlusIcon from './Icons/Plus'; -import MinusIcon from './Icons/Minus'; -import FitviewIcon from './Icons/FitView'; -import LockIcon from './Icons/Lock'; -import UnlockIcon from './Icons/Unlock'; -import ControlButton from './ControlButton'; - +import { PlusIcon } from './Icons/Plus'; +import { MinusIcon } from './Icons/Minus'; +import { FitViewIcon } from './Icons/FitView'; +import { LockIcon } from './Icons/Lock'; +import { UnlockIcon } from './Icons/Unlock'; +import { ControlButton } from './ControlButton'; import type { ControlProps } from './types'; const selector = (s: ReactFlowState) => ({ @@ -22,7 +21,7 @@ const selector = (s: ReactFlowState) => ({ maxZoomReached: s.transform[2] >= s.maxZoom, }); -const Controls: FC> = ({ +function ControlsComponent({ style, showZoom = true, showFitView = true, @@ -35,7 +34,7 @@ const Controls: FC> = ({ className, children, position = 'bottom-left', -}) => { +}: ControlProps) { const store = useStoreApi(); const { isInteractive, minZoomReached, maxZoomReached } = useStore(selector, shallow); const { zoomIn, zoomOut, fitView } = useReactFlow(); @@ -101,7 +100,7 @@ const Controls: FC> = ({ title="fit view" aria-label="fit view" > - + )} {showInteractive && ( @@ -117,8 +116,8 @@ const Controls: FC> = ({ {children} ); -}; +} -Controls.displayName = 'Controls'; +ControlsComponent.displayName = 'Controls'; -export default memo(Controls); +export const Controls = memo(ControlsComponent); diff --git a/packages/react/src/additional-components/Controls/Icons/FitView.tsx b/packages/react/src/additional-components/Controls/Icons/FitView.tsx index a5926730..cf67758e 100644 --- a/packages/react/src/additional-components/Controls/Icons/FitView.tsx +++ b/packages/react/src/additional-components/Controls/Icons/FitView.tsx @@ -1,9 +1,7 @@ -function FitViewIcon() { +export function FitViewIcon() { return ( ); } - -export default FitViewIcon; diff --git a/packages/react/src/additional-components/Controls/Icons/Lock.tsx b/packages/react/src/additional-components/Controls/Icons/Lock.tsx index 7f62ff65..f0c4b51c 100644 --- a/packages/react/src/additional-components/Controls/Icons/Lock.tsx +++ b/packages/react/src/additional-components/Controls/Icons/Lock.tsx @@ -1,9 +1,7 @@ -function LockIcon() { +export function LockIcon() { return ( ); } - -export default LockIcon; diff --git a/packages/react/src/additional-components/Controls/Icons/Minus.tsx b/packages/react/src/additional-components/Controls/Icons/Minus.tsx index 89a8b354..befbc12c 100644 --- a/packages/react/src/additional-components/Controls/Icons/Minus.tsx +++ b/packages/react/src/additional-components/Controls/Icons/Minus.tsx @@ -1,9 +1,7 @@ -function MinusIcon() { +export function MinusIcon() { return ( ); } - -export default MinusIcon; diff --git a/packages/react/src/additional-components/Controls/Icons/Plus.tsx b/packages/react/src/additional-components/Controls/Icons/Plus.tsx index eaa5efb8..b4ff4137 100644 --- a/packages/react/src/additional-components/Controls/Icons/Plus.tsx +++ b/packages/react/src/additional-components/Controls/Icons/Plus.tsx @@ -1,9 +1,7 @@ -function PlusIcon() { +export function PlusIcon() { return ( ); } - -export default PlusIcon; diff --git a/packages/react/src/additional-components/Controls/Icons/Unlock.tsx b/packages/react/src/additional-components/Controls/Icons/Unlock.tsx index ce113166..f68ae0b9 100644 --- a/packages/react/src/additional-components/Controls/Icons/Unlock.tsx +++ b/packages/react/src/additional-components/Controls/Icons/Unlock.tsx @@ -1,9 +1,7 @@ -function UnlockIcon() { +export function UnlockIcon() { return ( ); } - -export default UnlockIcon; diff --git a/packages/react/src/additional-components/Controls/index.tsx b/packages/react/src/additional-components/Controls/index.tsx index ac6f816c..7a5ce679 100644 --- a/packages/react/src/additional-components/Controls/index.tsx +++ b/packages/react/src/additional-components/Controls/index.tsx @@ -1,3 +1,3 @@ -export { default as Controls } from './Controls'; -export { default as ControlButton } from './ControlButton'; -export * from './types'; +export { Controls } from './Controls'; +export { ControlButton } from './ControlButton'; +export type { ControlProps, ControlButtonProps } from './types'; diff --git a/packages/react/src/additional-components/Controls/types.ts b/packages/react/src/additional-components/Controls/types.ts index 2d93540c..3833c50f 100644 --- a/packages/react/src/additional-components/Controls/types.ts +++ b/packages/react/src/additional-components/Controls/types.ts @@ -1,4 +1,4 @@ -import type { ButtonHTMLAttributes, HTMLAttributes } from 'react'; +import type { ButtonHTMLAttributes, HTMLAttributes, ReactNode } from 'react'; import type { PanelPosition } from '@xyflow/system'; import type { FitViewOptions } from '../../types'; @@ -13,6 +13,7 @@ export type ControlProps = HTMLAttributes & { onFitView?: () => void; onInteractiveChange?: (interactiveStatus: boolean) => void; position?: PanelPosition; + children?: ReactNode; }; export type ControlButtonProps = ButtonHTMLAttributes; diff --git a/packages/react/src/additional-components/MiniMap/MiniMap.tsx b/packages/react/src/additional-components/MiniMap/MiniMap.tsx index 8d1f0538..34a66fa1 100644 --- a/packages/react/src/additional-components/MiniMap/MiniMap.tsx +++ b/packages/react/src/additional-components/MiniMap/MiniMap.tsx @@ -6,11 +6,11 @@ import { shallow } from 'zustand/shallow'; import { getNodesBounds, getBoundsOfRects, XYMinimap, type Rect, type XYMinimapInstance } from '@xyflow/system'; import { useStore, useStoreApi } from '../../hooks/useStore'; -import Panel from '../../components/Panel'; +import { Panel } from '../../components/Panel'; import type { ReactFlowState } from '../../types'; -import type { MiniMapProps } from './types'; import MiniMapNodes from './MiniMapNodes'; +import type { MiniMapProps } from './types'; const defaultWidth = 200; const defaultHeight = 150; @@ -37,7 +37,7 @@ const selector = (s: ReactFlowState) => { const ARIA_LABEL_KEY = 'react-flow__minimap-desc'; -function MiniMap({ +function MiniMapComponent({ style, className, nodeStrokeColor, @@ -171,6 +171,6 @@ function MiniMap({ ); } -MiniMap.displayName = 'MiniMap'; +MiniMapComponent.displayName = 'MiniMap'; -export default memo(MiniMap); +export const MiniMap = memo(MiniMapComponent); diff --git a/packages/react/src/additional-components/MiniMap/MiniMapNode.tsx b/packages/react/src/additional-components/MiniMap/MiniMapNode.tsx index 76edf5e6..ec9fd725 100644 --- a/packages/react/src/additional-components/MiniMap/MiniMapNode.tsx +++ b/packages/react/src/additional-components/MiniMap/MiniMapNode.tsx @@ -3,7 +3,7 @@ import cc from 'classcat'; import type { MiniMapNodeProps } from './types'; -function MiniMapNode({ +function MiniMapNodeComponent({ id, x, y, @@ -42,4 +42,4 @@ function MiniMapNode({ ); } -export default memo(MiniMapNode); +export const MiniMapNode = memo(MiniMapNodeComponent); diff --git a/packages/react/src/additional-components/MiniMap/MiniMapNodes.tsx b/packages/react/src/additional-components/MiniMap/MiniMapNodes.tsx index 71cce50b..63851aad 100644 --- a/packages/react/src/additional-components/MiniMap/MiniMapNodes.tsx +++ b/packages/react/src/additional-components/MiniMap/MiniMapNodes.tsx @@ -5,8 +5,8 @@ import { NodeOrigin, getNodePositionWithOrigin } from '@xyflow/system'; import { shallow } from 'zustand/shallow'; import { useStore } from '../../hooks/useStore'; +import { MiniMapNode } from './MiniMapNode'; import type { ReactFlowState } from '../../types'; -import MiniMapNode from './MiniMapNode'; import type { MiniMapNodes as MiniMapNodesProps, GetMiniMapNodeAttribute, MiniMapNodeProps } from './types'; declare const window: any; diff --git a/packages/react/src/additional-components/MiniMap/index.tsx b/packages/react/src/additional-components/MiniMap/index.tsx index 7b91e95d..f08cb9de 100644 --- a/packages/react/src/additional-components/MiniMap/index.tsx +++ b/packages/react/src/additional-components/MiniMap/index.tsx @@ -1,2 +1,2 @@ -export { default as MiniMap } from './MiniMap'; +export { MiniMap } from './MiniMap'; export * from './types'; diff --git a/packages/react/src/additional-components/NodeToolbar/NodeToolbar.tsx b/packages/react/src/additional-components/NodeToolbar/NodeToolbar.tsx index 6f4ad13c..a681d6f3 100644 --- a/packages/react/src/additional-components/NodeToolbar/NodeToolbar.tsx +++ b/packages/react/src/additional-components/NodeToolbar/NodeToolbar.tsx @@ -6,8 +6,8 @@ import { getNodesBounds, Rect, Position, internalsSymbol, getNodeToolbarTransfor import { Node, ReactFlowState } from '../../types'; import { useStore } from '../../hooks/useStore'; import { useNodeId } from '../../contexts/NodeIdContext'; -import NodeToolbarPortal from './NodeToolbarPortal'; -import { NodeToolbarProps } from './types'; +import { NodeToolbarPortal } from './NodeToolbarPortal'; +import type { NodeToolbarProps } from './types'; const nodeEqualityFn = (a?: Node, b?: Node) => a?.computed?.positionAbsolute?.x !== b?.computed?.positionAbsolute?.x || @@ -35,7 +35,7 @@ const storeSelector = (state: ReactFlowState) => ({ selectedNodesCount: state.nodes.filter((node) => node.selected).length, }); -function NodeToolbar({ +export function NodeToolbar({ nodeId, children, className, @@ -96,5 +96,3 @@ function NodeToolbar({ ); } - -export default NodeToolbar; diff --git a/packages/react/src/additional-components/NodeToolbar/NodeToolbarPortal.tsx b/packages/react/src/additional-components/NodeToolbar/NodeToolbarPortal.tsx index 4b8d8d02..c7301c77 100644 --- a/packages/react/src/additional-components/NodeToolbar/NodeToolbarPortal.tsx +++ b/packages/react/src/additional-components/NodeToolbar/NodeToolbarPortal.tsx @@ -6,7 +6,7 @@ import { useStore } from '../../hooks/useStore'; const selector = (state: ReactFlowState) => state.domNode?.querySelector('.react-flow__renderer'); -function NodeToolbarPortal({ children }: { children: ReactNode }) { +export function NodeToolbarPortal({ children }: { children: ReactNode }) { const wrapperRef = useStore(selector); if (!wrapperRef) { @@ -15,5 +15,3 @@ function NodeToolbarPortal({ children }: { children: ReactNode }) { return createPortal(children, wrapperRef); } - -export default NodeToolbarPortal; diff --git a/packages/react/src/additional-components/NodeToolbar/index.tsx b/packages/react/src/additional-components/NodeToolbar/index.tsx index 3cded08b..d42a83c5 100644 --- a/packages/react/src/additional-components/NodeToolbar/index.tsx +++ b/packages/react/src/additional-components/NodeToolbar/index.tsx @@ -1,2 +1,2 @@ -export { default as NodeToolbar } from './NodeToolbar'; -export * from './types'; +export { NodeToolbar } from './NodeToolbar'; +export type { NodeToolbarProps } from './types'; diff --git a/packages/react/src/components/A11yDescriptions/index.tsx b/packages/react/src/components/A11yDescriptions/index.tsx index a92f27ac..51b4a939 100644 --- a/packages/react/src/components/A11yDescriptions/index.tsx +++ b/packages/react/src/components/A11yDescriptions/index.tsx @@ -32,7 +32,7 @@ function AriaLiveMessage({ rfId }: { rfId: string }) { ); } -function A11yDescriptions({ rfId, disableKeyboardA11y }: { rfId: string; disableKeyboardA11y: boolean }) { +export function A11yDescriptions({ rfId, disableKeyboardA11y }: { rfId: string; disableKeyboardA11y: boolean }) { return ( <>
@@ -47,5 +47,3 @@ function A11yDescriptions({ rfId, disableKeyboardA11y }: { rfId: string; disable ); } - -export default A11yDescriptions; diff --git a/packages/react/src/components/Attribution/index.tsx b/packages/react/src/components/Attribution/index.tsx index 8c2aa484..eb69bd13 100644 --- a/packages/react/src/components/Attribution/index.tsx +++ b/packages/react/src/components/Attribution/index.tsx @@ -1,13 +1,13 @@ import type { PanelPosition, ProOptions } from '@xyflow/system'; -import Panel from '../Panel'; +import { Panel } from '../Panel'; type AttributionProps = { proOptions?: ProOptions; position?: PanelPosition; }; -function Attribution({ proOptions, position = 'bottom-right' }: AttributionProps) { +export function Attribution({ proOptions, position = 'bottom-right' }: AttributionProps) { if (proOptions?.hideAttribution) { return null; } @@ -24,5 +24,3 @@ function Attribution({ proOptions, position = 'bottom-right' }: AttributionProps ); } - -export default Attribution; diff --git a/packages/react/src/components/ConnectionLine/index.tsx b/packages/react/src/components/ConnectionLine/index.tsx index 143ec6ef..4fe2ca76 100644 --- a/packages/react/src/components/ConnectionLine/index.tsx +++ b/packages/react/src/components/ConnectionLine/index.tsx @@ -142,7 +142,7 @@ const selector = (s: ReactFlowState) => ({ height: s.height, }); -function ConnectionLineWrapper({ containerStyle, style, type, component }: ConnectionLineWrapperProps) { +export function ConnectionLineWrapper({ containerStyle, style, type, component }: ConnectionLineWrapperProps) { const { nodeId, handleType, nodesConnectable, width, height, connectionStatus } = useStore(selector, shallow); const isValid = !!(nodeId && handleType && width && nodesConnectable); @@ -170,5 +170,3 @@ function ConnectionLineWrapper({ containerStyle, style, type, component }: Conne ); } - -export default ConnectionLineWrapper; diff --git a/packages/react/src/components/EdgeLabelRenderer/index.tsx b/packages/react/src/components/EdgeLabelRenderer/index.tsx index 85c94291..c66b70ae 100644 --- a/packages/react/src/components/EdgeLabelRenderer/index.tsx +++ b/packages/react/src/components/EdgeLabelRenderer/index.tsx @@ -6,7 +6,7 @@ import type { ReactFlowState } from '../../types'; const selector = (s: ReactFlowState) => s.domNode?.querySelector('.react-flow__edgelabel-renderer'); -function EdgeLabelRenderer({ children }: { children: ReactNode }) { +export function EdgeLabelRenderer({ children }: { children: ReactNode }) { const edgeLabelRenderer = useStore(selector); if (!edgeLabelRenderer) { @@ -15,5 +15,3 @@ function EdgeLabelRenderer({ children }: { children: ReactNode }) { return createPortal(children, edgeLabelRenderer); } - -export default EdgeLabelRenderer; diff --git a/packages/react/src/components/EdgeWrapper/EdgeUpdateAnchors.tsx b/packages/react/src/components/EdgeWrapper/EdgeUpdateAnchors.tsx index 57c81724..3e3f3bf7 100644 --- a/packages/react/src/components/EdgeWrapper/EdgeUpdateAnchors.tsx +++ b/packages/react/src/components/EdgeWrapper/EdgeUpdateAnchors.tsx @@ -18,7 +18,7 @@ type EdgeUpdateAnchorsProps = { setUpdating: (updating: boolean) => void; } & EdgePosition; -function EdgeUpdateAnchors({ +export function EdgeUpdateAnchors({ isUpdatable, edgeUpdaterRadius, edge, @@ -133,5 +133,3 @@ function EdgeUpdateAnchors({ ); } - -export default EdgeUpdateAnchors; diff --git a/packages/react/src/components/EdgeWrapper/index.tsx b/packages/react/src/components/EdgeWrapper/index.tsx index 9d96948c..cb9b9c8b 100644 --- a/packages/react/src/components/EdgeWrapper/index.tsx +++ b/packages/react/src/components/EdgeWrapper/index.tsx @@ -1,4 +1,4 @@ -import { memo, useState, useMemo, useRef, type KeyboardEvent, useCallback } from 'react'; +import { useState, useMemo, useRef, type KeyboardEvent, useCallback } from 'react'; import cc from 'classcat'; import { shallow } from 'zustand/shallow'; import { @@ -11,11 +11,11 @@ import { import { useStoreApi, useStore } from '../../hooks/useStore'; import { ARIA_EDGE_DESC_KEY } from '../A11yDescriptions'; -import type { EdgeWrapperProps } from '../../types'; import { builtinEdgeTypes, nullPosition } from './utils'; -import EdgeUpdateAnchors from './EdgeUpdateAnchors'; +import { EdgeUpdateAnchors } from './EdgeUpdateAnchors'; +import type { EdgeWrapperProps } from '../../types'; -function EdgeWrapper({ +export function EdgeWrapper({ id, edgesFocusable, edgesUpdatable, @@ -258,7 +258,3 @@ function EdgeWrapper({ ); } - -EdgeWrapper.displayName = 'EdgeWrapper'; - -export default memo(EdgeWrapper); diff --git a/packages/react/src/components/Edges/BaseEdge.tsx b/packages/react/src/components/Edges/BaseEdge.tsx index ae14b472..fab06220 100644 --- a/packages/react/src/components/Edges/BaseEdge.tsx +++ b/packages/react/src/components/Edges/BaseEdge.tsx @@ -1,10 +1,10 @@ import { isNumeric } from '@xyflow/system'; +import cc from 'classcat'; +import { EdgeText } from './EdgeText'; import type { BaseEdgeProps } from '../../types'; -import EdgeText from './EdgeText'; -import classcat from 'classcat'; -const BaseEdge = ({ +export function BaseEdge({ id, path, labelX, @@ -20,7 +20,7 @@ const BaseEdge = ({ markerStart, className, interactionWidth = 20, -}: BaseEdgeProps) => { +}: BaseEdgeProps) { return ( <> @@ -55,8 +55,4 @@ const BaseEdge = ({ ) : null} ); -}; - -BaseEdge.displayName = 'BaseEdge'; - -export default BaseEdge; +} diff --git a/packages/react/src/components/Edges/BezierEdge.tsx b/packages/react/src/components/Edges/BezierEdge.tsx index 2a0b54a2..482f1fd8 100644 --- a/packages/react/src/components/Edges/BezierEdge.tsx +++ b/packages/react/src/components/Edges/BezierEdge.tsx @@ -1,7 +1,7 @@ import { memo } from 'react'; import { Position, getBezierPath } from '@xyflow/system'; -import BaseEdge from './BaseEdge'; +import { BaseEdge } from './BaseEdge'; import type { BezierEdgeProps } from '../../types'; function createBezierEdge(params: { isInternal: boolean }) { diff --git a/packages/react/src/components/Edges/EdgeAnchor.tsx b/packages/react/src/components/Edges/EdgeAnchor.tsx index 575023b3..a975eaf5 100644 --- a/packages/react/src/components/Edges/EdgeAnchor.tsx +++ b/packages/react/src/components/Edges/EdgeAnchor.tsx @@ -1,4 +1,4 @@ -import type { FC, MouseEvent as ReactMouseEvent, SVGAttributes } from 'react'; +import type { MouseEvent as ReactMouseEvent, SVGAttributes } from 'react'; import cc from 'classcat'; import { Position } from '@xyflow/system'; @@ -27,7 +27,7 @@ export interface EdgeAnchorProps extends SVGAttributes { const EdgeUpdaterClassName = 'react-flow__edgeupdater'; -export const EdgeAnchor: FC = ({ +export function EdgeAnchor({ position, centerX, centerY, @@ -36,16 +36,18 @@ export const EdgeAnchor: FC = ({ onMouseEnter, onMouseOut, type, -}: EdgeAnchorProps) => ( - -); +}: EdgeAnchorProps) { + return ( + + ); +} diff --git a/packages/react/src/components/Edges/EdgeText.tsx b/packages/react/src/components/Edges/EdgeText.tsx index 8cc5c388..2e671895 100644 --- a/packages/react/src/components/Edges/EdgeText.tsx +++ b/packages/react/src/components/Edges/EdgeText.tsx @@ -1,10 +1,10 @@ -import { memo, useState, type FC, type PropsWithChildren, useCallback } from 'react'; +import { memo, useState, useCallback } from 'react'; import cc from 'classcat'; import type { Rect } from '@xyflow/system'; import type { EdgeTextProps } from '../../types'; -const EdgeText: FC> = ({ +function EdgeTextComponent({ x, y, label, @@ -16,7 +16,7 @@ const EdgeText: FC> = ({ children, className, ...rest -}) => { +}: EdgeTextProps) { const [edgeTextBbox, setEdgeTextBbox] = useState({ x: 1, y: 0, width: 0, height: 0 }); const edgeTextClasses = cc(['react-flow__edge-textwrapper', className]); @@ -68,5 +68,6 @@ const EdgeText: FC> = ({ {children} ); -}; -export default memo(EdgeText); +} + +export const EdgeText = memo(EdgeTextComponent); diff --git a/packages/react/src/components/Edges/SimpleBezierEdge.tsx b/packages/react/src/components/Edges/SimpleBezierEdge.tsx index 09c7a752..b3378c48 100644 --- a/packages/react/src/components/Edges/SimpleBezierEdge.tsx +++ b/packages/react/src/components/Edges/SimpleBezierEdge.tsx @@ -1,7 +1,7 @@ import { memo } from 'react'; import { Position, getBezierEdgeCenter } from '@xyflow/system'; -import BaseEdge from './BaseEdge'; +import { BaseEdge } from './BaseEdge'; import type { SimpleBezierEdgeProps } from '../../types'; export interface GetSimpleBezierPathParams { diff --git a/packages/react/src/components/Edges/SmoothStepEdge.tsx b/packages/react/src/components/Edges/SmoothStepEdge.tsx index 8eb10d89..1f6bcfd1 100644 --- a/packages/react/src/components/Edges/SmoothStepEdge.tsx +++ b/packages/react/src/components/Edges/SmoothStepEdge.tsx @@ -1,7 +1,7 @@ import { memo } from 'react'; import { Position, getSmoothStepPath } from '@xyflow/system'; -import BaseEdge from './BaseEdge'; +import { BaseEdge } from './BaseEdge'; import type { SmoothStepEdgeProps } from '../../types'; function createSmoothStepEdge(params: { isInternal: boolean }) { diff --git a/packages/react/src/components/Edges/StraightEdge.tsx b/packages/react/src/components/Edges/StraightEdge.tsx index 5a3c824d..53d1ac29 100644 --- a/packages/react/src/components/Edges/StraightEdge.tsx +++ b/packages/react/src/components/Edges/StraightEdge.tsx @@ -1,7 +1,7 @@ import { memo } from 'react'; import { getStraightPath } from '@xyflow/system'; -import BaseEdge from './BaseEdge'; +import { BaseEdge } from './BaseEdge'; import type { StraightEdgeProps } from '../../types'; function createStraightEdge(params: { isInternal: boolean }) { diff --git a/packages/react/src/components/Handle/index.tsx b/packages/react/src/components/Handle/index.tsx index a2c0101f..41bf492c 100644 --- a/packages/react/src/components/Handle/index.tsx +++ b/packages/react/src/components/Handle/index.tsx @@ -47,7 +47,7 @@ const connectingSelector = }; }; -const Handle = forwardRef( +const HandleComponent = forwardRef( ( { type = 'source', @@ -216,6 +216,6 @@ const Handle = forwardRef( } ); -Handle.displayName = 'Handle'; +HandleComponent.displayName = 'Handle'; -export default memo(Handle); +export const Handle = memo(HandleComponent); diff --git a/packages/react/src/components/NodeWrapper/index.tsx b/packages/react/src/components/NodeWrapper/index.tsx index 461abf5a..64b5ac66 100644 --- a/packages/react/src/components/NodeWrapper/index.tsx +++ b/packages/react/src/components/NodeWrapper/index.tsx @@ -1,4 +1,4 @@ -import { useEffect, useRef, memo, type MouseEvent, type KeyboardEvent } from 'react'; +import { useEffect, useRef, type MouseEvent, type KeyboardEvent } from 'react'; import cc from 'classcat'; import { shallow } from 'zustand/shallow'; import { @@ -19,7 +19,7 @@ import { handleNodeClick } from '../Nodes/utils'; import { arrowKeyDiffs, builtinNodeTypes } from './utils'; import type { NodeWrapperProps } from '../../types'; -const NodeWrapper = ({ +export function NodeWrapper({ id, onClick, onMouseEnter, @@ -40,7 +40,7 @@ const NodeWrapper = ({ nodeExtent, nodeOrigin, onError, -}: NodeWrapperProps) => { +}: NodeWrapperProps) { const { node, positionAbsoluteX, positionAbsoluteY, zIndex, isParent } = useStore((s) => { const node = s.nodeLookup.get(id)!; @@ -257,8 +257,4 @@ const NodeWrapper = ({
); -}; - -NodeWrapper.displayName = 'NodeWrapper'; - -export default memo(NodeWrapper); +} diff --git a/packages/react/src/components/NodeWrapper/utils.tsx b/packages/react/src/components/NodeWrapper/utils.tsx index 6ae5f994..5dd73964 100644 --- a/packages/react/src/components/NodeWrapper/utils.tsx +++ b/packages/react/src/components/NodeWrapper/utils.tsx @@ -1,10 +1,10 @@ import type { ComponentType } from 'react'; import type { NodeProps, XYPosition } from '@xyflow/system'; -import InputNode from '../Nodes/InputNode'; -import DefaultNode from '../Nodes/DefaultNode'; -import GroupNode from '../Nodes/GroupNode'; -import OutputNode from '../Nodes/OutputNode'; +import { InputNode } from '../Nodes/InputNode'; +import { DefaultNode } from '../Nodes/DefaultNode'; +import { GroupNode } from '../Nodes/GroupNode'; +import { OutputNode } from '../Nodes/OutputNode'; import type { NodeTypes } from '../../types'; export const arrowKeyDiffs: Record = { diff --git a/packages/react/src/components/Nodes/DefaultNode.tsx b/packages/react/src/components/Nodes/DefaultNode.tsx index 611e6165..132044c5 100644 --- a/packages/react/src/components/Nodes/DefaultNode.tsx +++ b/packages/react/src/components/Nodes/DefaultNode.tsx @@ -1,14 +1,13 @@ -import { memo } from 'react'; import { Position, type NodeProps } from '@xyflow/system'; -import Handle from '../../components/Handle'; +import { Handle } from '../../components/Handle'; -const DefaultNode = ({ +export function DefaultNode({ data, isConnectable, targetPosition = Position.Top, sourcePosition = Position.Bottom, -}: NodeProps) => { +}: NodeProps) { return ( <> @@ -16,8 +15,4 @@ const DefaultNode = ({ ); -}; - -DefaultNode.displayName = 'DefaultNode'; - -export default memo(DefaultNode); +} diff --git a/packages/react/src/components/Nodes/GroupNode.tsx b/packages/react/src/components/Nodes/GroupNode.tsx index cea42e43..a8a1ad14 100644 --- a/packages/react/src/components/Nodes/GroupNode.tsx +++ b/packages/react/src/components/Nodes/GroupNode.tsx @@ -1,5 +1,3 @@ -const GroupNode = () => null; - -GroupNode.displayName = 'GroupNode'; - -export default GroupNode; +export function GroupNode() { + return null; +} diff --git a/packages/react/src/components/Nodes/InputNode.tsx b/packages/react/src/components/Nodes/InputNode.tsx index 354da2ce..e4b9da9b 100644 --- a/packages/react/src/components/Nodes/InputNode.tsx +++ b/packages/react/src/components/Nodes/InputNode.tsx @@ -1,15 +1,12 @@ -import { memo } from 'react'; import { Position, type NodeProps } from '@xyflow/system'; -import Handle from '../../components/Handle'; +import { Handle } from '../../components/Handle'; -const InputNode = ({ data, isConnectable, sourcePosition = Position.Bottom }: NodeProps) => ( - <> - {data?.label} - - -); - -InputNode.displayName = 'InputNode'; - -export default memo(InputNode); +export function InputNode({ data, isConnectable, sourcePosition = Position.Bottom }: NodeProps) { + return ( + <> + {data?.label} + + + ); +} diff --git a/packages/react/src/components/Nodes/OutputNode.tsx b/packages/react/src/components/Nodes/OutputNode.tsx index 8d52ba1e..64af091c 100644 --- a/packages/react/src/components/Nodes/OutputNode.tsx +++ b/packages/react/src/components/Nodes/OutputNode.tsx @@ -1,15 +1,12 @@ -import { memo } from 'react'; import { Position, type NodeProps } from '@xyflow/system'; -import Handle from '../../components/Handle'; +import { Handle } from '../../components/Handle'; -const OutputNode = ({ data, isConnectable, targetPosition = Position.Top }: NodeProps) => ( - <> - - {data?.label} - -); - -OutputNode.displayName = 'OutputNode'; - -export default memo(OutputNode); +export function OutputNode({ data, isConnectable, targetPosition = Position.Top }: NodeProps) { + return ( + <> + + {data?.label} + + ); +} diff --git a/packages/react/src/components/Nodes/utils.ts b/packages/react/src/components/Nodes/utils.ts index 26b1f246..81939bbc 100644 --- a/packages/react/src/components/Nodes/utils.ts +++ b/packages/react/src/components/Nodes/utils.ts @@ -1,8 +1,8 @@ import type { RefObject } from 'react'; import type { StoreApi } from 'zustand'; +import { errorMessages } from '@xyflow/system'; import type { ReactFlowState } from '../../types'; -import { errorMessages } from '@xyflow/system'; // this handler is called by // 1. the click handler when node is not draggable or selectNodesOnDrag = false diff --git a/packages/react/src/components/NodesSelection/index.tsx b/packages/react/src/components/NodesSelection/index.tsx index c485d65c..f8aeb77c 100644 --- a/packages/react/src/components/NodesSelection/index.tsx +++ b/packages/react/src/components/NodesSelection/index.tsx @@ -3,7 +3,7 @@ * made a selection with on or several nodes */ -import { memo, useRef, useEffect, type MouseEvent, type KeyboardEvent } from 'react'; +import { useRef, useEffect, type MouseEvent, type KeyboardEvent } from 'react'; import cc from 'classcat'; import { shallow } from 'zustand/shallow'; import { getNodesBounds } from '@xyflow/system'; @@ -32,7 +32,7 @@ const selector = (s: ReactFlowState) => { }; }; -function NodesSelection({ onSelectionContextMenu, noPanClassName, disableKeyboardA11y }: NodesSelectionProps) { +export function NodesSelection({ onSelectionContextMenu, noPanClassName, disableKeyboardA11y }: NodesSelectionProps) { const store = useStoreApi(); const { width, height, transformString, userSelectionActive } = useStore(selector, shallow); const updatePositions = useUpdateNodePositions(); @@ -93,5 +93,3 @@ function NodesSelection({ onSelectionContextMenu, noPanClassName, disableKeyboar
); } - -export default memo(NodesSelection); diff --git a/packages/react/src/components/Panel/index.tsx b/packages/react/src/components/Panel/index.tsx index 7bcf6f97..cde20716 100644 --- a/packages/react/src/components/Panel/index.tsx +++ b/packages/react/src/components/Panel/index.tsx @@ -6,13 +6,13 @@ import { useStore } from '../../hooks/useStore'; import type { ReactFlowState } from '../../types'; export type PanelProps = HTMLAttributes & { - position: PanelPosition; + position?: PanelPosition; children: ReactNode; }; const selector = (s: ReactFlowState) => (s.userSelectionActive ? 'none' : 'all'); -function Panel({ position, children, className, style, ...rest }: PanelProps) { +export function Panel({ position = 'top-left', children, className, style, ...rest }: PanelProps) { const pointerEvents = useStore(selector); const positionClasses = `${position}`.split('-'); @@ -26,5 +26,3 @@ function Panel({ position, children, className, style, ...rest }: PanelProps) {
); } - -export default Panel; diff --git a/packages/react/src/components/ReactFlowProvider/index.tsx b/packages/react/src/components/ReactFlowProvider/index.tsx index 07f011ca..34999c6f 100644 --- a/packages/react/src/components/ReactFlowProvider/index.tsx +++ b/packages/react/src/components/ReactFlowProvider/index.tsx @@ -6,7 +6,7 @@ import { Provider } from '../../contexts/RFStoreContext'; import { createRFStore } from '../../store'; import type { ReactFlowState, Node, Edge } from '../../types'; -function ReactFlowProvider({ +export function ReactFlowProvider({ children, initialNodes, initialEdges, @@ -35,7 +35,3 @@ function ReactFlowProvider({ return {children}; } - -ReactFlowProvider.displayName = 'ReactFlowProvider'; - -export default ReactFlowProvider; diff --git a/packages/react/src/components/SelectionListener/index.tsx b/packages/react/src/components/SelectionListener/index.tsx index 4ef1e130..0a3fa5a9 100644 --- a/packages/react/src/components/SelectionListener/index.tsx +++ b/packages/react/src/components/SelectionListener/index.tsx @@ -4,7 +4,7 @@ * or is using the useOnSelectionChange hook. * @TODO: Now that we have the onNodesChange and on EdgesChange listeners, do we still need this component? */ -import { memo, useEffect } from 'react'; +import { useEffect } from 'react'; import { shallow } from 'zustand/shallow'; import { useStore, useStoreApi } from '../../hooks/useStore'; @@ -30,7 +30,7 @@ function areEqual(a: SelectorSlice, b: SelectorSlice) { ); } -const SelectionListener = memo(({ onSelectionChange }: SelectionListenerProps) => { +function SelectionListenerInner({ onSelectionChange }: SelectionListenerProps) { const store = useStoreApi(); const { selectedNodes, selectedEdges } = useStore(selector, areEqual); @@ -42,20 +42,16 @@ const SelectionListener = memo(({ onSelectionChange }: SelectionListenerProps) = }, [selectedNodes, selectedEdges, onSelectionChange]); return null; -}); - -SelectionListener.displayName = 'SelectionListener'; +} const changeSelector = (s: ReactFlowState) => !!s.onSelectionChangeHandlers; -function Wrapper({ onSelectionChange }: SelectionListenerProps) { +export function SelectionListener({ onSelectionChange }: SelectionListenerProps) { const storeHasSelectionChangeHandlers = useStore(changeSelector); if (onSelectionChange || storeHasSelectionChangeHandlers) { - return ; + return ; } return null; } - -export default Wrapper; diff --git a/packages/react/src/components/StoreUpdater/index.tsx b/packages/react/src/components/StoreUpdater/index.tsx index 344c718f..3a12594c 100644 --- a/packages/react/src/components/StoreUpdater/index.tsx +++ b/packages/react/src/components/StoreUpdater/index.tsx @@ -84,7 +84,7 @@ const selector = (s: ReactFlowState) => ({ reset: s.reset, }); -const StoreUpdater = (props: StoreUpdaterProps) => { +export function StoreUpdater(props: StoreUpdaterProps) { const { setNodes, setEdges, @@ -149,6 +149,4 @@ const StoreUpdater = (props: StoreUpdaterProps) => { ); return null; -}; - -export default StoreUpdater; +} diff --git a/packages/react/src/components/UserSelection/index.tsx b/packages/react/src/components/UserSelection/index.tsx index 00bbcd63..45a4e228 100644 --- a/packages/react/src/components/UserSelection/index.tsx +++ b/packages/react/src/components/UserSelection/index.tsx @@ -8,7 +8,7 @@ const selector = (s: ReactFlowState) => ({ userSelectionRect: s.userSelectionRect, }); -function UserSelection() { +export function UserSelection() { const { userSelectionActive, userSelectionRect } = useStore(selector, shallow); const isActive = userSelectionActive && userSelectionRect; @@ -27,5 +27,3 @@ function UserSelection() { /> ); } - -export default UserSelection; diff --git a/packages/react/src/components/ViewportPortal/index.tsx b/packages/react/src/components/ViewportPortal/index.tsx index 4195a608..c1b9b406 100644 --- a/packages/react/src/components/ViewportPortal/index.tsx +++ b/packages/react/src/components/ViewportPortal/index.tsx @@ -6,7 +6,7 @@ import type { ReactFlowState } from '../../types'; const selector = (s: ReactFlowState) => s.domNode?.querySelector('.react-flow__viewport-portal'); -function ViewportPortal({ children }: { children: ReactNode }) { +export function ViewportPortal({ children }: { children: ReactNode }) { const viewPortalDiv = useStore(selector); if (!viewPortalDiv) { @@ -15,5 +15,3 @@ function ViewportPortal({ children }: { children: ReactNode }) { return createPortal(children, viewPortalDiv); } - -export default ViewportPortal; diff --git a/packages/react/src/container/EdgeRenderer/MarkerSymbols.tsx b/packages/react/src/container/EdgeRenderer/MarkerSymbols.tsx index 13ebfd92..6b59d04e 100644 --- a/packages/react/src/container/EdgeRenderer/MarkerSymbols.tsx +++ b/packages/react/src/container/EdgeRenderer/MarkerSymbols.tsx @@ -57,5 +57,3 @@ export function useMarkerSymbol(type: MarkerType) { return symbol; } - -export default MarkerSymbols; diff --git a/packages/react/src/container/EdgeRenderer/index.tsx b/packages/react/src/container/EdgeRenderer/index.tsx index ef78ed80..5fdaa1af 100644 --- a/packages/react/src/container/EdgeRenderer/index.tsx +++ b/packages/react/src/container/EdgeRenderer/index.tsx @@ -2,10 +2,10 @@ import { memo, ReactNode } from 'react'; import { shallow } from 'zustand/shallow'; import { useStore } from '../../hooks/useStore'; -import useVisibleEdgeIds from '../../hooks/useVisibleEdgeIds'; +import { useVisibleEdgeIds } from '../../hooks/useVisibleEdgeIds'; import MarkerDefinitions from './MarkerDefinitions'; import { GraphViewProps } from '../GraphView'; -import EdgeWrapper from '../../components/EdgeWrapper'; +import { EdgeWrapper } from '../../components/EdgeWrapper'; import type { ReactFlowState } from '../../types'; type EdgeRendererProps = Pick< @@ -40,7 +40,7 @@ const selector = (s: ReactFlowState) => ({ onError: s.onError, }); -const EdgeRenderer = ({ +function EdgeRendererComponent({ defaultMarkerColor, onlyRenderVisibleElements, rfId, @@ -56,8 +56,7 @@ const EdgeRenderer = ({ onEdgeDoubleClick, onEdgeUpdateStart, onEdgeUpdateEnd, - children, -}: EdgeRendererProps) => { +}: EdgeRendererProps) { const { edgesFocusable, edgesUpdatable, elementsSelectable, onError } = useStore(selector, shallow); const edgeIds = useVisibleEdgeIds(onlyRenderVisibleElements); @@ -90,11 +89,10 @@ const EdgeRenderer = ({ /> ); })} - {children} ); -}; +} -EdgeRenderer.displayName = 'EdgeRenderer'; +EdgeRendererComponent.displayName = 'EdgeRenderer'; -export default memo(EdgeRenderer); +export const EdgeRenderer = memo(EdgeRendererComponent); diff --git a/packages/react/src/container/FlowRenderer/index.tsx b/packages/react/src/container/FlowRenderer/index.tsx index 04604ec9..06d6fab6 100644 --- a/packages/react/src/container/FlowRenderer/index.tsx +++ b/packages/react/src/container/FlowRenderer/index.tsx @@ -4,9 +4,9 @@ import { useStore } from '../../hooks/useStore'; import { useGlobalKeyHandler } from '../../hooks/useGlobalKeyHandler'; import { useKeyPress } from '../../hooks/useKeyPress'; import { GraphViewProps } from '../GraphView'; -import ZoomPane from '../ZoomPane'; -import Pane from '../Pane'; -import NodesSelection from '../../components/NodesSelection'; +import { ZoomPane } from '../ZoomPane'; +import { Pane } from '../Pane'; +import { NodesSelection } from '../../components/NodesSelection'; import type { ReactFlowState } from '../../types'; export type FlowRendererProps = Omit< @@ -30,7 +30,7 @@ export type FlowRendererProps = Omit< const selector = (s: ReactFlowState) => s.nodesSelectionActive; -const FlowRenderer = ({ +const FlowRendererComponent = ({ children, onPaneClick, onPaneMouseEnter, @@ -125,6 +125,6 @@ const FlowRenderer = ({ ); }; -FlowRenderer.displayName = 'FlowRenderer'; +FlowRendererComponent.displayName = 'FlowRenderer'; -export default memo(FlowRenderer); +export const FlowRenderer = memo(FlowRendererComponent); diff --git a/packages/react/src/container/GraphView/index.tsx b/packages/react/src/container/GraphView/index.tsx index ae67d6b4..fd7ac277 100644 --- a/packages/react/src/container/GraphView/index.tsx +++ b/packages/react/src/container/GraphView/index.tsx @@ -1,14 +1,14 @@ import { memo } from 'react'; -import FlowRenderer from '../FlowRenderer'; -import NodeRenderer from '../NodeRenderer'; -import EdgeRenderer from '../EdgeRenderer'; -import ViewportWrapper from '../Viewport'; +import { FlowRenderer } from '../FlowRenderer'; +import { NodeRenderer } from '../NodeRenderer'; +import { EdgeRenderer } from '../EdgeRenderer'; +import { Viewport } from '../Viewport'; import { useOnInitHandler } from '../../hooks/useOnInitHandler'; import { useViewportSync } from '../../hooks/useViewportSync'; -import ConnectionLine from '../../components/ConnectionLine'; -import type { ReactFlowProps } from '../../types'; +import { ConnectionLineWrapper } from '../../components/ConnectionLine'; import { useNodeOrEdgeTypesWarning } from './useNodeOrEdgeTypesWarning'; +import type { ReactFlowProps } from '../../types'; export type GraphViewProps = Omit< ReactFlowProps, @@ -38,7 +38,7 @@ export type GraphViewProps = Omit< rfId: string; }; -const GraphView = ({ +function GraphViewComponent({ nodeTypes, edgeTypes, onInit, @@ -102,7 +102,7 @@ const GraphView = ({ rfId, viewport, onViewportChange, -}: GraphViewProps) => { +}: GraphViewProps) { useNodeOrEdgeTypesWarning(nodeTypes); useNodeOrEdgeTypesWarning(edgeTypes); @@ -147,7 +147,7 @@ const GraphView = ({ onViewportChange={onViewportChange} isControlledViewport={!!viewport} > - + - - + ); -}; +} -GraphView.displayName = 'GraphView'; +GraphViewComponent.displayName = 'GraphView'; -export default memo(GraphView); +export const GraphView = memo(GraphViewComponent); diff --git a/packages/react/src/container/NodeRenderer/index.tsx b/packages/react/src/container/NodeRenderer/index.tsx index e61b8bc5..11cab66f 100644 --- a/packages/react/src/container/NodeRenderer/index.tsx +++ b/packages/react/src/container/NodeRenderer/index.tsx @@ -1,13 +1,13 @@ import { memo } from 'react'; import { shallow } from 'zustand/shallow'; -import useVisibleNodesIds from '../../hooks/useVisibleNodeIds'; +import { useVisibleNodeIds } from '../../hooks/useVisibleNodeIds'; import { useStore } from '../../hooks/useStore'; import { containerStyle } from '../../styles/utils'; import { GraphViewProps } from '../GraphView'; +import { useResizeObserver } from './useResizeObserver'; +import { NodeWrapper } from '../../components/NodeWrapper'; import type { ReactFlowState } from '../../types'; -import useResizeObserver from './useResizeObserver'; -import NodeWrapper from '../../components/NodeWrapper'; export type NodeRendererProps = Pick< GraphViewProps, @@ -35,9 +35,9 @@ const selector = (s: ReactFlowState) => ({ onError: s.onError, }); -const NodeRenderer = (props: NodeRendererProps) => { +const NodeRendererComponent = (props: NodeRendererProps) => { const { nodesDraggable, nodesConnectable, nodesFocusable, elementsSelectable, onError } = useStore(selector, shallow); - const nodeIds = useVisibleNodesIds(props.onlyRenderVisibleElements); + const nodeIds = useVisibleNodeIds(props.onlyRenderVisibleElements); const resizeObserver = useResizeObserver(); return ( @@ -96,6 +96,6 @@ const NodeRenderer = (props: NodeRendererProps) => { ); }; -NodeRenderer.displayName = 'NodeRenderer'; +NodeRendererComponent.displayName = 'NodeRenderer'; -export default memo(NodeRenderer); +export const NodeRenderer = memo(NodeRendererComponent); diff --git a/packages/react/src/container/NodeRenderer/useResizeObserver.ts b/packages/react/src/container/NodeRenderer/useResizeObserver.ts index d109d798..f0d0a22e 100644 --- a/packages/react/src/container/NodeRenderer/useResizeObserver.ts +++ b/packages/react/src/container/NodeRenderer/useResizeObserver.ts @@ -5,7 +5,7 @@ import { useStore } from '../../hooks/useStore'; const selector = (s: ReactFlowState) => s.updateNodeDimensions; -export default function useResizeObserver() { +export function useResizeObserver() { const updateNodeDimensions = useStore(selector); const resizeObserverRef = useRef(); diff --git a/packages/react/src/container/Pane/index.tsx b/packages/react/src/container/Pane/index.tsx index 6acd7770..af1ca28e 100644 --- a/packages/react/src/container/Pane/index.tsx +++ b/packages/react/src/container/Pane/index.tsx @@ -2,12 +2,12 @@ * The user selection rectangle gets displayed when a user drags the mouse while pressing shift */ -import { memo, useRef, type MouseEvent as ReactMouseEvent, type ReactNode } from 'react'; +import { useRef, type MouseEvent as ReactMouseEvent, type ReactNode } from 'react'; import { shallow } from 'zustand/shallow'; import cc from 'classcat'; import { getNodesInside, getEventPosition, SelectionMode } from '@xyflow/system'; -import UserSelection from '../../components/UserSelection'; +import { UserSelection } from '../../components/UserSelection'; import { containerStyle } from '../../styles/utils'; import { useStore, useStoreApi } from '../../hooks/useStore'; import { getSelectionChanges } from '../../utils'; @@ -50,196 +50,190 @@ const selector = (s: ReactFlowState) => ({ dragging: s.paneDragging, }); -const Pane = memo( - ({ - isSelecting, - selectionMode = SelectionMode.Full, - panOnDrag, - onSelectionStart, - onSelectionEnd, - onPaneClick, - onPaneContextMenu, - onPaneScroll, - onPaneMouseEnter, - onPaneMouseMove, - onPaneMouseLeave, - children, - }: PaneProps) => { - const container = useRef(null); - const store = useStoreApi(); - const prevSelectedNodesCount = useRef(0); - const prevSelectedEdgesCount = useRef(0); - const containerBounds = useRef(); - const { userSelectionActive, elementsSelectable, dragging } = useStore(selector, shallow); +export function Pane({ + isSelecting, + selectionMode = SelectionMode.Full, + panOnDrag, + onSelectionStart, + onSelectionEnd, + onPaneClick, + onPaneContextMenu, + onPaneScroll, + onPaneMouseEnter, + onPaneMouseMove, + onPaneMouseLeave, + children, +}: PaneProps) { + const container = useRef(null); + const store = useStoreApi(); + const prevSelectedNodesCount = useRef(0); + const prevSelectedEdgesCount = useRef(0); + const containerBounds = useRef(); + const { userSelectionActive, elementsSelectable, dragging } = useStore(selector, shallow); - const resetUserSelection = () => { - store.setState({ userSelectionActive: false, userSelectionRect: null }); + const resetUserSelection = () => { + store.setState({ userSelectionActive: false, userSelectionRect: null }); - prevSelectedNodesCount.current = 0; - prevSelectedEdgesCount.current = 0; + prevSelectedNodesCount.current = 0; + prevSelectedEdgesCount.current = 0; + }; + + const onClick = (event: ReactMouseEvent) => { + onPaneClick?.(event); + store.getState().resetSelectedElements(); + store.setState({ nodesSelectionActive: false }); + }; + + const onContextMenu = (event: ReactMouseEvent) => { + if (Array.isArray(panOnDrag) && panOnDrag?.includes(2)) { + event.preventDefault(); + return; + } + + onPaneContextMenu?.(event); + }; + + const onWheel = onPaneScroll ? (event: React.WheelEvent) => onPaneScroll(event) : undefined; + + const onMouseDown = (event: ReactMouseEvent): void => { + const { resetSelectedElements, domNode } = store.getState(); + containerBounds.current = domNode?.getBoundingClientRect(); + + if ( + !elementsSelectable || + !isSelecting || + event.button !== 0 || + event.target !== container.current || + !containerBounds.current + ) { + return; + } + + const { x, y } = getEventPosition(event.nativeEvent, containerBounds.current); + + resetSelectedElements(); + + store.setState({ + userSelectionRect: { + width: 0, + height: 0, + startX: x, + startY: y, + x, + y, + }, + }); + + onSelectionStart?.(event); + }; + + const onMouseMove = (event: ReactMouseEvent): void => { + const { userSelectionRect, edges, transform, nodeOrigin, nodes, onNodesChange, onEdgesChange } = store.getState(); + if (!isSelecting || !containerBounds.current || !userSelectionRect) { + return; + } + + store.setState({ userSelectionActive: true, nodesSelectionActive: false }); + + const mousePos = getEventPosition(event.nativeEvent, containerBounds.current); + const startX = userSelectionRect.startX ?? 0; + const startY = userSelectionRect.startY ?? 0; + + const nextUserSelectRect = { + ...userSelectionRect, + x: mousePos.x < startX ? mousePos.x : startX, + y: mousePos.y < startY ? mousePos.y : startY, + width: Math.abs(mousePos.x - startX), + height: Math.abs(mousePos.y - startY), }; - const onClick = (event: ReactMouseEvent) => { - onPaneClick?.(event); - store.getState().resetSelectedElements(); - store.setState({ nodesSelectionActive: false }); - }; - - const onContextMenu = (event: ReactMouseEvent) => { - if (Array.isArray(panOnDrag) && panOnDrag?.includes(2)) { - event.preventDefault(); - return; - } - - onPaneContextMenu?.(event); - }; - - const onWheel = onPaneScroll ? (event: React.WheelEvent) => onPaneScroll(event) : undefined; - - const onMouseDown = (event: ReactMouseEvent): void => { - const { resetSelectedElements, domNode } = store.getState(); - containerBounds.current = domNode?.getBoundingClientRect(); - - if ( - !elementsSelectable || - !isSelecting || - event.button !== 0 || - event.target !== container.current || - !containerBounds.current - ) { - return; - } - - const { x, y } = getEventPosition(event.nativeEvent, containerBounds.current); - - resetSelectedElements(); - - store.setState({ - userSelectionRect: { - width: 0, - height: 0, - startX: x, - startY: y, - x, - y, - }, - }); - - onSelectionStart?.(event); - }; - - const onMouseMove = (event: ReactMouseEvent): void => { - const { userSelectionRect, edges, transform, nodeOrigin, nodes, onNodesChange, onEdgesChange } = store.getState(); - if (!isSelecting || !containerBounds.current || !userSelectionRect) { - return; - } - - store.setState({ userSelectionActive: true, nodesSelectionActive: false }); - - const mousePos = getEventPosition(event.nativeEvent, containerBounds.current); - const startX = userSelectionRect.startX ?? 0; - const startY = userSelectionRect.startY ?? 0; - - const nextUserSelectRect = { - ...userSelectionRect, - x: mousePos.x < startX ? mousePos.x : startX, - y: mousePos.y < startY ? mousePos.y : startY, - width: Math.abs(mousePos.x - startX), - height: Math.abs(mousePos.y - startY), - }; - - const selectedNodes = getNodesInside( - nodes, - nextUserSelectRect, - transform, - selectionMode === SelectionMode.Partial, - true, - nodeOrigin - ); - - const selectedEdgeIds = new Set(); - const selectedNodeIds = new Set(); - - for (const selectedNode of selectedNodes) { - selectedNodeIds.add(selectedNode.id); - - for (const edge of edges) { - if (edge.source === selectedNode.id || edge.target === selectedNode.id) { - selectedEdgeIds.add(edge.id); - } - } - } - - if (prevSelectedNodesCount.current !== selectedNodeIds.size) { - prevSelectedNodesCount.current = selectedNodeIds.size; - const changes = getSelectionChanges(nodes, selectedNodeIds, true) as NodeChange[]; - if (changes.length) { - onNodesChange?.(changes); - } - } - - if (prevSelectedEdgesCount.current !== selectedEdgeIds.size) { - prevSelectedEdgesCount.current = selectedEdgeIds.size; - const changes = getSelectionChanges(edges, selectedEdgeIds) as EdgeChange[]; - if (changes.length) { - onEdgesChange?.(changes); - } - } - - store.setState({ - userSelectionRect: nextUserSelectRect, - }); - }; - - const onMouseUp = (event: ReactMouseEvent) => { - if (event.button !== 0) { - return; - } - const { userSelectionRect } = store.getState(); - // We only want to trigger click functions when in selection mode if - // the user did not move the mouse. - if (!userSelectionActive && userSelectionRect && event.target === container.current) { - onClick?.(event); - } - - store.setState({ nodesSelectionActive: prevSelectedNodesCount.current > 0 }); - - resetUserSelection(); - onSelectionEnd?.(event); - }; - - const onMouseLeave = (event: ReactMouseEvent) => { - if (userSelectionActive) { - store.setState({ nodesSelectionActive: prevSelectedNodesCount.current > 0 }); - onSelectionEnd?.(event); - } - - resetUserSelection(); - }; - - const hasActiveSelection = elementsSelectable && (isSelecting || userSelectionActive); - - return ( -
- {children} - -
+ const selectedNodes = getNodesInside( + nodes, + nextUserSelectRect, + transform, + selectionMode === SelectionMode.Partial, + true, + nodeOrigin ); - } -); -Pane.displayName = 'Pane'; + const selectedEdgeIds = new Set(); + const selectedNodeIds = new Set(); -export default Pane; + for (const selectedNode of selectedNodes) { + selectedNodeIds.add(selectedNode.id); + + for (const edge of edges) { + if (edge.source === selectedNode.id || edge.target === selectedNode.id) { + selectedEdgeIds.add(edge.id); + } + } + } + + if (prevSelectedNodesCount.current !== selectedNodeIds.size) { + prevSelectedNodesCount.current = selectedNodeIds.size; + const changes = getSelectionChanges(nodes, selectedNodeIds, true) as NodeChange[]; + if (changes.length) { + onNodesChange?.(changes); + } + } + + if (prevSelectedEdgesCount.current !== selectedEdgeIds.size) { + prevSelectedEdgesCount.current = selectedEdgeIds.size; + const changes = getSelectionChanges(edges, selectedEdgeIds) as EdgeChange[]; + if (changes.length) { + onEdgesChange?.(changes); + } + } + + store.setState({ + userSelectionRect: nextUserSelectRect, + }); + }; + + const onMouseUp = (event: ReactMouseEvent) => { + if (event.button !== 0) { + return; + } + const { userSelectionRect } = store.getState(); + // We only want to trigger click functions when in selection mode if + // the user did not move the mouse. + if (!userSelectionActive && userSelectionRect && event.target === container.current) { + onClick?.(event); + } + + store.setState({ nodesSelectionActive: prevSelectedNodesCount.current > 0 }); + + resetUserSelection(); + onSelectionEnd?.(event); + }; + + const onMouseLeave = (event: ReactMouseEvent) => { + if (userSelectionActive) { + store.setState({ nodesSelectionActive: prevSelectedNodesCount.current > 0 }); + onSelectionEnd?.(event); + } + + resetUserSelection(); + }; + + const hasActiveSelection = elementsSelectable && (isSelecting || userSelectionActive); + + return ( +
+ {children} + +
+ ); +} diff --git a/packages/react/src/container/ReactFlow/Wrapper.tsx b/packages/react/src/container/ReactFlow/Wrapper.tsx index d658c5a3..4d3cb7b7 100644 --- a/packages/react/src/container/ReactFlow/Wrapper.tsx +++ b/packages/react/src/container/ReactFlow/Wrapper.tsx @@ -1,10 +1,10 @@ import { useContext, type ReactNode } from 'react'; import StoreContext from '../../contexts/RFStoreContext'; -import ReactFlowProvider from '../../components/ReactFlowProvider'; +import { ReactFlowProvider } from '../../components/ReactFlowProvider'; import type { Node, Edge } from '../../types'; -function Wrapper({ +export function Wrapper({ children, nodes, edges, @@ -39,7 +39,3 @@ function Wrapper({ ); } - -Wrapper.displayName = 'ReactFlowWrapper'; - -export default Wrapper; diff --git a/packages/react/src/container/ReactFlow/index.tsx b/packages/react/src/container/ReactFlow/index.tsx index 5f1f2628..d64af5ec 100644 --- a/packages/react/src/container/ReactFlow/index.tsx +++ b/packages/react/src/container/ReactFlow/index.tsx @@ -5,19 +5,18 @@ import { PanOnScrollMode, SelectionMode, infiniteExtent, + isMacOs, type NodeOrigin, type Viewport, - isMacOs, } from '@xyflow/system'; -import Attribution from '../../components/Attribution'; - -import SelectionListener from '../../components/SelectionListener'; -import StoreUpdater from '../../components/StoreUpdater'; -import A11yDescriptions from '../../components/A11yDescriptions'; +import { A11yDescriptions } from '../../components/A11yDescriptions'; +import { Attribution } from '../../components/Attribution'; +import { SelectionListener } from '../../components/SelectionListener'; +import { StoreUpdater } from '../../components/StoreUpdater'; import { useColorModeClass } from '../../hooks/useColorModeClass'; -import GraphView from '../GraphView'; -import Wrapper from './Wrapper'; +import { GraphView } from '../GraphView'; +import { Wrapper } from './Wrapper'; import type { ReactFlowProps, ReactFlowRefType } from '../../types'; export const initNodeOrigin: NodeOrigin = [0, 0]; diff --git a/packages/react/src/container/Viewport/index.tsx b/packages/react/src/container/Viewport/index.tsx index b0de6954..bf12b907 100644 --- a/packages/react/src/container/Viewport/index.tsx +++ b/packages/react/src/container/Viewport/index.tsx @@ -9,7 +9,7 @@ type ViewportProps = { children: ReactNode; }; -export default function Viewport({ children }: ViewportProps) { +export function Viewport({ children }: ViewportProps) { const transform = useStore(selector); return ( diff --git a/packages/react/src/container/ZoomPane/index.tsx b/packages/react/src/container/ZoomPane/index.tsx index f79e5c29..f6e7a79c 100644 --- a/packages/react/src/container/ZoomPane/index.tsx +++ b/packages/react/src/container/ZoomPane/index.tsx @@ -27,7 +27,7 @@ const selector = (s: ReactFlowState) => ({ lib: s.lib, }); -const ZoomPane = ({ +export function ZoomPane({ onPaneContextMenu, zoomOnScroll = true, zoomOnPinch = true, @@ -47,7 +47,7 @@ const ZoomPane = ({ noPanClassName, onViewportChange, isControlledViewport, -}: ZoomPaneProps) => { +}: ZoomPaneProps) { const store = useStoreApi(); const zoomPane = useRef(null); const { userSelectionActive, lib } = useStore(selector, shallow); @@ -142,6 +142,4 @@ const ZoomPane = ({ {children} ); -}; - -export default ZoomPane; +} diff --git a/packages/react/src/hooks/useVisibleEdgeIds.ts b/packages/react/src/hooks/useVisibleEdgeIds.ts index ceb40f31..4505de9c 100644 --- a/packages/react/src/hooks/useVisibleEdgeIds.ts +++ b/packages/react/src/hooks/useVisibleEdgeIds.ts @@ -12,7 +12,7 @@ import { type ReactFlowState } from '../types'; * @param onlyRenderVisible * @returns array with visible edge ids */ -function useVisibleEdgeIds(onlyRenderVisible: boolean): string[] { +export function useVisibleEdgeIds(onlyRenderVisible: boolean): string[] { const edgeIds = useStore( useCallback( (s: ReactFlowState) => { @@ -52,5 +52,3 @@ function useVisibleEdgeIds(onlyRenderVisible: boolean): string[] { return edgeIds; } - -export default useVisibleEdgeIds; diff --git a/packages/react/src/hooks/useVisibleNodeIds.ts b/packages/react/src/hooks/useVisibleNodeIds.ts index 803fde6d..309391dc 100644 --- a/packages/react/src/hooks/useVisibleNodeIds.ts +++ b/packages/react/src/hooks/useVisibleNodeIds.ts @@ -20,10 +20,8 @@ const selector = (onlyRenderVisible: boolean) => (s: ReactFlowState) => { * @param onlyRenderVisible * @returns array with visible node ids */ -function useVisibleNodeIds(onlyRenderVisible: boolean) { +export function useVisibleNodeIds(onlyRenderVisible: boolean) { const nodeIds = useStore(useCallback(selector(onlyRenderVisible), [onlyRenderVisible]), shallow); return nodeIds; } - -export default useVisibleNodeIds; diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts index 3d419470..c0f28fa9 100644 --- a/packages/react/src/index.ts +++ b/packages/react/src/index.ts @@ -1,16 +1,16 @@ export { default as ReactFlow } from './container/ReactFlow'; -export { default as Handle, type HandleComponentProps } from './components/Handle'; -export { default as EdgeText } from './components/Edges/EdgeText'; +export { Handle, type HandleComponentProps } from './components/Handle'; +export { EdgeText } from './components/Edges/EdgeText'; export { StraightEdge } from './components/Edges/StraightEdge'; export { StepEdge } from './components/Edges/StepEdge'; export { BezierEdge } from './components/Edges/BezierEdge'; export { SimpleBezierEdge, getSimpleBezierPath } from './components/Edges/SimpleBezierEdge'; export { SmoothStepEdge } from './components/Edges/SmoothStepEdge'; -export { default as BaseEdge } from './components/Edges/BaseEdge'; -export { default as ReactFlowProvider } from './components/ReactFlowProvider'; -export { default as Panel, type PanelProps } from './components/Panel'; -export { default as EdgeLabelRenderer } from './components/EdgeLabelRenderer'; -export { default as ViewportPortal } from './components/ViewportPortal'; +export { BaseEdge } from './components/Edges/BaseEdge'; +export { ReactFlowProvider } from './components/ReactFlowProvider'; +export { Panel, type PanelProps } from './components/Panel'; +export { EdgeLabelRenderer } from './components/EdgeLabelRenderer'; +export { ViewportPortal } from './components/ViewportPortal'; export { useReactFlow } from './hooks/useReactFlow'; export { useUpdateNodeInternals } from './hooks/useUpdateNodeInternals'; From c8a5c25b1476acc925147869704497d7b31bb990 Mon Sep 17 00:00:00 2001 From: moklick Date: Mon, 8 Jan 2024 13:31:59 +0100 Subject: [PATCH 7/8] chore(react): bump --- packages/react/CHANGELOG.md | 6 +++--- packages/react/package.json | 2 +- packages/react/src/components/Edges/EdgeText.tsx | 2 ++ 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/react/CHANGELOG.md b/packages/react/CHANGELOG.md index cb1deb41..ebb84a56 100644 --- a/packages/react/CHANGELOG.md +++ b/packages/react/CHANGELOG.md @@ -5,7 +5,7 @@ ### Minor changes - fix applyChanges: handle empty flows + addNodes/addEdges closes -- cleanup hook exports +- cleanup exports ## 12.0.0-next.3 @@ -41,7 +41,7 @@ Svelte Flow had a big impact on this release as well. While combing through each Before you can try out the new features, you need to do some minor updates: - **A new npm package name:** Our name changed from `reactflow` to `@xyflow/react` and the main component is no longer a default, but a named import: - - v11: `import { ReactFlow } from '@xyflow/react';` + - v11: `import ReactFlow from 'reactflow';` - v12: `import { ReactFlow } from '@xyflow/react';` - **Node attribute “computed”:** All computed node values are now stored in `node.computed` - v11: `node.width`, `node.height` ,`node.positionAbsolute` @@ -72,7 +72,7 @@ Before you can try out the new features, you need to do some minor updates: - affected functions: `useNodes`, `useNodesState`, `useEdgesState`, `applyNodeChange`, `onInit`, `applyEdgeChanges` , `MiniMapProps` - **Removal of deprecated functions:** - `getTransformForBounds` (new name: `getViewportForBounds`), - - `getRectOfNodes` \*\*\*\*(new name: `getNodesBounds`) + - `getRectOfNodes` (new name: `getNodesBounds`) - `project` (new name: `screenToFlowPosition`) - `getMarkerEndId` diff --git a/packages/react/package.json b/packages/react/package.json index 9bd90350..b68f6e63 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -1,6 +1,6 @@ { "name": "@xyflow/react", - "version": "12.0.0-next.3", + "version": "12.0.0-next.4", "description": "React Flow - A highly customizable React library for building node-based editors and interactive flow charts.", "keywords": [ "react", diff --git a/packages/react/src/components/Edges/EdgeText.tsx b/packages/react/src/components/Edges/EdgeText.tsx index 2e671895..d6c68caa 100644 --- a/packages/react/src/components/Edges/EdgeText.tsx +++ b/packages/react/src/components/Edges/EdgeText.tsx @@ -70,4 +70,6 @@ function EdgeTextComponent({ ); } +EdgeTextComponent.displayName = 'EdgeText'; + export const EdgeText = memo(EdgeTextComponent); From 2870c2f367a25f954e466b7d6d9072d074ee6cac Mon Sep 17 00:00:00 2001 From: moklick Date: Mon, 8 Jan 2024 15:28:04 +0100 Subject: [PATCH 8/8] fix(react): applyChanges broken for multi changes for one node --- packages/react/CHANGELOG.md | 6 ++++++ packages/react/src/utils/changes.ts | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/react/CHANGELOG.md b/packages/react/CHANGELOG.md index ebb84a56..dc2b1210 100644 --- a/packages/react/CHANGELOG.md +++ b/packages/react/CHANGELOG.md @@ -1,5 +1,11 @@ # @xyflow/react +## 12.0.0-next.5 + +### Minor changes + +- fix applyChanges: handle multi changes for one node + ## 12.0.0-next.4 ### Minor changes diff --git a/packages/react/src/utils/changes.ts b/packages/react/src/utils/changes.ts index be9460d0..372c9aa9 100644 --- a/packages/react/src/utils/changes.ts +++ b/packages/react/src/utils/changes.ts @@ -141,8 +141,9 @@ function applyChanges(changes: any[], elements: any[]): any[] { } } } - updatedElements.push(updateItem); } + + updatedElements.push(updateItem); } return updatedElements;