Merge branch 'main' into middlewares
This commit is contained in:
@@ -50,6 +50,7 @@ import CancelConnection from '../examples/CancelConnection';
|
||||
import InteractiveMinimap from '../examples/InteractiveMinimap';
|
||||
import UseOnSelectionChange from '../examples/UseOnSelectionChange';
|
||||
import NodeToolbar from '../examples/NodeToolbar';
|
||||
import EdgeToolbar from '../examples/EdgeToolbar';
|
||||
import UseConnection from '../examples/UseConnection';
|
||||
import UseNodesInitialized from '../examples/UseNodesInit';
|
||||
import UseNodesData from '../examples/UseNodesData';
|
||||
@@ -193,6 +194,11 @@ const routes: IRoute[] = [
|
||||
path: 'edge-routing',
|
||||
component: EdgeRouting,
|
||||
},
|
||||
{
|
||||
name: 'Edge Toolbar',
|
||||
path: 'edge-toolbar',
|
||||
component: EdgeToolbar,
|
||||
},
|
||||
{
|
||||
name: 'Empty',
|
||||
path: 'empty',
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { MouseEvent, useCallback } from 'react';
|
||||
import { MouseEvent, useCallback, useState } from 'react';
|
||||
import {
|
||||
ReactFlow,
|
||||
MiniMap,
|
||||
@@ -134,47 +134,57 @@ const BasicFlow = () => {
|
||||
});
|
||||
fitView();
|
||||
};
|
||||
const [isHidden, setIsHidden] = useState(false);
|
||||
|
||||
const toggleVisibility = () => {
|
||||
setIsHidden(!isHidden);
|
||||
};
|
||||
return (
|
||||
<ReactFlow
|
||||
defaultNodes={initialNodes}
|
||||
defaultEdges={initialEdges}
|
||||
onNodesChange={console.log}
|
||||
onNodeClick={onNodeClick}
|
||||
onNodeDragStop={onNodeDragStop}
|
||||
onNodeDragStart={onNodeDragStart}
|
||||
onNodeDrag={onNodeDrag}
|
||||
onSelectionDragStart={printSelectionEvent('selection drag start')}
|
||||
onSelectionDrag={printSelectionEvent('selection drag')}
|
||||
onSelectionDragStop={printSelectionEvent('selection drag stop')}
|
||||
className="react-flow-basic-example"
|
||||
minZoom={0.2}
|
||||
maxZoom={4}
|
||||
fitView
|
||||
fitViewOptions={fitViewOptions}
|
||||
defaultEdgeOptions={defaultEdgeOptions}
|
||||
selectNodesOnDrag={false}
|
||||
elevateEdgesOnSelect
|
||||
elevateNodesOnSelect={false}
|
||||
nodeDragThreshold={0}
|
||||
>
|
||||
<Background variant={BackgroundVariant.Dots} />
|
||||
<MiniMap />
|
||||
<Controls />
|
||||
<>
|
||||
<ReactFlow
|
||||
defaultNodes={initialNodes}
|
||||
defaultEdges={initialEdges}
|
||||
onNodesChange={console.log}
|
||||
onNodeClick={onNodeClick}
|
||||
onNodeDragStop={onNodeDragStop}
|
||||
onNodeDragStart={onNodeDragStart}
|
||||
onNodeDrag={onNodeDrag}
|
||||
onSelectionDragStart={printSelectionEvent('selection drag start')}
|
||||
onSelectionDrag={printSelectionEvent('selection drag')}
|
||||
onSelectionDragStop={printSelectionEvent('selection drag stop')}
|
||||
className="react-flow-basic-example"
|
||||
style={{ display: isHidden ? 'none' : 'block' }}
|
||||
minZoom={0.2}
|
||||
maxZoom={4}
|
||||
fitView
|
||||
fitViewOptions={fitViewOptions}
|
||||
defaultEdgeOptions={defaultEdgeOptions}
|
||||
selectNodesOnDrag={false}
|
||||
elevateEdgesOnSelect
|
||||
elevateNodesOnSelect={false}
|
||||
nodeDragThreshold={0}
|
||||
>
|
||||
<Background variant={BackgroundVariant.Dots} />
|
||||
<MiniMap />
|
||||
<Controls />
|
||||
|
||||
<Panel position="top-right">
|
||||
<button onClick={resetTransform}>reset transform</button>
|
||||
<button onClick={updatePos}>change pos</button>
|
||||
<button onClick={toggleClassnames}>toggle classnames</button>
|
||||
<button onClick={logToObject}>toObject</button>
|
||||
<Panel position="top-right">
|
||||
<button onClick={resetTransform}>reset transform</button>
|
||||
<button onClick={updatePos}>change pos</button>
|
||||
<button onClick={toggleClassnames}>toggle classnames</button>
|
||||
<button onClick={logToObject}>toObject</button>
|
||||
|
||||
<button onClick={deleteSelectedElements}>deleteSelectedElements</button>
|
||||
<button onClick={deleteSomeElements}>deleteSomeElements</button>
|
||||
<button onClick={onSetNodes}>setNodes</button>
|
||||
<button onClick={onUpdateNode}>updateNode</button>
|
||||
<button onClick={addNode}>addNode</button>
|
||||
</Panel>
|
||||
</ReactFlow>
|
||||
<button onClick={deleteSelectedElements}>deleteSelectedElements</button>
|
||||
<button onClick={deleteSomeElements}>deleteSomeElements</button>
|
||||
<button onClick={onSetNodes}>setNodes</button>
|
||||
<button onClick={onUpdateNode}>updateNode</button>
|
||||
<button onClick={addNode}>addNode</button>
|
||||
</Panel>
|
||||
</ReactFlow>
|
||||
<button onClick={toggleVisibility} style={{ position: 'absolute', zIndex: 10, right: 10, top: 100 }}>
|
||||
{isHidden ? 'Show' : 'Hide'} Flow
|
||||
</button>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { ConnectionLineComponentProps } from '@xyflow/react';
|
||||
|
||||
function ConnectionLine({ fromX, fromY, toX, toY }: ConnectionLineComponentProps) {
|
||||
function ConnectionLine({ fromX, fromY, toX, toY, pointer }: ConnectionLineComponentProps) {
|
||||
console.log('pointer', pointer);
|
||||
return (
|
||||
<>
|
||||
<path
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { MouseEvent, CSSProperties, useCallback } from 'react';
|
||||
import { MouseEvent, CSSProperties, useCallback, useState } from 'react';
|
||||
|
||||
import {
|
||||
ReactFlow,
|
||||
@@ -14,19 +14,13 @@ import {
|
||||
ReactFlowInstance,
|
||||
useEdgesState,
|
||||
useNodesState,
|
||||
Panel,
|
||||
} from '@xyflow/react';
|
||||
|
||||
const onInit = (reactFlowInstance: ReactFlowInstance) => console.log('flow loaded:', reactFlowInstance);
|
||||
const onNodeClick = (_: MouseEvent, node: Node) => console.log('click', node);
|
||||
const onNodeDragStop = (_: MouseEvent, node: Node) => console.log('drag stop', node);
|
||||
|
||||
const buttonStyle: CSSProperties = {
|
||||
position: 'absolute',
|
||||
left: 10,
|
||||
top: 10,
|
||||
zIndex: 4,
|
||||
};
|
||||
|
||||
const CustomMiniMapNode = ({ x, y, width, height }: MiniMapNodeProps) => {
|
||||
return <circle cx={x} cy={y} r={Math.max(width, height) / 2} fill="#ffcc00" />;
|
||||
};
|
||||
@@ -34,6 +28,7 @@ const CustomMiniMapNode = ({ x, y, width, height }: MiniMapNodeProps) => {
|
||||
const CustomMiniMapNodeFlow = () => {
|
||||
const [nodes, setNodes, onNodesChange] = useNodesState<Node>([]);
|
||||
const [edges, setEdges, onEdgesChange] = useEdgesState<Edge>([]);
|
||||
const [hideAllNodes, setHideAllNodes] = useState(false);
|
||||
|
||||
const onConnect = useCallback((params: Connection | Edge) => setEdges((els) => addEdge(params, els)), [setEdges]);
|
||||
const addRandomNode = () => {
|
||||
@@ -45,10 +40,20 @@ const CustomMiniMapNodeFlow = () => {
|
||||
x: Math.random() * window.innerWidth,
|
||||
y: Math.random() * window.innerHeight,
|
||||
},
|
||||
hidden: hideAllNodes,
|
||||
};
|
||||
setNodes((nds) => nds.concat(newNode));
|
||||
};
|
||||
|
||||
const toggleHideAllNodes = () => {
|
||||
setHideAllNodes(prev => {
|
||||
const next = !prev;
|
||||
setNodes(nds => nds.map(n => ({ ...n, hidden: next })));
|
||||
setEdges(eds => eds.map(e => ({ ...e, hidden: next })));
|
||||
return next;
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<ReactFlow
|
||||
nodes={nodes}
|
||||
@@ -65,9 +70,14 @@ const CustomMiniMapNodeFlow = () => {
|
||||
<Background variant={BackgroundVariant.Lines} />
|
||||
<MiniMap nodeComponent={CustomMiniMapNode} />
|
||||
|
||||
<button type="button" onClick={addRandomNode} style={buttonStyle}>
|
||||
add node
|
||||
</button>
|
||||
<Panel position="top-left">
|
||||
<button type="button" onClick={addRandomNode}>
|
||||
add node
|
||||
</button>
|
||||
<button type="button" onClick={toggleHideAllNodes}>
|
||||
{hideAllNodes ? 'show all nodes' : 'hide all nodes'}
|
||||
</button>
|
||||
</Panel>
|
||||
</ReactFlow>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -30,7 +30,7 @@ function ColorSelectorNode({ data, isConnectable }: NodeProps<ColorSelectorNode>
|
||||
<div>
|
||||
Custom Color Picker Node: <strong>{data.color}</strong>
|
||||
</div>
|
||||
<input className="nodrag" type="color" onChange={data.onChange} defaultValue={data.color} />
|
||||
<input className="nodrag nokey" type="color" onChange={data.onChange} defaultValue={data.color} />
|
||||
<Handle
|
||||
type="source"
|
||||
position={Position.Right}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
import { getBezierPath, BaseEdge, EdgeProps, useReactFlow, getStraightPath, getSmoothStepPath } from '@xyflow/react';
|
||||
import { EdgeToolbar } from '@xyflow/react';
|
||||
|
||||
const getPath = (props: EdgeProps) => {
|
||||
switch (props.data!.type) {
|
||||
case 'smoothstep':
|
||||
return getSmoothStepPath(props);
|
||||
case 'straight':
|
||||
return getStraightPath(props);
|
||||
default:
|
||||
return getBezierPath(props);
|
||||
}
|
||||
};
|
||||
|
||||
export function CustomEdge(props: EdgeProps) {
|
||||
const [edgePath, centerX, centerY] = getPath(props);
|
||||
const { setEdges } = useReactFlow();
|
||||
|
||||
const deleteEdge = () => {
|
||||
setEdges((edges) => edges.filter((edge) => edge.id !== props.id));
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<BaseEdge id={props.id} path={edgePath} />
|
||||
<EdgeToolbar
|
||||
edgeId={props.id}
|
||||
x={centerX + 0}
|
||||
y={centerY + 0}
|
||||
alignX={props.data?.align?.[0] ?? 'center'}
|
||||
alignY={props.data?.align?.[1] ?? 'center'}
|
||||
isVisible
|
||||
>
|
||||
<button style={{}} onClick={deleteEdge}>
|
||||
Delete
|
||||
</button>
|
||||
</EdgeToolbar>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
import {
|
||||
Background,
|
||||
BackgroundVariant,
|
||||
Controls,
|
||||
Edge,
|
||||
EdgeTypes,
|
||||
MiniMap,
|
||||
Node,
|
||||
Position,
|
||||
ReactFlow,
|
||||
} from '@xyflow/react';
|
||||
|
||||
import { CustomEdge } from './CustomEdge';
|
||||
|
||||
const edgeTypes: EdgeTypes = {
|
||||
custom: CustomEdge,
|
||||
};
|
||||
|
||||
const initialNodes: Node[] = [
|
||||
{
|
||||
id: '1',
|
||||
data: { label: 'Node 1', toolbarPosition: Position.Top },
|
||||
position: { x: 0, y: 0 },
|
||||
className: 'react-flow__node-default',
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
data: { label: 'Node 2', toolbarPosition: Position.Top },
|
||||
position: { x: 100, y: 150 },
|
||||
className: 'react-flow__node-default',
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
data: { label: 'Node 3', toolbarPosition: Position.Top },
|
||||
position: { x: 200, y: 0 },
|
||||
className: 'react-flow__node-default',
|
||||
},
|
||||
];
|
||||
|
||||
const initialEdges: Edge[] = [
|
||||
{
|
||||
id: 'e1-2',
|
||||
source: '1',
|
||||
target: '2',
|
||||
type: 'custom',
|
||||
data: { type: 'smoothstep', align: ['left', 'bottom'] },
|
||||
},
|
||||
{
|
||||
id: 'e3-2',
|
||||
source: '3',
|
||||
target: '2',
|
||||
type: 'custom',
|
||||
data: { type: 'bezier', align: ['right', 'bottom'] },
|
||||
},
|
||||
{
|
||||
id: 'e1-3',
|
||||
source: '1',
|
||||
target: '3',
|
||||
type: 'custom',
|
||||
data: { type: 'straight', align: ['center', 'center'] },
|
||||
},
|
||||
];
|
||||
|
||||
export default function EdgeToolbarExample() {
|
||||
return (
|
||||
<ReactFlow
|
||||
defaultNodes={initialNodes}
|
||||
defaultEdges={initialEdges}
|
||||
className="react-flow-edge-toolbar-example"
|
||||
minZoom={0.2}
|
||||
maxZoom={4}
|
||||
fitView
|
||||
edgeTypes={edgeTypes}
|
||||
>
|
||||
<Background variant={BackgroundVariant.Dots} />
|
||||
<MiniMap />
|
||||
<Controls />
|
||||
</ReactFlow>
|
||||
);
|
||||
}
|
||||
@@ -30,10 +30,11 @@ const BasicFlow = () => {
|
||||
<ReactFlow
|
||||
defaultNodes={initialNodes}
|
||||
defaultEdges={initialEdges}
|
||||
selectionOnDrag
|
||||
selectionOnDrag={true}
|
||||
selectionMode={SelectionMode.Partial}
|
||||
panOnDrag={panOnDrag}
|
||||
panOnScroll
|
||||
paneClickDistance={100}
|
||||
zoomActivationKeyCode="Meta"
|
||||
multiSelectionKeyCode={MULTI_SELECT_KEY}
|
||||
onPaneContextMenu={onPaneContextMenu}
|
||||
@@ -43,6 +44,12 @@ const BasicFlow = () => {
|
||||
onMoveStart={onMoveStart}
|
||||
onMove={onMove}
|
||||
onMoveEnd={onMoveEnd}
|
||||
onPaneClick={(e) => console.log('pane click', e)}
|
||||
onSelectionStart={(e) => console.log('on selection start', e)}
|
||||
onSelectionEnd={(e) => console.log('on selection end', e)}
|
||||
onPointerDown={(e) => console.log('pointer down', e)}
|
||||
onPointerUp={(e) => console.log('pointer up', e)}
|
||||
onClick={(e) => console.log('click', e)}
|
||||
>
|
||||
<Background variant={BackgroundVariant.Cross} />
|
||||
<Controls />
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { memo, FC } from 'react';
|
||||
import { Handle, Position, NodeProps, NodeResizer } from '@xyflow/react';
|
||||
import { Handle, Position, NodeProps, NodeResizer, useKeyPress } from '@xyflow/react';
|
||||
|
||||
const DefaultResizerNode: FC<NodeProps> = ({ data, selected }) => {
|
||||
const keepAspectRatio = useKeyPress('k');
|
||||
|
||||
return (
|
||||
<>
|
||||
<NodeResizer
|
||||
@@ -14,7 +16,7 @@ const DefaultResizerNode: FC<NodeProps> = ({ data, selected }) => {
|
||||
onResizeStart={data.onResizeStart ?? undefined}
|
||||
onResize={data.onResize ?? undefined}
|
||||
onResizeEnd={data.onResizeEnd ?? undefined}
|
||||
keepAspectRatio={data.keepAspectRatio ?? undefined}
|
||||
keepAspectRatio={keepAspectRatio || (data.keepAspectRatio ?? undefined)}
|
||||
/>
|
||||
<Handle type="target" position={Position.Left} />
|
||||
<div>{data.label}</div>
|
||||
|
||||
@@ -239,6 +239,16 @@ const StressFlow = () => {
|
||||
<button onClick={remount}>re-mount</button>
|
||||
<button onClick={updatePos}>change pos</button>
|
||||
<button onClick={updateElements}>update elements</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
setNodes((nds) => [
|
||||
...nds,
|
||||
{ id: (nds.length + 1).toString(), position: { x: 0, y: 0 }, data: { label: `Node ${nds.length + 1}` } },
|
||||
]);
|
||||
}}
|
||||
>
|
||||
Add element
|
||||
</button>
|
||||
</Panel>
|
||||
</ReactFlow>
|
||||
);
|
||||
|
||||
@@ -27,15 +27,15 @@ const onEdgeClick = (_: MouseEvent, edge: Edge) => console.log('click', edge);
|
||||
|
||||
const defaultViewport = { x: 0, y: 0, zoom: 1.5 };
|
||||
const initialNodes: Node[] = [
|
||||
{
|
||||
id: 'extent',
|
||||
position: { x: 0, y: 0 },
|
||||
width: 1000,
|
||||
height: 1000,
|
||||
data: { label: 'Extent' },
|
||||
origin: [0, 0],
|
||||
zIndex: -1,
|
||||
},
|
||||
// {
|
||||
// id: 'extent',
|
||||
// position: { x: 0, y: 0 },
|
||||
// width: 1000,
|
||||
// height: 1000,
|
||||
// data: { label: 'Extent' },
|
||||
// origin: [0, 0],
|
||||
// zIndex: -1,
|
||||
// },
|
||||
{
|
||||
id: '1',
|
||||
type: 'input',
|
||||
@@ -96,12 +96,12 @@ const initialNodes: Node[] = [
|
||||
},
|
||||
{
|
||||
id: '5',
|
||||
type: 'group',
|
||||
// type: 'group',
|
||||
data: { label: 'Node 5' },
|
||||
position: { x: 650, y: 250 },
|
||||
className: 'light',
|
||||
style: { width: 100, height: 100 },
|
||||
zIndex: 1000,
|
||||
// zIndex: 1000,
|
||||
},
|
||||
{
|
||||
id: '5a',
|
||||
|
||||
Reference in New Issue
Block a user