All files / src/tree-graph-flex tree-graph-flex.tsx

100% Statements 11/11
50% Branches 1/2
100% Functions 4/4
100% Lines 11/11

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91                                                                1x                                       7x   7x 7x 7x 7x 7x 127x             7x         127x                     120x                
import * as React from "react";
import "./tree-styles.css";
import pathShapes, { staticRadiusRoundedAngles } from "./path-shapes";
import {
  processTree,
  createNodesArray,
  createConnectingLinesArray,
}
  from "./tree-build-functions";
import {
  PathFunction,
  TreeElementWithCoords,
  TreeProps,
  Path
}
  from "./interfaces";
 
export class TreeGraphFlex extends React.Component<TreeProps> {
  /**
  * @class Tree 
  * builds tree graph from user's object. Graph exist is rectangles(nodes) and connecting lines. 
  * @param {TreeElement} data - source user's object.
  * @param {number} nodeWidth - width of the rectangle(node) in pixels, that user's content is placed in. Not mandatory. 100 pixels by default.
  * @param {number} nodeHeight - height of the node in pixels. 50 pixels by default.
  * @param {number | function} xOffset -  distance by x between adjacent two nodes. By default 50 pixels. Also, it may be a custom function.
  * @param {number} yOffset -  distance by y between adjacent two nodes. By default 50 pixels.
  * @param {PathShape | PathFunction} pathShape - funcion, calculates svg lines between two nodes. There are three offered functions. "bezier" by default. Also, it may be a custom function.
  * @param {function} nodeContent - user's function, returns HTML element, which will be placed into node box.
  * @param {string} lineClassName - connecting lines className. Locates in tree.style.css. By default "connectingLine".
  * @param {string} nodeBoxClassName - className, defines style of node view. Locates in tree.style.css. By default "nodeBox".
  * @returns {HTMLElement} renders tree
  */
  static defaultProps: Pick<TreeProps, "pathShape" | "nodeWidth" | "nodeHeight" | "lineClassName" | "xOffset" | "yOffset" | "nodeBoxClassName"> = {
    pathShape: pathShapes.bezier,
    nodeWidth: 100,
    nodeHeight: 50,
    lineClassName: "connectingLine",
    nodeBoxClassName: "nodeBox",
    xOffset: 50,
    yOffset: 50,
  };
 
  render(): React.ReactElement {
    const {
      nodeWidth,
      nodeHeight,
      data,
      yOffset,
      xOffset,
      lineClassName,
      nodeBoxClassName,
      nodeContent: content
    }: TreeProps = this.props;
 
    const pathStyle: PathFunction = typeof this.props.pathShape == "function" ? this.props.pathShape : pathShapes[this.props.pathShape];
    const dataTree: TreeElementWithCoords = processTree(data, yOffset, xOffset, nodeWidth, nodeHeight);
    const dataList: TreeElementWithCoords[] = createNodesArray(dataTree);
    const connectingLines: Path[] = createConnectingLinesArray(dataTree, nodeWidth, nodeHeight, pathStyle);
    const { width, height }: { width: number; height: number } = dataList.reduce(
      (limits, node) => ({
        width: Math.max(limits.width, node.x + node.width),
        height: Math.max(limits.height, node.y + node.height)
      }),
      { width: 0, height: 0 }
    );
 
    return (
      <div>
        <div className="root" style={{ width: width, height: height }}>
          <div>
            {dataList.map(node => (
              <div
                style={{ height: nodeHeight, width: nodeWidth, top: node.y, left: node.x }}
                className={nodeBoxClassName}
                key={node.id}
              >
                {content(node)}
              </div>
            ))}
          </div>
          <svg width={width} height={height}>
            {connectingLines.map((path: Path) => (
              <path d={path.path} className={lineClassName} key={path.id} />
            ))}
          </svg>
        </div>
      </div>
    );
  };
};