Files
breadcrumb-the-shire/web/js/components/app-flash-auto-dismiss.js

70 lines
1.7 KiB
JavaScript
Raw Normal View History

/**
* Auto-dismisses flash notices after their data-flash-timeout expires.
*/
import { resolveHost } from '../core/app-dom.js';
export function initFlashAutoDismiss(root = document, options = {}) {
2026-02-04 23:31:53 +01:00
const {
selector = '.flash-stack .notice[data-flash-timeout]',
defaultTimeout = 0,
2026-02-04 23:31:53 +01:00
} = options;
const host = resolveHost(root);
const notices = Array.from(host.querySelectorAll(selector));
2026-02-04 23:31:53 +01:00
if (!notices.length) {
return { destroy: () => {} };
2026-02-04 23:31:53 +01:00
}
const timers = [];
let destroyed = false;
2026-02-04 23:31:53 +01:00
const postForm = async (form) => {
const action = form.getAttribute('action');
if (!action) {
return null;
}
2026-02-04 23:31:53 +01:00
const body = new URLSearchParams(new FormData(form));
return fetch(action, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'X-Requested-With': 'fetch',
2026-02-04 23:31:53 +01:00
},
body,
2026-02-04 23:31:53 +01:00
});
};
notices.forEach((notice) => {
const timeout = Number.parseInt(
notice.dataset.flashTimeout || `${defaultTimeout}`,
10
);
if (!timeout || timeout <= 0) {
return;
}
notice.style.setProperty('--flash-timeout', `${timeout}ms`);
notice.classList.add('flash-timed');
const timer = window.setTimeout(async () => {
if (destroyed) {
return;
}
2026-02-04 23:31:53 +01:00
const form = notice.querySelector('form');
if (form) {
const response = await postForm(form);
if (!response || !response.ok) {
return;
}
}
notice.remove();
}, timeout);
timers.push(timer);
2026-02-04 23:31:53 +01:00
});
const destroy = () => {
destroyed = true;
timers.forEach((timer) => window.clearTimeout(timer));
};
return { destroy };
2026-02-04 23:31:53 +01:00
}