57 lines
1.4 KiB
JavaScript
57 lines
1.4 KiB
JavaScript
const routes = [];
|
|
let currentCleanup = null;
|
|
|
|
export function addRoute(pattern, handler) {
|
|
let regex;
|
|
const paramNames = [];
|
|
if (pattern instanceof RegExp) {
|
|
regex = pattern;
|
|
} else {
|
|
const parts = pattern.replace(/\/:([^/]+)/g, (_, name) => {
|
|
paramNames.push(name);
|
|
return '/([^/]+)';
|
|
});
|
|
regex = new RegExp('^' + parts + '$');
|
|
}
|
|
routes.push({ regex, paramNames, handler });
|
|
}
|
|
|
|
export function navigate(hash) {
|
|
window.location.hash = hash;
|
|
}
|
|
|
|
export function currentHash() {
|
|
return window.location.hash.slice(1) || '/';
|
|
}
|
|
|
|
async function resolve() {
|
|
if (typeof currentCleanup === 'function') {
|
|
currentCleanup();
|
|
currentCleanup = null;
|
|
}
|
|
|
|
const path = currentHash();
|
|
for (const route of routes) {
|
|
const match = path.match(route.regex);
|
|
if (match) {
|
|
const params = {};
|
|
route.paramNames.forEach((name, i) => {
|
|
params[name] = decodeURIComponent(match[i + 1]);
|
|
});
|
|
try {
|
|
currentCleanup = await route.handler(params) || null;
|
|
} catch (e) {
|
|
console.error('Route handler error:', e);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
// fallback: dashboard
|
|
navigate('#/');
|
|
}
|
|
|
|
export function startRouter() {
|
|
window.addEventListener('hashchange', resolve);
|
|
resolve();
|
|
}
|