Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/improsocial/impro
An extensible Bluesky client for web impro.social
Something went wrong. Try again.
JavaScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687// Observes drag-and-drop events on a target, ignores non-file eventsexport class DragAndDropObserver { constructor(rootEl, { onDragStart, onDragEnd, onDrop } = {}) { if (!rootEl) throw new Error("DragAndDropObserver requires rootEl"); this.rootEl = rootEl; this.onDragStart = onDragStart; this.onDragEnd = onDragEnd; this.onDrop = onDrop; this._counter = 0; this._active = false;
this._onDragEnter = this._onDragEnter.bind(this); this._onDragOver = this._onDragOver.bind(this); this._onDragLeave = this._onDragLeave.bind(this); this._onDrop = this._onDrop.bind(this); this._onDragEnd = this._onDragEnd.bind(this); rootEl.addEventListener("dragenter", this._onDragEnter); rootEl.addEventListener("dragover", this._onDragOver); rootEl.addEventListener("dragleave", this._onDragLeave); rootEl.addEventListener("drop", this._onDrop); rootEl.addEventListener("dragend", this._onDragEnd); }
disconnect() { this.rootEl.removeEventListener("dragenter", this._onDragEnter); this.rootEl.removeEventListener("dragover", this._onDragOver); this.rootEl.removeEventListener("dragleave", this._onDragLeave); this.rootEl.removeEventListener("drop", this._onDrop); this.rootEl.removeEventListener("dragend", this._onDragEnd); this._reset(); }
_hasFiles(event) { const types = event.dataTransfer?.types; if (!types) return false; return Array.from(types).includes("Files"); }
_onDragEnter(event) { if (!this._hasFiles(event)) return; this._counter += 1; if (!this._active) { this._active = true; this.onDragStart?.(); } }
_onDragOver(event) { if (!this._hasFiles(event)) return; event.preventDefault(); if (event.dataTransfer) event.dataTransfer.dropEffect = "copy"; }
_onDragLeave(event) { if (event.relatedTarget === null) { this._reset(); return; } if (!this._hasFiles(event)) return; this._counter = Math.max(0, this._counter - 1); if (this._counter === 0 && this._active) { this._active = false; this.onDragEnd?.(); } }
_onDragEnd() { this._reset(); }
_onDrop(event) { const files = Array.from(event.dataTransfer?.files ?? []); this._reset(); if (files.length === 0) return; event.preventDefault(); this.onDrop?.(files, event); }
_reset() { this._counter = 0; if (this._active) { this._active = false; this.onDragEnd?.(); } }}