@@ -12,7 +12,6 @@ import {
|
||||
Node,
|
||||
Edge,
|
||||
} from '@xyflow/react';
|
||||
import '@xyflow/react/dist/style.css';
|
||||
|
||||
const initialNodes: Node[] = [
|
||||
{
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { ReactFlow } from '@xyflow/react';
|
||||
import '@xyflow/react/dist/style.css';
|
||||
|
||||
import { useDispatch, useSelector, Provider } from 'react-redux';
|
||||
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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]);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}, []);
|
||||
}
|
||||
@@ -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';
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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.`.
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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 = [
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user