(() => { const root = document.querySelector("[data-overlay-list]"); if (!root) return; const select = document.querySelector("[data-overlay-add]"); const empty = document.querySelector("[data-overlay-empty]"); let dragRow = null; const clearDropMarkers = () => { root .querySelectorAll(".drop-before, .drop-after") .forEach((el) => el.classList.remove("drop-before", "drop-after")); }; const refreshEmpty = () => { if (!empty) return; empty.hidden = root.children.length > 0; }; const buildHiddenInput = (overlayId) => { const input = document.createElement("input"); input.type = "hidden"; input.name = "overlay_ids"; input.value = overlayId; return input; }; const buildRow = (overlayId, overlayName) => { const li = document.createElement("li"); li.className = "overlay-picker-row"; li.draggable = true; li.dataset.overlayId = overlayId; li.dataset.overlayName = overlayName; const handle = document.createElement("span"); handle.className = "overlay-picker-handle"; handle.setAttribute("aria-hidden", "true"); handle.textContent = "⋮⋮"; const name = document.createElement("span"); name.className = "overlay-picker-name"; name.textContent = overlayName; const remove = document.createElement("button"); remove.type = "button"; remove.className = "overlay-picker-remove"; remove.dataset.action = "remove"; remove.setAttribute("aria-label", `Remove ${overlayName}`); remove.textContent = "×"; li.append(handle, name, remove, buildHiddenInput(overlayId)); return li; }; const insertOptionSorted = (overlayId, overlayName) => { if (!select) return; const option = document.createElement("option"); option.value = overlayId; option.dataset.overlayName = overlayName; option.textContent = overlayName; const lower = overlayName.toLowerCase(); const existing = Array.from(select.querySelectorAll("option[value]:not([value=''])")); const next = existing.find( (opt) => (opt.dataset.overlayName || opt.textContent).toLowerCase() > lower, ); if (next) { select.insertBefore(option, next); } else { select.appendChild(option); } }; root.addEventListener("dragstart", (event) => { const row = event.target.closest(".overlay-picker-row"); if (!row) return; dragRow = row; row.classList.add("is-dragging"); if (event.dataTransfer) { event.dataTransfer.effectAllowed = "move"; event.dataTransfer.setData("text/plain", row.dataset.overlayId || ""); } }); root.addEventListener("dragend", () => { if (dragRow) { dragRow.classList.remove("is-dragging"); } clearDropMarkers(); dragRow = null; }); root.addEventListener("dragover", (event) => { if (!dragRow) return; const row = event.target.closest(".overlay-picker-row"); event.preventDefault(); if (event.dataTransfer) { event.dataTransfer.dropEffect = "move"; } clearDropMarkers(); if (row && row !== dragRow) { const rect = row.getBoundingClientRect(); const before = event.clientY < rect.top + rect.height / 2; row.classList.add(before ? "drop-before" : "drop-after"); } }); root.addEventListener("dragleave", (event) => { const row = event.target.closest(".overlay-picker-row"); if (row) { row.classList.remove("drop-before", "drop-after"); } }); root.addEventListener("drop", (event) => { if (!dragRow) return; event.preventDefault(); const row = event.target.closest(".overlay-picker-row"); if (row && row !== dragRow) { const before = row.classList.contains("drop-before"); row.classList.remove("drop-before", "drop-after"); if (before) { root.insertBefore(dragRow, row); } else { root.insertBefore(dragRow, row.nextSibling); } } else if (!row) { root.appendChild(dragRow); } clearDropMarkers(); }); root.addEventListener("click", (event) => { const trigger = event.target.closest("[data-action='remove']"); if (!trigger) return; const row = trigger.closest(".overlay-picker-row"); if (!row) return; const overlayId = row.dataset.overlayId; const overlayName = row.dataset.overlayName || ""; row.remove(); if (overlayId) insertOptionSorted(overlayId, overlayName); refreshEmpty(); }); if (select) { select.addEventListener("change", () => { const value = select.value; if (!value) return; const option = select.querySelector(`option[value="${CSS.escape(value)}"]`); const overlayName = option ? option.dataset.overlayName || option.textContent : ""; root.appendChild(buildRow(value, overlayName)); if (option) option.remove(); select.value = ""; refreshEmpty(); }); } refreshEmpty(); })();