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

100% Statements 23/23
80% Branches 4/5
100% Functions 9/9
100% Lines 21/21

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 92 93 94 95 96 97 98 99 100                                                21x   318x 297x     318x 129x   189x 189x   318x 318x                   21x                 212x                             171x 171x 171x 171x 171x 171x                                 178x 178x 168x     178x  
import {
  TreeElement,
  PathFunction,
  TreeElementWithCoords,
  Path
}
  from "./interfaces";
 
/**
 * Calculates and adds coordinates into source object
 * @param rootElement - source object
 * @param {number} yOffset - distance between adjacent nodes by y
 * @param { number | function } xOffset - distance between adjacent nodes by x
 * @param { number } cellwidth - node width
 * @param { number } cellHeight - node height
 * @returns {object} sourse object with coordinates
 */
export function processTree(
  rootElement: TreeElement,
  yOffset: number,
  xOffset: number | ((level: number) => number),
  cellwidth: number,
  cellHeight: number
): TreeElementWithCoords {
  let maxY: number = 0;
  function calculateCoords(treeElement: TreeElement, level: number = 0): TreeElementWithCoords {
    const children: TreeElementWithCoords[] = treeElement.children.map((child: TreeElement) =>
      calculateCoords(child, level + 1)
    );
    let y: number;
    if (children.length !== 0) {
      y = Math.round((children[0].y + children[children.length - 1].y) / 2);
    } else {
      y = maxY;
      maxY = maxY + yOffset + cellHeight;
    };
    const curentXOffset: number = typeof xOffset === "number" ? xOffset : xOffset(level);
    return {
      ...treeElement,
      x: level * (curentXOffset + cellwidth),
      y: y,
      children: children,
      height: cellHeight,
      width: cellwidth,
      level: level
    };
  };
  return calculateCoords(rootElement);
};
 
/**
 * makes flat array from tree object
 * @param { TreeElementWithCoords } node - source object with coordinates
 * @returns nodes array
 */
export function createNodesArray(node: TreeElementWithCoords): TreeElementWithCoords[] {
  return node.children.reduce((nodes, child) => [...nodes, ...createNodesArray(child)], [node]);
};
 
/**
 * creates connecting line between adjacent nodes 
 * @param { TreeElementWithCoords } parentNode - node from which the line begins
 * @param { TreeElementWithCoords } childNode - node to which the line ends
 * @param { enum | function} pathStyle - function which define line shape 
 * @returns attribute d for <path> tsg
 */
export function createPath(
  parentNode: TreeElementWithCoords,
  childNode: TreeElementWithCoords,
  pathStyle: PathFunction
): Path {
  const parentNodeX: number = parentNode.x + parentNode.width;
  const parentNodeY: number = parentNode.y + parentNode.height / 2;
  const childNodeX: number = childNode.x;
  const childNodeY: number = childNode.y + childNode.height / 2;
  const id: string = parentNode.id + "--" + childNode.id;
  return { path: pathStyle(parentNodeX, parentNodeY, childNodeX, childNodeY), id: id };
};
 
/**
 * Creates array of connecting lines
 * @param {object} node - source object with coordinates
 * @param {number} cellwidth - node width
 * @param {number} cellHeight - node height
 * @param {function} pathStyle - path style function
 * @returns array of objects with line id and b attribute of <path> tag  
 */
export function createConnectingLinesArray(
  node: TreeElementWithCoords,
  cellwidth: number,
  cellHeight: number,
  pathStyle: PathFunction
): Path[] {
  const linesToChildren: Path[] = node.children.map(child => createPath(node, child, pathStyle));
  const connectingLines: Path[] = node.children.reduce(
    (lines, node) => [...lines, ...createConnectingLinesArray(node, cellwidth, cellHeight, pathStyle)],
    linesToChildren
  );
  return connectingLines;
};