/**
* admin-gallery.js
* Fixes filepond gallery layout:
* - Moves .filepond--drop-label to end of root (after uploaded items)
* - Overrides JS-set absolute positioning so items flow in CSS flex layout
* - Re-runs on DOM changes (file added/removed, Livewire re-render)
*/
!(function () {
'use strict';
var CELL = 88, GAP = 8;
function fixGallery(root) {
// Panel: stays pinned in background
var panel = root.querySelector('.filepond--panel');
if (panel) {
panel.style.position = 'absolute';
panel.style.inset = '0';
panel.style.pointerEvents = 'none';
panel.style.zIndex = '0';
}
// List scroller: must be static to participate in flex flow
// (FilePond's internal "list" layout keeps re-applying an inline
// translate3d(0, Npx, 0) here to push content below the drop-label's
// old height — that's the offset that was making the gallery items
// render disconnected/below the add-slot. Must be neutralized too.)
var scroller = root.querySelector('.filepond--list-scroller');
if (scroller) {
scroller.style.position = 'static';
scroller.style.top = 'auto';
scroller.style.left = 'auto';
scroller.style.margin = '0';
scroller.style.padding = '0';
scroller.style.transform = 'none';
scroller.style.height = 'auto';
scroller.style.overflow = 'visible';
scroller.style.flexShrink = '0';
scroller.style.zIndex = '1';
}
// List: flex container so items wrap naturally
// (FilePond also keeps re-applying an inline left/top offset here —
// same class of bug as the scroller transform above — which was
// pushing every uploaded item down-and-right and inflating the gap
// to the add-slot. Must be neutralized too.)
var list = root.querySelector('.filepond--list');
if (list) {
list.style.position = 'relative';
list.style.top = 'auto';
list.style.left = 'auto';
list.style.right = 'auto';
list.style.transform = 'none';
list.style.margin = '0';
list.style.padding = '0';
list.style.height = 'auto';
list.style.display = 'flex';
list.style.flexWrap = 'wrap';
}
// Items: reset JS-applied absolute positioning
root.querySelectorAll('.filepond--item').forEach(function (item) {
item.style.position = 'relative';
item.style.top = 'auto';
item.style.left = 'auto';
item.style.transform = 'none';
item.style.width = CELL + 'px';
item.style.height = CELL + 'px';
item.style.margin = '0 ' + GAP + 'px ' + GAP + 'px 0';
item.style.flexShrink = '0';
});
// Drop-label: physically move to end of root → appears after items
var drop = root.querySelector('.filepond--drop-label');
if (drop) {
if (drop !== root.lastElementChild) {
root.appendChild(drop); // DOM move (survives CSS order changes)
}
// Reset JS positioning
drop.style.position = 'relative';
drop.style.top = 'auto';
drop.style.left = 'auto';
drop.style.right = 'auto';
drop.style.bottom = 'auto';
drop.style.transform = 'none';
drop.style.width = CELL + 'px';
drop.style.height = CELL + 'px';
drop.style.minHeight = '0';
drop.style.flexShrink = '0';
drop.style.margin = '0 ' + GAP + 'px ' + GAP + 'px 0';
drop.style.display = 'inline-flex';
drop.style.alignItems = 'center';
drop.style.justifyContent = 'center';
drop.style.cursor = 'pointer';
drop.style.zIndex = '1';
}
}
function fixAll() {
document.querySelectorAll('.stp-gallery-upload .filepond--root').forEach(fixGallery);
}
// ── Observer: re-run whenever filepond updates styles/DOM ──────────────
var guard = false;
var timer;
function scheduleRun() {
if (guard) return;
clearTimeout(timer);
timer = setTimeout(function () {
guard = true;
fixAll();
// Release guard after a tick so genuine filepond updates
// (e.g. next file added) are still caught.
setTimeout(function () { guard = false; }, 120);
}, 40);
}
function init() {
// First run: give filepond ~300ms to initialise
setTimeout(fixAll, 300);
// Safety re-run in case of slow Livewire boot
setTimeout(fixAll, 1200);
var obs = new MutationObserver(function (mutations) {
var relevant = mutations.some(function (m) {
return m.target && m.target.closest && m.target.closest('.stp-gallery-upload');
});
if (relevant) scheduleRun();
});
obs.observe(document.body, {
childList: true,
subtree: true,
attributes: true,
attributeFilter: ['style', 'class']
});
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', function () { setTimeout(init, 100); });
} else {
setTimeout(init, 100);
}
})();