@alegendstale/holly-components
Version:
Reusable UI components created using lit
78 lines (77 loc) • 3.19 kB
JavaScript
class g {
constructor(e, t, r) {
this.dropzones = e, this.draggables = t, this.result = { beforeElement: null, insertedElement: null, afterElement: null, order: this.draggables }, this.onDrop = r, this.load();
}
dragStart(e, t) {
e.classList.toggle("is-dragging", !0);
}
dragOver(e, t) {
if (t.dataTransfer && Array.from(t.dataTransfer.items).some((l) => l.kind !== "element"))
return;
t.preventDefault(), this.result.beforeElement = this.getDragBeforeElement(t.clientX), this.result.insertedElement = this.getDraggingElement(), this.result.afterElement = this.getDragAfterElement(t.clientX);
const r = this.draggables.indexOf(this.result.insertedElement);
if (this.result.afterElement === null)
e.appendChild(this.result.insertedElement), this.result.order.splice(r, 1), this.result.order.push(this.result.insertedElement);
else {
e.insertBefore(this.result.insertedElement, this.result.afterElement), this.result.order.splice(r, 1);
const s = this.draggables.indexOf(this.result.afterElement);
this.result.order.splice(s, 0, this.result.insertedElement);
}
}
dragEnd(e, t) {
e.classList.toggle("is-dragging", !1), this.onDrop(t, this.result), this.result = { beforeElement: null, insertedElement: null, afterElement: null, order: this.draggables };
}
load() {
for (let e of this.draggables)
e.setAttribute("draggable", "true"), e.addEventListener("dragstart", (t) => this.dragStart(e, t)), e.addEventListener("dragend", (t) => this.dragEnd(e, t));
for (let e of this.dropzones)
e.addEventListener("dragover", (t) => this.dragOver(e, t));
}
unload() {
for (let e of this.draggables)
e.removeEventListener("dragstart", (t) => this.dragStart(e, t)), e.removeEventListener("dragend", (t) => this.dragEnd(e, t));
for (let e of this.dropzones)
e.removeEventListener("dragover", (t) => this.dragOver(e, t));
}
/**
* @returns The element which is being dragged
*/
getDraggingElement() {
return this.draggables.filter((e) => e.classList.contains("is-dragging"))[0];
}
/**
* @returns All draggable elements not being dragged
*/
getDraggableElements() {
return this.draggables.filter((e) => !e.classList.contains("is-dragging"));
}
/**
* Gets the closest element before the dragged element
*/
getDragBeforeElement(e) {
return this.getDraggableElements().reduce(
(t, r) => {
const s = r.getBoundingClientRect(), l = e - s.left, i = s.width / 2, n = l - i;
return n > 0 && n < t.offset ? { offset: n, element: r } : t;
},
// Initial closest value
{ offset: Number.POSITIVE_INFINITY, element: null }
).element;
}
/**
* Gets the closest element after the dragged element
*/
getDragAfterElement(e) {
return this.getDraggableElements().reduce(
(t, r) => {
const s = r.getBoundingClientRect(), l = e - s.left, i = s.width / 2, n = l - i;
return n < 0 && n > t.offset ? { offset: n, element: r } : t;
},
// Initial closest value
{ offset: Number.NEGATIVE_INFINITY, element: null }
).element;
}
}
export {
g as DragDrop
};