Drag and Drop API

by Nicholas Berlette

HTML

<script src="https://unpkg.com/@unocss/[email protected]/attributify.global.js"></script>
<link rel="stylesheet" href="https://unpkg.com/[email protected]/normalize.css">
<div class="flex flex-col flex-nowrap w-full !opacity-100" un-cloak style="opacity:0;transition:opacity 0.666s 0.5s ease-in;">

  <div class="dropzone flex-initial shrink-0 grow" role="drop-target">
    <div class="draggable" draggable="true">DRAG ME SOMEWHERE NEW!</div>
  </div>
  <div class="dropzone flex-none grow shrink-0" role="drop-target"></div>
  <div class="dropzone !bg-rose-600/60 flex-initial grow shrink-0" role="drop-target">
    <div class="draggable" draggable="true">DRAG ME<span class="dots" id="dots">...</span></div>
  </div>

  <div class=" flex-initial grow shrink-0 !h-30 relative !bg-emerald-500/50 !rounded-xl" role="drop-target">
    <pre class="w-full h-full before:[content:'STATE'] before:text-xs before:absolute before:top-2 before:right-2 before:ring-2 before:ring-white before:rounded-full before:px-1.5 before:py-0.5 before:font-bold before:text-white before:opacity-100 before:shadow-xl text-xs text-white" id="state"></pre>
  </div>
</div>

CSS

body {
  color-scheme: dark;
  background-color: #333;

  /* Prevent the user selecting text in the example */
  user-select: none;
  background-color: #333;
  
  display: table;
  width: 100vw !important;
  height: 100vh !important;
  margin: 0;
  padding: 0;
}

[draggable='true'] {
  text-align: center;
  font-weight: 700;
  background: #fff4;
  color: #fff;
  border-radius: 0.666rem;
  padding: 0.666rem;
}

[role='drop-target'] {
  width: auto;
  max-width: 25rem;
  opacity: 1;
  height: 20px;
  background: dodgerblue;
  margin: 20px;
  padding: 1rem 15px 2.25rem;
  border-radius: 0.75rem;
  transition: all 0.3s ease-in, width 1s ease-in;
}

[role='drop-target'].dragover {
  opacity: 0.666 !important;
}

.dragging {
  opacity: 0.5;
}

JavaScript

/* const $ = document.querySelector.bind(document); */
/* const $$ = document.querySelectorAll.bind(document); */
const $x = XPathEvaluator.bind(window);

const k$1 = Symbol("$.querySelector");
const k$2 = Symbol("$.querySelectorAll");

class Money {
	static #cache = new WeakMap();


  constructor(
    context = document,
    selector = document.querySelector,
    selectorAll = document.querySelectorAll
  ) {
    context = context instanceof Element ? context : document;

    if (typeof selector === "string") {
      if (!(selector in context)) selector = "querySelector";
      if (typeof context[selector] === "function") {
        selector = context[selector];
      }
    } else if (typeof selector !== "function") {
      selector = context.querySelector || document.querySelector;
    }

    if (typeof selectorAll === "string") {
      if (!(selectorAll in context)) selectorAll = "querySelectorAll";
      if (typeof context[selectorAll] === "function") {
        selectorAll = context[selectorAll];
      }
    } else if (typeof selectorAll !== "function") {
      selectorAll = context.querySelectorAll || document.querySelectorAll;
    }

    this[k$1] = selector.bind(context);
    this[k$2] = selectorAll.bind(context);
    this.__results = [];
    this.__proxify = this.__proxify.bind(this);
    this.$ = this.$.bind(this);
    this.$$ = this.$$.bind(this);
  }

  __proxify(target, handler = {}, hoisted = {
    addEventListener: ["addEventListener", "addListener", "on"],
    removeEventListener: ["removeEventListener", "removeListener", "off"],
  }) {
    const methods = Object.values(hoisted).flat();
    const resolve = v => Object.keys(hoisted).find(
      (k) => (k === v) || [hoisted[k]].flat().includes(v)
    );

    handler = {
      apply(method, thisArg, args) {
        if (typeof method !== "function") return thisArg;
        const result = Reflect.apply(method, thisArg, args);
        return (result === undefined) ? thisArg : result;
      },
      has(t,...