Merge pull request #4258 from xyflow/next

React Flow 12.0.0-next.18
This commit is contained in:
Moritz Klack
2024-05-08 22:49:13 +02:00
committed by GitHub
22 changed files with 113 additions and 92 deletions

View File

@@ -12,7 +12,6 @@ import {
Node,
Edge,
} from '@xyflow/react';
import '@xyflow/react/dist/style.css';
const initialNodes: Node[] = [
{

View File

@@ -1,5 +1,4 @@
import { ReactFlow } from '@xyflow/react';
import '@xyflow/react/dist/style.css';
import { useDispatch, useSelector, Provider } from 'react-redux';

View File

@@ -1,7 +1,7 @@
import { memo, FC, useEffect, useCallback } from 'react';
import { Handle, Position, NodeProps, useHandleConnections, Connection, HandleComponentProps } from '@xyflow/react';
import { Handle, Position, NodeProps, useHandleConnections, Connection, HandleProps } from '@xyflow/react';
function CustomHandle({ nodeId, ...handleProps }: HandleComponentProps & { nodeId: string }) {
function CustomHandle({ nodeId, ...handleProps }: HandleProps & { nodeId: string }) {
const onConnect = useCallback(
(connections: Connection[]) => console.log('onConnect handler, node id:', nodeId, connections),
[nodeId]

View File

@@ -1,7 +1,7 @@
import { memo, FC, useEffect, useCallback } from 'react';
import { Handle, Position, NodeProps, useHandleConnections, Connection, HandleComponentProps } from '@xyflow/react';
import { Handle, Position, NodeProps, useHandleConnections, Connection, HandleProps } from '@xyflow/react';
function CustomHandle({ nodeId, ...handleProps }: HandleComponentProps & { nodeId: string }) {
function CustomHandle({ nodeId, ...handleProps }: HandleProps & { nodeId: string }) {
const onConnect = useCallback(
(connections: Connection[]) => {
console.log('onConnect handler, node id:', nodeId, connections);

View File

@@ -1,5 +1,12 @@
# @xyflow/react
## 12.0.0-next.18
- don't show nodeTypes warning if not necessary you've created a new nodeTypes or edgeTypes
- add node resizer styles to base.css
- remove `HandleComponentProps` type, only export `HandleProps` type
- add warning when styles not loaded
## 12.0.0-next.17
- fix broken `defaultNodes`
@@ -9,6 +16,7 @@
- return user node in node event handlers
- cleanup `useReactFlow`
- export `KeyCode` and `Align` type
- remove `Instance` in favour of `ReactFlowInstance` type
## 12.0.0-next.16

View File

@@ -1,6 +1,6 @@
{
"name": "@xyflow/react",
"version": "12.0.0-next.17",
"version": "12.0.0-next.18",
"description": "React Flow - A highly customizable React library for building node-based editors and interactive flow charts.",
"keywords": [
"react",

View File

@@ -14,10 +14,11 @@ import {
getHostForElement,
isMouseEvent,
addEdge,
type HandleProps,
type HandleProps as HandlePropsSystem,
type Connection,
type HandleType,
ConnectionMode,
OnConnect,
} from '@xyflow/system';
import { useStore, useStoreApi } from '../../hooks/useStore';
@@ -25,7 +26,10 @@ import { useNodeId } from '../../contexts/NodeIdContext';
import { type ReactFlowState } from '../../types';
import { fixedForwardRef } from '../../utils';
export interface HandleComponentProps extends HandleProps, Omit<HTMLAttributes<HTMLDivElement>, 'id'> {}
export interface HandleProps extends HandlePropsSystem, Omit<HTMLAttributes<HTMLDivElement>, 'id'> {
/** Callback called when connection is made */
onConnect?: OnConnect;
}
const selector = (s: ReactFlowState) => ({
connectOnClick: s.connectOnClick,
@@ -75,7 +79,7 @@ function HandleComponent(
onMouseDown,
onTouchStart,
...rest
}: HandleComponentProps,
}: HandleProps,
ref: ForwardedRef<HTMLDivElement>
) {
const handleId = id || null;

View File

@@ -9,6 +9,7 @@ import { useViewportSync } from '../../hooks/useViewportSync';
import { ConnectionLineWrapper } from '../../components/ConnectionLine';
import { useNodeOrEdgeTypesWarning } from './useNodeOrEdgeTypesWarning';
import type { Edge, Node, ReactFlowProps } from '../../types';
import { useStylesLoadedWarning } from './useStylesLoadedWarning';
export type GraphViewProps<NodeType extends Node = Node, EdgeType extends Edge = Edge> = Omit<
ReactFlowProps<NodeType, EdgeType>,
@@ -104,6 +105,7 @@ function GraphViewComponent<NodeType extends Node = Node, EdgeType extends Edge
}: GraphViewProps<NodeType, EdgeType>) {
useNodeOrEdgeTypesWarning(nodeTypes);
useNodeOrEdgeTypesWarning(edgeTypes);
useStylesLoadedWarning();
useOnInitHandler(onInit);
useViewportSync(viewport);

View File

@@ -1,27 +1,36 @@
import { useEffect, useRef } from 'react';
import { errorMessages } from '@xyflow/system';
import type { EdgeTypes, NodeTypes } from '../../types';
import { useStoreApi } from '../../hooks/useStore';
import type { EdgeTypes, NodeTypes } from '../../types';
const emptyTypes = {};
/*
* This hook warns the user if node or edgeTypes change.
/**
* This hook warns the user if nodeTypes or edgeTypes changed.
* It is only used in development mode.
*
* @internal
*/
export function useNodeOrEdgeTypesWarning(nodeOrEdgeTypes?: NodeTypes): void;
export function useNodeOrEdgeTypesWarning(nodeOrEdgeTypes?: EdgeTypes): void;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function useNodeOrEdgeTypesWarning(nodeOrEdgeTypes: any = emptyTypes): any {
const updateCount = useRef(0);
const typesRef = useRef(nodeOrEdgeTypes);
const store = useStoreApi();
useEffect(() => {
if (process.env.NODE_ENV === 'development') {
if (updateCount.current > 1) {
store.getState().onError?.('002', errorMessages['error002']());
const usedKeys = new Set([...Object.keys(typesRef.current), ...Object.keys(nodeOrEdgeTypes)]);
for (const key of usedKeys) {
if (typesRef.current[key] !== nodeOrEdgeTypes[key]) {
store.getState().onError?.('002', errorMessages['error002']());
break;
}
}
updateCount.current += 1;
typesRef.current = nodeOrEdgeTypes;
}
}, [nodeOrEdgeTypes]);
}

View File

@@ -0,0 +1,23 @@
import { useEffect, useRef } from 'react';
import { errorMessages } from '@xyflow/system';
import { useStoreApi } from '../../hooks/useStore';
export function useStylesLoadedWarning() {
const store = useStoreApi();
const checked = useRef(false);
useEffect(() => {
if (process.env.NODE_ENV === 'development') {
if (!checked.current) {
const pane = document.querySelector('.react-flow__pane');
if (pane && !(window.getComputedStyle(pane).zIndex === '1')) {
store.getState().onError?.('013', errorMessages['error013']('react'));
}
checked.current = true;
}
}
}, []);
}

View File

@@ -1,5 +1,5 @@
export { default as ReactFlow } from './container/ReactFlow';
export { Handle, type HandleComponentProps } from './components/Handle';
export { Handle, type HandleProps } from './components/Handle';
export { EdgeText } from './components/Edges/EdgeText';
export { StraightEdge } from './components/Edges/StraightEdge';
export { StepEdge } from './components/Edges/StepEdge';

View File

@@ -1,4 +1,4 @@
import { ReactNode, Ref, RefAttributes, forwardRef } from 'react';
import { type Ref, type RefAttributes, forwardRef } from 'react';
import { isNodeBase, isEdgeBase } from '@xyflow/system';
import type { Edge, Node } from '../types';
@@ -25,8 +25,8 @@ export const isEdge = <EdgeType extends Edge = Edge>(element: unknown): element
// eslint-disable-next-line @typescript-eslint/ban-types
export function fixedForwardRef<T, P = {}>(
render: (props: P, ref: Ref<T>) => ReactNode
): (props: P & RefAttributes<T>) => ReactNode {
render: (props: P, ref: Ref<T>) => JSX.Element
): (props: P & RefAttributes<T>) => JSX.Element {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return forwardRef(render) as any;
}

View File

@@ -1,5 +1,17 @@
# @xyflow/svelte
## 0.1.3
- fix `NodeToolbar` for subflows
## 0.1.2
- export `InternalNode` type
## 0.1.1
- export `useInternalNode` hook
## 0.1.0
This is a bigger update for Svelte Flow to keep up with the latest changes we made for React Flow and the Svelte5 rewrite. The biggest change is the separation of user nodes (type `Node`) and internal nodes (type `InternalNode`), which includes a renaming of the `node.computed` attribute to `node.measured`. In the previous versions, we stored internals in `node[internalsSymbol]`. This doesn't exist anymore, but we only add it to our internal nodes in `node.internals.`.

View File

@@ -1,6 +1,6 @@
{
"name": "@xyflow/svelte",
"version": "0.1.0",
"version": "0.1.3",
"description": "Svelte Flow - A highly customizable Svelte library for building node-based editors, workflow systems, diagrams and more.",
"keywords": [
"svelte",

View File

@@ -13,9 +13,9 @@
} from '@xyflow/system';
import { useStore } from '$lib/store';
import type { HandleComponentProps } from '$lib/types';
import type { HandleProps } from '$lib/types';
type $$Props = HandleComponentProps;
type $$Props = HandleProps;
export let id: $$Props['id'] = undefined;
export let type: $$Props['type'] = 'source';

View File

@@ -32,6 +32,7 @@ export * from '$lib/hooks/useConnection';
export * from '$lib/hooks/useNodesEdges';
export * from '$lib/hooks/useHandleConnections';
export * from '$lib/hooks/useNodesData';
export * from '$lib/hooks/useInternalNode';
export { useInitialized, useNodesInitialized } from '$lib/hooks/useInitialized';
// types
@@ -45,8 +46,15 @@ export type {
EdgeTypes,
DefaultEdgeOptions
} from '$lib/types/edges';
export type { HandleComponentProps, FitViewOptions } from '$lib/types/general';
export type { Node, NodeTypes, DefaultNodeOptions, BuiltInNode, NodeProps } from '$lib/types/nodes';
export type { HandleProps, FitViewOptions } from '$lib/types/general';
export type {
Node,
NodeTypes,
DefaultNodeOptions,
BuiltInNode,
NodeProps,
InternalNode
} from '$lib/types/nodes';
export type { SvelteFlowStore } from '$lib/store/types';
// system types

View File

@@ -42,18 +42,7 @@
}
$: {
let nodeRect: Rect | undefined = undefined;
if (toolbarNodes.length === 1) {
const toolbarNode = toolbarNodes[0];
nodeRect = {
...toolbarNode.position,
width: toolbarNode.measured.width ?? toolbarNode.width ?? 0,
height: toolbarNode.measured.height ?? toolbarNode.height ?? 0
};
} else if (toolbarNodes.length > 1) {
nodeRect = getNodesBounds(toolbarNodes, { nodeOrigin: $nodeOrigin });
}
const nodeRect = getNodesBounds(toolbarNodes, { nodeOrigin: $nodeOrigin });
if (nodeRect) {
transform = getNodeToolbarTransform(nodeRect, $viewport, _position, _offset, _align);

View File

@@ -1,12 +1,11 @@
import type { ShortcutModifierDefinition } from '@svelte-put/shortcut';
import type {
FitViewOptionsBase,
HandleType,
Position,
XYPosition,
ConnectingHandle,
Connection,
OnBeforeDeleteBase
OnBeforeDeleteBase,
HandleProps as HandlePropsSystem
} from '@xyflow/system';
import type { Node } from './nodes';
@@ -23,32 +22,9 @@ export type ConnectionData = {
connectionStatus: string | null;
};
export type HandleComponentProps = {
/** Type of the handle
* @example HandleType.Source, HandleType.Target
*/
type: HandleType;
/** Position of the handle
* @example Position.TopLeft, Position.TopRight,
* Position.BottomLeft, Position.BottomRight
*/
position?: Position;
/** Id of the handle
* @remarks optional if there is only one handle of this type
*/
id?: string;
export type HandleProps = HandlePropsSystem & {
class?: string;
style?: string;
/** Should you be able to connect from/to this handle */
isConnectable?: boolean;
/** Shoould you be able to connect from this handle */
isConnectableStart?: boolean;
/** Should you be able to connect to this handle */
isConnectableEnd?: boolean;
/** Function that is called when checking if connection is valid.
* Overrides the isValidConnection on the Flow component.
*/
isValidConnection?: IsValidConnection;
onconnect?: (connections: Connection[]) => void;
ondisconnect?: (connections: Connection[]) => void;
};

View File

@@ -1,6 +1,6 @@
{
"name": "@xyflow/system",
"version": "0.0.25",
"version": "0.0.26",
"description": "xyflow core system that powers React Flow and Svelte Flow.",
"keywords": [
"node-based UI",

View File

@@ -1,6 +1,5 @@
import { CoordinateExtent, HandleType } from './types';
// @todo: update URLs to xyflow
export const errorMessages = {
error001: () =>
'[React Flow]: Seems like you have not used zustand provider as an ancestor. Help: https://reactflow.dev/error#001',
@@ -23,6 +22,8 @@ export const errorMessages = {
error011: (edgeType: string) => `Edge type "${edgeType}" not found. Using fallback type "default".`,
error012: (id: string) =>
`Node with id "${id}" does not exist, it may have been removed. This can happen when a node is deleted before the "onNodeClick" handler is called.`,
error013: (lib: string = 'react') =>
`It seems that you haven't loaded the styles. Please import '@xyflow/${lib}/dist/style.css' or base.css to make sure everything is working properly.`,
};
export const infiniteExtent: CoordinateExtent = [

View File

@@ -1,4 +1,4 @@
import type { Position, OnConnect, IsValidConnection } from '.';
import type { Position, IsValidConnection } from '.';
export type HandleType = 'source' | 'target';
@@ -42,8 +42,6 @@ export type HandleProps = {
isConnectableStart?: boolean;
/** Should you be able to connect to this handle */
isConnectableEnd?: boolean;
/** Callback called when connection is made */
onConnect?: OnConnect;
/** Callback if connection is valid
* @remarks connection becomes an edge if isValidConnection returns true
*/

View File

@@ -254,13 +254,10 @@ export function updateNodeInternals<NodeType extends InternalNodeBase>(
const node = nodeLookup.get(update.id);
if (node?.hidden) {
nodeLookup.set(node.id, {
...node,
internals: {
...node.internals,
handleBounds: undefined,
},
});
node.internals = {
...node.internals,
handleBounds: undefined,
};
updatedInternals = true;
} else if (node) {
const dimensions = getDimensions(update.nodeElement);
@@ -272,33 +269,29 @@ export function updateNodeInternals<NodeType extends InternalNodeBase>(
);
if (doUpdate) {
const newNode = {
...node,
measured: dimensions,
internals: {
...node.internals,
handleBounds: {
source: getHandleBounds('.source', update.nodeElement, zoom, node.origin || nodeOrigin),
target: getHandleBounds('.target', update.nodeElement, zoom, node.origin || nodeOrigin),
},
node.measured = dimensions;
node.internals = {
...node.internals,
handleBounds: {
source: getHandleBounds('.source', update.nodeElement, zoom, node.origin || nodeOrigin),
target: getHandleBounds('.target', update.nodeElement, zoom, node.origin || nodeOrigin),
},
};
nodeLookup.set(node.id, newNode);
updatedInternals = true;
if (dimensionChanged) {
changes.push({
id: newNode.id,
id: node.id,
type: 'dimensions',
dimensions,
});
if (newNode.expandParent && newNode.parentId) {
if (node.expandParent && node.parentId) {
parentExpandChildren.push({
id: newNode.id,
parentId: newNode.parentId,
rect: nodeToRect(newNode, newNode.origin || nodeOrigin),
id: node.id,
parentId: node.parentId,
rect: nodeToRect(node, nodeOrigin),
});
}
}