JSFiddle - React, Tailwind, and code Playground

by thmsdnnr

HTML

<div class="container">
  <div class="items" id="itemContainer">
    <div class="item item1">ITEM 1</div>
    <div class="item item2">ITEM 2</div>
    <div class="item item3">ITEM 3</div>
    <div class="item item4">ITEM 4</div>
  </div>
  <div class="info">
  </div>
</div>
</div>

CSS

div.contanier {
  margin: 10px;
}

div.info {
  display: absolute;
  left: 250px;
}

div.items {
  padding: 5px;
  width: 500px;
  margin: auto;
  display: flex;
  flex-wrap: row wrap;
}

div.item {
  width: 100px;
  height: 100px;
  position: absolute;
  display: inline-block;
  background-color: rgba(255, 0, 0, 0.5);
}

.item1 {
  top: 100px;
  left: 100px;
}

.item2 {
  top: 140px;
  left: 140px;
}

.item3 {
  top: 160px;
  left: 160px;
}

.item4 {
  top: 180px;
  left: 180px;
}

JavaScript

let mouseDown = false;
  let overlap = false;

  let divs = document.querySelectorAll('div.item');
  let container = document.querySelector('div.container');

  divs.forEach((d) => d.addEventListener('mousedown', down));
  divs.forEach((d) => d.addEventListener('mouseup', function() {
    mouseDown = false;
  }));
  divs.forEach((d) => d.addEventListener('mouseleave', function() {
    mouseDown = false;
  }));

  function down(e) {
    if (e.target.id === 'itemContainer') {
      return;
    }
    e.stopPropagation();
    mouseDown = true;
  }

  container.addEventListener('mousemove', mouseMove);

  function mouseMove(e) {
    if (!mouseDown) {
      return;
    }
    let coords = e.target.getBoundingClientRect();
    let movX = e.movementX;
    let movY = e.movementY;
    if (!collision(movX, movY, e.target.classList[1], coords)) {
      e.target.style.left = `${coords.left+movX}px`;
      e.target.style.top = `${coords.top+movY}px`;
    }
  }

  function collision(newX, newY, movingPart, movingRect) {
    let takenPositions = []; //array of arrays of rects' L, R, Top, Bottom coords
    let newCoords = {
      id: movingPart,
      left: movingRect.left + newX,
      right: movingRect.right + newX,
      bottom: movingRect.bottom + newY,
      top: movingRect.top + newY
    };

    let collision = false;

    divs.forEach((d) => {
      if (d.classList[1] !== movingPart) { // a thing can't collide with itself
        let c = d.getBoundingClientRect();
        takenPositions.push({
          id: d.classList[1],
          left: c.left,
          right: c.right,
          top: c.top,
          bottom: c.bottom
        });
      }
    });

    takenPositions.forEach((p) => {
      //if new bottom hits existing top
      //or new top is hits existing bottom
      //is it the case that they aren't side by side but actually colliding?
      if ((newCoords.bottom == p.top) && ((newCoords.right > p.left) || (newCoords.left < p.right))) {
        collision = true;
     ...