From e6ab0a205207742ad73ab5440756c6cd941cbf63 Mon Sep 17 00:00:00 2001 From: natxocc Date: Tue, 7 Apr 2026 13:23:12 +0200 Subject: [PATCH] Actualizar sigpro.ts --- sigpro.ts | 110 ++++++++++++++++++------------------------------------ 1 file changed, 37 insertions(+), 73 deletions(-) diff --git a/sigpro.ts b/sigpro.ts index 2ea6b90..30b150a 100644 --- a/sigpro.ts +++ b/sigpro.ts @@ -497,107 +497,71 @@ export const Transition = ( type Route = { path: string; - component: Component | (() => Promise); + component: Component; }; -export const Router = (routes: Route[]) => { - const getPath = () => window.location.hash.replace(/^#/, "") || "/"; - const currentPath = $(getPath()); - +type RouterInstance = { + view: Node; + to: (path: string) => void; + back: () => void; + params: Signal>; +}; + +export const Router = (routes: Route[]): RouterInstance => { + const getPath = () => window.location.hash.slice(1) || "/"; + const path = $(getPath()); const params = $>({}); - const update = () => { - currentPath(getPath()); - }; - - window.addEventListener("hashchange", update); - - const outlet = h("div", { class: "router-outlet" }); - let currentView: Node | null = null; - let currentCleanup: CleanupFn | null = null; - - const loadComponent = async (route: Route) => { - let comp = route.component; - if (typeof comp === "function" && comp.toString().includes("import")) { - const mod = await (comp as () => Promise)(); - comp = mod.default || mod; - } - return comp as Component; - }; - - const matchRoute = (path: string): { route: Route; params: Record } | null => { + const matchRoute = (path: string): { component: Component; params: Record } | null => { for (const route of routes) { const routeParts = route.path.split("/").filter(Boolean); const pathParts = path.split("/").filter(Boolean); + if (routeParts.length !== pathParts.length) continue; + const matchedParams: Record = {}; - let match = true; + let ok = true; + for (let i = 0; i < routeParts.length; i++) { if (routeParts[i].startsWith(":")) { matchedParams[routeParts[i].slice(1)] = pathParts[i]; } else if (routeParts[i] !== pathParts[i]) { - match = false; + ok = false; break; } } - if (match) return { route, params: matchedParams }; + + if (ok) return { component: route.component, params: matchedParams }; } + + const wildcard = routes.find(r => r.path === "*"); + if (wildcard) return { component: wildcard.component, params: {} }; + return null; }; + window.addEventListener("hashchange", () => path(getPath())); + + const outlet = h("div"); + effect(() => { - const path = currentPath(); - const matched = matchRoute(path); + const matched = matchRoute(path()); if (!matched) return; - const { route, params: routeParams } = matched; - params(routeParams); + params(matched.params); - const load = async () => { - if (currentCleanup) { - currentCleanup(); - currentCleanup = null; - } - if (currentView && currentView.parentNode) { - remove(currentView); - currentView = null; - } - const Comp = await loadComponent(route); - const instance = h(Comp, routeParams); - if (isNode(instance)) { - currentView = instance; - outlet.appendChild(instance); - if ((instance as ElementWithLifecycle).$c) { - currentCleanup = () => { - (instance as ElementWithLifecycle).$s?.(); - if (instance.parentNode) remove(instance); - }; - } else { - currentCleanup = () => { - if (instance.parentNode) remove(instance); - }; - } - } - }; - load(); + while (outlet.firstChild) outlet.removeChild(outlet.firstChild); + outlet.appendChild(h(matched.component)); }); - return outlet; + return { + view: outlet, + to: (p: string) => { window.location.hash = p; }, + back: () => window.history.back(), + params: () => params, + }; }; -Router.to = (path: string) => { - window.location.hash = path.replace(/^#?\/?/, "#/"); -}; - -Router.back = () => { - window.history.back(); -}; - -Router.params = (() => { - const p = $>({}); - return p; -})(); - export const mount = ( component: Component, target: string | HTMLElement,