@pyreon/router 0.13.1 → 0.15.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
@@ -13,9 +13,10 @@ bun add @pyreon/router
13
13
  ```tsx
14
14
  import { createRouter, RouterProvider, RouterView, RouterLink } from '@pyreon/router'
15
15
 
16
- const router = createRouter({
16
+ // Type-safe named navigation — route names are checked at compile time
17
+ const router = createRouter<'home' | 'user'>({
17
18
  routes: [
18
- { path: '/', component: Home },
19
+ { path: '/', component: Home, name: 'home' },
19
20
  { path: '/user/:id', component: UserPage, name: 'user' },
20
21
  {
21
22
  path: '/admin',
@@ -112,3 +113,73 @@ Route changes are wrapped in `document.startViewTransition()` automatically when
112
113
  | `finished` | Full animation completed | no -- `.catch()` only |
113
114
 
114
115
  `afterEach` hooks and scroll restoration fire after the VT callback completes, so they observe the new route state when invoked.
116
+
117
+ ## notFound()
118
+
119
+ Throw `notFound()` in a loader or component to render a 404 boundary:
120
+
121
+ ```tsx
122
+ import { notFound, NotFoundBoundary, RouterView } from '@pyreon/router'
123
+
124
+ // Route loader:
125
+ { path: '/user/:id', component: UserPage, loader: async ({ params }) => {
126
+ const user = await fetchUser(params.id)
127
+ if (!user) notFound()
128
+ return user
129
+ }}
130
+
131
+ // App layout:
132
+ <NotFoundBoundary fallback={<NotFoundPage />}>
133
+ <RouterView />
134
+ </NotFoundBoundary>
135
+ ```
136
+
137
+ ## Pending Components
138
+
139
+ Show a skeleton while route loaders run:
140
+
141
+ ```ts
142
+ {
143
+ path: '/dashboard',
144
+ component: Dashboard,
145
+ loader: fetchDashboardData,
146
+ pendingComponent: DashboardSkeleton,
147
+ pendingMs: 200, // delay before showing skeleton (avoid flash)
148
+ pendingMinMs: 500, // minimum display time (avoid flicker)
149
+ }
150
+ ```
151
+
152
+ ## Validated Search Params
153
+
154
+ Type-safe query string validation per route — works with Zod, Valibot, or plain functions:
155
+
156
+ ```ts
157
+ import { useValidatedSearch } from '@pyreon/router'
158
+
159
+ // Route config:
160
+ {
161
+ path: '/search',
162
+ component: SearchPage,
163
+ validateSearch: (raw) => ({
164
+ page: Number(raw.page) || 1,
165
+ q: raw.q ?? '',
166
+ }),
167
+ }
168
+
169
+ // With Zod:
170
+ {
171
+ path: '/search',
172
+ component: SearchPage,
173
+ validateSearch: z.object({
174
+ page: z.coerce.number().default(1),
175
+ q: z.string().default(''),
176
+ }).parse,
177
+ }
178
+
179
+ // In component:
180
+ const search = useValidatedSearch<{ page: number; q: string }>()
181
+ search().page // number — typed + validated
182
+ search().q // string — typed + validated
183
+ ```
184
+
185
+ Structural sharing: `useValidatedSearch()` returns the same object reference when the validated values haven't changed, preventing unnecessary downstream re-renders.
@@ -5386,7 +5386,7 @@ var drawChart = (function (exports) {
5386
5386
  </script>
5387
5387
  <script>
5388
5388
  /*<!--*/
5389
- const data = {"version":2,"tree":{"name":"root","children":[{"name":"index.js","children":[{"name":"src","children":[{"uid":"aa1c31e3-1","name":"loader.ts"},{"uid":"aa1c31e3-3","name":"match.ts"},{"uid":"aa1c31e3-5","name":"scroll.ts"},{"uid":"aa1c31e3-7","name":"types.ts"},{"uid":"aa1c31e3-9","name":"router.ts"},{"uid":"aa1c31e3-11","name":"components.tsx"},{"uid":"aa1c31e3-13","name":"index.ts"}]}]}],"isRoot":true},"nodeParts":{"aa1c31e3-1":{"renderedLength":2824,"gzipLength":1233,"brotliLength":0,"metaUid":"aa1c31e3-0"},"aa1c31e3-3":{"renderedLength":12203,"gzipLength":3691,"brotliLength":0,"metaUid":"aa1c31e3-2"},"aa1c31e3-5":{"renderedLength":2194,"gzipLength":899,"brotliLength":0,"metaUid":"aa1c31e3-4"},"aa1c31e3-7":{"renderedLength":385,"gzipLength":246,"brotliLength":0,"metaUid":"aa1c31e3-6"},"aa1c31e3-9":{"renderedLength":23568,"gzipLength":6469,"brotliLength":0,"metaUid":"aa1c31e3-8"},"aa1c31e3-11":{"renderedLength":7151,"gzipLength":2635,"brotliLength":0,"metaUid":"aa1c31e3-10"},"aa1c31e3-13":{"renderedLength":0,"gzipLength":0,"brotliLength":0,"metaUid":"aa1c31e3-12"}},"nodeMetas":{"aa1c31e3-0":{"id":"/src/loader.ts","moduleParts":{"index.js":"aa1c31e3-1"},"imported":[{"uid":"aa1c31e3-14"}],"importedBy":[{"uid":"aa1c31e3-12"},{"uid":"aa1c31e3-10"}]},"aa1c31e3-2":{"id":"/src/match.ts","moduleParts":{"index.js":"aa1c31e3-3"},"imported":[],"importedBy":[{"uid":"aa1c31e3-12"},{"uid":"aa1c31e3-8"}]},"aa1c31e3-4":{"id":"/src/scroll.ts","moduleParts":{"index.js":"aa1c31e3-5"},"imported":[],"importedBy":[{"uid":"aa1c31e3-8"}]},"aa1c31e3-6":{"id":"/src/types.ts","moduleParts":{"index.js":"aa1c31e3-7"},"imported":[],"importedBy":[{"uid":"aa1c31e3-12"},{"uid":"aa1c31e3-8"}]},"aa1c31e3-8":{"id":"/src/router.ts","moduleParts":{"index.js":"aa1c31e3-9"},"imported":[{"uid":"aa1c31e3-14"},{"uid":"aa1c31e3-15"},{"uid":"aa1c31e3-2"},{"uid":"aa1c31e3-4"},{"uid":"aa1c31e3-6"}],"importedBy":[{"uid":"aa1c31e3-12"},{"uid":"aa1c31e3-10"}]},"aa1c31e3-10":{"id":"/src/components.tsx","moduleParts":{"index.js":"aa1c31e3-11"},"imported":[{"uid":"aa1c31e3-14"},{"uid":"aa1c31e3-0"},{"uid":"aa1c31e3-8"}],"importedBy":[{"uid":"aa1c31e3-12"}]},"aa1c31e3-12":{"id":"/src/index.ts","moduleParts":{"index.js":"aa1c31e3-13"},"imported":[{"uid":"aa1c31e3-10"},{"uid":"aa1c31e3-0"},{"uid":"aa1c31e3-2"},{"uid":"aa1c31e3-8"},{"uid":"aa1c31e3-6"}],"importedBy":[],"isEntry":true},"aa1c31e3-14":{"id":"@pyreon/core","moduleParts":{},"imported":[],"importedBy":[{"uid":"aa1c31e3-10"},{"uid":"aa1c31e3-0"},{"uid":"aa1c31e3-8"}]},"aa1c31e3-15":{"id":"@pyreon/reactivity","moduleParts":{},"imported":[],"importedBy":[{"uid":"aa1c31e3-8"}]}},"env":{"rollup":"4.23.0"},"options":{"gzip":true,"brotli":false,"sourcemap":false}};
5389
+ const data = {"version":2,"tree":{"name":"root","children":[{"name":"index.js","children":[{"name":"src","children":[{"uid":"25bb3a92-1","name":"loader.ts"},{"uid":"25bb3a92-3","name":"match.ts"},{"uid":"25bb3a92-5","name":"redirect.ts"},{"uid":"25bb3a92-7","name":"scroll.ts"},{"uid":"25bb3a92-9","name":"types.ts"},{"uid":"25bb3a92-11","name":"router.ts"},{"uid":"25bb3a92-13","name":"components.tsx"},{"uid":"25bb3a92-15","name":"not-found.ts"},{"uid":"25bb3a92-17","name":"index.ts"}]}]}],"isRoot":true},"nodeParts":{"25bb3a92-1":{"renderedLength":3376,"gzipLength":1507,"brotliLength":0,"metaUid":"25bb3a92-0"},"25bb3a92-3":{"renderedLength":13072,"gzipLength":3951,"brotliLength":0,"metaUid":"25bb3a92-2"},"25bb3a92-5":{"renderedLength":1966,"gzipLength":1043,"brotliLength":0,"metaUid":"25bb3a92-4"},"25bb3a92-7":{"renderedLength":2194,"gzipLength":899,"brotliLength":0,"metaUid":"25bb3a92-6"},"25bb3a92-9":{"renderedLength":385,"gzipLength":246,"brotliLength":0,"metaUid":"25bb3a92-8"},"25bb3a92-11":{"renderedLength":29129,"gzipLength":8078,"brotliLength":0,"metaUid":"25bb3a92-10"},"25bb3a92-13":{"renderedLength":10571,"gzipLength":3518,"brotliLength":0,"metaUid":"25bb3a92-12"},"25bb3a92-15":{"renderedLength":1315,"gzipLength":682,"brotliLength":0,"metaUid":"25bb3a92-14"},"25bb3a92-17":{"renderedLength":0,"gzipLength":0,"brotliLength":0,"metaUid":"25bb3a92-16"}},"nodeMetas":{"25bb3a92-0":{"id":"/src/loader.ts","moduleParts":{"index.js":"25bb3a92-1"},"imported":[{"uid":"25bb3a92-18"}],"importedBy":[{"uid":"25bb3a92-16"},{"uid":"25bb3a92-12"}]},"25bb3a92-2":{"id":"/src/match.ts","moduleParts":{"index.js":"25bb3a92-3"},"imported":[],"importedBy":[{"uid":"25bb3a92-16"},{"uid":"25bb3a92-10"}]},"25bb3a92-4":{"id":"/src/redirect.ts","moduleParts":{"index.js":"25bb3a92-5"},"imported":[],"importedBy":[{"uid":"25bb3a92-16"},{"uid":"25bb3a92-10"}]},"25bb3a92-6":{"id":"/src/scroll.ts","moduleParts":{"index.js":"25bb3a92-7"},"imported":[],"importedBy":[{"uid":"25bb3a92-10"}]},"25bb3a92-8":{"id":"/src/types.ts","moduleParts":{"index.js":"25bb3a92-9"},"imported":[],"importedBy":[{"uid":"25bb3a92-16"},{"uid":"25bb3a92-10"}]},"25bb3a92-10":{"id":"/src/router.ts","moduleParts":{"index.js":"25bb3a92-11"},"imported":[{"uid":"25bb3a92-18"},{"uid":"25bb3a92-19"},{"uid":"25bb3a92-2"},{"uid":"25bb3a92-4"},{"uid":"25bb3a92-6"},{"uid":"25bb3a92-8"}],"importedBy":[{"uid":"25bb3a92-16"},{"uid":"25bb3a92-12"}]},"25bb3a92-12":{"id":"/src/components.tsx","moduleParts":{"index.js":"25bb3a92-13"},"imported":[{"uid":"25bb3a92-18"},{"uid":"25bb3a92-19"},{"uid":"25bb3a92-0"},{"uid":"25bb3a92-10"}],"importedBy":[{"uid":"25bb3a92-16"}]},"25bb3a92-14":{"id":"/src/not-found.ts","moduleParts":{"index.js":"25bb3a92-15"},"imported":[{"uid":"25bb3a92-18"}],"importedBy":[{"uid":"25bb3a92-16"}]},"25bb3a92-16":{"id":"/src/index.ts","moduleParts":{"index.js":"25bb3a92-17"},"imported":[{"uid":"25bb3a92-12"},{"uid":"25bb3a92-14"},{"uid":"25bb3a92-4"},{"uid":"25bb3a92-0"},{"uid":"25bb3a92-2"},{"uid":"25bb3a92-10"},{"uid":"25bb3a92-8"}],"importedBy":[],"isEntry":true},"25bb3a92-18":{"id":"@pyreon/core","moduleParts":{},"imported":[],"importedBy":[{"uid":"25bb3a92-12"},{"uid":"25bb3a92-14"},{"uid":"25bb3a92-0"},{"uid":"25bb3a92-10"}]},"25bb3a92-19":{"id":"@pyreon/reactivity","moduleParts":{},"imported":[],"importedBy":[{"uid":"25bb3a92-12"},{"uid":"25bb3a92-10"}]}},"env":{"rollup":"4.23.0"},"options":{"gzip":true,"brotli":false,"sourcemap":false}};
5390
5390
 
5391
5391
  const run = () => {
5392
5392
  const width = window.innerWidth;