svelte-navigator-lite 2.0.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # svelte-navigator-lite
2
2
 
3
+ [![Publish Package](https://github.com/jeremyjfleming/svelte-navigator-lite/actions/workflows/npm-publish-github-packages.yml/badge.svg)](https://github.com/jeremyjfleming/svelte-navigator-lite/actions/workflows/npm-publish-github-packages.yml)
4
+ [![npm version](https://img.shields.io/npm/v/svelte-navigator-lite)](https://www.npmjs.com/package/svelte-navigator-lite)
5
+
3
6
  A lightweight, pattern-based router for Svelte 5. Routes are defined with familiar URL patterns, guards are reusable named functions, and the reactive `router` singleton integrates directly with Svelte runes.
4
7
 
5
8
  ## Installation
@@ -19,16 +22,19 @@ Define your routes and guards, then call `createRouter` on mount.
19
22
  import { createRouter, router } from 'svelte-navigator-lite';
20
23
  import { auth } from '$stores/auth.svelte';
21
24
  import AppShell from '$lib/components/AppShell.svelte';
25
+ import { overlayMap } from '$lib/routes';
26
+
27
+ let currentOverlay = $derived(overlayMap[router.route] ?? null);
22
28
 
23
29
  onMount(() => {
24
30
  createRouter({
25
31
  routes: [
26
- { name: 'cal', pattern: '/cal' },
27
- { name: 'cal-date', pattern: '/cal/:mm/:dd/:yyyy' },
28
- { name: 'event', pattern: '/event/:eventId' },
29
- { name: 'edit', pattern: '/event/:eventId/edit' },
30
- { name: 'login', pattern: '/login', guards: ['unauth'] },
31
- { name: 'signup', pattern: '/signup', guards: ['unauth'] },
32
+ { name: 'cal', pattern: '/cal' },
33
+ { name: 'cal-date', pattern: '/cal/:mm/:dd/:yyyy' },
34
+ { name: 'event', pattern: '/event/:eventId', meta: { overlay: true } },
35
+ { name: 'edit', pattern: '/event/:eventId/edit', meta: { overlay: true } },
36
+ { name: 'login', pattern: '/login', guards: ['unauth'], meta: { overlay: true } },
37
+ { name: 'signup', pattern: '/signup', guards: ['unauth'], meta: { overlay: true } },
32
38
  ],
33
39
  guards: {
34
40
  auth: { condition: () => !auth.isValid(), redirectTo: 'login' },
@@ -40,6 +46,9 @@ Define your routes and guards, then call `createRouter` on mount.
40
46
  </script>
41
47
 
42
48
  <AppShell />
49
+ {#if router.meta?.overlay}
50
+ <svelte:component this={currentOverlay} />
51
+ {/if}
43
52
  ```
44
53
 
45
54
  ## Route patterns
@@ -81,14 +90,40 @@ import { router } from 'svelte-navigator-lite';
81
90
  router.route // current route name: string
82
91
  router.params // path params: Record<string, string>
83
92
  router.searchParams // query params: Record<string, string>
93
+ router.meta // meta object for the current route (or undefined)
84
94
  router.notFound // true if the URL matched no route and the fallback was used
85
95
 
86
- router.is('cal') // true if current route === 'cal'
96
+ router.is('cal') // true if current route === 'cal'
87
97
  router.matches(['cal', 'event']) // true if current route is in the list
88
98
  ```
89
99
 
90
100
  All properties are reactive — use them in Svelte templates or `$effect` blocks and they update automatically on navigation.
91
101
 
102
+ ## Route meta
103
+
104
+ Attach arbitrary metadata to any route via the `meta` field. The router exposes `router.meta` so your components can read it reactively.
105
+
106
+ ```typescript
107
+ routes: [
108
+ { name: 'cal', pattern: '/cal' },
109
+ { name: 'event', pattern: '/event/:eventId', meta: { overlay: true } },
110
+ { name: 'edit', pattern: '/event/:eventId/edit', meta: { overlay: true } },
111
+ { name: 'admin', pattern: '/admin', meta: { role: 'admin' } },
112
+ ]
113
+ ```
114
+
115
+ ```svelte
116
+ <!-- The base layout always renders -->
117
+ <AppShell />
118
+
119
+ <!-- Use any meta value to drive rendering -->
120
+ {#if router.meta?.overlay}
121
+ <svelte:component this={overlayMap[router.route]} />
122
+ {/if}
123
+ ```
124
+
125
+ `meta` is not interpreted by the router — it is plain data for your components to use however they need.
126
+
92
127
  ## Guards
93
128
 
94
129
  Guards are defined once in `createRouter` and referenced by name in route definitions.
@@ -96,9 +131,9 @@ Guards are defined once in `createRouter` and referenced by name in route defini
96
131
  ```typescript
97
132
  createRouter({
98
133
  routes: [
99
- { name: 'cal', pattern: '/cal', guards: ['auth'] },
100
- { name: 'login', pattern: '/login', guards: ['unauth'] },
101
- { name: 'verify-email', pattern: '/verify-email', guards: ['unauth'] },
134
+ { name: 'cal', pattern: '/cal', guards: ['auth'] },
135
+ { name: 'login', pattern: '/login', guards: ['unauth'] },
136
+ { name: 'verify-email', pattern: '/verify-email', guards: ['unauth'] },
102
137
  { name: 'login-check', pattern: '/login', guards: ['unauth', 'emailCheck'] },
103
138
  ],
104
139
  guards: {
@@ -150,7 +185,7 @@ await goto('/some/path', { replaceState: true }); // replace instead of push
150
185
 
151
186
  ## Migrating from v1
152
187
 
153
- The `rootPath` + `segments` route definition is replaced by a single `pattern` string, and `routeGuards` inline on each route are replaced by named guards defined once.
188
+ The `rootPath` + `segments` route definition is replaced by a single `pattern` string, `routeGuards` inline on each route are replaced by named guards defined once, and the new `meta` field replaces any separate modal-route maps you maintained manually.
154
189
 
155
190
  ```typescript
156
191
  // v1
@@ -161,6 +196,6 @@ The `rootPath` + `segments` route definition is replaced by a single `pattern` s
161
196
  }
162
197
 
163
198
  // v2
164
- { name: 'edit', pattern: '/event/:eventId/edit', guards: ['auth'] }
165
- // with guard defined once in createRouter: auth: { condition: () => !auth.isValid(), redirectTo: 'login' }
199
+ { name: 'edit', pattern: '/event/:eventId/edit', guards: ['auth'], meta: { overlay: true } }
200
+ // guard defined once: auth: { condition: () => !auth.isValid(), redirectTo: 'login' }
166
201
  ```
package/dist/match.d.ts CHANGED
@@ -5,6 +5,7 @@ type CompiledRoute = {
5
5
  regex: RegExp;
6
6
  paramNames: string[];
7
7
  guards: string[];
8
+ meta: Record<string, unknown> | undefined;
8
9
  };
9
10
  export type RouteMatch = {
10
11
  name: string;
package/dist/match.js CHANGED
@@ -20,6 +20,7 @@ export function compileRoutes(routes) {
20
20
  regex: new RegExp(`^${regexStr}/?$`),
21
21
  paramNames,
22
22
  guards: route.guards ?? [],
23
+ meta: route.meta,
23
24
  };
24
25
  });
25
26
  }
@@ -10,6 +10,7 @@ declare function _createRouter(): {
10
10
  readonly params: Record<string, string>;
11
11
  readonly searchParams: Record<string, string>;
12
12
  readonly notFound: boolean;
13
+ readonly meta: Record<string, unknown> | undefined;
13
14
  is(route: string): boolean;
14
15
  matches(routes: string[]): boolean;
15
16
  parseUrl: (url: string) => void;
@@ -22,6 +23,7 @@ export declare const router: {
22
23
  readonly params: Record<string, string>;
23
24
  readonly searchParams: Record<string, string>;
24
25
  readonly notFound: boolean;
26
+ readonly meta: Record<string, unknown> | undefined;
25
27
  is(route: string): boolean;
26
28
  matches(routes: string[]): boolean;
27
29
  parseUrl: (url: string) => void;
@@ -70,6 +70,7 @@ function _createRouter() {
70
70
  get params() { return state.params; },
71
71
  get searchParams() { return state.searchParams; },
72
72
  get notFound() { return state.notFound; },
73
+ get meta() { return compiled.find(r => r.name === state.current)?.meta; },
73
74
  is(route) { return state.current === route; },
74
75
  matches(routes) { return routes.includes(state.current); },
75
76
  parseUrl,
package/dist/types.d.ts CHANGED
@@ -2,6 +2,7 @@ export type RouteDefinition = {
2
2
  name: string;
3
3
  pattern: string;
4
4
  guards?: string[];
5
+ meta?: Record<string, unknown>;
5
6
  };
6
7
  export type Guard = {
7
8
  condition: () => boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svelte-navigator-lite",
3
- "version": "2.0.0",
3
+ "version": "2.2.0",
4
4
  "description": "A lightweight router for Svelte 5",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -12,7 +12,9 @@
12
12
  "types": "./dist/index.d.ts"
13
13
  }
14
14
  },
15
- "files": ["dist"],
15
+ "files": [
16
+ "dist"
17
+ ],
16
18
  "scripts": {
17
19
  "build": "tsc",
18
20
  "dev": "tsc --watch",
@@ -29,10 +31,15 @@
29
31
  "typescript": "^5.0.0",
30
32
  "vitest": "^3.0.0"
31
33
  },
32
- "keywords": ["svelte", "router", "navigation", "svelte5"],
34
+ "keywords": [
35
+ "svelte",
36
+ "router",
37
+ "navigation",
38
+ "svelte5"
39
+ ],
33
40
  "license": "MIT",
34
41
  "repository": {
35
42
  "type": "git",
36
- "url": "https://github.com/jeremyjfleming/svelte-navigator-lite"
43
+ "url": "git+https://github.com/jeremyjfleming/svelte-navigator-lite.git"
37
44
  }
38
45
  }