From 9975e96d41c7343318ab07ba62af5e4703ae1d7f Mon Sep 17 00:00:00 2001 From: Zac Date: Wed, 19 Nov 2025 00:35:55 -0700 Subject: [PATCH 1/3] experiment with transitions --- src/lib/router/BrowserRouter.svelte | 18 +-------------- src/lib/router/Route.svelte | 27 +++++++++++++++++++--- src/lib/router/Route404.svelte | 35 ++++++++++++++++++++++++++--- src/routes/[...any]/+page.svelte | 13 +++++++++++ 4 files changed, 70 insertions(+), 23 deletions(-) diff --git a/src/lib/router/BrowserRouter.svelte b/src/lib/router/BrowserRouter.svelte index 63f76f9..cd63e1a 100644 --- a/src/lib/router/BrowserRouter.svelte +++ b/src/lib/router/BrowserRouter.svelte @@ -45,20 +45,4 @@ and displays the appropriate component based on the current route. -{@render children?.()} - -{#snippet layoutRender(remaining: LayoutData[])} - {#if remaining.length === 0} - {@render currentAppRoute?.component?.()} - {:else} - {@const next = remaining[0]} - - {#snippet renderer()} - {@render layoutRender(remaining.slice(1))} - {/snippet} - - {@render next.renderer(renderer)} - {/if} -{/snippet} - -{@render layoutRender(layouts)} +{@render children?.()} \ No newline at end of file diff --git a/src/lib/router/Route.svelte b/src/lib/router/Route.svelte index 0d52019..8dad62a 100644 --- a/src/lib/router/Route.svelte +++ b/src/lib/router/Route.svelte @@ -20,7 +20,7 @@ The children of this component make the content that will be displayed when the + +{#snippet layoutRender(remaining: LayoutData[])} + {#if remaining.length === 0} + {@render currentAppRoute?.component?.()} + {:else} + {@const next = remaining[0]} + + {#snippet renderer()} + {@render layoutRender(remaining.slice(1))} + {/snippet} + + {@render next.renderer(renderer)} + {/if} +{/snippet} + +{#if currentAppRoute === route} + {@render layoutRender(layouts)} +{/if} diff --git a/src/lib/router/Route404.svelte b/src/lib/router/Route404.svelte index e6bc500..439dca1 100644 --- a/src/lib/router/Route404.svelte +++ b/src/lib/router/Route404.svelte @@ -11,13 +11,21 @@ \ No newline at end of file + + const currentAppRoute = $derived(router.currentRoute?.route); + const layouts = $derived(getAllLayouts(currentAppRoute?.layout)); + + +{#snippet layoutRender(remaining: LayoutData[])} + {#if remaining.length === 0} + {@render currentAppRoute?.component?.()} + {:else} + {@const next = remaining[0]} + + {#snippet renderer()} + {@render layoutRender(remaining.slice(1))} + {/snippet} + + {@render next.renderer(renderer)} + {/if} +{/snippet} + +{#if currentAppRoute === route} + {@render layoutRender(layouts)} +{/if} \ No newline at end of file diff --git a/src/routes/[...any]/+page.svelte b/src/routes/[...any]/+page.svelte index 049e6dd..1f53842 100644 --- a/src/routes/[...any]/+page.svelte +++ b/src/routes/[...any]/+page.svelte @@ -6,6 +6,7 @@ import { PageInfo } from '$lib'; import PersistenceLayout from './PersistenceLayout.svelte'; import EscapingLayouts from './EscapingLayouts.svelte'; + import { fly } from 'svelte/transition'; const router = createWebRouter() @@ -49,6 +50,18 @@ As such, it has some pretty esoteric routes and components for the sake of testi {@render linkTo("/route-params/foo/bar")} + +
+ helo go to 2 +
+
+ + +
+ helo from 2 go to 1 +
+
+ {@render identify('links-component-start')} Go to /links/component/finish From 7bda8946cdfe230b53dc14d19fd5b89e2903b169 Mon Sep 17 00:00:00 2001 From: Zac Date: Wed, 19 Nov 2025 13:53:37 -0700 Subject: [PATCH 2/3] make transitions work when switching between routes --- src/lib/router/BrowserRouter.svelte | 25 ++++++++++++++++++++++++- src/lib/router/Layout.svelte | 4 +--- src/lib/router/Route.svelte | 23 +++++------------------ src/lib/router/Route404.svelte | 23 +++++------------------ src/lib/router/impl/webRouter.svelte.ts | 12 +++++++----- 5 files changed, 42 insertions(+), 45 deletions(-) diff --git a/src/lib/router/BrowserRouter.svelte b/src/lib/router/BrowserRouter.svelte index cd63e1a..caf8173 100644 --- a/src/lib/router/BrowserRouter.svelte +++ b/src/lib/router/BrowserRouter.svelte @@ -37,7 +37,11 @@ and displays the appropriate component based on the current route. setRouterContext(router); const currentAppRoute = $derived(router.currentRoute?.route); + const allRoutes = $derived(router.getAllRoutes()); const layouts = $derived(getAllLayouts(currentAppRoute?.layout)); + const lastLayout = $derived( + layouts.length > 0 ? layouts[layouts.length - 1] : undefined + ); @@ -45,4 +49,23 @@ and displays the appropriate component based on the current route. -{@render children?.()} \ No newline at end of file +{@render children?.()} + +{#snippet layoutRender(remaining: LayoutData[])} + {#if remaining.length === 0} + + {#each allRoutes.filter(it => it.layout === lastLayout) as route (route)} + {@render route?.component?.()} + {/each} + {:else} + {@const next = remaining[0]} + + {#snippet renderer()} + {@render layoutRender(remaining.slice(1))} + {/snippet} + + {@render next.renderer(renderer)} + {/if} +{/snippet} + +{@render layoutRender(layouts)} \ No newline at end of file diff --git a/src/lib/router/Layout.svelte b/src/lib/router/Layout.svelte index ef84264..2b7fdd9 100644 --- a/src/lib/router/Layout.svelte +++ b/src/lib/router/Layout.svelte @@ -15,7 +15,7 @@ - - {@render routes()} \ No newline at end of file diff --git a/src/lib/router/Route.svelte b/src/lib/router/Route.svelte index 8dad62a..51cad8f 100644 --- a/src/lib/router/Route.svelte +++ b/src/lib/router/Route.svelte @@ -44,7 +44,7 @@ The children of this component make the content that will be displayed when the route = { path: RoutePath.fromString(combinedPath), - component: children, + component: conditionalRender, layout: container.isRouter() ? undefined : container as LayoutData }; container.registerRoute(route); @@ -58,23 +58,10 @@ The children of this component make the content that will be displayed when the }) const currentAppRoute = $derived(router.currentRoute?.route); - const layouts = $derived(getAllLayouts(currentAppRoute?.layout)); -{#snippet layoutRender(remaining: LayoutData[])} - {#if remaining.length === 0} - {@render currentAppRoute?.component?.()} - {:else} - {@const next = remaining[0]} - - {#snippet renderer()} - {@render layoutRender(remaining.slice(1))} - {/snippet} - - {@render next.renderer(renderer)} +{#snippet conditionalRender()} + {#if currentAppRoute === route} + {@render children?.()} {/if} -{/snippet} - -{#if currentAppRoute === route} - {@render layoutRender(layouts)} -{/if} +{/snippet} \ No newline at end of file diff --git a/src/lib/router/Route404.svelte b/src/lib/router/Route404.svelte index 439dca1..0fff73f 100644 --- a/src/lib/router/Route404.svelte +++ b/src/lib/router/Route404.svelte @@ -36,7 +36,7 @@ route = { path: RoutePath.fromString(layoutPath, true), - component: children, + component: conditionalRender, layout: container.isRouter() ? undefined : container as LayoutData }; container.registerRoute404(route); @@ -50,23 +50,10 @@ }) const currentAppRoute = $derived(router.currentRoute?.route); - const layouts = $derived(getAllLayouts(currentAppRoute?.layout)); -{#snippet layoutRender(remaining: LayoutData[])} - {#if remaining.length === 0} - {@render currentAppRoute?.component?.()} - {:else} - {@const next = remaining[0]} - - {#snippet renderer()} - {@render layoutRender(remaining.slice(1))} - {/snippet} - - {@render next.renderer(renderer)} +{#snippet conditionalRender()} + {#if currentAppRoute === route} + {@render children?.()} {/if} -{/snippet} - -{#if currentAppRoute === route} - {@render layoutRender(layouts)} -{/if} \ No newline at end of file +{/snippet} \ No newline at end of file diff --git a/src/lib/router/impl/webRouter.svelte.ts b/src/lib/router/impl/webRouter.svelte.ts index 1f0da8c..cc5812c 100644 --- a/src/lib/router/impl/webRouter.svelte.ts +++ b/src/lib/router/impl/webRouter.svelte.ts @@ -19,8 +19,8 @@ type HistoryState = { * A router used for an entire application on the web. */ class WebRouter implements Router { - private readonly _routes: ApplicationRoute[] = []; - private readonly _routes404: ApplicationRoute[] = []; + private _routes: ApplicationRoute[] = $state.raw([]); + private _routes404: ApplicationRoute[] = $state.raw([]); // routes are stored in reverse order for easier matching // the most recently added routes are matched first @@ -59,6 +59,7 @@ class WebRouter implements Router { public get params(): RouteParams { return this.currentRoute?.queryParams ?? {}; } + public get queryParams(): RouteParams { return this.currentRoute?.queryParams ?? {}; } @@ -127,11 +128,12 @@ class WebRouter implements Router { } public registerRoute(route: ApplicationRoute): void { - this._routes.push(route); + this._routes = [...this._routes, route]; } public registerRoute404(route: ApplicationRoute): void { - this._routes404.push(route); + this._routes404 = [...this._routes404, route]; + // switch to the new route if it's a 404 route and the current route is undefined if (this.currentRoute?.route == undefined) { @@ -209,7 +211,7 @@ class WebRouter implements Router { } public getAllRoutes(): ApplicationRoute[] { - return [...this.routes]; + return [...this.routes, ...this.routes404]; } isRouter(): this is Router { return true; } From 08071ff5bb045c87fe056b9ca7462b0d66bebf85 Mon Sep 17 00:00:00 2001 From: Zac Date: Tue, 24 Feb 2026 21:09:50 -0700 Subject: [PATCH 3/3] make transitions work when switching between routes --- package.json | 2 +- src/lib/router/BrowserRouter.svelte | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 19a507e..6cacfa4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@snapstrat/switchboard", - "version": "1.0.0", + "version": "1.0.1", "scripts": { "dev": "vite dev", "build": "vite build && npm run package", diff --git a/src/lib/router/BrowserRouter.svelte b/src/lib/router/BrowserRouter.svelte index caf8173..38e051e 100644 --- a/src/lib/router/BrowserRouter.svelte +++ b/src/lib/router/BrowserRouter.svelte @@ -58,13 +58,16 @@ and displays the appropriate component based on the current route. {@render route?.component?.()} {/each} {:else} - {@const next = remaining[0]} {#snippet renderer()} {@render layoutRender(remaining.slice(1))} {/snippet} - {@render next.renderer(renderer)} + {#each remaining as next (next)} + {#if next === remaining[0]} + {@render next.renderer(renderer)} + {/if} + {/each} {/if} {/snippet}