refactor(background): export background as component closes #235

This commit is contained in:
moklick
2020-05-25 15:53:56 +02:00
parent 10cd70c6ee
commit 7324c79fd0
24 changed files with 229 additions and 227 deletions
@@ -0,0 +1,56 @@
import React, { memo, HTMLAttributes, CSSProperties } from 'react';
import classnames from 'classnames';
import { useStoreState } from '../../store/hooks';
import { BackgroundVariant } from '../../types';
import { createGridLinesPath, createGridDotsPath } from './utils';
interface BackgroundProps extends HTMLAttributes<SVGElement> {
variant?: BackgroundVariant;
gap?: number;
color?: string;
size?: number;
}
const baseStyles: CSSProperties = {
position: 'absolute',
top: 0,
left: 0,
};
const defaultColors = {
[BackgroundVariant.Dots]: '#999',
[BackgroundVariant.Lines]: '#eee',
};
const Background = memo(
({ variant = BackgroundVariant.Dots, gap = 24, size = 0.5, color, style = {}, className = '' }: BackgroundProps) => {
const {
width,
height,
transform: [x, y, scale],
} = useStoreState((s) => s);
const bgClasses = classnames('react-flow__background', className);
const bgColor = color ? color : defaultColors[variant];
const scaledGap = gap * scale;
const xOffset = x % scaledGap;
const yOffset = y % scaledGap;
const isLines = variant === BackgroundVariant.Lines;
const path = isLines
? createGridLinesPath(width, height, xOffset, yOffset, scaledGap)
: createGridDotsPath(width, height, xOffset, yOffset, scaledGap, size);
const fill = isLines ? 'none' : bgColor;
const stroke = isLines ? bgColor : 'none';
return (
<svg width={width} height={height} style={{ ...baseStyles, ...style }} className={bgClasses}>
<path fill={fill} stroke={stroke} strokeWidth={size} d={path} />
</svg>
);
}
);
Background.displayName = 'Background';
export default Background;
@@ -0,0 +1,37 @@
export const createGridLinesPath = (
width: number,
height: number,
xOffset: number,
yOffset: number,
gap: number
): string => {
const lineCountX = Math.ceil(width / gap) + 1;
const lineCountY = Math.ceil(height / gap) + 1;
const xValues = Array.from({ length: lineCountX }, (_, i) => `M${i * gap + xOffset} 0 V${height}`);
const yValues = Array.from({ length: lineCountY }, (_, i) => `M0 ${i * gap + yOffset} H${width}`);
return [...xValues, ...yValues].join(' ');
};
export const createGridDotsPath = (
width: number,
height: number,
xOffset: number,
yOffset: number,
gap: number,
size: number
): string => {
const lineCountX = Math.ceil(width / gap) + 1;
const lineCountY = Math.ceil(height / gap) + 1;
const values = Array.from({ length: lineCountX }, (_, col) => {
const x = col * gap + xOffset;
return Array.from({ length: lineCountY }, (_, row) => {
const y = row * gap + yOffset;
return `M${x} ${y - size} l${size} ${size} l${-size} ${size} l${-size} ${-size}z`;
}).join(' ');
});
return values.join(' ');
};
+6
View File
@@ -0,0 +1,6 @@
// These components are not used by React Flow directly
// but the user can add them as a child of a React Flow component
export { default as MiniMap } from './MiniMap';
export { default as Controls } from './Controls';
export { default as Background } from './Background';
-108
View File
@@ -1,108 +0,0 @@
import React, { memo, HTMLAttributes, CSSProperties } from 'react';
import classnames from 'classnames';
import { useStoreState } from '../../store/hooks';
import { GridType } from '../../types';
interface GridProps extends HTMLAttributes<SVGElement> {
backgroundType?: GridType;
gap?: number;
color?: string;
size?: number;
}
const baseStyles: CSSProperties = {
position: 'absolute',
top: 0,
left: 0,
};
const createGridLines = (
width: number,
height: number,
xOffset: number,
yOffset: number,
gap: number
): string => {
const lineCountX = Math.ceil(width / gap) + 1;
const lineCountY = Math.ceil(height / gap) + 1;
const xValues = Array.from(
{ length: lineCountX },
(_, i) => `M${i * gap + xOffset} 0 V${height}`
);
const yValues = Array.from(
{ length: lineCountY },
(_, i) => `M0 ${i * gap + yOffset} H${width}`
);
return [...xValues, ...yValues].join(' ');
};
const createGridDots = (
width: number,
height: number,
xOffset: number,
yOffset: number,
gap: number,
size: number
): string => {
const lineCountX = Math.ceil(width / gap) + 1;
const lineCountY = Math.ceil(height / gap) + 1;
const values = Array.from({ length: lineCountX }, (_, col) => {
const x = col * gap + xOffset;
return Array.from({ length: lineCountY }, (_, row) => {
const y = row * gap + yOffset;
return `M${x} ${y -
size} l${size} ${size} l${-size} ${size} l${-size} ${-size}z`;
}).join(' ');
});
return values.join(' ');
};
const Grid = memo(
({
gap = 24,
color = '#aaa',
size = 0.5,
style = {},
className = '',
backgroundType = GridType.Dots,
}: GridProps) => {
const {
width,
height,
transform: [x, y, scale],
} = useStoreState(s => s);
const gridClasses = classnames('react-flow__grid', className);
const scaledGap = gap * scale;
const xOffset = x % scaledGap;
const yOffset = y % scaledGap;
const isLines = backgroundType === 'lines';
const path = isLines
? createGridLines(width, height, xOffset, yOffset, scaledGap)
: createGridDots(width, height, xOffset, yOffset, scaledGap, size);
const fill = isLines ? 'none' : color;
const stroke = isLines ? color : 'none';
return (
<svg
width={width}
height={height}
style={{ ...baseStyles, ...style }}
className={gridClasses}
>
<path fill={fill} stroke={stroke} strokeWidth={size} d={path} />
</svg>
);
}
);
Grid.displayName = 'Grid';
export default Grid;
+1 -13
View File
@@ -6,14 +6,13 @@ import NodeRenderer from '../NodeRenderer';
import EdgeRenderer from '../EdgeRenderer';
import UserSelection from '../../components/UserSelection';
import NodesSelection from '../../components/NodesSelection';
import BackgroundGrid from '../../components/BackgroundGrid';
import useKeyPress from '../../hooks/useKeyPress';
import useD3Zoom from '../../hooks/useD3Zoom';
import useGlobalKeyHandler from '../../hooks/useGlobalKeyHandler';
import useElementUpdater from '../../hooks/useElementUpdater';
import { getDimensions } from '../../utils';
import { fitView, zoomIn, zoomOut, project } from '../../utils/graph';
import { Elements, NodeTypesType, EdgeTypesType, GridType, OnLoadFunc, Node, Edge, Connection } from '../../types';
import { Elements, NodeTypesType, EdgeTypesType, OnLoadFunc, Node, Edge, Connection } from '../../types';
export interface GraphViewProps {
elements: Elements;
@@ -30,10 +29,6 @@ export interface GraphViewProps {
connectionLineType: string;
connectionLineStyle: CSSProperties;
deleteKeyCode: number;
showBackground: boolean;
backgroundGap: number;
backgroundColor: string;
backgroundType: GridType;
snapToGrid: boolean;
snapGrid: [number, number];
onlyRenderVisibleNodes: boolean;
@@ -55,10 +50,6 @@ const GraphView = memo(
onElementsRemove,
deleteKeyCode,
elements,
showBackground,
backgroundGap,
backgroundColor,
backgroundType,
onConnect,
snapToGrid,
snapGrid,
@@ -135,9 +126,6 @@ const GraphView = memo(
return (
<div className={rendererClasses} ref={rendererNode}>
{showBackground && (
<BackgroundGrid gap={backgroundGap} color={backgroundColor} backgroundType={backgroundType} />
)}
<NodeRenderer
nodeTypes={nodeTypes}
onElementClick={onElementClick}
+1 -17
View File
@@ -20,7 +20,7 @@ import StraightEdge from '../../components/Edges/StraightEdge';
import StepEdge from '../../components/Edges/StepEdge';
import { createEdgeTypes } from '../EdgeRenderer/utils';
import store from '../../store';
import { Elements, NodeTypesType, EdgeTypesType, GridType, OnLoadFunc, Node, Edge, Connection } from '../../types';
import { Elements, NodeTypesType, EdgeTypesType, OnLoadFunc, Node, Edge, Connection } from '../../types';
import '../../style.css';
@@ -40,10 +40,6 @@ export interface ReactFlowProps extends Omit<HTMLAttributes<HTMLDivElement>, 'on
connectionLineStyle: CSSProperties;
deleteKeyCode: number;
selectionKeyCode: number;
showBackground: boolean;
backgroundGap: number;
backgroundColor: string;
backgroundType: GridType;
snapToGrid: boolean;
snapGrid: [number, number];
onlyRenderVisibleNodes: boolean;
@@ -69,10 +65,6 @@ const ReactFlow = ({
connectionLineStyle,
deleteKeyCode,
selectionKeyCode,
showBackground,
backgroundGap,
backgroundType,
backgroundColor,
snapToGrid,
snapGrid,
onlyRenderVisibleNodes,
@@ -99,10 +91,6 @@ const ReactFlow = ({
deleteKeyCode={deleteKeyCode}
elements={elements}
onConnect={onConnect}
backgroundColor={backgroundColor}
backgroundGap={backgroundGap}
showBackground={showBackground}
backgroundType={backgroundType}
snapToGrid={snapToGrid}
snapGrid={snapGrid}
onlyRenderVisibleNodes={onlyRenderVisibleNodes}
@@ -139,10 +127,6 @@ ReactFlow.defaultProps = {
connectionLineStyle: {},
deleteKeyCode: 8,
selectionKeyCode: 16,
backgroundColor: '#eee',
backgroundGap: 24,
showBackground: true,
backgroundType: GridType.Dots,
snapToGrid: false,
snapGrid: [16, 16],
onlyRenderVisibleNodes: true,
+1 -1
View File
@@ -4,8 +4,8 @@ export default ReactFlow;
export { default as Handle } from './components/Handle';
export { default as EdgeText } from './components/Edges/EdgeText';
export { MiniMap, Controls } from './plugins';
export { isNode, isEdge, removeElements, addEdge, getOutgoers } from './utils/graph';
export * from './additional-components';
export * from './types';
-2
View File
@@ -1,2 +0,0 @@
export { default as MiniMap } from './MiniMap';
export { default as Controls } from './Controls';
+1 -1
View File
@@ -54,7 +54,7 @@ export interface Edge {
animated?: boolean;
}
export enum GridType {
export enum BackgroundVariant {
Lines = 'lines',
Dots = 'dots',
}