Initial commit

This commit is contained in:
PROFERIS - Mi³osz Stocki
2026-07-06 11:34:03 +02:00
commit 67b4eda6aa
12 changed files with 2735 additions and 0 deletions
+91
View File
@@ -0,0 +1,91 @@
/**
* WijiBoard Hash-based SPA Router
* web/js/router.js
*
* Usage:
* Router.register('home', homeModule);
* Router.register('stepper-test', stepperModule);
* Router.init('#view', '#home'); // outlet element id, default route
*
* Each section module must export:
* { mount(containerEl), unmount() }
*/
const Router = (() => {
const routes = new Map(); // hash → module
let outlet = null; // DOM element to render into
let current = null; // currently active route key
let currentMod = null; // currently mounted module
// ── Register a route ─────────────────────────────────────────
function register(hash, module) {
routes.set(hash, module);
}
// ── Navigate to a route ──────────────────────────────────────
async function navigate(hash) {
const key = hash.replace(/^#/, '');
if (!routes.has(key)) {
console.warn(`[Router] Unknown route: "${key}"`);
return;
}
if (key === current) return; // already there
// Unmount old section
if (currentMod?.unmount) {
try { await currentMod.unmount(); } catch (e) { console.error('[Router] unmount error', e); }
}
// Clear outlet
outlet.innerHTML = '';
// Mount new section
const mod = routes.get(key);
currentMod = mod;
current = key;
try {
await mod.mount(outlet);
} catch (e) {
console.error('[Router] mount error', e);
outlet.innerHTML = `<p style="color:var(--accent-red);padding:24px">
Failed to load section: ${e.message}</p>`;
}
// Update sidebar active state
document.querySelectorAll('.sidebar-nav-item').forEach(el => {
el.classList.toggle('active', el.dataset.route === key);
});
// Update URL hash (without re-triggering hashchange)
if (location.hash.replace('#','') !== key) {
history.replaceState(null, '', `#${key}`);
}
}
// ── Init: wire up outlet + default route ─────────────────────
function init(outletSelector, defaultHash = '#home') {
outlet = document.querySelector(outletSelector);
if (!outlet) throw new Error(`[Router] Outlet "${outletSelector}" not found`);
// Listen for hash changes
window.addEventListener('hashchange', () => {
navigate(location.hash || defaultHash);
});
// Handle initial load
const initial = location.hash && location.hash.length > 1
? location.hash
: defaultHash;
// Small defer to let the page fully render first
requestAnimationFrame(() => navigate(initial));
}
// ── Active route getter ───────────────────────────────────────
function getActive() { return current; }
return { register, navigate, init, getActive };
})();
export default Router;