@lamvuvu43/react-org-chart
v1.0.2
Published
A simple React wrapper around [d3-org-chart](https://github.com/bumbeishvili/org-chart) with custom node rendering and configurable link styles.
Downloads
7
Readme
react-org-chart
A simple React wrapper around d3-org-chart with custom node rendering and configurable link styles.
📦 Installation
npm install @lamvuvu43/react-org-chart🚀 Usage
import OrgChartComponent from "react-org-chart";
const data = [
{
"name": "Ian Devling",
"imageUrl": "https://raw.githubusercontent.com/bumbeishvili/Assets/master/Projects/D3/Organization%20Chart/cto.jpg",
"area": "Corporate",
"profileUrl": "http://example.com/employee/profile",
"office": "CTO office",
"tags": "Ceo,tag1,manager,cto",
"isLoggedUser": "false",
"positionName": "Chief Executive Officer ",
"id": "O-6066",
"parentId": "",
"size": ""
},
{
"name": "Davolio Nancy",
"imageUrl": "https://raw.githubusercontent.com/bumbeishvili/Assets/master/Projects/D3/Organization%20Chart/general.jpg",
"area": "Corporate",
"profileUrl": "http://example.com/employee/profile",
"office": "CEO office",
"tags": "Ceo,tag1, tag2",
"isLoggedUser": "false",
"positionName": "CTO ",
"id": "O-6067",
"parentId": "O-6066",
"size": ""
},
];
export function NodeChartItem(
d: any,
idSelected?: string | number
) {
const color = "#FFFFFF";
const imageDiffVert = 25 + 2;
const isSelected = idSelected === d.data.id;
return `
<div style="
width: ${d.width}px;
height: ${d.height}px;
padding-top: ${imageDiffVert - 2}px;
padding-left: 1px;
padding-right: 1px;
">
<div style="
font-family: 'Inter', sans-serif;
background-color: ${color};
margin-left: -1px;
width: ${d.width - 2}px;
height: ${d.height - imageDiffVert}px;
border-radius: 10px;
border: ${isSelected ? `2px solid #e0240bff` : `1px solid #2fcd80`};
box-shadow: ${isSelected ? '0 0 10px #e0240bff' : 'none'};
">
<div style="
display: flex;
justify-content: flex-end;
margin-top: 5px;
margin-right: 8px;
">
#${d.data.id}
</div>
<div style="
background-color: ${color};
margin-top: ${-imageDiffVert - 20}px;
margin-left: 15px;
border-radius: 100px;
width: 50px;
height: 50px;
"></div>
<div style="
margin-top: ${-imageDiffVert - 20}px;
">
<img src="${d.data.imageUrl}"
style="
margin-left: 20px;
border-radius: 100px;
width: 40px;
height: 40px;
border: 2px solid #cb117133;
"
/>
</div>
<div style="
font-size: 15px;
margin-left: 20px;
margin-top: 10px;
background: linear-gradient(
90deg,
rgba(194,161,12,1) 0%,
rgba(9,121,24,0.25) 35%,
rgba(255,0,249,0.93) 100%
);
background-clip: text;
color: transparent;
">
${d.data.name}
</div>
<div style="
color: #716E7B;
margin-left: 20px;
margin-top: 3px;
font-size: 10px;
">
${d.data.positionName}
</div>
</div>
</div>
`;
}
export function ActionButtons(chartRef) {
return (
<div>
<button
className="border rounded-md p-2 m-2"
onClick={() => chartRef.current.zoomIn()}
>
Zoom In
</button>
<button
className="border rounded-md p-2 m-2"
onClick={() => chartRef.current.zoomOut()}
>
Zoom Out
</button>
</div>
);
}
export default function OrgChartPage() {
const [data, setData] = useState(null);
const selectNodeId = useRef(null);
let addNodeChildFunc = null;
function addNode() {
const node = {
"name": "Demo Added Node",
"imageUrl": "https://raw.githubusercontent.com/bumbeishvili/Assets/master/Projects/D3/Organization%20Chart/cto.jpg",
"area": "Corporate",
"profileUrl": "http://example.com/employee/profile",
"office": "CTO office",
"tags": "Ceo,tag1,manager,cto",
"isLoggedUser": "false",
"positionName": "Chief Executive Officer ",
"id": "O-" + Math.floor(Math.random() * 1000),
"parentId": selectNodeId.current,
"size": "",
};
addNodeChildFunc(node);
}
function onNodeClick(node) {
selectNodeId.current = node.data.id;
}
function handleSetClick(func) {
addNodeChildFunc = func;
}
useEffect(() => {
d3.csv(
'https://raw.githubusercontent.com/bumbeishvili/sample-data/main/org.csv'
).then((data) => {
setData(data);
});
}, [true]);
return (
<div>
<button style={{ border: "1px", borderRadius: "5px", backgroundColor: "lightblue" }} onClick={() => addNode()}>Add node</button>
<br></br>
<OrgChartComponent
linkFuncAddNode={(funcAddNode) => addNodeChildFunc = funcAddNode}
onNodeClick={onNodeClick}
data={data}
selectNodeId={selectNodeId.current}
nodeItem={NodeChartItem}
actionButtons={ActionButtons}
/>
</div>
);
}
⚙️ Props
| Prop | Type | Description |
| ---- | ---- | ------------ |
| data | [{ [key: string]: any }] | Org chart data in hierarchical format |
| linkFuncAddNode | (node: any) => void | Function to get internal addNode function |
| onNodeClick | (node: any) => void | Callback when a node is clicked |
| nodeItem | (d: any, nodeIdSelected?: string \| number) => string | Custom node content renderer |
| nodeConfig | { width?: number, height?: number } | Node size config |
| lineOptions | { stroke?: string, strokeWidth?: number } | Line (link) color and width |
| actionButtons | (chartRef: any) => React.ReactNode | Custom action buttons, default is built-in |
🗂️ Features
✅ Uses D3 Org Chart under the hood
✅ Custom node rendering with nodeItem
✅ Configurable line stroke and strokeWidth
✅ Support for external add node function
✅ Click handler for each node
✅ Action buttons slot
📄 License
MIT
