/**
* Offline indicator UI.
*
* Mounts a small fixed badge in the corner of the page that appears when the
* browser reports `navigator.onLine === false` and hides when back online.
* Listens to `online` and `offline` window events so it reacts immediately.
*
* Usage:
* import { mountOfflineIndicator } from '../lib/offline-indicator.js';
* mountOfflineIndicator();
*/
const BADGE_ID = 'atmos-offline-badge';
let mounted = false;
let onlineHandler: (() => void) | null = null;
let offlineHandler: (() => void) | null = null;
function ensureBadge(): HTMLElement | null {
if (typeof document === 'undefined') return null;
let badge = document.getElementById(BADGE_ID);
if (badge) return badge;
badge = document.createElement('div');
badge.id = BADGE_ID;
badge.className = 'offline-badge';
badge.setAttribute('role', 'status');
badge.setAttribute('aria-live', 'polite');
badge.innerHTML = 'Offline';
badge.style.display = 'none';
document.body.appendChild(badge);
return badge;
}
function update(): void {
const badge = ensureBadge();
if (!badge) return;
const online = typeof navigator !== 'undefined' ? navigator.onLine !== false : true;
badge.style.display = online ? 'none' : 'flex';
}
/**
* Mount the offline indicator. Safe to call multiple times — only wires
* listeners once. Returns an unmount function for tests.
*/
export function mountOfflineIndicator(): () => void {
if (mounted) return unmountOfflineIndicator;
mounted = true;
ensureBadge();
update();
if (typeof window !== 'undefined') {
onlineHandler = () => update();
offlineHandler = () => update();
window.addEventListener('online', onlineHandler);
window.addEventListener('offline', offlineHandler);
}
return unmountOfflineIndicator;
}
/** Remove the badge and its listeners. Exposed for tests. */
export function unmountOfflineIndicator(): void {
if (!mounted) return;
mounted = false;
if (typeof window !== 'undefined') {
if (onlineHandler) window.removeEventListener('online', onlineHandler);
if (offlineHandler) window.removeEventListener('offline', offlineHandler);
}
onlineHandler = null;
offlineHandler = null;
const badge = typeof document !== 'undefined' ? document.getElementById(BADGE_ID) : null;
if (badge) badge.remove();
}
/** Returns true if the browser reports offline. Stable wrapper for tests. */
export function isOffline(): boolean {
return typeof navigator !== 'undefined' && navigator.onLine === false;
}