{"size": 2206, "ext": "js", "max_stars_repo_path": "packages/graph/src/highs/useBoxer.js", "max_stars_repo_name": "Izhaki/regraph", "max_stars_repo_stars_event_min_datetime": "2019-11-21T07:38:48.000Z", "max_stars_repo_stars_event_max_datetime": "2022-01-28T19:52:50.000Z", "max_issues_repo_path": "packages/graph/src/highs/useBoxer.js", "max_issues_repo_name": "Izhaki/regraph", "max_issues_repo_issues_event_min_datetime": "2020-01-03T23:54:15.000Z", "max_issues_repo_issues_event_max_datetime": "2020-04-07T00:10:22.000Z", "max_forks_repo_path": "packages/graph/src/highs/useBoxer.js", "max_forks_repo_name": "Izhaki/regraph", "max_forks_repo_forks_event_min_datetime": "2019-11-21T07:39:09.000Z", "max_forks_repo_forks_event_max_datetime": "2021-08-29T11:32:34.000Z"}
{"max_stars_count": 16, "max_issues_count": 5, "max_forks_count": 3, "avg_line_length": 28.2820512821, "max_line_length": 80, "alphanum_fraction": 0.6491387126}
import { useEffect, useState, useRef } from 'react';
import { queryRelativeBox } from './boxQueries';
import useForceUpdate from './useForceUpdate';

const addRequest = requests => request => {
  // Add the node
  const { port, ...nodeRequest } = request;
  requests.set(nodeRequest.id, nodeRequest);
  // Add the port if needed
  if (port) {
    const portId = `${request.id}/${port}`;
    requests.set(portId, request);
  }
};

const getBoxReducer = (boxes, graphBox) => (newBoxes, request) => {
  const { id, port } = request;

  if (port) {
    const portId = `${id}/${port}`;
    const parentBox = newBoxes[id] || boxes[id];
    const box = queryRelativeBox({ id: portId }, graphBox);
    box.x -= parentBox.x;
    box.y -= parentBox.y;
    box.parent = id;
    newBoxes[portId] = box;
  } else {
    newBoxes[id] = queryRelativeBox(request, graphBox);
  }
  return newBoxes;
};

export default (inBoxes, boxRequests = [], onBoxes, graphRef) => {
  const forceUpdate = useForceUpdate();
  const [stateBoxes, setStateBoxes] = useState(inBoxes);

  const [boxes, updateBoxes] = onBoxes
    ? [inBoxes, onBoxes]
    : [stateBoxes, newBoxes => setStateBoxes({ ...boxes, ...newBoxes })];

  const originalBoxes = useRef(inBoxes).current;

  if (process.env.NODE_ENV !== 'production') {
    if (!onBoxes && inBoxes !== originalBoxes) {
      console.error(`Regraph: New boxes in props but no onBoxes.`);
    }
  }

  const requests = useRef(new Map()).current;

  // Add box requests from parent components
  boxRequests.forEach(addRequest(requests));

  // Box context allows children to make requests
  const boxContext = useRef({
    requestBox: request => {
      addRequest(requests)(request);
      forceUpdate();
    },
  }).current;

  // After rendering get the boxes for all requests
  useEffect(() => {
    if (requests.size) {
      const graphBox = graphRef.current.getBoundingClientRect();
      const requestsArray = Array.from(requests.values());
      const newBoxes = requestsArray.reduce(getBoxReducer(boxes, graphBox), {});
      requests.clear();
      updateBoxes(newBoxes);
    }
  }); // eslint-disable-line react-hooks/exhaustive-deps

  return {
    boxes,
    boxContext,
  };
};
