JSFiddle - React, Tailwind, and code Playground

HTML

<body>
  <div class="container">
    <div class="editor">
      <nav class="aside">
      </nav>
      <div class="editor--wrapper">
        <div class="editor--container" data-component-type="container"></div>
      </div>
    </div>
  </div>
</body>

CSS

* {
  box-sizing: border-box;
}

.container {
  height: 600px;
}

.editor {
  display: flex;
  height: 100%;
  align-content: stretch;
}

nav {
  width: 200px;
  border: 1px solid black;
}

.editor--wrapper {
  flex: 1;
  display: flex;
  flex-direction: column;
  border: 1px solid black;
}

.editor--toolbar {
}

.editor--container {
  flex: 1;
  border: 1px solid red;
}

[contenteditable=true]:empty:before{
  content: attr(placeholder);
  display: block; /* For Firefox */
}

[contenteditable=true] {
  border: 1px dashed #AAA;
  padding: 5px;
}

/* Draggable elements */

[draggable] {
  -moz-user-select: none;
  -khtml-user-select: none;
  -webkit-user-select: none;
  user-select: none;
  -khtml-user-drag: element;
  -webkit-user-drag: element;
}

.editor__item {
  height: 90px;
  width: 90px;
  float: left;
  border: 2px solid #666666;
  background-color: #ccc;
  margin-right: 5px;
  text-align: center;
  cursor: move;
}

JavaScript

var editor = (function(w, d, c) {
  var draggingElement,
    placeholder,
    components = [],
    options;

  function _init() {
    var master,
        elements;

    options = {
      componentListClass: 'aside',
      editorViewClass: 'editor--container',
      draggingClass: 'dragging-item',
      placeHolderClass: 'placeholder-item'
    };

    master = d.getElementsByClassName(options.editorViewClass)[0];
    elements = master.getElementsByTagName("*");
    c.log(master);

    // TODO: combine both arrays
    _on(master, 'dragenter', _handleDragEnter);
    _on(master, 'dragover', _handleDragOver);
    _on(master, 'dragleave', _handleDragLeave);
    _on(master, 'drop', _handleDrop);

    if (elements.length) {
      _on(elements, 'dragenter', _handleDragEnter);
      _on(elements, 'dragover', _handleDragOver);
      _on(elements, 'dragleave', _handleDragLeave);
      _on(elements, 'drop', _handleDrop);
    }

    [].forEach.call(components, function(component) {
      _initComponent(component);
    });
    
    placeholder = d.createElement('div');
    placeholder.setAttribute('style', 'height: 25px; background-color: red;');
  }

  function _initComponent(component) {
    var element = d.createElement('div');
    element.innerHTML = 'component ' + component.name;
    _attr(element, 'class', 'editor__item');
    _attr(element, 'draggable', 'true');
    _attr(element, 'data-component-type', component.type);
    _on(element, 'dragstart', _handleDragStart);
    _on(element, 'dragend', _handleDragEnd);

    d.getElementsByClassName(options.componentListClass)[0].appendChild(element);
  }

  function _on(element, event, callback) {
    if (element instanceof Array) {
      for (var i = 0; i < element.length; i++) {
        _on(element[i], event, callback);
      }
      return;
    }
    element.addEventListener(event, callback);
  }

  function _off(element, event, callback) {
    if (element instanceof Array) {
      for (var i = 0; i < element.length; i++) {
...