Merge branch 'main' into feat/packages
This commit is contained in:
@@ -54,6 +54,7 @@ export default (EdgeComponent: ComponentType<EdgeProps>) => {
|
||||
rfId,
|
||||
ariaLabel,
|
||||
isFocusable,
|
||||
isUpdatable,
|
||||
pathOptions,
|
||||
interactionWidth,
|
||||
}: WrapEdgeProps): JSX.Element | null => {
|
||||
@@ -137,7 +138,6 @@ export default (EdgeComponent: ComponentType<EdgeProps>) => {
|
||||
const onEdgeUpdaterMouseOut = () => setUpdateHover(false);
|
||||
|
||||
const inactive = !elementsSelectable && !onClick;
|
||||
const handleEdgeUpdate = typeof onEdgeUpdate !== 'undefined';
|
||||
|
||||
const onKeyDown = (event: KeyboardEvent) => {
|
||||
if (elementSelectionKeys.includes(event.key) && elementsSelectable) {
|
||||
@@ -204,28 +204,32 @@ export default (EdgeComponent: ComponentType<EdgeProps>) => {
|
||||
interactionWidth={interactionWidth}
|
||||
/>
|
||||
)}
|
||||
{handleEdgeUpdate && (
|
||||
{isUpdatable && (
|
||||
<>
|
||||
<EdgeAnchor
|
||||
position={sourcePosition}
|
||||
centerX={sourceX}
|
||||
centerY={sourceY}
|
||||
radius={edgeUpdaterRadius}
|
||||
onMouseDown={onEdgeUpdaterSourceMouseDown}
|
||||
onMouseEnter={onEdgeUpdaterMouseEnter}
|
||||
onMouseOut={onEdgeUpdaterMouseOut}
|
||||
type="source"
|
||||
/>
|
||||
<EdgeAnchor
|
||||
position={targetPosition}
|
||||
centerX={targetX}
|
||||
centerY={targetY}
|
||||
radius={edgeUpdaterRadius}
|
||||
onMouseDown={onEdgeUpdaterTargetMouseDown}
|
||||
onMouseEnter={onEdgeUpdaterMouseEnter}
|
||||
onMouseOut={onEdgeUpdaterMouseOut}
|
||||
type="target"
|
||||
/>
|
||||
{(isUpdatable === 'source' || isUpdatable === true) && (
|
||||
<EdgeAnchor
|
||||
position={sourcePosition}
|
||||
centerX={sourceX}
|
||||
centerY={sourceY}
|
||||
radius={edgeUpdaterRadius}
|
||||
onMouseDown={onEdgeUpdaterSourceMouseDown}
|
||||
onMouseEnter={onEdgeUpdaterMouseEnter}
|
||||
onMouseOut={onEdgeUpdaterMouseOut}
|
||||
type="source"
|
||||
/>
|
||||
)}
|
||||
{(isUpdatable === 'target' || isUpdatable === true) && (
|
||||
<EdgeAnchor
|
||||
position={targetPosition}
|
||||
centerX={targetX}
|
||||
centerY={targetY}
|
||||
radius={edgeUpdaterRadius}
|
||||
onMouseDown={onEdgeUpdaterTargetMouseDown}
|
||||
onMouseEnter={onEdgeUpdaterMouseEnter}
|
||||
onMouseOut={onEdgeUpdaterMouseOut}
|
||||
type="target"
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</g>
|
||||
|
||||
@@ -95,10 +95,17 @@ export function handlePointerDown({
|
||||
|
||||
setState({
|
||||
connectionPosition,
|
||||
connectionStatus: null,
|
||||
// connectionNodeId etc will be removed in the next major in favor of connectionStartHandle
|
||||
connectionNodeId: nodeId,
|
||||
connectionHandleId: handleId,
|
||||
connectionHandleType: handleType,
|
||||
connectionStatus: null,
|
||||
connectionStartHandle: {
|
||||
nodeId,
|
||||
handleId,
|
||||
type: handleType,
|
||||
},
|
||||
connectionEndHandle: null,
|
||||
});
|
||||
|
||||
onConnectStart?.(event, { nodeId, handleId, handleType });
|
||||
@@ -145,6 +152,7 @@ export function handlePointerDown({
|
||||
)
|
||||
: connectionPosition,
|
||||
connectionStatus: getConnectionStatus(!!prevClosestHandle, isValid),
|
||||
connectionEndHandle: result.endHandle,
|
||||
});
|
||||
|
||||
if (!prevClosestHandle && !isValid && !handleDomNode) {
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import { memo, HTMLAttributes, forwardRef, MouseEvent as ReactMouseEvent, TouchEvent as ReactTouchEvent } from 'react';
|
||||
import cc from 'classcat';
|
||||
import { shallow } from 'zustand/shallow';
|
||||
import { errorMessages, Position, type HandleProps, type Connection } from '@reactflow/system';
|
||||
import { errorMessages, Position, type HandleProps, type Connection, type HandleType } from '@reactflow/system';
|
||||
import { getHostForElement, isMouseEvent } from '@reactflow/utils';
|
||||
|
||||
import { useStore, useStoreApi } from '../../hooks/useStore';
|
||||
import { useNodeId } from '../../contexts/NodeIdContext';
|
||||
import { handlePointerDown } from './handler';
|
||||
import { addEdge } from '../../utils/';
|
||||
import { type ReactFlowState } from '../../types';
|
||||
import { isValidHandle } from './utils';
|
||||
import { addEdge } from '../../utils';
|
||||
import type { ReactFlowState } from '../../types';
|
||||
|
||||
const alwaysValid = () => true;
|
||||
|
||||
@@ -21,6 +21,23 @@ const selector = (s: ReactFlowState) => ({
|
||||
noPanClassName: s.noPanClassName,
|
||||
});
|
||||
|
||||
const connectingSelector =
|
||||
(nodeId: string | null, handleId: string | null, type: HandleType) => (state: ReactFlowState) => {
|
||||
const {
|
||||
connectionStartHandle: startHandle,
|
||||
connectionEndHandle: endHandle,
|
||||
connectionClickStartHandle: clickHandle,
|
||||
} = state;
|
||||
|
||||
return {
|
||||
connecting:
|
||||
(startHandle?.nodeId === nodeId && startHandle?.handleId === handleId && startHandle?.type === type) ||
|
||||
(endHandle?.nodeId === nodeId && endHandle?.handleId === handleId && endHandle?.type === type),
|
||||
clickConnecting:
|
||||
clickHandle?.nodeId === nodeId && clickHandle?.handleId === handleId && clickHandle?.type === type,
|
||||
};
|
||||
};
|
||||
|
||||
const Handle = forwardRef<HTMLDivElement, HandleComponentProps>(
|
||||
(
|
||||
{
|
||||
@@ -28,6 +45,8 @@ const Handle = forwardRef<HTMLDivElement, HandleComponentProps>(
|
||||
position = Position.Top,
|
||||
isValidConnection,
|
||||
isConnectable = true,
|
||||
isConnectableStart = true,
|
||||
isConnectableEnd = true,
|
||||
id,
|
||||
onConnect,
|
||||
children,
|
||||
@@ -38,19 +57,16 @@ const Handle = forwardRef<HTMLDivElement, HandleComponentProps>(
|
||||
},
|
||||
ref
|
||||
) => {
|
||||
const store = useStoreApi();
|
||||
const nodeId = useNodeId();
|
||||
|
||||
if (!nodeId) {
|
||||
store.getState().onError?.('010', errorMessages['010']());
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
const { connectionStartHandle, connectOnClick, noPanClassName } = useStore(selector, shallow);
|
||||
|
||||
const handleId = id || null;
|
||||
const isTarget = type === 'target';
|
||||
const store = useStoreApi();
|
||||
const nodeId = useNodeId();
|
||||
const { connectOnClick, noPanClassName } = useStore(selector, shallow);
|
||||
const { connecting, clickConnecting } = useStore(connectingSelector(nodeId, handleId, type));
|
||||
|
||||
if (!nodeId) {
|
||||
store.getState().onError?.('010', errorMessages['error010']());
|
||||
}
|
||||
|
||||
const onConnectExtended = (params: Connection) => {
|
||||
const { defaultEdgeOptions, onConnect: onConnectAction, hasDefaultEdges } = store.getState();
|
||||
@@ -69,9 +85,16 @@ const Handle = forwardRef<HTMLDivElement, HandleComponentProps>(
|
||||
};
|
||||
|
||||
const onPointerDown = (event: ReactMouseEvent<HTMLDivElement> | ReactTouchEvent<HTMLDivElement>) => {
|
||||
if (!nodeId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const isMouseTriggered = isMouseEvent(event.nativeEvent);
|
||||
|
||||
if ((isMouseTriggered && (event as ReactMouseEvent<HTMLDivElement>).button === 0) || !isMouseTriggered) {
|
||||
if (
|
||||
isConnectableStart &&
|
||||
((isMouseTriggered && (event as ReactMouseEvent<HTMLDivElement>).button === 0) || !isMouseTriggered)
|
||||
) {
|
||||
handlePointerDown({
|
||||
event,
|
||||
handleId,
|
||||
@@ -95,12 +118,18 @@ const Handle = forwardRef<HTMLDivElement, HandleComponentProps>(
|
||||
const {
|
||||
onClickConnectStart,
|
||||
onClickConnectEnd,
|
||||
connectionClickStartHandle,
|
||||
connectionMode,
|
||||
isValidConnection: isValidConnectionStore,
|
||||
} = store.getState();
|
||||
if (!connectionStartHandle) {
|
||||
|
||||
if (!nodeId || (!connectionClickStartHandle && !isConnectableStart)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!connectionClickStartHandle) {
|
||||
onClickConnectStart?.(event, { nodeId, handleId, handleType: type });
|
||||
store.setState({ connectionStartHandle: { nodeId, type, handleId } });
|
||||
store.setState({ connectionClickStartHandle: { nodeId, type, handleId } });
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -114,9 +143,9 @@ const Handle = forwardRef<HTMLDivElement, HandleComponentProps>(
|
||||
type,
|
||||
},
|
||||
connectionMode,
|
||||
connectionStartHandle.nodeId,
|
||||
connectionStartHandle.handleId || null,
|
||||
connectionStartHandle.type,
|
||||
connectionClickStartHandle.nodeId,
|
||||
connectionClickStartHandle.handleId || null,
|
||||
connectionClickStartHandle.type,
|
||||
isValidConnectionHandler,
|
||||
doc
|
||||
);
|
||||
@@ -127,7 +156,7 @@ const Handle = forwardRef<HTMLDivElement, HandleComponentProps>(
|
||||
|
||||
onClickConnectEnd?.(event as unknown as MouseEvent);
|
||||
|
||||
store.setState({ connectionStartHandle: null });
|
||||
store.setState({ connectionClickStartHandle: null });
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -146,10 +175,12 @@ const Handle = forwardRef<HTMLDivElement, HandleComponentProps>(
|
||||
source: !isTarget,
|
||||
target: isTarget,
|
||||
connectable: isConnectable,
|
||||
connecting:
|
||||
connectionStartHandle?.nodeId === nodeId &&
|
||||
connectionStartHandle?.handleId === handleId &&
|
||||
connectionStartHandle?.type === type,
|
||||
connectablestart: isConnectableStart,
|
||||
connectableend: isConnectableEnd,
|
||||
connecting: clickConnecting,
|
||||
// this class is used to style the handle when the user is connecting
|
||||
connectionindicator:
|
||||
isConnectable && ((isConnectableStart && !connecting) || (isConnectableEnd && connecting)),
|
||||
},
|
||||
])}
|
||||
onMouseDown={onPointerDown}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { MouseEvent as ReactMouseEvent, TouchEvent as ReactTouchEvent } from 'react';
|
||||
import {
|
||||
internalsSymbol,
|
||||
ConnectionMode,
|
||||
ConnectionStatus,
|
||||
type ConnectingHandle,
|
||||
type Connection,
|
||||
type HandleType,
|
||||
type XYPosition,
|
||||
type NodeHandleBounds,
|
||||
type XYPosition,
|
||||
} from '@reactflow/system';
|
||||
import { getEventPosition } from '@reactflow/utils';
|
||||
|
||||
@@ -67,6 +67,7 @@ type Result = {
|
||||
handleDomNode: Element | null;
|
||||
isValid: boolean;
|
||||
connection: Connection;
|
||||
endHandle: ConnectingHandle | null;
|
||||
};
|
||||
|
||||
const nullConnection: Connection = { source: null, target: null, sourceHandle: null, targetHandle: null };
|
||||
@@ -78,7 +79,7 @@ export function isValidHandle(
|
||||
connectionMode: ConnectionMode,
|
||||
fromNodeId: string,
|
||||
fromHandleId: string | null,
|
||||
fromType: string,
|
||||
fromType: HandleType,
|
||||
isValidConnection: ValidConnectionFunc,
|
||||
doc: Document | ShadowRoot
|
||||
) {
|
||||
@@ -94,12 +95,15 @@ export function isValidHandle(
|
||||
handleDomNode: handleToCheck,
|
||||
isValid: false,
|
||||
connection: nullConnection,
|
||||
endHandle: null,
|
||||
};
|
||||
|
||||
if (handleToCheck) {
|
||||
const handleType = getHandleType(undefined, handleToCheck);
|
||||
const handleNodeId = handleToCheck.getAttribute('data-nodeid');
|
||||
const handleId = handleToCheck.getAttribute('data-handleid');
|
||||
const connectable = handleToCheck.classList.contains('connectable');
|
||||
const connectableEnd = handleToCheck.classList.contains('connectableend');
|
||||
|
||||
const connection: Connection = {
|
||||
source: isTarget ? handleNodeId : fromNodeId,
|
||||
@@ -110,14 +114,21 @@ export function isValidHandle(
|
||||
|
||||
result.connection = connection;
|
||||
|
||||
const isConnectable = connectable && connectableEnd;
|
||||
// in strict mode we don't allow target to target or source to source connections
|
||||
const isValid =
|
||||
handleToCheck.classList.contains('connectable') &&
|
||||
isConnectable &&
|
||||
(connectionMode === ConnectionMode.Strict
|
||||
? (isTarget && handleType === 'source') || (!isTarget && handleType === 'target')
|
||||
: handleNodeId !== fromNodeId || handleId !== fromHandleId);
|
||||
|
||||
if (isValid) {
|
||||
result.endHandle = {
|
||||
nodeId: handleNodeId as string,
|
||||
handleId,
|
||||
type: handleType as HandleType,
|
||||
};
|
||||
|
||||
result.isValid = isValidConnection(connection);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ type StoreUpdaterProps = Pick<
|
||||
| 'nodesConnectable'
|
||||
| 'nodesFocusable'
|
||||
| 'edgesFocusable'
|
||||
| 'edgesUpdatable'
|
||||
| 'minZoom'
|
||||
| 'maxZoom'
|
||||
| 'nodeExtent'
|
||||
@@ -99,6 +100,7 @@ const StoreUpdater = ({
|
||||
nodesConnectable,
|
||||
nodesFocusable,
|
||||
edgesFocusable,
|
||||
edgesUpdatable,
|
||||
elevateNodesOnSelect,
|
||||
minZoom,
|
||||
maxZoom,
|
||||
@@ -163,6 +165,7 @@ const StoreUpdater = ({
|
||||
useDirectStoreUpdater('nodesConnectable', nodesConnectable, store.setState);
|
||||
useDirectStoreUpdater('nodesFocusable', nodesFocusable, store.setState);
|
||||
useDirectStoreUpdater('edgesFocusable', edgesFocusable, store.setState);
|
||||
useDirectStoreUpdater('edgesUpdatable', edgesUpdatable, store.setState);
|
||||
useDirectStoreUpdater('elementsSelectable', elementsSelectable, store.setState);
|
||||
useDirectStoreUpdater('elevateNodesOnSelect', elevateNodesOnSelect, store.setState);
|
||||
useDirectStoreUpdater('snapToGrid', snapToGrid, store.setState);
|
||||
|
||||
@@ -43,7 +43,7 @@ export function useMarkerSymbol(type: MarkerType) {
|
||||
const symbolExists = Object.prototype.hasOwnProperty.call(MarkerSymbols, type);
|
||||
|
||||
if (!symbolExists) {
|
||||
store.getState().onError?.('009', errorMessages['009'](type));
|
||||
store.getState().onError?.('009', errorMessages['error009'](type));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ type EdgeRendererProps = Pick<
|
||||
const selector = (s: ReactFlowState) => ({
|
||||
nodesConnectable: s.nodesConnectable,
|
||||
edgesFocusable: s.edgesFocusable,
|
||||
edgesUpdatable: s.edgesUpdatable,
|
||||
elementsSelectable: s.elementsSelectable,
|
||||
width: s.width,
|
||||
height: s.height,
|
||||
@@ -65,10 +66,8 @@ const EdgeRenderer = ({
|
||||
onEdgeUpdateEnd,
|
||||
children,
|
||||
}: EdgeRendererProps) => {
|
||||
const { edgesFocusable, elementsSelectable, width, height, connectionMode, nodeInternals, onError } = useStore(
|
||||
selector,
|
||||
shallow
|
||||
);
|
||||
const { edgesFocusable, edgesUpdatable, elementsSelectable, width, height, connectionMode, nodeInternals, onError } =
|
||||
useStore(selector, shallow);
|
||||
const edgeTree = useVisibleEdges(onlyRenderVisibleElements, nodeInternals, elevateEdgesOnSelect);
|
||||
|
||||
if (!width) {
|
||||
@@ -98,7 +97,7 @@ const EdgeRenderer = ({
|
||||
let edgeType = edge.type || 'default';
|
||||
|
||||
if (!edgeTypes[edgeType]) {
|
||||
onError?.('011', errorMessages['011'](edgeType));
|
||||
onError?.('011', errorMessages['error011'](edgeType));
|
||||
edgeType = 'default';
|
||||
}
|
||||
|
||||
@@ -113,9 +112,12 @@ const EdgeRenderer = ({
|
||||
const sourcePosition = sourceHandle?.position || Position.Bottom;
|
||||
const targetPosition = targetHandle?.position || Position.Top;
|
||||
const isFocusable = !!(edge.focusable || (edgesFocusable && typeof edge.focusable === 'undefined'));
|
||||
const isUpdatable =
|
||||
typeof onEdgeUpdate !== 'undefined' &&
|
||||
(edge.updatable || (edgesUpdatable && typeof edge.updatable === 'undefined'));
|
||||
|
||||
if (!sourceHandle || !targetHandle) {
|
||||
onError?.('008', errorMessages['008'](sourceHandle, edge));
|
||||
onError?.('008', errorMessages['error008'](sourceHandle, edge));
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -172,6 +174,7 @@ const EdgeRenderer = ({
|
||||
rfId={rfId}
|
||||
ariaLabel={edge.ariaLabel}
|
||||
isFocusable={isFocusable}
|
||||
isUpdatable={isUpdatable}
|
||||
pathOptions={'pathOptions' in edge ? edge.pathOptions : undefined}
|
||||
interactionWidth={edge.interactionWidth}
|
||||
/>
|
||||
|
||||
@@ -75,7 +75,7 @@ const NodeRenderer = (props: NodeRendererProps) => {
|
||||
let nodeType = node.type || 'default';
|
||||
|
||||
if (!props.nodeTypes[nodeType]) {
|
||||
onError?.('003', errorMessages['003'](nodeType));
|
||||
onError?.('003', errorMessages['error003'](nodeType));
|
||||
|
||||
nodeType = 'default';
|
||||
}
|
||||
|
||||
@@ -119,6 +119,7 @@ const ReactFlow = forwardRef<ReactFlowRefType, ReactFlowProps>(
|
||||
nodesFocusable,
|
||||
nodeOrigin = initNodeOrigin,
|
||||
edgesFocusable,
|
||||
edgesUpdatable,
|
||||
elementsSelectable,
|
||||
defaultViewport = initDefaultViewport,
|
||||
minZoom = 0.5,
|
||||
@@ -270,6 +271,7 @@ const ReactFlow = forwardRef<ReactFlowRefType, ReactFlowProps>(
|
||||
nodesConnectable={nodesConnectable}
|
||||
nodesFocusable={nodesFocusable}
|
||||
edgesFocusable={edgesFocusable}
|
||||
edgesUpdatable={edgesUpdatable}
|
||||
elementsSelectable={elementsSelectable}
|
||||
elevateNodesOnSelect={elevateNodesOnSelect}
|
||||
minZoom={minZoom}
|
||||
|
||||
@@ -17,7 +17,7 @@ export function useNodeOrEdgeTypes(nodeOrEdgeTypes: any, createTypes: any): any
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
const typeKeys = Object.keys(nodeOrEdgeTypes);
|
||||
if (shallow(typesKeysRef.current, typeKeys)) {
|
||||
devWarn('002', errorMessages['002']());
|
||||
devWarn('002', errorMessages['error002']());
|
||||
}
|
||||
|
||||
typesKeysRef.current = typeKeys;
|
||||
|
||||
@@ -139,7 +139,7 @@ const ZoomPane = ({
|
||||
-(deltaX / currentZoom) * panOnScrollSpeed,
|
||||
-(deltaY / currentZoom) * panOnScrollSpeed
|
||||
);
|
||||
});
|
||||
}, { passive: false });
|
||||
} else if (typeof d3ZoomHandler !== 'undefined') {
|
||||
d3Selection.on('wheel.zoom', function (event: any, d: any) {
|
||||
if (!preventScrolling || isWrappedWithClass(event, noWheelClassName)) {
|
||||
@@ -148,7 +148,7 @@ const ZoomPane = ({
|
||||
|
||||
event.preventDefault();
|
||||
d3ZoomHandler.call(this, event, d);
|
||||
});
|
||||
}, { passive: false });
|
||||
}
|
||||
}
|
||||
}, [
|
||||
|
||||
@@ -103,7 +103,7 @@ export function calcNextPosition(
|
||||
]
|
||||
: currentExtent;
|
||||
} else {
|
||||
onError?.('005', errorMessages['005']());
|
||||
onError?.('005', errorMessages['error005']());
|
||||
|
||||
currentExtent = nodeExtent;
|
||||
}
|
||||
|
||||
@@ -3,16 +3,27 @@ import { internalsSymbol } from '@reactflow/system';
|
||||
import { useStore } from './useStore';
|
||||
import type { ReactFlowState } from '../types';
|
||||
|
||||
const selector = (s: ReactFlowState) => {
|
||||
export type UseNodesInitializedOptions = {
|
||||
includeHiddenNodes?: boolean;
|
||||
};
|
||||
|
||||
const selector = (options: UseNodesInitializedOptions) => (s: ReactFlowState) => {
|
||||
if (s.nodeInternals.size === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return s.getNodes().every((n) => n[internalsSymbol]?.handleBounds !== undefined);
|
||||
return s
|
||||
.getNodes()
|
||||
.filter((n) => (options.includeHiddenNodes ? true : !n.hidden))
|
||||
.every((n) => n[internalsSymbol]?.handleBounds !== undefined);
|
||||
};
|
||||
|
||||
function useNodesInitialized(): boolean {
|
||||
const initialized = useStore(selector);
|
||||
const defaultOptions = {
|
||||
includeHiddenNodes: false,
|
||||
};
|
||||
|
||||
function useNodesInitialized(options: UseNodesInitializedOptions = defaultOptions): boolean {
|
||||
const initialized = useStore(selector(options));
|
||||
|
||||
return initialized;
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ function useResizeHandler(rendererNode: MutableRefObject<HTMLDivElement | null>)
|
||||
const size = getDimensions(rendererNode.current);
|
||||
|
||||
if (size.height === 0 || size.width === 0) {
|
||||
store.getState().onError?.('004', errorMessages['004']());
|
||||
store.getState().onError?.('004', errorMessages['error004']());
|
||||
}
|
||||
|
||||
store.setState({ width: size.width || 500, height: size.height || 500 });
|
||||
|
||||
@@ -5,7 +5,7 @@ import { errorMessages } from '@reactflow/system';
|
||||
import StoreContext from '../contexts/RFStoreContext';
|
||||
import type { ReactFlowState } from '../types';
|
||||
|
||||
const zustandErrorMessage = errorMessages['001']();
|
||||
const zustandErrorMessage = errorMessages['error001']();
|
||||
|
||||
type ExtractState = StoreApi<ReactFlowState> extends { getState: () => infer T } ? T : never;
|
||||
|
||||
|
||||
@@ -19,9 +19,9 @@ export { default as useViewport } from './hooks/useViewport';
|
||||
export { default as useKeyPress } from './hooks/useKeyPress';
|
||||
export * from './hooks/useNodesEdgesState';
|
||||
export { useStore, useStoreApi } from './hooks/useStore';
|
||||
export { default as useOnViewportChange } from './hooks/useOnViewportChange';
|
||||
export { default as useOnSelectionChange } from './hooks/useOnSelectionChange';
|
||||
export { default as useNodesInitialized } from './hooks/useNodesInitialized';
|
||||
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 { default as useGetPointerPosition } from './hooks/useGetPointerPosition';
|
||||
export { useNodeId } from './contexts/NodeIdContext';
|
||||
export * from '@reactflow/edge-utils';
|
||||
|
||||
@@ -35,8 +35,8 @@ const createRFStore = () =>
|
||||
return Array.from(get().nodeInternals.values());
|
||||
},
|
||||
setEdges: (edges: Edge[]) => {
|
||||
const { defaultEdgeOptions = null } = get();
|
||||
set({ edges: defaultEdgeOptions ? edges.map((e) => ({ ...defaultEdgeOptions, ...e })) : edges });
|
||||
const { defaultEdgeOptions = {} } = get();
|
||||
set({ edges: edges.map((e) => ({ ...defaultEdgeOptions, ...e })) });
|
||||
},
|
||||
setDefaultNodesAndEdges: (nodes?: Node[], edges?: Edge[]) => {
|
||||
const hasDefaultNodes = typeof nodes !== 'undefined';
|
||||
@@ -299,6 +299,8 @@ const createRFStore = () =>
|
||||
connectionHandleId: initialState.connectionHandleId,
|
||||
connectionHandleType: initialState.connectionHandleType,
|
||||
connectionStatus: initialState.connectionStatus,
|
||||
connectionStartHandle: initialState.connectionStartHandle,
|
||||
connectionEndHandle: initialState.connectionEndHandle,
|
||||
}),
|
||||
reset: () => set({ ...initialState }),
|
||||
}));
|
||||
|
||||
@@ -42,6 +42,7 @@ const initialState: ReactFlowStore = {
|
||||
nodesConnectable: true,
|
||||
nodesFocusable: true,
|
||||
edgesFocusable: true,
|
||||
edgesUpdatable: true,
|
||||
elementsSelectable: true,
|
||||
elevateNodesOnSelect: true,
|
||||
fitViewOnInit: false,
|
||||
@@ -51,6 +52,8 @@ const initialState: ReactFlowStore = {
|
||||
multiSelectionActive: false,
|
||||
|
||||
connectionStartHandle: null,
|
||||
connectionEndHandle: null,
|
||||
connectionClickStartHandle: null,
|
||||
connectOnClick: true,
|
||||
|
||||
ariaLiveMessage: '',
|
||||
|
||||
@@ -144,7 +144,7 @@
|
||||
min-width: 5px;
|
||||
min-height: 5px;
|
||||
|
||||
&.connectable {
|
||||
&.connectionindicator {
|
||||
pointer-events: all;
|
||||
cursor: crosshair;
|
||||
}
|
||||
|
||||
@@ -114,6 +114,7 @@ export type ReactFlowProps = HTMLAttributes<HTMLDivElement> & {
|
||||
nodesFocusable?: boolean;
|
||||
nodeOrigin?: NodeOrigin;
|
||||
edgesFocusable?: boolean;
|
||||
edgesUpdatable?: boolean;
|
||||
initNodeOrigin?: NodeOrigin;
|
||||
elementsSelectable?: boolean;
|
||||
selectNodesOnDrag?: boolean;
|
||||
|
||||
@@ -25,11 +25,14 @@ export type EdgeLabelOptions = {
|
||||
labelBgBorderRadius?: number;
|
||||
};
|
||||
|
||||
export type EdgeUpdatable = boolean | HandleType;
|
||||
|
||||
export type DefaultEdge<EdgeData = any> = BaseEdge<EdgeData> & {
|
||||
style?: CSSProperties;
|
||||
className?: string;
|
||||
sourceNode?: Node;
|
||||
targetNode?: Node;
|
||||
updatable?: EdgeUpdatable;
|
||||
} & EdgeLabelOptions;
|
||||
|
||||
type SmoothStepEdgeType<T> = DefaultEdge<T> & {
|
||||
@@ -68,6 +71,7 @@ export type WrapEdgeProps<T = any> = Omit<Edge<T>, 'sourceHandle' | 'targetHandl
|
||||
onEdgeUpdateEnd?: (event: MouseEvent | TouchEvent, edge: Edge, handleType: HandleType) => void;
|
||||
rfId?: string;
|
||||
isFocusable: boolean;
|
||||
isUpdatable: EdgeUpdatable;
|
||||
pathOptions?: BezierPathOptions | SmoothStepPathOptions;
|
||||
};
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
OnViewportChange,
|
||||
SelectionRect,
|
||||
SnapGrid,
|
||||
StartHandle,
|
||||
ConnectingHandle,
|
||||
Transform,
|
||||
XYPosition,
|
||||
} from '@reactflow/system';
|
||||
@@ -80,12 +80,15 @@ export type ReactFlowStore = {
|
||||
nodesConnectable: boolean;
|
||||
nodesFocusable: boolean;
|
||||
edgesFocusable: boolean;
|
||||
edgesUpdatable: boolean;
|
||||
elementsSelectable: boolean;
|
||||
elevateNodesOnSelect: boolean;
|
||||
|
||||
multiSelectionActive: boolean;
|
||||
|
||||
connectionStartHandle: StartHandle | null;
|
||||
connectionStartHandle: ConnectingHandle | null;
|
||||
connectionEndHandle: ConnectingHandle | null;
|
||||
connectionClickStartHandle: ConnectingHandle | null;
|
||||
|
||||
onNodeDragStart?: NodeDragHandler;
|
||||
onNodeDrag?: NodeDragHandler;
|
||||
|
||||
Reference in New Issue
Block a user