JSFiddle - React, Tailwind, and code Playground

by amindunited

HTML

<drag-subject srcElement=true>Drag Subject 01</drag-subject>
<drag-subject srcElement=true>Drag Subject 02</drag-subject>
<drag-subject srcElement=true>Drag Subject 03</drag-subject>

<hr/>

<drag-subject>Drag to Here</drag-subject>

CSS

drag-subject {
  display: inline-block;
  padding: 8px;
  margin: 8px;
  border: solid 1px green;
}
drop-target {
  display: block;
  width: 200px;
  height: 200px;
  border: solid 1px green;
}
.hovered {
  background-color: azure;
}
.drag-placeholder {
  border: dashed 1px gray;
  min-height: 200px;
  min-width: 50%;
}

JavaScript

class DragSubject extends HTMLElement {
  constructor () {
    super();
    this.shadow = this.attachShadow({ mode: 'open'});
  }

  render () {
    const frag = document.createDocumentFragment();
    const container = document.createElement('slot');
    frag.appendChild(container);
    this.shadow.appendChild(frag);
  }

  /**
   * When this element is Dragged
   */
  handleDrag (e) {
    e.stopImmediatePropagation();
    console.log('im being dragged');
    e.dataTransfer.setData('tag-name', this.tagName);
    e.dataTransfer.setData('text/html', this.innerHTML);
  }

  handleDragEnd (e) {
    e.preventDefault();
    // e.stopImmediatePropagation();
    console.log('drag End', e, this);
    console.log('is srcElement', e);
    // If this isn't a srElement we are moving it, so we remove the original
    if (!e.target.getAttribute('srcElement')) {
      this.parentElement.removeChild(this);
    }
  }

  removeOldPlaceHolder () {
    const oldPlaceholders = this.querySelectorAll('.drag-placeholder');
    [...oldPlaceholders].forEach((oldPlaceholder) => {
      if (oldPlaceholder && oldPlaceholder.parentElement === this) {
        this.removeChild(oldPlaceholder);
      }
    });
  }

  createPlaceholder (e) {

    const placeholder = document.createElement('div');
    placeholder.classList.add('drag-placeholder');

    if (this.childSubjects && this.childSubjects.length > 0) {
      console.log('has child subjects');
      // It will never be over a child, because the child will take the drag over event
      const childToInsertBefore = this.childSubjects.find((elm) => {
        if ((e.pageX < elm.offsetLeft) || (e.pageY < elm.offsetTop)) {
          return true;
        }
        return false;
      });

      this.removeOldPlaceHolder();
      this.insertBefore(placeholder, childToInsertBefore);

    } else {

      const currentPlaceholder = [...this.childNodes].find((elm) => {
        return (elm.classList && elm.classList.contains('drag-placeholder'));
     ...