resig.js
Version:
Universal reactive signal library with complete platform features: signals, animations, CRDTs, scheduling, DOM integration. Works identically across React, SolidJS, Svelte, Vue, and Qwik.
170 lines • 12.7 kB
JavaScript
/**
* Router Coalgebra Implementation
* Isomorphic router with Signal integration
*/
import { Some, None } from './types';
import { signal } from '../core/signal';
import { matchRoute } from './route';
import { createNavigationEffects } from './navigation';
/**
* Creates a router coalgebra that maintains isomorphism
* between path strings and route states
*/
export const createRouter = (routes, env) => {
const routerInstance = {
route: (path) => {
return matchRoute(routes, path);
},
generate: (state) => {
// Find the first route that can generate a path for this state
for (const route of routes) {
try {
return route.generate(state);
}
catch {
continue;
}
}
throw new Error('No route found for state');
},
current: signal(matchRoute(routes, env.getCurrentPath())),
params: signal((() => {
const match = matchRoute(routes, env.getCurrentPath());
if (match.tag === 'Some') {
const parsed = match.value.parse(env.getCurrentPath());
return parsed;
}
return null;
})())
};
// Update signals when path changes
env.onPathChange((newPath) => {
const newMatch = matchRoute(routes, newPath);
routerInstance.current._set(newMatch);
if (newMatch.tag === 'Some') {
const parsed = newMatch.value.parse(newPath);
routerInstance.params._set(parsed);
}
else {
routerInstance.params._set(null);
}
});
return routerInstance;
};
/**
* Creates a reactive router signal
*/
export const createRouterSignal = (routes, env) => {
const router = createRouter(routes, env);
const navEffects = createNavigationEffects(env);
const routerSignal = {
value: () => router.params.value(),
map: (f) => {
return router.params.map(f);
},
subscribe: (fn) => {
return router.params.subscribe(fn);
},
route: router.current,
params: router.params,
navigate: (to) => {
return navEffects.push(to);
},
back: () => {
return navEffects.back();
},
forward: () => {
return navEffects.forward();
},
replace: (to) => {
return navEffects.replace(to);
}
};
return routerSignal;
};
/**
* Route Tree Matching - for nested routing
*/
export const matchRouteTree = (tree, path) => {
// Try to match the current route
if (tree.route.matches(path)) {
const params = tree.route.parse(path);
if (params) {
return Some({
route: tree.route,
params,
path
});
}
}
// Try children if they exist
if (tree.children) {
for (const child of tree.children) {
const childMatch = matchRouteTree(child, path);
if (childMatch.tag === 'Some') {
return childMatch;
}
}
}
return None;
};
/**
* Route Tree Router - for complex nested routing
*/
export const createTreeRouter = (tree, env) => {
const currentMatch = signal(matchRouteTree(tree, env.getCurrentPath()));
const navEffects = createNavigationEffects(env);
// Update match when path changes
env.onPathChange((newPath) => {
const newMatch = matchRouteTree(tree, newPath);
currentMatch._set(newMatch);
});
const routerSignal = {
value: () => {
const match = currentMatch.value();
return match.tag === 'Some' ? match.value.params : null;
},
map: (f) => {
return currentMatch.map(match => match.tag === 'Some' ? f(match.value.params) : f(null));
},
subscribe: (fn) => {
return currentMatch.subscribe(match => {
fn(match.tag === 'Some' ? match.value.params : null);
});
},
route: currentMatch.map(match => match.tag === 'Some' ? Some(match.value.route) : None),
params: currentMatch.map(match => match.tag === 'Some' ? match.value.params : null),
navigate: (to) => {
return navEffects.push(to);
},
back: () => {
return navEffects.back();
},
forward: () => {
return navEffects.forward();
},
replace: (to) => {
return navEffects.replace(to);
}
};
return routerSignal;
};
/**
* Router factory with environment detection
*/
export const router = (routes, env) => {
const environment = env || (typeof window !== 'undefined'
? require('./navigation').createBrowserNav()
: require('./navigation').createNodeNav());
return createRouterSignal(routes, environment);
};
/**
* Tree router factory with environment detection
*/
export const treeRouter = (tree, env) => {
const environment = env || (typeof window !== 'undefined'
? require('./navigation').createBrowserNav()
: require('./navigation').createNodeNav());
return createTreeRouter(tree, environment);
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3JvdXRlci9yb3V0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7OztHQUdHO0FBRUgsT0FBTyxFQUE4RCxJQUFJLEVBQUUsSUFBSSxFQUFpQixNQUFNLFNBQVMsQ0FBQztBQUNoSCxPQUFPLEVBQVUsTUFBTSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFaEQsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUNyQyxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFFdkQ7OztHQUdHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sWUFBWSxHQUFHLENBQzFCLE1BQXNCLEVBQ3RCLEdBQWtCLEVBQ0gsRUFBRTtJQUNqQixNQUFNLGNBQWMsR0FBa0I7UUFDcEMsS0FBSyxFQUFFLENBQUMsSUFBWSxFQUF3QixFQUFFO1lBQzVDLE9BQU8sVUFBVSxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQztRQUNsQyxDQUFDO1FBRUQsUUFBUSxFQUFFLENBQUMsS0FBWSxFQUFVLEVBQUU7WUFDakMsK0RBQStEO1lBQy9ELEtBQUssTUFBTSxLQUFLLElBQUksTUFBTSxFQUFFLENBQUM7Z0JBQzNCLElBQUksQ0FBQztvQkFDSCxPQUFPLEtBQUssQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUM7Z0JBQy9CLENBQUM7Z0JBQUMsTUFBTSxDQUFDO29CQUNQLFNBQVM7Z0JBQ1gsQ0FBQztZQUNILENBQUM7WUFDRCxNQUFNLElBQUksS0FBSyxDQUFDLDBCQUEwQixDQUFDLENBQUM7UUFDOUMsQ0FBQztRQUVELE9BQU8sRUFBRSxNQUFNLENBQUMsVUFBVSxDQUFDLE1BQU0sRUFBRSxHQUFHLENBQUMsY0FBYyxFQUFFLENBQUMsQ0FBQztRQUV6RCxNQUFNLEVBQUUsTUFBTSxDQUFDLENBQUMsR0FBRyxFQUFFO1lBQ25CLE1BQU0sS0FBSyxHQUFH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