import { d3 } from './constants'; import { D3Node, OrgChartConnection, OrgChartDataItem, OrgChartOptions } from './types'; import { BaseType } from 'd3-selection'; import { getTextWidth } from './utils/core'; import { diagonal, hdiagonal } from './utils/calculations'; const canvasContext = document.createElement('canvas').getContext('2d'); export const getChartOptions = (): OrgChartOptions => ({ svgWidth: 800, svgHeight: window.innerHeight - 100, container: document.body, nodeIdKey: 'id', parentNodeIdKey: 'parentId', data: null, onDataChange: () => {}, connections: [], rootMargin: 40, neighbourMargin: () => 80, siblingsMargin: () => 20, childrenMargin: () => 60, linkYOffset: 30, expandLevel: 0, defaultFont: 'Helvetica', duration: 400, imageName: 'Chart', setActiveNodeCentered: true, layout: 'top', compact: true, compactNoChildren: false, compactNoChildrenMargin: 15, compactToggleButtonMargin: 10, compactMarginPair: () => 100, compactMarginBetween: () => 20, compactNoChildrenUpdate: function (compactGroupRect) { compactGroupRect.attr('fill', '#fff').attr('rx', 10).attr('stroke', '#e4e2e9').attr('stroke-width', 1); }, compactCollapsedContent: (d) => `
${d.data._directSubordinates}
`, compactCollapsedNodeUpdate: function (nodeGroup) { nodeGroup.select('.node-rect').attr('stroke', '#333').attr('stroke-width', 1); }, compactCollapsedNodeWidth: function (d) { return this.nodeWidth(d); }, compactCollapsedNodeHeight: function (d) { return this.nodeHeight(d); }, scaleExtent: [0.001, 20], onZoomStart: () => {}, onZoom: () => {}, onZoomEnd: () => {}, enableDoubleClickZoom: false, enableWheelZoom: true, nodeWidth: (_) => 250, nodeHeight: (_) => 150, onNodeClick: (d) => d, nodeContent: (d) => `
Sample Node(id=${d.id}), override using
chart.nodeContent({data}=>{
    return '' // Custom HTML
})

Or check different layout examples
`, nodeUpdate: function (nodeGroup, d) { nodeGroup .select('.node-rect') .attr('stroke', (d) => (d.data._highlighted || d.data._upToTheRootHighlighted ? '#E27396' : 'none')) .attr('stroke-width', d.data._highlighted || d.data._upToTheRootHighlighted ? 10 : 1); }, dragNDrop: true, onNodeDrop: () => true, isNodeDraggable: () => true, isNodeDroppable: () => true, isNodeButtonVisible: ({ data }) => { return !!data._directSubordinates && data._directSubordinates > 0; }, nodeButtonWidth: () => 40, nodeButtonHeight: () => 40, nodeButtonX: () => -20, nodeButtonY: () => -20, buttonContent: ({ node, state }) => { const icons = { left: (d?: Array> | null) => d ? `
${node.data._directSubordinates}
` : `
${node.data._directSubordinates}
`, bottom: (d?: Array> | null) => d ? `
${node.data._directSubordinates}
` : `
${node.data._directSubordinates}
`, right: (d?: Array> | null) => d ? `
${node.data._directSubordinates}
` : `
${node.data._directSubordinates}
`, top: (d?: Array> | null) => d ? `
${node.data._directSubordinates}
` : `
${node.data._directSubordinates}
`, }; return `
${icons[ state.layout ](node.children)}
`; }, linkUpdate: function (d) { d3.select>(this) .attr('stroke', (d) => (d.data._upToTheRootHighlighted ? '#E27396' : '#E4E2E9')) .attr('stroke-width', (d) => (d.data._upToTheRootHighlighted ? 5 : 1)); if (d.data._upToTheRootHighlighted) { d3.select(this).raise(); } }, defs: function (state, visibleConnections) { return ` ${visibleConnections .map((conn) => { const labelWidth = getTextWidth(conn.label, { ctx: canvasContext, fontSize: 2, defaultFont: state.defaultFont, }); return ` ${conn.label || ''} `; }) .join('')} `; }, connectionsUpdate: function () { d3.select(this) .attr('stroke', () => '#E27396') .attr('stroke-linecap', 'round') .attr('stroke-width', () => '5') .attr('pointer-events', 'none') .attr('marker-start', (d) => `url(#${d.from + '_' + d.to})`) .attr('marker-end', (d) => `url(#arrow-${d.from + '_' + d.to})`); }, linkGroupArc: d3 .linkHorizontal>() .x((d: D3Node) => d.x) .y((d: D3Node) => d.y), layoutBindings: { left: { nodeLeftX: () => 0, nodeRightX: (node) => node.width, nodeTopY: (node) => -node.height / 2, nodeBottomY: (node) => node.height / 2, nodeJoinX: (node) => node.x + node.width, nodeJoinY: (node) => node.y - node.height / 2, linkJoinX: (node) => node.x + node.width, linkJoinY: (node) => node.y, linkX: (node) => node.x, linkY: (node) => node.y, linkCompactXStart: (node) => node.x + node.width / 2, linkCompactYStart: (node) => node.y + (node.compactEven ? node.height / 2 : -node.height / 2), compactLinkMidX: (node) => node.firstCompactNode?.x ?? 0, compactLinkMidY: (node, state) => (node.firstCompactNode?.y ?? 0) + (node.firstCompactNode?.flexCompactDim![0] ?? 0) / 4 + state.compactMarginPair(node) / 4, linkParentX: (node) => (node.parent?.x ?? 0) + (node.parent?.width ?? 0), linkParentY: (node) => node.parent?.y ?? 0, buttonX: (node) => node.width, buttonY: (node) => node.height / 2, centerTransform: ({ rootMargin, centerY, scale }) => `translate(${rootMargin},${centerY}) scale(${scale})`, compactDimension: { sizeColumn: (node) => node.height, sizeRow: (node) => node.width, reverse: (arr) => arr.slice().reverse(), }, nodeFlexSize: ({ height, width, siblingsMargin, childrenMargin, state, node }) => { if (state.compact && node.flexCompactDim) { return [node.flexCompactDim[0], node.flexCompactDim[1]]; } return [height + siblingsMargin, width + childrenMargin]; }, zoomTransform: ({ centerY, scale }) => `translate(${0},${centerY}) scale(${scale})`, diagonal: hdiagonal.bind(this), swap: (d) => { const x = d.x; d.x = d.y; d.y = x; }, nodeUpdateTransform: ({ x, y, height }) => `translate(${x},${y - height / 2})`, }, top: { nodeLeftX: (node) => -node.width / 2, nodeRightX: (node) => node.width / 2, nodeTopY: () => 0, nodeBottomY: (node) => node.height, nodeJoinX: (node) => node.x - node.width / 2, nodeJoinY: (node) => node.y + node.height, linkJoinX: (node) => node.x, linkJoinY: (node) => node.y + node.height, linkCompactXStart: (node) => node.x + (node.compactEven ? node.width / 2 : -node.width / 2), linkCompactYStart: (node) => node.y + node.height / 2, compactLinkMidX: (node, state) => (node.firstCompactNode?.x ?? 0) + (node.firstCompactNode?.flexCompactDim![0] ?? 0) / 4 + state.compactMarginPair(node) / 4, compactLinkMidY: (node) => node.firstCompactNode?.y ?? 0, compactDimension: { sizeColumn: (node) => node.width, sizeRow: (node) => node.height, reverse: (arr) => arr, }, linkX: (node) => node.x, linkY: (node) => node.y, linkParentX: (node) => node.parent?.x ?? 0, linkParentY: (node) => (node.parent?.y ?? 0) + (node.parent?.height ?? 0), buttonX: (node) => node.width / 2, buttonY: (node) => node.height, centerTransform: ({ rootMargin, scale, centerX }) => `translate(${centerX},${rootMargin}) scale(${scale})`, nodeFlexSize: ({ height, width, siblingsMargin, childrenMargin, state, node }) => { if (state.compact && node.flexCompactDim) { return [node.flexCompactDim[0], node.flexCompactDim[1]]; } return [width + siblingsMargin, height + childrenMargin]; }, zoomTransform: ({ centerX, scale }) => `translate(${centerX},0}) scale(${scale})`, diagonal: diagonal.bind(this), swap: () => {}, nodeUpdateTransform: ({ x, y, width }) => `translate(${x - width / 2},${y})`, }, bottom: { nodeLeftX: (node) => -node.width / 2, nodeRightX: (node) => node.width / 2, nodeTopY: (node) => -node.height, nodeBottomY: () => 0, nodeJoinX: (node) => node.x - node.width / 2, nodeJoinY: (node) => node.y - node.height - node.height, linkJoinX: (node) => node.x, linkJoinY: (node) => node.y - node.height, linkCompactXStart: (node) => node.x + (node.compactEven ? node.width / 2 : -node.width / 2), linkCompactYStart: (node) => node.y - node.height / 2, compactLinkMidX: (node, state) => (node.firstCompactNode?.x ?? 0) + (node.firstCompactNode?.flexCompactDim![0] ?? 0) / 4 + state.compactMarginPair(node) / 4, compactLinkMidY: (node) => node.firstCompactNode?.y ?? 0, linkX: (node) => node.x, linkY: (node) => node.y, compactDimension: { sizeColumn: (node) => node.width, sizeRow: (node) => node.height, reverse: (arr) => arr, }, linkParentX: (node) => node.parent?.x ?? 0, linkParentY: (node) => (node.parent?.y ?? 0) - (node.parent?.height ?? 0), buttonX: (node) => node.width / 2, buttonY: () => 0, centerTransform: ({ rootMargin, scale, centerX, chartHeight }) => `translate(${centerX},${chartHeight - rootMargin}) scale(${scale})`, nodeFlexSize: ({ height, width, siblingsMargin, childrenMargin, state, node }) => { if (state.compact && node.flexCompactDim) { return [node.flexCompactDim[0], node.flexCompactDim[1]]; } return [width + siblingsMargin, height + childrenMargin]; }, zoomTransform: ({ centerX, scale }) => `translate(${centerX},0}) scale(${scale})`, diagonal: diagonal.bind(this), swap: (d) => { d.y = -d.y; }, nodeUpdateTransform: ({ x, y, width, height }) => `translate(${x - width / 2},${y - height})`, }, right: { nodeLeftX: (node) => -node.width, nodeRightX: () => 0, nodeTopY: (node) => -node.height / 2, nodeBottomY: (node) => node.height / 2, nodeJoinX: (node) => node.x - node.width - node.width, nodeJoinY: (node) => node.y - node.height / 2, linkJoinX: (node) => node.x - node.width, linkJoinY: (node) => node.y, linkX: (node) => node.x, linkY: (node) => node.y, linkParentX: (node) => (node.parent?.x ?? 0) - (node.parent?.width ?? 0), linkParentY: (node) => node.parent?.y ?? 0, buttonX: () => 0, buttonY: (node) => node.height / 2, linkCompactXStart: (node) => node.x - node.width / 2, linkCompactYStart: (node) => node.y + (node.compactEven ? node.height / 2 : -node.height / 2), compactLinkMidX: (node) => node.firstCompactNode?.x ?? 0, compactLinkMidY: (node, state) => (node.firstCompactNode?.y ?? 0) + (node.firstCompactNode?.flexCompactDim![0] ?? 0) / 4 + state.compactMarginPair(node) / 4, centerTransform: ({ rootMargin, centerY, scale, chartWidth }) => `translate(${chartWidth - rootMargin},${centerY}) scale(${scale})`, nodeFlexSize: ({ height, width, siblingsMargin, childrenMargin, state, node }) => { if (state.compact && node.flexCompactDim) { return [node.flexCompactDim[0], node.flexCompactDim[1]]; } return [height + siblingsMargin, width + childrenMargin]; }, compactDimension: { sizeColumn: (node) => node.height, sizeRow: (node) => node.width, reverse: (arr) => arr.slice().reverse(), }, zoomTransform: ({ centerY, scale }) => `translate(${0},${centerY}) scale(${scale})`, diagonal: hdiagonal.bind(this), swap: (d) => { const x = d.x; d.x = -d.y; d.y = x; }, nodeUpdateTransform: ({ x, y, width, height }) => `translate(${x - width},${y - height / 2})`, }, }, });