Skip to content

Commit a555df0

Browse files
committed
feat(nodes): add class name option closes xyflow#254
1 parent a3c5d23 commit a555df0

File tree

7 files changed

+47
-21
lines changed

7 files changed

+47
-21
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ Node example: `{ id: '1', type: 'input', data: { label: 'Node 1' }, position: {
132132
- `data`: {} *(required if you are using a standard type, otherwise depends on your implementation)*
133133
- `type`: 'input' | 'output' | 'default' or a custom one you implemented
134134
- `style`: css properties
135+
- `className`: additional class name
135136
- `targetPosition`: 'left' | 'right' | 'top' | 'bottom' handle position - default: 'top'
136137
- `sourcePosition`: 'left' | 'right' | 'top' | 'bottom' handle position - default: 'bottom'
137138

example/src/Horizontal/index.js

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ const onLoad = (graph) => {
77
};
88

99
const initialElements = [
10-
{ id: '1', sourcePosition: 'right', type: 'input', data: { label: 'Input' }, position: { x: 0, y: 80 } },
10+
{ id: '1', sourcePosition: 'right', type: 'input', className: 'dark-node', data: { label: 'Input' }, position: { x: 0, y: 80 } },
1111
{ id: '2', sourcePosition: 'right', targetPosition: 'left', data: { label: 'A Node' }, position: { x: 250, y: 0 } },
1212
{ id: '3', sourcePosition: 'right', targetPosition: 'left', data: { label: 'Another node' }, position: { x: 250, y: 160 } },
1313
{ id: '4', sourcePosition: 'right', targetPosition: 'left', data: { label: 'Node 4' }, position: { x: 500, y: 80 } },
@@ -21,6 +21,15 @@ const HorizontalFlow = () => {
2121
const onElementsRemove = (elementsToRemove) =>
2222
setElements(els => removeElements(elementsToRemove, els));
2323
const onConnect = (params) => setElements(els => addEdge(params, els));
24+
const changeClassName = () => {
25+
setElements(elms => elms.map(el => {
26+
if (el.type === 'input') {
27+
el.className = el.className ? '' : 'dark-node';
28+
}
29+
30+
return {...el};
31+
}))
32+
}
2433

2534
return (
2635
<ReactFlow
@@ -29,7 +38,14 @@ const HorizontalFlow = () => {
2938
onConnect={onConnect}
3039
onLoad={onLoad}
3140
selectNodesOnDrag={false}
32-
/>
41+
>
42+
<button
43+
onClick={changeClassName}
44+
style={{ position: 'absolute', right: 10, top: 30, zIndex: 4 }}
45+
>
46+
change class name
47+
</button>
48+
</ReactFlow>
3349
);
3450
}
3551

example/src/index.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,11 @@ nav a.active:before {
136136
color: #111;
137137
}
138138

139+
.dark-node>div {
140+
background: #333 !important;
141+
color: #f8f8f8 !important;
142+
}
143+
139144
@media screen and (min-width: 768px) {
140145
nav {
141146
position: relative;

src/components/Nodes/wrapNode.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ export default (NodeComponent: ComponentType<NodeComponentProps>) => {
142142
onNodeDragStart,
143143
onNodeDragStop,
144144
style,
145+
className,
145146
isInteractive,
146147
selectNodesOnDrag,
147148
sourcePosition,
@@ -151,7 +152,8 @@ export default (NodeComponent: ComponentType<NodeComponentProps>) => {
151152
const [offset, setOffset] = useState({ x: 0, y: 0 });
152153
const [isDragging, setDragging] = useState(false);
153154
const position = { x: xPos, y: yPos };
154-
const nodeClasses = cx('react-flow__node', { selected });
155+
const nodeClasses = cx('react-flow__node', `react-flow__node-${type}`, className, { selected });
156+
155157
const nodeStyle: CSSProperties = {
156158
zIndex: selected ? 10 : 3,
157159
transform: `translate(${xPos}px,${yPos}px)`,

src/container/NodeRenderer/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ function renderNode(
4242
transform={transform}
4343
selected={isSelected}
4444
style={node.style}
45+
className={node.className}
4546
isInteractive={isInteractive}
4647
sourcePosition={node.sourcePosition}
4748
targetPosition={node.targetPosition}

src/hooks/useElementUpdater.ts

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -28,34 +28,33 @@ const useElementUpdater = (elements: Elements): void => {
2828
? { ...existingNode.style, ...propNode.style }
2929
: existingNode.style;
3030

31+
const className = existingNode.className === propNode.className ? existingNode.className : propNode.className;
32+
3133
const positionChanged =
3234
existingNode.position.x !== propNode.position.x || existingNode.position.y !== propNode.position.y;
3335

36+
const nodeProps = {
37+
...existingNode,
38+
data,
39+
};
40+
3441
if (positionChanged) {
35-
return {
36-
...existingNode,
37-
__rg: {
38-
...existingNode.__rg,
39-
position: propNode.position,
40-
},
42+
nodeProps.__rg = {
43+
...existingNode.__rg,
4144
position: propNode.position,
42-
data,
43-
style,
4445
};
46+
nodeProps.position = propNode.position;
4547
}
4648

47-
if (style) {
48-
return {
49-
...existingNode,
50-
data,
51-
style,
52-
};
49+
if (typeof style !== 'undefined') {
50+
nodeProps.style = style;
5351
}
5452

55-
return {
56-
...existingNode,
57-
data,
58-
};
53+
if (typeof className !== 'undefined') {
54+
nodeProps.className = className;
55+
}
56+
57+
return nodeProps;
5958
}
6059

6160
return parseElement(propNode) as Node;

src/types/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ export interface Node {
3737
__rg?: any;
3838
data?: any;
3939
style?: CSSProperties;
40+
className?: string;
4041
targetPosition?: Position;
4142
sourcePosition?: Position;
4243
}
@@ -128,6 +129,7 @@ export interface WrapNodeProps {
128129
onNodeDragStart?: (node: Node) => void;
129130
onNodeDragStop?: (node: Node) => void;
130131
style?: CSSProperties;
132+
className?: string;
131133
sourcePosition?: Position;
132134
targetPosition?: Position;
133135
}

0 commit comments

Comments
 (0)