JSFiddle - React, Tailwind, and code Playground

by Hugo Carneiro

HTML

<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container-fluid wrapper">
  <div class="row">
    <div class="col-8 iframe-holder">
      <iframe id="clientframe" src="https://getbootstrap.com/docs/4.3/examples/jumbotron/" frameborder="0" onload="frameLoaded(this)"></iframe>
    </div>
    <div class="col components-holder">
      <div draggable="true" class="component">
        <i class="fa fa-comments"></i>
      </div>
      <div draggable="true" class="component">
        <i class="fa fa-picture-o"></i>
      </div>
    </div>
  </div>
</div>

SCSS

html, body {
  width: 100%;
  height: 100%;
  overflow: hidden;
}

.wrapper {
  width: 100%;
  height: 100%;

  .row {
    height: 100%;
  }

  #clientframe {
    width: 100%;
    height: 100%;
  }

  .components-holder {
    padding-top: 20px;
    display: flex;

    .component {
      display: flex;
      align-items: center;
      justify-content: center;
      width: 55px;
      height: 55px;
      border: 1px solid rgba(51, 51, 51, 0.2);
      cursor: move;
      cursor: grab;
      cursor: -moz-grab;
      cursor: -webkit-grab;

      + .component {
        margin-left: 10px;
      }
    }
  }
}

.reserved-drop-marker {
  width: 100%;
  height: 2px;
  background: blue;
  margin: 0;
}

JavaScript

$(".components-holder .component").on('dragstart', function() {
  console.log("Drag Started");
});

$(".components-holder .component").on('dragend', function() {
  console.log("Drag End");
});

function frameLoaded() {
	var clientFrameWindow = $('#clientframe').get(0).contentWindow;
  var total = 0;
  console.log('frame loaded');
  $(clientFrameWindow.document.body).find('*').on('dragenter', function(event) {
    event.preventDefault();
    event.stopPropagation();
    console.log('Drag Enter');
    total += 1;
  }).on('dragover', function(event) {
    event.preventDefault();
    event.stopPropagation();
    console.log('Drag Over');
    total += 1;
  });

  $(clientFrameWindow.document).find('body,html').on('drop', function(event) {
    event.preventDefault();
    event.stopPropagation();
    console.log('Drop event');
    total += 1;
    console.log("Total Events Fired = " + total);
    total = 0;
  });

  $(clientFrameWindow.document.body).find('*').on('dragover', function(event) {
    event.preventDefault();
    event.stopPropagation();
    $(clientFrameWindow.document.body).find('.reserved-drop-marker').remove();
    $(event.target).append("<p class='reserved-drop-marker'></p>");
    console.log('Drag Over');
  });
}