JSFiddle - React, Tailwind, and code Playground

by adamfeuer

HTML

<head>
<meta charset="utf-8">
<link rel="stylesheet" href="foundation.css" />
<link rel="stylesheet" href="app.css" />
<link rel="stylesheet" href="d3-context-menu.css" />
</head>
<body>

        <div id="tree-container"></div>
<script src="https://code.jquery.com/jquery-3.6.0.js" integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk=" crossorigin="anonymous"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.1/d3.min.js"></script>

</body>

CSS

.node {
  cursor: pointer;
}

.overlay{
    background-color:#EEE;
}
 
.node circle {
  fill: #fff;
  stroke: steelblue;
  stroke-width: 1.5px;
}
 
.node text {
  font-size:10px; 
  font-family:sans-serif;
}
 
.link {
  fill: none;
  stroke: #ccc;
  stroke-width: 1.5px;
}

.templink {
  fill: none;
  stroke: red;
  stroke-width: 3px;
}

.ghostCircle.show{
    display:block;
}

.ghostCircle, .activeDrag .ghostCircle{
     display: none;
}

.hidden {
        display: none;
}

JavaScript

d3.contextMenu = function(menu, openCallback) {

  // create the div element that will hold the context menu
  d3.selectAll('.d3-context-menu').data([1])
    .enter()
    .append('div')
    .attr('class', 'd3-context-menu');

  // close menu
  d3.select('body').on('click.d3-context-menu', function() {
    d3.select('.d3-context-menu').style('display', 'none');
  });

  // this gets executed when a contextmenu event occurs
  return function(data, index) {
    var elm = this;

    d3.selectAll('.d3-context-menu').html('');
    var list = d3.selectAll('.d3-context-menu').append('ul');
    list.selectAll('li').data(menu).enter()
      .append('li')
      .html(function(d) {
        return (typeof d.title === 'string') ? d.title : d.title(data);
      })
      .on('click', function(d, i) {
        d.action(elm, data, index);
        d3.select('.d3-context-menu').style('display', 'none');
      });

    // the openCallback allows an action to fire before the menu is displayed
    // an example usage would be closing a tooltip
    if (openCallback) {
      if (openCallback(data, index) === false) {
        return;
      }
    }

    // display context menu
    d3.select('.d3-context-menu')
      .style('left', (d3.event.pageX - 2) + 'px')
      .style('top', (d3.event.pageY - 2) + 'px')
      .style('display', 'block');

    d3.event.preventDefault();
    d3.event.stopPropagation();
  };
};
var treeJSON = d3.json("https://gist.githubusercontent.com/adamfeuer/4d737c7169a5cdfa592c47d33cfb87be/raw/", draw_tree);

function draw_tree(error, treeData) {

  // Calculate total nodes, max label length
  var totalNodes = 0;
  var maxLabelLength = 0;
  // variables for drag/drop
  var selectedNode = null;
  var draggingNode = null;
  // panning variables
  var panSpeed = 200;
  var panBoundary = 20; // Within 20px from edges will pan when dragging.
  // Misc. variables
  var i = 0;
  var duration = 750;
  var root;

  // size of the diagram
  var viewerWidth =...