(() => {
const { wireOf, wireFrom } =
typeof module !== 'undefined' && module.exports
? require('./wire.js')
: window.TabloWire;
function transportFor(root) {
return root.querySelector('form[data-bulk-form] input[name="ids"]');
}
function allBoxesIn(root) {
return Array.from(root.querySelectorAll('input[data-row-select]'));
}
function boxesIn(root) {
return allBoxesIn(root).filter((box) => !box.disabled);
}
function selectionKeys(boxes, currentWire) {
const pageKeys = new Set(boxes.map((box) => box.value));
const kept = wireOf(currentWire).filter((key) => !pageKeys.has(key));
const checked = boxes
.filter((box) => box.checked && !box.disabled)
.map((box) => box.value);
return [...new Set([...kept, ...checked])];
}
function selectionFrom(root, currentWire) {
return selectionKeys(allBoxesIn(root), currentWire);
}
function headerState(boxes) {
const checked = boxes.filter((box) => box.checked);
return {
checked: boxes.length > 0 && checked.length === boxes.length,
indeterminate: checked.length > 0 && checked.length < boxes.length,
};
}
function sync(root, wire) {
const keys = new Set(wireOf(wire));
allBoxesIn(root).forEach((box) => {
box.checked = !box.disabled && keys.has(box.value);
});
const all = root.querySelector('input[data-bulk-select-all]');
if (all) {
const state = headerState(boxesIn(root));
all.checked = state.checked;
all.indeterminate = state.indeterminate;
}
}
function update(root) {
const transport = transportFor(root);
const wire = wireFrom(selectionFrom(root, transport ? transport.value : ''));
if (transport && transport.value !== wire) {
transport.value = wire;
transport.dispatchEvent(new Event('change', { bubbles: true }));
}
sync(root, wire);
}
function install() {
document.addEventListener('change', (e) => {
const all = e.target.closest('[data-bulk-select-all]');
const row = e.target.closest('input[data-row-select]');
if (!all && !row) return;
const root = (all || row).closest('[data-table-root]');
if (!root) return;
if (all) {
boxesIn(root).forEach((box) => {
box.checked = all.checked;
});
}
update(root);
});
document.addEventListener('click', (e) => {
const trigger = e.target.closest('[data-bulk-confirm-trigger]');
if (!trigger) return;
const form = trigger.closest('form[data-bulk-form]');
const dialog = form && form.querySelector('[data-bulk-confirm-dialog]');
if (!dialog) return;
const root = form.closest('[data-table-root]');
if (root) update(root);
const description = dialog.querySelector('[data-bulk-confirm-description]');
const count = wireOf(transportFor(root || form)?.value).length;
if (description) {
if (count === 0) {
description.textContent = 'Select at least one row first.';
} else if (count === 1) {
description.textContent = 'This action cannot be undone. 1 record is selected.';
} else {
description.textContent =
`This action cannot be undone. ${count} records are selected.`;
}
}
if (typeof dialog.showModal === 'function') dialog.showModal();
else dialog.setAttribute('open', '');
});
const observers = new WeakMap();
function observe(root) {
if (observers.has(root)) return;
const observer = new MutationObserver(() => {
const transport = transportFor(root);
sync(root, transport ? transport.value : '');
});
observer.observe(root, { childList: true, subtree: true });
observers.set(root, observer);
}
function watch(scope) {
(scope || document).querySelectorAll('[data-table-root]').forEach((root) => {
observe(root);
const transport = transportFor(root);
sync(root, transport ? transport.value : '');
});
}
document.addEventListener('DOMContentLoaded', () => watch());
document.addEventListener('submit', (e) => {
const form = e.target.closest('form[data-bulk-form]');
if (!form) return;
const root = form.closest('[data-table-root]') || document;
const transport = transportFor(root);
if (!transport) return;
transport.value = wireFrom(selectionFrom(root, transport.value));
});
new MutationObserver(() => watch()).observe(document.documentElement, {
childList: true,
subtree: true,
});
}
if (typeof document !== 'undefined') install();
if (typeof module !== 'undefined' && module.exports) {
module.exports = { boxesIn, headerState, selectionKeys };
}
})();