Refactor: CSS handling (#2344)
* refactor(css): only load base styles, add css task, cleanup exports * style(base): add edge label bg * refactor(css): use css-utils * feat(core): add Panel component * refactor(background): cleanup * refactor(css-handling): cleanup
This commit is contained in:
@@ -1 +1,5 @@
|
||||
nodeLinker: node-modules
|
||||
|
||||
plugins:
|
||||
- path: .yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs
|
||||
spec: "@yarnpkg/plugin-workspace-tools"
|
||||
|
||||
@@ -4,5 +4,4 @@ module.exports = {
|
||||
'@babel/preset-typescript',
|
||||
'@babel/preset-env',
|
||||
],
|
||||
plugins: ['./tooling/inject-css-babel-plugin'],
|
||||
};
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"dev": "yarn run copystyles && next dev",
|
||||
"copystyles": "cp ../../packages/core/src/styles/theme-default.css ./styles/theme-default.css",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "next lint"
|
||||
@@ -23,6 +24,9 @@
|
||||
"devDependencies": {
|
||||
"@types/dagre": "^0.7.47",
|
||||
"eslint": "8.19.0",
|
||||
"eslint-config-next": "12.2.2"
|
||||
"eslint-config-next": "12.2.2",
|
||||
"postcss-flexbugs-fixes": "^5.0.2",
|
||||
"postcss-nested": "^5.0.6",
|
||||
"postcss-preset-env": "^7.7.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
import React, { FC } from 'react';
|
||||
|
||||
import ReactFlow, {
|
||||
import {
|
||||
ReactFlow,
|
||||
Node,
|
||||
ReactFlowProvider,
|
||||
useNodesState,
|
||||
} from '@react-flow/core';
|
||||
|
||||
import Background, {
|
||||
import {
|
||||
Background,
|
||||
BackgroundProps,
|
||||
BackgroundVariant,
|
||||
} from '@react-flow/background';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
|
||||
import ReactFlow, {
|
||||
import {
|
||||
ReactFlow,
|
||||
useReactFlow,
|
||||
Node,
|
||||
Edge,
|
||||
@@ -8,8 +8,7 @@ import ReactFlow, {
|
||||
useNodesState,
|
||||
useEdgesState,
|
||||
} from '@react-flow/core';
|
||||
|
||||
import Background, { BackgroundVariant } from '@react-flow/background';
|
||||
import { Background, BackgroundVariant } from '@react-flow/background';
|
||||
|
||||
const defaultNodes: Node[] = [
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React, { useCallback } from 'react';
|
||||
import ReactFlow, {
|
||||
import {
|
||||
ReactFlow,
|
||||
Node,
|
||||
addEdge,
|
||||
Connection,
|
||||
@@ -7,8 +8,7 @@ import ReactFlow, {
|
||||
useNodesState,
|
||||
useEdgesState,
|
||||
} from '@react-flow/core';
|
||||
|
||||
import Background, { BackgroundVariant } from '@react-flow/background';
|
||||
import { Background, BackgroundVariant } from '@react-flow/background';
|
||||
|
||||
import ConnectionLine from './ConnectionLine';
|
||||
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import React, { memo, FC, CSSProperties } from 'react';
|
||||
|
||||
import {
|
||||
Handle,
|
||||
Position,
|
||||
NodeProps,
|
||||
Connection,
|
||||
Edge,
|
||||
} from '@react-flow/core';
|
||||
} from '@react-flow/renderer';
|
||||
|
||||
const targetHandleStyle: CSSProperties = { background: '#555' };
|
||||
const sourceHandleStyleA: CSSProperties = { ...targetHandleStyle, top: 10 };
|
||||
@@ -23,7 +22,7 @@ const ColorSelectorNode: FC<NodeProps> = ({ data, isConnectable }) => {
|
||||
return (
|
||||
<>
|
||||
<Handle
|
||||
type='target'
|
||||
type="target"
|
||||
position={Position.Left}
|
||||
style={targetHandleStyle}
|
||||
onConnect={onConnect}
|
||||
@@ -32,15 +31,15 @@ const ColorSelectorNode: FC<NodeProps> = ({ data, isConnectable }) => {
|
||||
Custom Color Picker Node: <strong>{data.color}</strong>
|
||||
</div>
|
||||
<input
|
||||
className='nodrag'
|
||||
type='color'
|
||||
className="nodrag"
|
||||
type="color"
|
||||
onChange={data.onChange}
|
||||
defaultValue={data.color}
|
||||
/>
|
||||
<Handle
|
||||
type='source'
|
||||
type="source"
|
||||
position={Position.Right}
|
||||
id='a'
|
||||
id="a"
|
||||
style={sourceHandleStyleA}
|
||||
isConnectable={isConnectable}
|
||||
onMouseDown={(e) => {
|
||||
@@ -48,9 +47,9 @@ const ColorSelectorNode: FC<NodeProps> = ({ data, isConnectable }) => {
|
||||
}}
|
||||
/>
|
||||
<Handle
|
||||
type='source'
|
||||
type="source"
|
||||
position={Position.Right}
|
||||
id='b'
|
||||
id="b"
|
||||
style={sourceHandleStyleB}
|
||||
isConnectable={isConnectable}
|
||||
/>
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import React, { useState, useEffect, MouseEvent } from 'react';
|
||||
import { ChangeEvent } from 'react';
|
||||
|
||||
import ReactFlow, {
|
||||
import React, { useState, useEffect, MouseEvent, ChangeEvent } from 'react';
|
||||
import {
|
||||
ReactFlow,
|
||||
MiniMap,
|
||||
Controls,
|
||||
addEdge,
|
||||
Node,
|
||||
ReactFlowInstance,
|
||||
@@ -10,10 +11,7 @@ import ReactFlow, {
|
||||
Connection,
|
||||
useNodesState,
|
||||
useEdgesState,
|
||||
} from '@react-flow/core';
|
||||
|
||||
import MiniMap from '@react-flow/minimap';
|
||||
import Controls from '@react-flow/controls';
|
||||
} from '@react-flow/renderer';
|
||||
|
||||
import ColorSelectorNode from './ColorSelectorNode';
|
||||
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import React from 'react';
|
||||
|
||||
import ReactFlow, {
|
||||
import {
|
||||
ReactFlow,
|
||||
useReactFlow,
|
||||
Node,
|
||||
Edge,
|
||||
ReactFlowProvider,
|
||||
} from '@react-flow/core';
|
||||
|
||||
import Background, { BackgroundVariant } from '@react-flow/background';
|
||||
import { Background, BackgroundVariant } from '@react-flow/background';
|
||||
|
||||
const defaultNodes: Node[] = [
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React, { MouseEvent } from 'react';
|
||||
import ReactFlow, {
|
||||
import {
|
||||
ReactFlow,
|
||||
Node,
|
||||
Edge,
|
||||
useNodesState,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React, { useState, DragEvent } from 'react';
|
||||
import ReactFlow, {
|
||||
import {
|
||||
ReactFlow,
|
||||
ReactFlowProvider,
|
||||
addEdge,
|
||||
ReactFlowInstance,
|
||||
@@ -9,7 +10,7 @@ import ReactFlow, {
|
||||
useNodesState,
|
||||
useEdgesState,
|
||||
} from '@react-flow/core';
|
||||
import Controls from '@react-flow/controls';
|
||||
import { Controls } from '@react-flow/controls';
|
||||
|
||||
import Sidebar from './Sidebar';
|
||||
|
||||
|
||||
@@ -3,18 +3,18 @@
|
||||
*/
|
||||
import React from 'react';
|
||||
|
||||
import ReactFlow, {
|
||||
import {
|
||||
ReactFlow,
|
||||
Background,
|
||||
Controls,
|
||||
MiniMap,
|
||||
addEdge,
|
||||
ReactFlowInstance,
|
||||
Connection,
|
||||
Edge,
|
||||
useNodesState,
|
||||
useEdgesState,
|
||||
} from '@react-flow/core';
|
||||
|
||||
import Background from '@react-flow/background';
|
||||
import Controls from '@react-flow/controls';
|
||||
import MiniMap from '@react-flow/minimap';
|
||||
} from '@react-flow/renderer';
|
||||
|
||||
import { getElements } from './utils';
|
||||
|
||||
@@ -44,10 +44,10 @@ const EdgeTypesFlow = () => {
|
||||
onConnect={onConnect}
|
||||
minZoom={0.2}
|
||||
zoomOnScroll={false}
|
||||
selectionKeyCode='a+s'
|
||||
selectionKeyCode="a+s"
|
||||
multiSelectionKeyCode={multiSelectionKeyCode}
|
||||
deleteKeyCode={deleteKeyCode}
|
||||
zoomActivationKeyCode='z'
|
||||
zoomActivationKeyCode="z"
|
||||
>
|
||||
<MiniMap />
|
||||
<Controls />
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
import React, { MouseEvent, useCallback } from 'react';
|
||||
import ReactFlow, {
|
||||
import {
|
||||
Controls,
|
||||
Background,
|
||||
ReactFlow,
|
||||
MiniMap,
|
||||
addEdge,
|
||||
Connection,
|
||||
Edge,
|
||||
EdgeTypes,
|
||||
MarkerType,
|
||||
Node,
|
||||
ReactFlowInstance,
|
||||
useEdgesState,
|
||||
useNodesState,
|
||||
} from '@react-flow/core';
|
||||
|
||||
import Controls from '@react-flow/controls';
|
||||
import Background from '@react-flow/background';
|
||||
import MiniMap from '@react-flow/minimap';
|
||||
} from '@react-flow/renderer';
|
||||
|
||||
import CustomEdge from './CustomEdge';
|
||||
import CustomEdge2 from './CustomEdge2';
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
import React, { MouseEvent, CSSProperties } from 'react';
|
||||
import React, { MouseEvent, CSSProperties, useCallback } from 'react';
|
||||
|
||||
import ReactFlow, {
|
||||
import {
|
||||
ReactFlow,
|
||||
Background,
|
||||
BackgroundVariant,
|
||||
Controls,
|
||||
addEdge,
|
||||
Node,
|
||||
Connection,
|
||||
@@ -8,10 +12,7 @@ import ReactFlow, {
|
||||
useNodesState,
|
||||
useEdgesState,
|
||||
ReactFlowInstance,
|
||||
} from '@react-flow/core';
|
||||
|
||||
import Controls from '@react-flow/controls';
|
||||
import Background, { BackgroundVariant } from '@react-flow/background';
|
||||
} from '@react-flow/renderer';
|
||||
|
||||
const onInit = (reactFlowInstance: ReactFlowInstance) =>
|
||||
console.log('flow loaded:', reactFlowInstance);
|
||||
@@ -30,8 +31,10 @@ const EmptyFlow = () => {
|
||||
const [nodes, setNodes, onNodesChange] = useNodesState([]);
|
||||
const [edges, setEdges, onEdgesChange] = useEdgesState([]);
|
||||
|
||||
const onConnect = (params: Connection | Edge) =>
|
||||
setEdges((els) => addEdge(params, els));
|
||||
const onConnect = useCallback(
|
||||
(params: Connection | Edge) => setEdges((els) => addEdge(params, els)),
|
||||
[setEdges]
|
||||
);
|
||||
const addRandomNode = () => {
|
||||
const nodeId = (nodes.length + 1).toString();
|
||||
const newNode: Node = {
|
||||
@@ -60,7 +63,7 @@ const EmptyFlow = () => {
|
||||
<Controls />
|
||||
<Background variant={BackgroundVariant.Lines} />
|
||||
|
||||
<button type='button' onClick={addRandomNode} style={buttonStyle}>
|
||||
<button type="button" onClick={addRandomNode} style={buttonStyle}>
|
||||
add node
|
||||
</button>
|
||||
</ReactFlow>
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import React, { useCallback } from 'react';
|
||||
|
||||
import ReactFlow, {
|
||||
import {
|
||||
ReactFlow,
|
||||
Background,
|
||||
addEdge,
|
||||
ReactFlowInstance,
|
||||
EdgeTypes,
|
||||
Connection,
|
||||
useNodesState,
|
||||
useEdgesState,
|
||||
} from '@react-flow/core';
|
||||
|
||||
import Background from '@react-flow/background';
|
||||
} from '@react-flow/renderer';
|
||||
|
||||
import styles from './style.module.css';
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, { useState, useEffect, useCallback } from 'react';
|
||||
|
||||
import ReactFlow, {
|
||||
import {
|
||||
ReactFlow,
|
||||
addEdge,
|
||||
Connection,
|
||||
Edge,
|
||||
@@ -9,8 +10,8 @@ import ReactFlow, {
|
||||
useEdgesState,
|
||||
} from '@react-flow/core';
|
||||
|
||||
import Controls from '@react-flow/controls';
|
||||
import MiniMap from '@react-flow/minimap';
|
||||
import { Controls } from '@react-flow/controls';
|
||||
import { MiniMap } from '@react-flow/minimap';
|
||||
|
||||
const initialNodes: Node[] = [
|
||||
{
|
||||
@@ -85,14 +86,14 @@ const HiddenFlow = () => {
|
||||
|
||||
<div style={{ position: 'absolute', left: 10, top: 10, zIndex: 4 }}>
|
||||
<div>
|
||||
<label htmlFor='ishidden'>
|
||||
<label htmlFor="ishidden">
|
||||
isHidden
|
||||
<input
|
||||
id='ishidden'
|
||||
type='checkbox'
|
||||
id="ishidden"
|
||||
type="checkbox"
|
||||
checked={isHidden}
|
||||
onChange={(event) => setIsHidden(event.target.checked)}
|
||||
className='react-flow__ishidden'
|
||||
className="react-flow__ishidden"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
@@ -3,7 +3,8 @@ import React, {
|
||||
MouseEvent as ReactMouseEvent,
|
||||
WheelEvent,
|
||||
} from 'react';
|
||||
import ReactFlow, {
|
||||
import {
|
||||
ReactFlow,
|
||||
addEdge,
|
||||
Node,
|
||||
Connection,
|
||||
@@ -14,8 +15,8 @@ import ReactFlow, {
|
||||
useEdgesState,
|
||||
} from '@react-flow/core';
|
||||
|
||||
import Controls from '@react-flow/controls';
|
||||
import MiniMap from '@react-flow/minimap';
|
||||
import { Controls } from '@react-flow/controls';
|
||||
import { MiniMap } from '@react-flow/minimap';
|
||||
|
||||
const initialNodes: Node[] = [
|
||||
{
|
||||
@@ -102,151 +103,151 @@ const InteractionFlow = () => {
|
||||
|
||||
<div style={{ position: 'absolute', left: 10, top: 10, zIndex: 4 }}>
|
||||
<div>
|
||||
<label htmlFor='draggable'>
|
||||
<label htmlFor="draggable">
|
||||
nodesDraggable
|
||||
<input
|
||||
id='draggable'
|
||||
type='checkbox'
|
||||
id="draggable"
|
||||
type="checkbox"
|
||||
checked={isDraggable}
|
||||
onChange={(event) => setIsDraggable(event.target.checked)}
|
||||
className='react-flow__draggable'
|
||||
className="react-flow__draggable"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor='connectable'>
|
||||
<label htmlFor="connectable">
|
||||
nodesConnectable
|
||||
<input
|
||||
id='connectable'
|
||||
type='checkbox'
|
||||
id="connectable"
|
||||
type="checkbox"
|
||||
checked={isConnectable}
|
||||
onChange={(event) => setIsConnectable(event.target.checked)}
|
||||
className='react-flow__connectable'
|
||||
className="react-flow__connectable"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor='selectable'>
|
||||
<label htmlFor="selectable">
|
||||
elementsSelectable
|
||||
<input
|
||||
id='selectable'
|
||||
type='checkbox'
|
||||
id="selectable"
|
||||
type="checkbox"
|
||||
checked={isSelectable}
|
||||
onChange={(event) => setIsSelectable(event.target.checked)}
|
||||
className='react-flow__selectable'
|
||||
className="react-flow__selectable"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor='zoomonscroll'>
|
||||
<label htmlFor="zoomonscroll">
|
||||
zoomOnScroll
|
||||
<input
|
||||
id='zoomonscroll'
|
||||
type='checkbox'
|
||||
id="zoomonscroll"
|
||||
type="checkbox"
|
||||
checked={zoomOnScroll}
|
||||
onChange={(event) => setZoomOnScroll(event.target.checked)}
|
||||
className='react-flow__zoomonscroll'
|
||||
className="react-flow__zoomonscroll"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor='zoomonpinch'>
|
||||
<label htmlFor="zoomonpinch">
|
||||
zoomOnPinch
|
||||
<input
|
||||
id='zoomonpinch'
|
||||
type='checkbox'
|
||||
id="zoomonpinch"
|
||||
type="checkbox"
|
||||
checked={zoomOnPinch}
|
||||
onChange={(event) => setZoomOnPinch(event.target.checked)}
|
||||
className='react-flow__zoomonpinch'
|
||||
className="react-flow__zoomonpinch"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor='panonscroll'>
|
||||
<label htmlFor="panonscroll">
|
||||
panOnScroll
|
||||
<input
|
||||
id='panonscroll'
|
||||
type='checkbox'
|
||||
id="panonscroll"
|
||||
type="checkbox"
|
||||
checked={panOnScroll}
|
||||
onChange={(event) => setPanOnScroll(event.target.checked)}
|
||||
className='react-flow__panonscroll'
|
||||
className="react-flow__panonscroll"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor='panonscrollmode'>
|
||||
<label htmlFor="panonscrollmode">
|
||||
panOnScrollMode
|
||||
<select
|
||||
id='panonscrollmode'
|
||||
id="panonscrollmode"
|
||||
value={panOnScrollMode}
|
||||
onChange={(event) =>
|
||||
setPanOnScrollMode(event.target.value as PanOnScrollMode)
|
||||
}
|
||||
className='react-flow__panonscrollmode'
|
||||
className="react-flow__panonscrollmode"
|
||||
>
|
||||
<option value='free'>free</option>
|
||||
<option value='horizontal'>horizontal</option>
|
||||
<option value='vertical'>vertical</option>
|
||||
<option value="free">free</option>
|
||||
<option value="horizontal">horizontal</option>
|
||||
<option value="vertical">vertical</option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor='zoomondbl'>
|
||||
<label htmlFor="zoomondbl">
|
||||
zoomOnDoubleClick
|
||||
<input
|
||||
id='zoomondbl'
|
||||
type='checkbox'
|
||||
id="zoomondbl"
|
||||
type="checkbox"
|
||||
checked={zoomOnDoubleClick}
|
||||
onChange={(event) => setZoomOnDoubleClick(event.target.checked)}
|
||||
className='react-flow__zoomondbl'
|
||||
className="react-flow__zoomondbl"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor='panondrag'>
|
||||
<label htmlFor="panondrag">
|
||||
panOnDrag
|
||||
<input
|
||||
id='panondrag'
|
||||
type='checkbox'
|
||||
id="panondrag"
|
||||
type="checkbox"
|
||||
checked={panOnDrag}
|
||||
onChange={(event) => setPanOnDrag(event.target.checked)}
|
||||
className='react-flow__panondrag'
|
||||
className="react-flow__panondrag"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor='capturezoompaneclick'>
|
||||
<label htmlFor="capturezoompaneclick">
|
||||
capture onPaneClick
|
||||
<input
|
||||
id='capturezoompaneclick'
|
||||
type='checkbox'
|
||||
id="capturezoompaneclick"
|
||||
type="checkbox"
|
||||
checked={captureZoomClick}
|
||||
onChange={(event) => setCaptureZoomClick(event.target.checked)}
|
||||
className='react-flow__capturezoompaneclick'
|
||||
className="react-flow__capturezoompaneclick"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor='capturezoompanescroll'>
|
||||
<label htmlFor="capturezoompanescroll">
|
||||
capture onPaneScroll
|
||||
<input
|
||||
id='capturezoompanescroll'
|
||||
type='checkbox'
|
||||
id="capturezoompanescroll"
|
||||
type="checkbox"
|
||||
checked={captureZoomScroll}
|
||||
onChange={(event) => setCaptureZoomScroll(event.target.checked)}
|
||||
className='react-flow__capturezoompanescroll'
|
||||
className="react-flow__capturezoompanescroll"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor='captureelementclick'>
|
||||
<label htmlFor="captureelementclick">
|
||||
capture onElementClick
|
||||
<input
|
||||
id='captureelementclick'
|
||||
type='checkbox'
|
||||
id="captureelementclick"
|
||||
type="checkbox"
|
||||
checked={captureElementClick}
|
||||
onChange={(event) => setCaptureElementClick(event.target.checked)}
|
||||
className='react-flow__captureelementclick'
|
||||
className="react-flow__captureelementclick"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import React, { useCallback } from 'react';
|
||||
import ReactFlow, {
|
||||
import {
|
||||
Controls,
|
||||
ReactFlow,
|
||||
ReactFlowProvider,
|
||||
addEdge,
|
||||
Connection,
|
||||
@@ -9,9 +11,8 @@ import ReactFlow, {
|
||||
useEdgesState,
|
||||
MarkerType,
|
||||
EdgeMarker,
|
||||
} from '@react-flow/core';
|
||||
} from '@react-flow/renderer';
|
||||
|
||||
import Controls from '@react-flow/controls';
|
||||
import dagre from 'dagre';
|
||||
|
||||
import initialItems from './initial-elements';
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import React, { FC } from 'react';
|
||||
|
||||
import ReactFlow, {
|
||||
import {
|
||||
ReactFlow,
|
||||
Background,
|
||||
addEdge,
|
||||
Node,
|
||||
Edge,
|
||||
@@ -9,9 +11,7 @@ import ReactFlow, {
|
||||
useNodesState,
|
||||
useEdgesState,
|
||||
MarkerType,
|
||||
} from '@react-flow/core';
|
||||
|
||||
import Background from '@react-flow/background';
|
||||
} from '@react-flow/renderer';
|
||||
|
||||
import styles from './multiflows.module.css';
|
||||
|
||||
@@ -79,8 +79,8 @@ const Flow: FC<{ id: string }> = ({ id }) => {
|
||||
|
||||
const MultiFlows: FC = () => (
|
||||
<div className={styles.multiflows}>
|
||||
<Flow id='flow-a' />
|
||||
<Flow id='flow-b' />
|
||||
<Flow id="flow-a" />
|
||||
<Flow id="flow-b" />
|
||||
</div>
|
||||
);
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import React, { useState, MouseEvent, useCallback } from 'react';
|
||||
|
||||
import ReactFlow, {
|
||||
import {
|
||||
Controls,
|
||||
MiniMap,
|
||||
Background,
|
||||
ReactFlow,
|
||||
addEdge,
|
||||
useNodesState,
|
||||
useEdgesState,
|
||||
@@ -8,11 +11,7 @@ import ReactFlow, {
|
||||
Edge,
|
||||
ReactFlowInstance,
|
||||
Connection,
|
||||
} from '@react-flow/core';
|
||||
|
||||
import Controls from '@react-flow/controls';
|
||||
import MiniMap from '@react-flow/minimap';
|
||||
import Background from '@react-flow/background';
|
||||
} from '@react-flow/renderer';
|
||||
|
||||
const onNodeDragStop = (_: MouseEvent, node: Node) =>
|
||||
console.log('drag stop', node);
|
||||
@@ -105,9 +104,12 @@ const NestedFlow = () => {
|
||||
const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
|
||||
const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
|
||||
|
||||
const onConnect = useCallback((connection: Connection) => {
|
||||
setEdges((eds) => addEdge(connection, eds));
|
||||
}, []);
|
||||
const onConnect = useCallback(
|
||||
(connection: Connection) => {
|
||||
setEdges((eds) => addEdge(connection, eds));
|
||||
},
|
||||
[setEdges]
|
||||
);
|
||||
const onInit = useCallback(
|
||||
(reactFlowInstance: ReactFlowInstance) => setRfInstance(reactFlowInstance),
|
||||
[]
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, { CSSProperties } from 'react';
|
||||
import React, { CSSProperties, useCallback } from 'react';
|
||||
|
||||
import ReactFlow, {
|
||||
import {
|
||||
ReactFlow,
|
||||
addEdge,
|
||||
Node,
|
||||
Position,
|
||||
@@ -42,8 +43,10 @@ const buttonStyle: CSSProperties = {
|
||||
const NodeTypeChangeFlow = () => {
|
||||
const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
|
||||
const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
|
||||
const onConnect = (params: Connection | Edge) =>
|
||||
setEdges((eds) => addEdge(params, eds));
|
||||
const onConnect = useCallback(
|
||||
(params: Connection | Edge) => setEdges((eds) => addEdge(params, eds)),
|
||||
[setEdges]
|
||||
);
|
||||
const changeType = () => {
|
||||
setNodes((nds) =>
|
||||
nds.map((node) => {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, { useState, CSSProperties, FC } from 'react';
|
||||
import React, { useState, CSSProperties, FC, useCallback } from 'react';
|
||||
|
||||
import ReactFlow, {
|
||||
import {
|
||||
ReactFlow,
|
||||
addEdge,
|
||||
Node,
|
||||
Position,
|
||||
@@ -65,10 +66,12 @@ const nodeTypesObjects: NodeTypesObject = {
|
||||
|
||||
const NodeTypeChangeFlow = () => {
|
||||
const [nodeTypesId, setNodeTypesId] = useState<string>('a');
|
||||
const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
|
||||
const [nodes, , onNodesChange] = useNodesState(initialNodes);
|
||||
const [edges, setEdges, onEdgesChange] = useEdgesState([]);
|
||||
const onConnect = (params: Connection | Edge) =>
|
||||
setEdges((eds) => addEdge(params, eds));
|
||||
const onConnect = useCallback(
|
||||
(params: Connection | Edge) => setEdges((eds) => addEdge(params, eds)),
|
||||
[setEdges]
|
||||
);
|
||||
const changeType = () => setNodeTypesId((nt) => (nt === 'a' ? 'b' : 'a'));
|
||||
|
||||
return (
|
||||
|
||||
@@ -4,7 +4,8 @@ import React, {
|
||||
useCallback,
|
||||
} from 'react';
|
||||
|
||||
import ReactFlow, {
|
||||
import {
|
||||
ReactFlow,
|
||||
addEdge,
|
||||
Node,
|
||||
Viewport,
|
||||
@@ -17,9 +18,9 @@ import ReactFlow, {
|
||||
OnSelectionChangeParams,
|
||||
} from '@react-flow/core';
|
||||
|
||||
import Controls from '@react-flow/controls';
|
||||
import Background from '@react-flow/background';
|
||||
import MiniMap from '@react-flow/minimap';
|
||||
import { Controls } from '@react-flow/controls';
|
||||
import { Background } from '@react-flow/background';
|
||||
import { MiniMap } from '@react-flow/minimap';
|
||||
|
||||
const onNodeDragStart = (_: ReactMouseEvent, node: Node, nodes: Node[]) =>
|
||||
console.log('drag start', node, nodes);
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import React, { MouseEvent } from 'react';
|
||||
import ReactFlow, {
|
||||
import React, { MouseEvent, useCallback } from 'react';
|
||||
import {
|
||||
ReactFlow,
|
||||
Controls,
|
||||
ReactFlowProvider,
|
||||
addEdge,
|
||||
Node,
|
||||
@@ -9,8 +11,7 @@ import ReactFlow, {
|
||||
useNodesState,
|
||||
useEdgesState,
|
||||
ReactFlowInstance,
|
||||
} from '@react-flow/core';
|
||||
import Controls from '@react-flow/controls';
|
||||
} from '@react-flow/renderer';
|
||||
|
||||
import Sidebar from './Sidebar';
|
||||
|
||||
@@ -40,8 +41,10 @@ const initialEdges: Edge[] = [
|
||||
const ProviderFlow = () => {
|
||||
const [nodes, , onNodesChange] = useNodesState(initialNodes);
|
||||
const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
|
||||
const onConnect = (params: Edge | Connection) =>
|
||||
setEdges((els) => addEdge(params, els));
|
||||
const onConnect = useCallback(
|
||||
(params: Edge | Connection) => setEdges((els) => addEdge(params, els)),
|
||||
[setEdges]
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={styles.providerflow}>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React, { useCallback } from 'react';
|
||||
import ReactFlow, {
|
||||
import {
|
||||
ReactFlow,
|
||||
ReactFlowProvider,
|
||||
Node,
|
||||
addEdge,
|
||||
@@ -8,7 +9,6 @@ import ReactFlow, {
|
||||
useNodesState,
|
||||
useEdgesState,
|
||||
} from '@react-flow/core';
|
||||
|
||||
import Controls from './Controls';
|
||||
|
||||
const initialNodes: Node[] = [
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React, { useState, CSSProperties, useCallback } from 'react';
|
||||
import ReactFlow, {
|
||||
import {
|
||||
ReactFlow,
|
||||
ReactFlowInstance,
|
||||
Edge,
|
||||
Node,
|
||||
@@ -10,10 +11,9 @@ import ReactFlow, {
|
||||
applyEdgeChanges,
|
||||
EdgeChange,
|
||||
} from '@react-flow/core';
|
||||
|
||||
import Controls from '@react-flow/controls';
|
||||
import Background from '@react-flow/background';
|
||||
import MiniMap from '@react-flow/minimap';
|
||||
import { Controls } from '@react-flow/controls';
|
||||
import { Background } from '@react-flow/background';
|
||||
import { MiniMap } from '@react-flow/minimap';
|
||||
|
||||
import { getNodesAndEdges } from './utils';
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useState, MouseEvent, useCallback } from 'react';
|
||||
|
||||
import ReactFlow, {
|
||||
import {
|
||||
ReactFlow,
|
||||
addEdge,
|
||||
Node,
|
||||
Edge,
|
||||
@@ -10,10 +10,9 @@ import ReactFlow, {
|
||||
useNodesState,
|
||||
useEdgesState,
|
||||
} from '@react-flow/core';
|
||||
|
||||
import Controls from '@react-flow/controls';
|
||||
import Background from '@react-flow/background';
|
||||
import MiniMap from '@react-flow/minimap';
|
||||
import { Controls } from '@react-flow/controls';
|
||||
import { Background } from '@react-flow/background';
|
||||
import { MiniMap } from '@react-flow/minimap';
|
||||
|
||||
import DebugNode from './DebugNode';
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React, { MouseEvent, useCallback } from 'react';
|
||||
import ReactFlow, {
|
||||
import {
|
||||
ReactFlow,
|
||||
addEdge,
|
||||
Node,
|
||||
Connection,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React, { useCallback } from 'react';
|
||||
import ReactFlow, {
|
||||
import {
|
||||
ReactFlow,
|
||||
Node,
|
||||
Edge,
|
||||
useNodesState,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, { MouseEvent, useCallback } from 'react';
|
||||
|
||||
import ReactFlow, {
|
||||
import {
|
||||
ReactFlow,
|
||||
useReactFlow,
|
||||
NodeTypes,
|
||||
addEdge,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React, { useState, useCallback } from 'react';
|
||||
import ReactFlow, {
|
||||
import {
|
||||
ReactFlow,
|
||||
updateEdge,
|
||||
addEdge,
|
||||
applyNodeChanges,
|
||||
@@ -13,7 +14,7 @@ import ReactFlow, {
|
||||
HandleType,
|
||||
} from '@react-flow/core';
|
||||
|
||||
import Controls from '@react-flow/controls';
|
||||
import { Controls } from '@react-flow/controls';
|
||||
|
||||
const initialNodes: Node[] = [
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import ReactFlow, {
|
||||
import {
|
||||
ReactFlow,
|
||||
Node,
|
||||
Edge,
|
||||
useNodesState,
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import React, { useCallback, MouseEvent, useEffect } from 'react';
|
||||
|
||||
import ReactFlow, {
|
||||
import {
|
||||
Background,
|
||||
MiniMap,
|
||||
ReactFlow,
|
||||
Node,
|
||||
addEdge,
|
||||
useReactFlow,
|
||||
@@ -9,10 +11,7 @@ import ReactFlow, {
|
||||
Edge,
|
||||
useNodesState,
|
||||
useEdgesState,
|
||||
} from '@react-flow/core';
|
||||
|
||||
import Background from '@react-flow/background';
|
||||
import MiniMap from '@react-flow/minimap';
|
||||
} from '@react-flow/renderer';
|
||||
|
||||
const initialNodes: Node[] = [
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useCallback, CSSProperties, MouseEvent } from 'react';
|
||||
|
||||
import ReactFlow, {
|
||||
import {
|
||||
ReactFlow,
|
||||
NodeTypes,
|
||||
addEdge,
|
||||
useReactFlow,
|
||||
@@ -13,6 +13,7 @@ import ReactFlow, {
|
||||
useNodesState,
|
||||
useEdgesState,
|
||||
} from '@react-flow/core';
|
||||
|
||||
import CustomNode from './CustomNode';
|
||||
|
||||
const initialHandleCount = 1;
|
||||
@@ -47,8 +48,10 @@ const getId = (): string => `${id++}`;
|
||||
const UpdateNodeInternalsFlow = () => {
|
||||
const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
|
||||
const [edges, setEdges, onEdgesChange] = useEdgesState([]);
|
||||
const onConnect = (params: Edge | Connection) =>
|
||||
setEdges((els) => addEdge(params, els));
|
||||
const onConnect = useCallback(
|
||||
(params: Edge | Connection) => setEdges((els) => addEdge(params, els)),
|
||||
[setEdges]
|
||||
);
|
||||
|
||||
const updateNodeInternals = useUpdateNodeInternals();
|
||||
const { project } = useReactFlow();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React, { FC, useCallback, useState } from 'react';
|
||||
import ReactFlow, {
|
||||
import {
|
||||
ReactFlow,
|
||||
addEdge,
|
||||
Handle,
|
||||
Connection,
|
||||
@@ -28,7 +29,7 @@ const CustomInput: FC<NodeProps> = () => (
|
||||
<>
|
||||
<div>Only connectable with B</div>
|
||||
<Handle
|
||||
type='source'
|
||||
type="source"
|
||||
position={Position.Right}
|
||||
isValidConnection={isValidConnection}
|
||||
/>
|
||||
@@ -38,13 +39,13 @@ const CustomInput: FC<NodeProps> = () => (
|
||||
const CustomNode: FC<NodeProps> = ({ id }) => (
|
||||
<>
|
||||
<Handle
|
||||
type='target'
|
||||
type="target"
|
||||
position={Position.Left}
|
||||
isValidConnection={isValidConnection}
|
||||
/>
|
||||
<div>{id}</div>
|
||||
<Handle
|
||||
type='source'
|
||||
type="source"
|
||||
position={Position.Right}
|
||||
isValidConnection={isValidConnection}
|
||||
/>
|
||||
|
||||
@@ -2,6 +2,13 @@ import React from 'react';
|
||||
import { useRouter } from 'next/router';
|
||||
import '../styles/globals.css';
|
||||
|
||||
// Unfortunately this doesn't work because preconsruct clears the dist folder and there is
|
||||
// no way to hook into the watch process to copy the files back to the dist folder
|
||||
// import '@react-flow/core/dist/theme-default.css';
|
||||
|
||||
// this is a workaround for testing the theme. See explanation above.
|
||||
// import '../styles/theme-default.css';
|
||||
|
||||
const routes = [
|
||||
'/',
|
||||
'/Backgrounds',
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
import React, { MouseEvent } from 'react';
|
||||
|
||||
import ReactFlow, {
|
||||
import {
|
||||
ReactFlow,
|
||||
ReactFlowProvider,
|
||||
Node,
|
||||
Edge,
|
||||
useReactFlow,
|
||||
} from '@react-flow/core';
|
||||
|
||||
import Minimap from '@react-flow/minimap';
|
||||
import Background, { BackgroundVariant } from '@react-flow/background';
|
||||
import Controls from '@react-flow/controls';
|
||||
import { MiniMap } from '@react-flow/minimap';
|
||||
import { Background, BackgroundVariant } from '@react-flow/background';
|
||||
import { Controls } from '@react-flow/controls';
|
||||
|
||||
const onNodeDrag = (_: MouseEvent, node: Node) => console.log('drag', node);
|
||||
const onNodeDragStop = (_: MouseEvent, node: Node) =>
|
||||
@@ -95,7 +96,7 @@ const BasicFlow = () => {
|
||||
selectNodesOnDrag={false}
|
||||
>
|
||||
<Background variant={BackgroundVariant.Lines} />
|
||||
<Minimap />
|
||||
<MiniMap />
|
||||
<Controls />
|
||||
|
||||
<div style={{ position: 'absolute', right: 10, top: 10, zIndex: 4 }}>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
&:focus,
|
||||
&:focus-visible {
|
||||
outline: none;
|
||||
|
||||
.react-flow__edge-path {
|
||||
stroke: #555;
|
||||
}
|
||||
@@ -29,10 +30,6 @@
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.react-flow__edge-textbg {
|
||||
fill: white;
|
||||
}
|
||||
|
||||
.react-flow__connection-path {
|
||||
stroke: #b1b1b7;
|
||||
stroke-width: 1;
|
||||
18
examples/nextjs/postcss.config.json
Normal file
18
examples/nextjs/postcss.config.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"plugins": [
|
||||
"postcss-nested",
|
||||
"postcss-flexbugs-fixes",
|
||||
[
|
||||
"postcss-preset-env",
|
||||
{
|
||||
"autoprefixer": {
|
||||
"flexbox": "no-2009"
|
||||
},
|
||||
"stage": 3,
|
||||
"features": {
|
||||
"custom-properties": false
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
106
examples/nextjs/styles/theme-default.css
Normal file
106
examples/nextjs/styles/theme-default.css
Normal file
@@ -0,0 +1,106 @@
|
||||
.react-flow__edge {
|
||||
&.selected,
|
||||
&:focus,
|
||||
&:focus-visible {
|
||||
outline: none;
|
||||
|
||||
.react-flow__edge-path {
|
||||
stroke: #555;
|
||||
}
|
||||
}
|
||||
|
||||
&.animated path {
|
||||
stroke-dasharray: 5;
|
||||
animation: dashdraw 0.5s linear infinite;
|
||||
}
|
||||
|
||||
&.updating {
|
||||
.react-flow__edge-path {
|
||||
stroke: #777;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.react-flow__edge-path {
|
||||
stroke: #b1b1b7;
|
||||
stroke-width: 1;
|
||||
}
|
||||
|
||||
.react-flow__edge-text {
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.react-flow__connection-path {
|
||||
stroke: #b1b1b7;
|
||||
stroke-width: 1;
|
||||
}
|
||||
|
||||
.react-flow__node-default,
|
||||
.react-flow__node-input,
|
||||
.react-flow__node-output,
|
||||
.react-flow__node-group {
|
||||
padding: 10px;
|
||||
border-radius: 3px;
|
||||
width: 150px;
|
||||
font-size: 12px;
|
||||
color: #222;
|
||||
text-align: center;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: #1a192b;
|
||||
|
||||
&.selected,
|
||||
&:focus,
|
||||
&:focus-visible {
|
||||
box-shadow: 0 0 0 0.5px #1a192b;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.react-flow__handle {
|
||||
background: #1a192b;
|
||||
}
|
||||
}
|
||||
|
||||
.react-flow__node-default.selectable,
|
||||
.react-flow__node-input.selectable,
|
||||
.react-flow__node-output.selectable,
|
||||
.react-flow__node-group.selectable {
|
||||
&:hover {
|
||||
box-shadow: 0 1px 4px 1px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
&.selected,
|
||||
&:focus,
|
||||
&:focus-visible {
|
||||
outline: none;
|
||||
box-shadow: 0 0 0 0.5px #1a192b;
|
||||
}
|
||||
}
|
||||
|
||||
.react-flow__node-group {
|
||||
background: rgba(240, 240, 240, 0.25);
|
||||
border-color: #1a192b;
|
||||
}
|
||||
|
||||
.react-flow__nodesselection-rect,
|
||||
.react-flow__selection {
|
||||
background: rgba(0, 89, 220, 0.08);
|
||||
border: 1px dotted rgba(0, 89, 220, 0.8);
|
||||
|
||||
&:focus,
|
||||
&:focus-visible {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
.react-flow__handle {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
background: #555;
|
||||
border: 1px solid white;
|
||||
border-radius: 100%;
|
||||
|
||||
&.connectable {
|
||||
cursor: crosshair;
|
||||
}
|
||||
}
|
||||
@@ -10,10 +10,11 @@
|
||||
],
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"postinstall": "preconstruct dev && yarn run packages",
|
||||
"dev": "preconstruct watch",
|
||||
"dev:example": "cd examples/nextjs && yarn dev",
|
||||
"postinstall": "preconstruct dev",
|
||||
"build": "preconstruct build",
|
||||
"build": "preconstruct build && yarn run packages",
|
||||
"packages": "yarn workspaces foreach --include '@react-flow/**' run build",
|
||||
"test:all": "yarn test:chrome && yarn test:firefox",
|
||||
"test:chrome": "cypress run --browser chrome",
|
||||
"test:firefox": "cypress run --browser firefox",
|
||||
@@ -29,10 +30,7 @@
|
||||
"@babel/preset-react": "^7.17.12",
|
||||
"@babel/preset-typescript": "^7.17.12",
|
||||
"@preconstruct/cli": "^2.1.8",
|
||||
"autoprefixer": "^10.4.7",
|
||||
"cypress": "^10.3.1",
|
||||
"postcss": "^8.4.14",
|
||||
"postcss-nested": "^5.0.6",
|
||||
"start-server-and-test": "^1.14.0",
|
||||
"typescript": "^4.7.4"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@react-flow/background",
|
||||
"version": "11.0.0",
|
||||
"description": "A background component for React Flow",
|
||||
"description": "Background component with different variants for React Flow",
|
||||
"main": "dist/react-flow-background.cjs.js",
|
||||
"module": "dist/react-flow-background.esm.js",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import React, { memo, FC, useRef, useId } from 'react';
|
||||
import React, { memo, useRef, useId } from 'react';
|
||||
import cc from 'classcat';
|
||||
import { useStore, ReactFlowState } from '@react-flow/core';
|
||||
|
||||
import { BackgroundProps, BackgroundVariant } from './types';
|
||||
import { DotPattern, LinePattern } from './utils';
|
||||
import { DotPattern, LinePattern } from './Patterns';
|
||||
|
||||
const defaultColors = {
|
||||
const defaultColor = {
|
||||
[BackgroundVariant.Dots]: '#91919a',
|
||||
[BackgroundVariant.Lines]: '#eee',
|
||||
[BackgroundVariant.Cross]: '#e2e2e2',
|
||||
@@ -34,8 +34,8 @@ function Background({
|
||||
const patternId = useId();
|
||||
const [tX, tY, tScale] = useStore(transformSelector);
|
||||
|
||||
const patternColor = color ? color : defaultColors[variant];
|
||||
const patternSize = size ? size : defaultSize[variant];
|
||||
const patternColor = color || defaultColor[variant];
|
||||
const patternSize = size || defaultSize[variant];
|
||||
const isDots = variant === BackgroundVariant.Dots;
|
||||
const isCross = variant === BackgroundVariant.Cross;
|
||||
const gapXY: [number, number] = Array.isArray(gap) ? gap : [gap, gap];
|
||||
@@ -55,15 +55,14 @@ function Background({
|
||||
|
||||
return (
|
||||
<svg
|
||||
className={cc([
|
||||
'react-flow__background',
|
||||
'react-flow__container',
|
||||
className,
|
||||
])}
|
||||
className={cc(['react-flow__background', className])}
|
||||
style={{
|
||||
...style,
|
||||
position: 'absolute',
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
top: 0,
|
||||
left: 0,
|
||||
}}
|
||||
ref={ref}
|
||||
>
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
export { default as Background, default } from './Background';
|
||||
export { default as Background } from './Background';
|
||||
export * from './types';
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
{
|
||||
"name": "@react-flow/controls",
|
||||
"version": "11.0.0",
|
||||
"description": "A component that controls the viewport of React Flow",
|
||||
"description": "A component to control the viewport of a React Flow instance",
|
||||
"main": "dist/react-flow-controls.cjs.js",
|
||||
"module": "dist/react-flow-controls.esm.js",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@react-flow/core": "11.0.0",
|
||||
"@react-flow/core": "^11.0.0",
|
||||
"@react-flow/css-utils": "^11.0.0",
|
||||
"classcat": "^5.0.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
||||
22
packages/controls/src/ControlButton.tsx
Normal file
22
packages/controls/src/ControlButton.tsx
Normal file
@@ -0,0 +1,22 @@
|
||||
import React, { FC, PropsWithChildren } from 'react';
|
||||
import cc from 'classcat';
|
||||
|
||||
import { ControlButtonProps } from './types';
|
||||
|
||||
const ControlButton: FC<PropsWithChildren<ControlButtonProps>> = ({
|
||||
children,
|
||||
className,
|
||||
...rest
|
||||
}) => (
|
||||
<button
|
||||
type="button"
|
||||
className={cc(['react-flow__controls-button', className])}
|
||||
{...rest}
|
||||
>
|
||||
{children}
|
||||
</button>
|
||||
);
|
||||
|
||||
ControlButton.displayName = 'ControlButton';
|
||||
|
||||
export default ControlButton;
|
||||
@@ -5,31 +5,21 @@ import {
|
||||
useStoreApi,
|
||||
useReactFlow,
|
||||
ReactFlowState,
|
||||
Panel,
|
||||
} from '@react-flow/core';
|
||||
import { injectStyle } from '@react-flow/css-utils';
|
||||
|
||||
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 baseStyle from './style';
|
||||
|
||||
import { ControlProps, ControlButtonProps } from './types';
|
||||
import { ControlProps } from './types';
|
||||
|
||||
import './style.css';
|
||||
|
||||
export const ControlButton: FC<PropsWithChildren<ControlButtonProps>> = ({
|
||||
children,
|
||||
className,
|
||||
...rest
|
||||
}) => (
|
||||
<button
|
||||
type='button'
|
||||
className={cc(['react-flow__controls-button', className])}
|
||||
{...rest}
|
||||
>
|
||||
{children}
|
||||
</button>
|
||||
);
|
||||
injectStyle(baseStyle);
|
||||
|
||||
const isInteractiveSelector = (s: ReactFlowState) =>
|
||||
s.nodesDraggable && s.nodesConnectable && s.elementsSelectable;
|
||||
@@ -46,6 +36,7 @@ const Controls: FC<PropsWithChildren<ControlProps>> = ({
|
||||
onInteractiveChange,
|
||||
className,
|
||||
children,
|
||||
position = 'bottom-left',
|
||||
}) => {
|
||||
const store = useStoreApi();
|
||||
const [isVisible, setIsVisible] = useState<boolean>(false);
|
||||
@@ -86,22 +77,26 @@ const Controls: FC<PropsWithChildren<ControlProps>> = ({
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={cc(['react-flow__controls', className])} style={style}>
|
||||
<Panel
|
||||
className={cc(['react-flow__controls', className])}
|
||||
position={position}
|
||||
style={style}
|
||||
>
|
||||
{showZoom && (
|
||||
<>
|
||||
<ControlButton
|
||||
onClick={onZoomInHandler}
|
||||
className='react-flow__controls-zoomin'
|
||||
title='zoom in'
|
||||
aria-label='zoom in'
|
||||
className="react-flow__controls-zoomin"
|
||||
title="zoom in"
|
||||
aria-label="zoom in"
|
||||
>
|
||||
<PlusIcon />
|
||||
</ControlButton>
|
||||
<ControlButton
|
||||
onClick={onZoomOutHandler}
|
||||
className='react-flow__controls-zoomout'
|
||||
title='zoom out'
|
||||
aria-label='zoom out'
|
||||
className="react-flow__controls-zoomout"
|
||||
title="zoom out"
|
||||
aria-label="zoom out"
|
||||
>
|
||||
<MinusIcon />
|
||||
</ControlButton>
|
||||
@@ -109,26 +104,26 @@ const Controls: FC<PropsWithChildren<ControlProps>> = ({
|
||||
)}
|
||||
{showFitView && (
|
||||
<ControlButton
|
||||
className='react-flow__controls-fitview'
|
||||
className="react-flow__controls-fitview"
|
||||
onClick={onFitViewHandler}
|
||||
title='fit view'
|
||||
aria-label='fit view'
|
||||
title="fit view"
|
||||
aria-label="fit view"
|
||||
>
|
||||
<FitviewIcon />
|
||||
</ControlButton>
|
||||
)}
|
||||
{showInteractive && (
|
||||
<ControlButton
|
||||
className='react-flow__controls-interactive'
|
||||
className="react-flow__controls-interactive"
|
||||
onClick={onToggleInteractivity}
|
||||
title='toggle interactivity'
|
||||
aria-label='toggle interactivity'
|
||||
title="toggle interactivity"
|
||||
aria-label="toggle interactivity"
|
||||
>
|
||||
{isInteractive ? <UnlockIcon /> : <LockIcon />}
|
||||
</ControlButton>
|
||||
)}
|
||||
{children}
|
||||
</div>
|
||||
</Panel>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
export { default as default } from './Controls';
|
||||
export { default as Controls } from './Controls';
|
||||
export { default as ControlButton } from './ControlButton';
|
||||
export * from './types';
|
||||
export * from './Controls';
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
.react-flow__controls {
|
||||
box-shadow: 0 0 2px 1px rgba(0, 0, 0, 0.08);
|
||||
position: absolute;
|
||||
z-index: 5;
|
||||
bottom: 20px;
|
||||
left: 15px;
|
||||
|
||||
&-button {
|
||||
border: none;
|
||||
background: #fefefe;
|
||||
border-bottom: 1px solid #eee;
|
||||
box-sizing: content-box;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
padding: 5px;
|
||||
|
||||
svg {
|
||||
width: 100%;
|
||||
max-width: 12px;
|
||||
max-height: 12px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: #f4f4f4;
|
||||
}
|
||||
}
|
||||
}
|
||||
31
packages/controls/src/style.ts
Normal file
31
packages/controls/src/style.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
const style = `
|
||||
.react-flow__controls {
|
||||
box-shadow: 0 0 2px 1px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.react-flow__controls-button {
|
||||
border: none;
|
||||
background: #fefefe;
|
||||
border-bottom: 1px solid #eee;
|
||||
box-sizing: content-box;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.react-flow__controls-button svg {
|
||||
width: 100%;
|
||||
max-width: 12px;
|
||||
max-height: 12px;
|
||||
}
|
||||
|
||||
.react-flow__controls-button:hover {
|
||||
background: #f4f4f4;
|
||||
}`;
|
||||
|
||||
export default style;
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ButtonHTMLAttributes, HTMLAttributes } from 'react';
|
||||
import { FitViewOptions } from '@react-flow/core';
|
||||
import { FitViewOptions, PanelPosition } from '@react-flow/core';
|
||||
|
||||
export interface ControlProps extends HTMLAttributes<HTMLDivElement> {
|
||||
showZoom?: boolean;
|
||||
@@ -10,6 +10,7 @@ export interface ControlProps extends HTMLAttributes<HTMLDivElement> {
|
||||
onZoomOut?: () => void;
|
||||
onFitView?: () => void;
|
||||
onInteractiveChange?: (interactiveStatus: boolean) => void;
|
||||
position?: PanelPosition;
|
||||
}
|
||||
|
||||
export interface ControlButtonProps
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 30">
|
||||
<path d="M3.692 4.63c0-.53.4-.938.939-.938h5.215V0H4.708C2.13 0 0 2.054 0 4.63v5.216h3.692V4.631zM27.354 0h-5.2v3.692h5.17c.53 0 .984.4.984.939v5.215H32V4.631A4.624 4.624 0 0027.354 0zm.954 24.83c0 .532-.4.94-.939.94h-5.215v3.768h5.215c2.577 0 4.631-2.13 4.631-4.707v-5.139h-3.692v5.139zm-23.677.94c-.531 0-.939-.4-.939-.94v-5.138H0v5.139c0 2.577 2.13 4.707 4.708 4.707h5.138V25.77H4.631z" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 463 B |
@@ -1,3 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 25 32">
|
||||
<path d="M21.333 10.667H19.81V7.619C19.81 3.429 16.38 0 12.19 0 8 0 4.571 3.429 4.571 7.619v3.048H3.048A3.056 3.056 0 000 13.714v15.238A3.056 3.056 0 003.048 32h18.285a3.056 3.056 0 003.048-3.048V13.714a3.056 3.056 0 00-3.048-3.047zM12.19 24.533a3.056 3.056 0 01-3.047-3.047 3.056 3.056 0 013.047-3.048 3.056 3.056 0 013.048 3.048 3.056 3.056 0 01-3.048 3.047zm4.724-13.866H7.467V7.619c0-2.59 2.133-4.724 4.723-4.724 2.591 0 4.724 2.133 4.724 4.724v3.048z" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 530 B |
@@ -1,3 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 5">
|
||||
<path d="M0 0h32v4.2H0z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 96 B |
@@ -1,3 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<path d="M32 18.133H18.133V32h-4.266V18.133H0v-4.266h13.867V0h4.266v13.867H32z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 152 B |
@@ -1,3 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 25 32">
|
||||
<path d="M21.333 10.667H19.81V7.619C19.81 3.429 16.38 0 12.19 0c-4.114 1.828-1.37 2.133.305 2.438 1.676.305 4.42 2.59 4.42 5.181v3.048H3.047A3.056 3.056 0 000 13.714v15.238A3.056 3.056 0 003.048 32h18.285a3.056 3.056 0 003.048-3.048V13.714a3.056 3.056 0 00-3.048-3.047zM12.19 24.533a3.056 3.056 0 01-3.047-3.047 3.056 3.056 0 013.047-3.048 3.056 3.056 0 013.048 3.048 3.056 3.056 0 01-3.048 3.047z" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 472 B |
19621
packages/core/package-lock.json
generated
19621
packages/core/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -12,8 +12,12 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/wbkd/react-flow.git"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "postcss src/styles/*.css --config ../../tooling/postcss.config.json --dir dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.18.0",
|
||||
"@react-flow/css-utils": "^11.0.0",
|
||||
"classcat": "^5.0.3",
|
||||
"d3-drag": "^3.0.0",
|
||||
"d3-selection": "^3.0.0",
|
||||
@@ -30,6 +34,11 @@
|
||||
],
|
||||
"devDependencies": {
|
||||
"@types/d3": "^7.4.0",
|
||||
"@types/react": "^18.0.15"
|
||||
"@types/react": "^18.0.15",
|
||||
"autoprefixer": "^10.4.8",
|
||||
"postcss": "^8.4.14",
|
||||
"postcss-cli": "^10.0.0",
|
||||
"postcss-import": "^14.1.0",
|
||||
"postcss-nested": "^5.0.6"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import React from 'react';
|
||||
import cc from 'classcat';
|
||||
|
||||
import { AttributionPosition, ProOptions } from '../../types';
|
||||
import Panel from '../Panel';
|
||||
import { PanelPosition, ProOptions } from '../../types';
|
||||
|
||||
type AttributionProps = {
|
||||
proOptions?: ProOptions;
|
||||
position?: AttributionPosition;
|
||||
position?: PanelPosition;
|
||||
};
|
||||
|
||||
function Attribution({ proOptions, position = 'bottom-right' }: AttributionProps) {
|
||||
@@ -13,17 +13,16 @@ function Attribution({ proOptions, position = 'bottom-right' }: AttributionProps
|
||||
return null;
|
||||
}
|
||||
|
||||
const positionClasses = `${position}`.split('-');
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cc(['react-flow__attribution', ...positionClasses])}
|
||||
<Panel
|
||||
position={position}
|
||||
className="react-flow__attribution"
|
||||
data-message="Please only hide this attribution when you are subscribed to React Flow Pro: https://pro.reactflow.dev"
|
||||
>
|
||||
<a href="https://reactflow.dev" target="_blank" rel="noopener noreferrer" aria-label="React Flow attribution">
|
||||
React Flow
|
||||
</a>
|
||||
</div>
|
||||
</Panel>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -113,7 +113,7 @@ export default ({
|
||||
|
||||
return (
|
||||
<g className="react-flow__connection">
|
||||
<path d={dAttr} className="react-flow__connection-path" style={connectionLineStyle} />
|
||||
<path d={dAttr} fill="none" className="react-flow__connection-path" style={connectionLineStyle} />
|
||||
</g>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -32,7 +32,14 @@ export default ({
|
||||
|
||||
return (
|
||||
<>
|
||||
<path style={style} d={path} className="react-flow__edge-path" markerEnd={markerEnd} markerStart={markerStart} />
|
||||
<path
|
||||
style={style}
|
||||
d={path}
|
||||
fill="none"
|
||||
className="react-flow__edge-path"
|
||||
markerEnd={markerEnd}
|
||||
markerStart={markerStart}
|
||||
/>
|
||||
{text}
|
||||
</>
|
||||
);
|
||||
|
||||
21
packages/core/src/components/Panel/index.tsx
Normal file
21
packages/core/src/components/Panel/index.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import React, { HTMLAttributes, ReactNode } from 'react';
|
||||
import cc from 'classcat';
|
||||
|
||||
import { PanelPosition } from '../../types';
|
||||
|
||||
export type PanelProps = HTMLAttributes<HTMLDivElement> & {
|
||||
position: PanelPosition;
|
||||
children: ReactNode;
|
||||
};
|
||||
|
||||
function Panel({ position, children, className, ...rest }: PanelProps) {
|
||||
const positionClasses = `${position}`.split('-');
|
||||
|
||||
return (
|
||||
<div className={cc(['react-flow__panel', className, ...positionClasses])} {...rest}>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Panel;
|
||||
@@ -9,6 +9,7 @@ import UserSelection from '../../components/UserSelection';
|
||||
import NodesSelection from '../../components/NodesSelection';
|
||||
|
||||
import { ReactFlowState } from '../../types';
|
||||
import { containerStyle } from '../../styles';
|
||||
|
||||
export type FlowRendererProps = Omit<
|
||||
GraphViewProps,
|
||||
@@ -104,13 +105,14 @@ const FlowRenderer = ({
|
||||
/>
|
||||
)}
|
||||
<div
|
||||
className="react-flow__pane react-flow__container"
|
||||
className="react-flow__pane"
|
||||
onClick={onClick}
|
||||
onMouseEnter={onPaneMouseEnter}
|
||||
onMouseMove={onPaneMouseMove}
|
||||
onMouseLeave={onPaneMouseLeave}
|
||||
onContextMenu={onContextMenu}
|
||||
onWheel={onWheel}
|
||||
style={containerStyle}
|
||||
/>
|
||||
</ZoomPane>
|
||||
);
|
||||
|
||||
@@ -3,6 +3,7 @@ import shallow from 'zustand/shallow';
|
||||
|
||||
import useVisibleNodes from '../../hooks/useVisibleNodes';
|
||||
import { useStore } from '../../store';
|
||||
import { containerStyle } from '../../styles';
|
||||
import { NodeMouseHandler, NodeTypesWrapped, Position, ReactFlowState, WrapNodeProps } from '../../types';
|
||||
import { internalsSymbol } from '../../utils';
|
||||
|
||||
@@ -61,7 +62,7 @@ const NodeRenderer = (props: NodeRendererProps) => {
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="react-flow__nodes react-flow__container">
|
||||
<div className="react-flow__nodes" style={containerStyle}>
|
||||
{nodes.map((node) => {
|
||||
let nodeType = node.type || 'default';
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React, { forwardRef, useId } from 'react';
|
||||
import React, { CSSProperties, forwardRef, useId } from 'react';
|
||||
import cc from 'classcat';
|
||||
import { injectStyle } from '@react-flow/css-utils';
|
||||
|
||||
import Attribution from '../../components/Attribution';
|
||||
import { BezierEdge, SmoothStepEdge, StepEdge, StraightEdge, SimpleBezierEdge } from '../../components/Edges';
|
||||
@@ -8,9 +9,9 @@ import InputNode from '../../components/Nodes/InputNode';
|
||||
import OutputNode from '../../components/Nodes/OutputNode';
|
||||
import SelectionListener from '../../components/SelectionListener';
|
||||
import StoreUpdater from '../../components/StoreUpdater';
|
||||
import baseStyle from '../../styles/base';
|
||||
|
||||
import '../../style.css';
|
||||
import '../../theme-default.css';
|
||||
injectStyle(baseStyle);
|
||||
|
||||
import {
|
||||
ConnectionLineType,
|
||||
@@ -48,6 +49,13 @@ const defaultEdgeTypes: EdgeTypes = {
|
||||
const initSnapGrid: [number, number] = [15, 15];
|
||||
const initDefaultViewport: Viewport = { x: 0, y: 0, zoom: 1 };
|
||||
|
||||
const wrapperStyle: CSSProperties = {
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
position: 'relative',
|
||||
overflow: 'hidden',
|
||||
};
|
||||
|
||||
const ReactFlow = forwardRef<ReactFlowRefType, ReactFlowProps>(
|
||||
(
|
||||
{
|
||||
@@ -143,6 +151,7 @@ const ReactFlow = forwardRef<ReactFlowRefType, ReactFlowProps>(
|
||||
defaultEdgeOptions,
|
||||
elevateEdgesOnSelect = false,
|
||||
disableKeyboardA11y = false,
|
||||
style,
|
||||
...rest
|
||||
},
|
||||
ref
|
||||
@@ -152,7 +161,7 @@ const ReactFlow = forwardRef<ReactFlowRefType, ReactFlowProps>(
|
||||
const rfId = useId();
|
||||
|
||||
return (
|
||||
<div {...rest} ref={ref} className={cc(['react-flow', className])}>
|
||||
<div {...rest} style={{ ...style, ...wrapperStyle }} ref={ref} className={cc(['react-flow', className])}>
|
||||
<Wrapper>
|
||||
<GraphView
|
||||
onInit={onInit}
|
||||
|
||||
@@ -9,6 +9,7 @@ import useResizeHandler from '../../hooks/useResizeHandler';
|
||||
import { useStore, useStoreApi } from '../../store';
|
||||
import { Viewport, PanOnScrollMode, ReactFlowState } from '../../types';
|
||||
import { FlowRendererProps } from '../FlowRenderer';
|
||||
import { containerStyle } from '../../styles';
|
||||
|
||||
type ZoomPaneProps = Omit<
|
||||
FlowRendererProps,
|
||||
@@ -253,7 +254,7 @@ const ZoomPane = ({
|
||||
]);
|
||||
|
||||
return (
|
||||
<div className="react-flow__renderer react-flow__container" ref={zoomPane}>
|
||||
<div className="react-flow__renderer" ref={zoomPane} style={containerStyle}>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
import ReactFlow from './container/ReactFlow';
|
||||
|
||||
export default ReactFlow;
|
||||
|
||||
export { default as ReactFlow } from './container/ReactFlow';
|
||||
export { default as Handle } from './components/Handle';
|
||||
export { default as EdgeText } from './components/Edges/EdgeText';
|
||||
export { default as StraightEdge } from './components/Edges/StraightEdge';
|
||||
@@ -18,7 +15,7 @@ export {
|
||||
} from './components/Edges/SimpleBezierEdge';
|
||||
export { default as SmoothStepEdge, getSmoothStepPath } from './components/Edges/SmoothStepEdge';
|
||||
|
||||
export { internalsSymbol } from './utils';
|
||||
export { internalsSymbol, rectToBox, boxToRect, getBoundsOfRects } from './utils';
|
||||
export {
|
||||
isNode,
|
||||
isEdge,
|
||||
@@ -33,6 +30,7 @@ export {
|
||||
export { applyNodeChanges, applyEdgeChanges } from './utils/changes';
|
||||
export { getMarkerEnd, getCenter as getEdgeCenter } from './components/Edges/utils';
|
||||
export { default as ReactFlowProvider } from './components/ReactFlowProvider';
|
||||
export { default as Panel } from './components/Panel';
|
||||
|
||||
export { default as useReactFlow } from './hooks/useReactFlow';
|
||||
export { default as useUpdateNodeInternals } from './hooks/useUpdateNodeInternals';
|
||||
|
||||
@@ -1,180 +0,0 @@
|
||||
.react-flow {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.react-flow__container {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.react-flow__pane {
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.react-flow__viewport {
|
||||
transform-origin: 0 0;
|
||||
z-index: 2;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.react-flow__renderer {
|
||||
z-index: 4;
|
||||
}
|
||||
|
||||
.react-flow__selectionpane {
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
.react-flow .react-flow__edges {
|
||||
pointer-events: none;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.react-flow .react-flow__connectionline {
|
||||
z-index: 1001;
|
||||
}
|
||||
|
||||
.react-flow__edge {
|
||||
pointer-events: visibleStroke;
|
||||
|
||||
&.inactive {
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes dashdraw {
|
||||
from {
|
||||
stroke-dashoffset: 10;
|
||||
}
|
||||
}
|
||||
|
||||
.react-flow__edge-path {
|
||||
fill: none;
|
||||
}
|
||||
|
||||
.react-flow__edge-textwrapper {
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
.react-flow__edge-text {
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.react-flow__connection {
|
||||
pointer-events: none;
|
||||
|
||||
.animated {
|
||||
stroke-dasharray: 5;
|
||||
animation: dashdraw 0.5s linear infinite;
|
||||
}
|
||||
}
|
||||
|
||||
.react-flow__connection-path {
|
||||
fill: none;
|
||||
}
|
||||
|
||||
.react-flow__nodes {
|
||||
pointer-events: none;
|
||||
transform-origin: 0 0;
|
||||
}
|
||||
|
||||
.react-flow__node {
|
||||
position: absolute;
|
||||
user-select: none;
|
||||
pointer-events: all;
|
||||
transform-origin: 0 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.react-flow__nodesselection {
|
||||
z-index: 3;
|
||||
transform-origin: left top;
|
||||
pointer-events: none;
|
||||
|
||||
&-rect {
|
||||
position: absolute;
|
||||
pointer-events: all;
|
||||
cursor: grab;
|
||||
}
|
||||
}
|
||||
|
||||
.react-flow__handle {
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
|
||||
&.connectable {
|
||||
pointer-events: all;
|
||||
}
|
||||
}
|
||||
|
||||
.react-flow__handle-bottom {
|
||||
top: auto;
|
||||
left: 50%;
|
||||
bottom: -4px;
|
||||
transform: translate(-50%, 0);
|
||||
}
|
||||
|
||||
.react-flow__handle-top {
|
||||
left: 50%;
|
||||
top: -4px;
|
||||
transform: translate(-50%, 0);
|
||||
}
|
||||
|
||||
.react-flow__handle-left {
|
||||
top: 50%;
|
||||
left: -4px;
|
||||
transform: translate(0, -50%);
|
||||
}
|
||||
|
||||
.react-flow__handle-right {
|
||||
right: -4px;
|
||||
top: 50%;
|
||||
transform: translate(0, -50%);
|
||||
}
|
||||
|
||||
.react-flow__edgeupdater {
|
||||
cursor: move;
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
.react-flow__attribution {
|
||||
font-size: 10px;
|
||||
position: absolute;
|
||||
z-index: 1000;
|
||||
background: rgba(255, 255, 255, 0.5);
|
||||
padding: 2px 3px;
|
||||
color: #999;
|
||||
|
||||
a {
|
||||
color: #555;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
&.top {
|
||||
top: 0;
|
||||
}
|
||||
|
||||
&.bottom {
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
&.left {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
&.right {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
&.center {
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
}
|
||||
226
packages/core/src/styles/base.ts
Normal file
226
packages/core/src/styles/base.ts
Normal file
@@ -0,0 +1,226 @@
|
||||
const style = `
|
||||
.react-flow__container {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.react-flow__pane {
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.react-flow__viewport {
|
||||
transform-origin: 0 0;
|
||||
z-index: 2;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.react-flow__renderer {
|
||||
z-index: 4;
|
||||
}
|
||||
|
||||
.react-flow__selectionpane {
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
.react-flow__nodesselection-rect,
|
||||
.react-flow__selection {
|
||||
background: rgba(150, 150, 180, 0.1);
|
||||
border: 1px dotted rgba(155, 155, 155, 0.8);
|
||||
}
|
||||
|
||||
.react-flow__nodesselection-rect:focus,
|
||||
.react-flow__nodesselection-rect:focus-visible {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.react-flow .react-flow__edges {
|
||||
pointer-events: none;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.react-flow__connection {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.react-flow__connection.animated {
|
||||
stroke-dasharray: 5;
|
||||
animation: dashdraw 0.5s linear infinite;
|
||||
}
|
||||
|
||||
.react-flow .react-flow__connectionline {
|
||||
z-index: 1001;
|
||||
}
|
||||
|
||||
.react-flow__connectionline path, .react-flow__edge path {
|
||||
fill: none;
|
||||
}
|
||||
|
||||
.react-flow__edge-path, .react-flow__connection-path {
|
||||
stroke: #b1b1b7;
|
||||
stroke-width: 1;
|
||||
}
|
||||
|
||||
.react-flow__edge {
|
||||
pointer-events: visibleStroke;
|
||||
}
|
||||
|
||||
.react-flow__edge.animated path {
|
||||
stroke-dasharray: 5;
|
||||
animation: dashdraw 0.5s linear infinite;
|
||||
}
|
||||
|
||||
.react-flow__edge.inactive {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.react-flow__edge.selected, .react-flow__edge:focus, .react-flow__edge:focus-visible {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.react-flow__edge.selected .react-flow__edge-path,
|
||||
.react-flow__edge:focus .react-flow__edge-path,
|
||||
.react-flow__edge:focus-visible .react-flow__edge-path {
|
||||
stroke: #555;
|
||||
}
|
||||
|
||||
@keyframes dashdraw {
|
||||
from {
|
||||
stroke-dashoffset: 10;
|
||||
}
|
||||
}
|
||||
|
||||
.react-flow__edge-textwrapper {
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
.react-flow__edge-text {
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.react-flow__edge-textbg {
|
||||
fill: white;
|
||||
}
|
||||
|
||||
.react-flow__nodes {
|
||||
pointer-events: none;
|
||||
transform-origin: 0 0;
|
||||
}
|
||||
|
||||
.react-flow__node {
|
||||
position: absolute;
|
||||
user-select: none;
|
||||
pointer-events: all;
|
||||
transform-origin: 0 0;
|
||||
box-sizing: border-box;
|
||||
background-color: white;
|
||||
cursor: grab;
|
||||
border: 1px solid #bbb;
|
||||
}
|
||||
|
||||
.react-flow__node.selected,
|
||||
.react-flow__node:focus,
|
||||
.react-flow__node:focus-visible {
|
||||
outline: none;
|
||||
border: 1px solid #555;
|
||||
}
|
||||
|
||||
.react-flow__nodesselection {
|
||||
z-index: 3;
|
||||
transform-origin: left top;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.react-flow__nodesselection-rect {
|
||||
position: absolute;
|
||||
pointer-events: all;
|
||||
cursor: grab;
|
||||
}
|
||||
|
||||
.react-flow__handle {
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
min-width: 5px;
|
||||
min-height: 5px;
|
||||
background-color: #333;
|
||||
}
|
||||
|
||||
.react-flow__handle.connectable {
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
.react-flow__handle-bottom {
|
||||
top: auto;
|
||||
left: 50%;
|
||||
bottom: -4px;
|
||||
transform: translate(-50%, 0);
|
||||
}
|
||||
|
||||
.react-flow__handle-top {
|
||||
left: 50%;
|
||||
top: -4px;
|
||||
transform: translate(-50%, 0);
|
||||
}
|
||||
|
||||
.react-flow__handle-left {
|
||||
top: 50%;
|
||||
left: -4px;
|
||||
transform: translate(0, -50%);
|
||||
}
|
||||
|
||||
.react-flow__handle-right {
|
||||
right: -4px;
|
||||
top: 50%;
|
||||
transform: translate(0, -50%);
|
||||
}
|
||||
|
||||
.react-flow__edgeupdater {
|
||||
cursor: move;
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
.react-flow__panel {
|
||||
position: absolute;
|
||||
z-index: 1000;
|
||||
margin: 15px;
|
||||
}
|
||||
|
||||
.react-flow__panel.top {
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.react-flow__panel.bottom {
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.react-flow__panel.left {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.react-flow__panel.right {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.react-flow__panel.center {
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
.react-flow__attribution {
|
||||
font-size: 10px;
|
||||
background: rgba(255, 255, 255, 0.5);
|
||||
padding: 2px 3px;
|
||||
color: #999;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.react-flow__attribution a {
|
||||
color: #555;
|
||||
text-decoration: none;
|
||||
}
|
||||
`;
|
||||
|
||||
export default style;
|
||||
9
packages/core/src/styles/index.ts
Normal file
9
packages/core/src/styles/index.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { CSSProperties } from 'react';
|
||||
|
||||
export const containerStyle: CSSProperties = {
|
||||
position: 'absolute',
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
top: 0,
|
||||
left: 0,
|
||||
};
|
||||
83
packages/core/src/styles/theme-default.css
Normal file
83
packages/core/src/styles/theme-default.css
Normal file
@@ -0,0 +1,83 @@
|
||||
.react-flow__edge {
|
||||
&.updating {
|
||||
.react-flow__edge-path {
|
||||
stroke: #777;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.react-flow__edge-text {
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.react-flow__node-default,
|
||||
.react-flow__node-input,
|
||||
.react-flow__node-output,
|
||||
.react-flow__node-group {
|
||||
padding: 10px;
|
||||
border-radius: 3px;
|
||||
width: 150px;
|
||||
font-size: 12px;
|
||||
color: #222;
|
||||
text-align: center;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: #1a192b;
|
||||
|
||||
&.selected,
|
||||
&:focus,
|
||||
&:focus-visible {
|
||||
border: none;
|
||||
box-shadow: 0 0 0 0.5px #1a192b;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.react-flow__handle {
|
||||
background: #1a192b;
|
||||
}
|
||||
}
|
||||
|
||||
.react-flow__node-default.selectable,
|
||||
.react-flow__node-input.selectable,
|
||||
.react-flow__node-output.selectable,
|
||||
.react-flow__node-group.selectable {
|
||||
&:hover {
|
||||
box-shadow: 0 1px 4px 1px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
&.selected,
|
||||
&:focus,
|
||||
&:focus-visible {
|
||||
border: none;
|
||||
box-shadow: 0 0 0 0.5px #1a192b;
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
.react-flow__node-group {
|
||||
background: rgba(240, 240, 240, 0.25);
|
||||
border-color: #1a192b;
|
||||
}
|
||||
|
||||
.react-flow__nodesselection-rect,
|
||||
.react-flow__selection {
|
||||
background: rgba(0, 89, 220, 0.08);
|
||||
border: 1px dotted rgba(0, 89, 220, 0.8);
|
||||
|
||||
&:focus,
|
||||
&:focus-visible {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
.react-flow__handle {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
background: #555;
|
||||
border: 1px solid white;
|
||||
border-radius: 100%;
|
||||
|
||||
&.connectable {
|
||||
cursor: crosshair;
|
||||
}
|
||||
}
|
||||
@@ -221,13 +221,7 @@ export type OnSelectionChangeParams = {
|
||||
|
||||
export type OnSelectionChangeFunc = (params: OnSelectionChangeParams) => void;
|
||||
|
||||
export type AttributionPosition =
|
||||
| 'top-left'
|
||||
| 'top-center'
|
||||
| 'top-right'
|
||||
| 'bottom-left'
|
||||
| 'bottom-center'
|
||||
| 'bottom-right';
|
||||
export type PanelPosition = 'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right';
|
||||
|
||||
export type ProOptions = {
|
||||
hideAttribution: boolean;
|
||||
|
||||
@@ -36,7 +36,7 @@ export const boxToRect = ({ x, y, x2, y2 }: Box): Rect => ({
|
||||
height: y2 - y,
|
||||
});
|
||||
|
||||
export const getBoundsofRects = (rect1: Rect, rect2: Rect): Rect =>
|
||||
export const getBoundsOfRects = (rect1: Rect, rect2: Rect): Rect =>
|
||||
boxToRect(getBoundsOfBoxes(rectToBox(rect1), rectToBox(rect2)));
|
||||
|
||||
export const isNumeric = (n: any): n is number => !isNaN(n) && isFinite(n);
|
||||
|
||||
8
packages/css-utils/package.json
Normal file
8
packages/css-utils/package.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "@react-flow/css-utils",
|
||||
"version": "11.0.0",
|
||||
"description": "Utils for handling styles.",
|
||||
"main": "dist/react-flow-css-utils.cjs.js",
|
||||
"module": "dist/react-flow-css-utils.esm.js",
|
||||
"license": "MIT"
|
||||
}
|
||||
10
packages/css-utils/src/index.ts
Normal file
10
packages/css-utils/src/index.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
export function injectStyle(css: string) {
|
||||
if (typeof document === 'undefined') return;
|
||||
|
||||
const head = document.head || document.getElementsByTagName('head')[0];
|
||||
const style = document.createElement('style');
|
||||
|
||||
head.prepend(style);
|
||||
|
||||
style.appendChild(document.createTextNode(css));
|
||||
}
|
||||
@@ -6,18 +6,13 @@
|
||||
"module": "dist/react-flow-minimap.esm.js",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@react-flow/core": "11.0.0",
|
||||
"@react-flow/core": "^11.0.0",
|
||||
"@react-flow/css-utils": "^11.0.0",
|
||||
"classcat": "^5.0.3",
|
||||
"d3-drag": "^3.0.0",
|
||||
"d3-selection": "^3.0.0",
|
||||
"zustand": "^3.7.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^18.1.0",
|
||||
"react-dom": ">=18"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/d3-drag": "^3.0.1",
|
||||
"@types/d3-selection": "^3.0.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,16 +4,18 @@ import shallow from 'zustand/shallow';
|
||||
import {
|
||||
useStore,
|
||||
getRectOfNodes,
|
||||
Box,
|
||||
ReactFlowState,
|
||||
Rect,
|
||||
Panel,
|
||||
getBoundsOfRects,
|
||||
} from '@react-flow/core';
|
||||
import { injectStyle } from '@react-flow/css-utils';
|
||||
|
||||
import MiniMapNode from './MiniMapNode';
|
||||
import MiniMapDrag from './MiniMapDrag';
|
||||
import { MiniMapProps, GetMiniMapNodeAttribute } from './types';
|
||||
import baseStyle from './style';
|
||||
|
||||
import './style.css';
|
||||
injectStyle(baseStyle);
|
||||
|
||||
declare const window: any;
|
||||
|
||||
@@ -30,30 +32,6 @@ const selector = (s: ReactFlowState) => ({
|
||||
const getAttrFunction = (func: any): GetMiniMapNodeAttribute =>
|
||||
func instanceof Function ? func : () => func;
|
||||
|
||||
export const getBoundsOfBoxes = (box1: Box, box2: Box): Box => ({
|
||||
x: Math.min(box1.x, box2.x),
|
||||
y: Math.min(box1.y, box2.y),
|
||||
x2: Math.max(box1.x2, box2.x2),
|
||||
y2: Math.max(box1.y2, box2.y2),
|
||||
});
|
||||
|
||||
export const rectToBox = ({ x, y, width, height }: Rect): Box => ({
|
||||
x,
|
||||
y,
|
||||
x2: x + width,
|
||||
y2: y + height,
|
||||
});
|
||||
|
||||
export const boxToRect = ({ x, y, x2, y2 }: Box): Rect => ({
|
||||
x,
|
||||
y,
|
||||
width: x2 - x,
|
||||
height: y2 - y,
|
||||
});
|
||||
|
||||
export const getBoundsofRects = (rect1: Rect, rect2: Rect): Rect =>
|
||||
boxToRect(getBoundsOfBoxes(rectToBox(rect1), rectToBox(rect2)));
|
||||
|
||||
const ARIA_LABEL_KEY = 'react-flow__minimap-desc';
|
||||
|
||||
function MiniMap({
|
||||
@@ -65,6 +43,7 @@ function MiniMap({
|
||||
nodeBorderRadius = 5,
|
||||
nodeStrokeWidth = 2,
|
||||
maskColor = 'rgb(240, 242, 243, 0.7)',
|
||||
position = 'bottom-right',
|
||||
}: MiniMapProps) {
|
||||
const minimapId = useId();
|
||||
const {
|
||||
@@ -85,7 +64,7 @@ function MiniMap({
|
||||
height: containerHeight / transform[2],
|
||||
};
|
||||
const boundingRect =
|
||||
nodes.length > 0 ? getBoundsofRects(getRectOfNodes(nodes), viewBB) : viewBB;
|
||||
nodes.length > 0 ? getBoundsOfRects(getRectOfNodes(nodes), viewBB) : viewBB;
|
||||
const scaledWidth = boundingRect.width / elementWidth;
|
||||
const scaledHeight = boundingRect.height / elementHeight;
|
||||
const viewScale = Math.max(scaledWidth, scaledHeight);
|
||||
@@ -103,54 +82,52 @@ function MiniMap({
|
||||
const labelledBy = `${ARIA_LABEL_KEY}-${minimapId}`;
|
||||
|
||||
return (
|
||||
<svg
|
||||
width={elementWidth}
|
||||
height={elementHeight}
|
||||
viewBox={`${x} ${y} ${width} ${height}`}
|
||||
<Panel
|
||||
position={position}
|
||||
style={style}
|
||||
className={cc(['react-flow__minimap', className])}
|
||||
role="img"
|
||||
aria-labelledby={labelledBy}
|
||||
>
|
||||
<title id={labelledBy}>React Flow mini map</title>
|
||||
{nodes
|
||||
.filter((node) => !node.hidden && node.width && node.height)
|
||||
.map((node) => {
|
||||
return (
|
||||
<MiniMapNode
|
||||
key={node.id}
|
||||
x={node.positionAbsolute?.x ?? 0}
|
||||
y={node.positionAbsolute?.y ?? 0}
|
||||
width={node.width!}
|
||||
height={node.height!}
|
||||
style={node.style}
|
||||
className={nodeClassNameFunc(node)}
|
||||
color={nodeColorFunc(node)}
|
||||
borderRadius={nodeBorderRadius}
|
||||
strokeColor={nodeStrokeColorFunc(node)}
|
||||
strokeWidth={nodeStrokeWidth}
|
||||
shapeRendering={shapeRendering}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
<MiniMapDrag
|
||||
x={viewBB.x}
|
||||
y={viewBB.y}
|
||||
width={viewBB.width}
|
||||
height={viewBB.height}
|
||||
/>
|
||||
<path
|
||||
className="react-flow__minimap-mask"
|
||||
d={`M${x - offset},${y - offset}h${width + offset * 2}v${
|
||||
height + offset * 2
|
||||
}h${-width - offset * 2}z
|
||||
<svg
|
||||
width={elementWidth}
|
||||
height={elementHeight}
|
||||
viewBox={`${x} ${y} ${width} ${height}`}
|
||||
role="img"
|
||||
aria-labelledby={labelledBy}
|
||||
>
|
||||
<title id={labelledBy}>React Flow mini map</title>
|
||||
{nodes
|
||||
.filter((node) => !node.hidden && node.width && node.height)
|
||||
.map((node) => {
|
||||
return (
|
||||
<MiniMapNode
|
||||
key={node.id}
|
||||
x={node.positionAbsolute?.x ?? 0}
|
||||
y={node.positionAbsolute?.y ?? 0}
|
||||
width={node.width!}
|
||||
height={node.height!}
|
||||
style={node.style}
|
||||
className={nodeClassNameFunc(node)}
|
||||
color={nodeColorFunc(node)}
|
||||
borderRadius={nodeBorderRadius}
|
||||
strokeColor={nodeStrokeColorFunc(node)}
|
||||
strokeWidth={nodeStrokeWidth}
|
||||
shapeRendering={shapeRendering}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
<path
|
||||
className="react-flow__minimap-mask"
|
||||
d={`M${x - offset},${y - offset}h${width + offset * 2}v${
|
||||
height + offset * 2
|
||||
}h${-width - offset * 2}z
|
||||
M${viewBB.x},${viewBB.y}h${viewBB.width}v${
|
||||
viewBB.height
|
||||
}h${-viewBB.width}z`}
|
||||
fill={maskColor}
|
||||
fillRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
viewBB.height
|
||||
}h${-viewBB.width}z`}
|
||||
fill={maskColor}
|
||||
fillRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</Panel>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
import { drag, D3DragEvent, SubjectPosition } from 'd3-drag';
|
||||
import { select } from 'd3-selection';
|
||||
import { useReactFlow } from '@react-flow/core';
|
||||
|
||||
function MiniMapDrag({ x = 0, y = 0, width = 0, height = 0 }) {
|
||||
const dragRef = useRef<SVGRectElement>(null);
|
||||
const { getViewport, setViewport } = useReactFlow();
|
||||
|
||||
useEffect(() => {
|
||||
if (dragRef.current) {
|
||||
const onDrag = (
|
||||
evt: D3DragEvent<SVGRectElement, null, SubjectPosition>
|
||||
) => {
|
||||
const { x, y, zoom } = getViewport();
|
||||
setViewport({ x: x - evt.dx * zoom, y: y - evt.dy * zoom, zoom });
|
||||
};
|
||||
|
||||
const selection = select(dragRef.current as Element);
|
||||
const dragBehaviour = drag().on('drag', onDrag);
|
||||
|
||||
selection.call(dragBehaviour);
|
||||
|
||||
return () => {
|
||||
selection.on('.drag', null);
|
||||
};
|
||||
}
|
||||
}, [getViewport, setViewport]);
|
||||
|
||||
return (
|
||||
<rect
|
||||
ref={dragRef}
|
||||
fill='rgba(255, 0,0,.5)'
|
||||
x={x}
|
||||
y={y}
|
||||
width={width}
|
||||
height={height}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default MiniMapDrag;
|
||||
@@ -1,2 +1,2 @@
|
||||
export * from './types';
|
||||
export { default as MiniMap, default } from './MiniMap';
|
||||
export { default as MiniMap } from './MiniMap';
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
.react-flow__minimap {
|
||||
background-color: #fff;
|
||||
position: absolute;
|
||||
z-index: 5;
|
||||
bottom: 20px;
|
||||
right: 15px;
|
||||
}
|
||||
6
packages/minimap/src/style.ts
Normal file
6
packages/minimap/src/style.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
const style = `
|
||||
.react-flow__minimap {
|
||||
background-color: #fff;
|
||||
}`;
|
||||
|
||||
export default style;
|
||||
@@ -1,5 +1,5 @@
|
||||
import { HTMLAttributes } from 'react';
|
||||
import { Node } from '@react-flow/core';
|
||||
import { Node, PanelPosition } from '@react-flow/core';
|
||||
|
||||
export type GetMiniMapNodeAttribute<NodeData = any> = (
|
||||
node: Node<NodeData>
|
||||
@@ -13,4 +13,5 @@ export interface MiniMapProps<NodeData = any>
|
||||
nodeBorderRadius?: number;
|
||||
nodeStrokeWidth?: number;
|
||||
maskColor?: string;
|
||||
position?: PanelPosition;
|
||||
}
|
||||
|
||||
28
packages/renderer/package.json
Normal file
28
packages/renderer/package.json
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"name": "@react-flow/renderer",
|
||||
"version": "11.0.0",
|
||||
"description": "The main React Flow package that comes with all the essentials.",
|
||||
"main": "dist/react-flow-renderer.cjs.js",
|
||||
"module": "dist/react-flow-renderer.esm.js",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"build": "postcss src/*.css --config ../../tooling/postcss.config.json --dir dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-flow/background": "11.0.0",
|
||||
"@react-flow/controls": "11.0.0",
|
||||
"@react-flow/core": "11.0.0",
|
||||
"@react-flow/minimap": "11.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^18.1.0",
|
||||
"react-dom": ">=18"
|
||||
},
|
||||
"devDependencies": {
|
||||
"autoprefixer": "^10.4.8",
|
||||
"postcss": "^8.4.14",
|
||||
"postcss-cli": "^10.0.0",
|
||||
"postcss-import": "^14.1.0",
|
||||
"postcss-nested": "^5.0.6"
|
||||
}
|
||||
}
|
||||
4
packages/renderer/src/index.ts
Normal file
4
packages/renderer/src/index.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export * from '@react-flow/core';
|
||||
export * from '@react-flow/minimap';
|
||||
export * from '@react-flow/controls';
|
||||
export * from '@react-flow/background';
|
||||
1
packages/renderer/src/theme-default.css
Normal file
1
packages/renderer/src/theme-default.css
Normal file
@@ -0,0 +1 @@
|
||||
@import '@react-flow/core/dist/theme-default.css';
|
||||
@@ -1,45 +0,0 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const postcss = require('postcss');
|
||||
const autoprefixer = require('autoprefixer');
|
||||
const nested = require('postcss-nested');
|
||||
|
||||
function getStyleInject(cssString) {
|
||||
return `
|
||||
(function(css) {
|
||||
if (!css || typeof document === 'undefined') return;
|
||||
|
||||
const head = document.head || document.getElementsByTagName('head')[0];
|
||||
const style = document.createElement('style');
|
||||
|
||||
head.appendChild(style);
|
||||
|
||||
style.appendChild(document.createTextNode(css));
|
||||
})("${cssString}")
|
||||
`;
|
||||
}
|
||||
|
||||
module.exports = function (babel) {
|
||||
return {
|
||||
name: 'inject-css-babel-plugin',
|
||||
visitor: {
|
||||
ImportDeclaration(item, state) {
|
||||
if (!item.node.source.value.includes('.css')) {
|
||||
return;
|
||||
}
|
||||
|
||||
const importFilePath = path.resolve(
|
||||
state.file.opts.filename,
|
||||
'..',
|
||||
item.node.source.value
|
||||
);
|
||||
|
||||
const css = fs.readFileSync(importFilePath).toString();
|
||||
const result = postcss([autoprefixer, nested]).process(css);
|
||||
const minified = result.css.replace(/\n/g, '');
|
||||
|
||||
item.replaceWithSourceString(getStyleInject(minified));
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
7
tooling/postcss.config.js
Normal file
7
tooling/postcss.config.js
Normal file
@@ -0,0 +1,7 @@
|
||||
module.exports = {
|
||||
plugins: [
|
||||
require('postcss-nested'),
|
||||
require('autoprefixer'),
|
||||
require('postcss-import'),
|
||||
],
|
||||
};
|
||||
Reference in New Issue
Block a user