@buzola/router 0.0.18 → 0.0.19

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.
Files changed (47) hide show
  1. package/dist/define/create-page.js +1 -1
  2. package/dist/engine/loader-cache.d.ts +1 -1
  3. package/dist/engine/loader-cache.js +1 -1
  4. package/dist/engine/loader-state.d.ts +5 -5
  5. package/dist/engine/loader-state.d.ts.map +1 -1
  6. package/dist/engine/loader-state.js +8 -8
  7. package/dist/engine/loader-state.js.map +1 -1
  8. package/dist/engine/matcher.js +4 -4
  9. package/dist/engine/matcher.js.map +1 -1
  10. package/dist/engine/navigation-adapter.js +2 -2
  11. package/dist/engine/navigation-adapter.js.map +1 -1
  12. package/dist/engine/route-tree.js +2 -2
  13. package/dist/engine/route-tree.js.map +1 -1
  14. package/dist/engine/router.d.ts +6 -6
  15. package/dist/engine/router.js +10 -10
  16. package/dist/engine/router.js.map +1 -1
  17. package/dist/engine/types.d.ts +8 -8
  18. package/dist/engine/types.d.ts.map +1 -1
  19. package/dist/engine/utils.d.ts +3 -3
  20. package/dist/engine/utils.js +3 -3
  21. package/dist/react/hooks.d.ts +2 -2
  22. package/dist/react/hooks.js +1 -1
  23. package/dist/react/link.d.ts +4 -4
  24. package/dist/react/link.js +1 -1
  25. package/dist/react/outlet.js +2 -2
  26. package/dist/react/outlet.js.map +1 -1
  27. package/package.json +1 -1
  28. package/src/__tests__/create-page.test.ts +1 -1
  29. package/src/__tests__/loader-cache.test.ts +1 -1
  30. package/src/__tests__/loader-state.test.ts +12 -12
  31. package/src/__tests__/navigation-adapter.test.ts +2 -2
  32. package/src/__tests__/react.test.tsx +4 -4
  33. package/src/__tests__/router.test.ts +2 -2
  34. package/src/__tests__/setup-dom.ts +1 -1
  35. package/src/__tests__/type-safety.test.tsx +22 -22
  36. package/src/define/create-page.tsx +1 -1
  37. package/src/engine/loader-cache.ts +1 -1
  38. package/src/engine/loader-state.ts +9 -9
  39. package/src/engine/matcher.ts +4 -4
  40. package/src/engine/navigation-adapter.ts +2 -2
  41. package/src/engine/route-tree.ts +3 -3
  42. package/src/engine/router.ts +11 -11
  43. package/src/engine/types.ts +8 -8
  44. package/src/engine/utils.ts +3 -3
  45. package/src/react/hooks.ts +2 -2
  46. package/src/react/link.tsx +5 -5
  47. package/src/react/outlet.tsx +2 -2
@@ -158,13 +158,13 @@ export function createMemoryNavigationAdapter(
158
158
  void interceptHandler().then(
159
159
  () => {},
160
160
  (error) => {
161
- // Guard aborts are expected — rethrow unexpected errors
161
+ // Guard aborts are expected: rethrow unexpected errors
162
162
  if (error instanceof Error && error.name === 'NavigationAbortedError') return
163
163
  throw error
164
164
  },
165
165
  )
166
166
  } else {
167
- // No interception — commit immediately
167
+ // No interception: commit immediately
168
168
  commitNavigation(false)
169
169
  }
170
170
  }
@@ -61,7 +61,7 @@ export function buildRouteTree(configs: RouteConfig[], parentPath = ''): RouteTr
61
61
  interface FlatEntry {
62
62
  /** The URL pattern for matching (e.g., "/project/:id/edit"). */
63
63
  pattern: string
64
- /** Layout chain from root to leaf — each becomes a RouteMatch. */
64
+ /** Layout chain from root to leaf: each becomes a RouteMatch. */
65
65
  chain: RouteNode[]
66
66
  }
67
67
 
@@ -127,7 +127,7 @@ function insertIntoTrie(root: TrieNode, pattern: string, chain: RouteNode[]): vo
127
127
  const segment = segments[i]
128
128
 
129
129
  if (segment.startsWith(':') && (segment.endsWith('+') || segment.endsWith('*'))) {
130
- // Catch-all segment — consumes all remaining segments
130
+ // Catch-all segment: consumes all remaining segments
131
131
  paramNames.push(segment.slice(1, -1))
132
132
  node.catchAllChild = { chain, paramNames }
133
133
  return
@@ -150,7 +150,7 @@ function insertIntoTrie(root: TrieNode, pattern: string, chain: RouteNode[]): vo
150
150
  }
151
151
  }
152
152
 
153
- // Terminal — route matches at this trie node
153
+ // Terminal: route matches at this trie node
154
154
  node.route = { chain, paramNames }
155
155
  }
156
156
 
@@ -47,7 +47,7 @@ export interface RouterOptions {
47
47
  loaderCacheSize?: number
48
48
  /**
49
49
  * Decides, per navigation, whether the router handles it in the current document.
50
- * Return `false` to have the browser load the destination as a new document instead —
50
+ * Return `false` to have the browser load the destination as a new document instead,
51
51
  * e.g. to pick up a newly deployed build on the next in-app navigation.
52
52
  *
53
53
  * Offered every push, replace and traverse the router would otherwise intercept, except
@@ -146,7 +146,7 @@ export class Router {
146
146
  */
147
147
  start(): () => void {
148
148
  const handler = (event: BuzolaNavigateEvent) => {
149
- // Consume the pending options before any early return — they belong to the
149
+ // Consume the pending options before any early return: they belong to the
150
150
  // navigation that armed them and must not leak into the next one.
151
151
  const scrollBehavior = this.pendingScrollBehavior
152
152
  const explicitFocusReset = this.pendingFocusReset
@@ -192,7 +192,7 @@ export class Router {
192
192
 
193
193
  const currentNavId = ++this.navigationId
194
194
  const useViewTransition = event.viewTransition || this.viewTransitions
195
- // Query-only navigations stay on the same page — keep focus where the user left it
195
+ // Query-only navigations stay on the same page, so keep focus where the user left it
196
196
  // (search boxes, filters, pagination). Path changes keep the browser's focus reset,
197
197
  // and so do fragment changes, which must move focus to the targeted section.
198
198
  const focusReset = explicitFocusReset
@@ -218,7 +218,7 @@ export class Router {
218
218
  pendingLocation: url,
219
219
  })
220
220
 
221
- // A newer navigation has started — abandon this one
221
+ // A newer navigation has started, so abandon this one
222
222
  if (this.navigationId !== currentNavId) return
223
223
 
224
224
  // Perform the DOM update
@@ -231,7 +231,7 @@ export class Router {
231
231
  pendingLocation: undefined,
232
232
  navigationState: this.adapter.getState(),
233
233
  })
234
- // Going to the URL we are already on is still a navigation — a browser
234
+ // Going to the URL we are already on is still a navigation: a browser
235
235
  // re-requests the document for it. Loader data is keyed by href, so it
236
236
  // would silently keep serving stale data without an explicit invalidation.
237
237
  if (previousHref === url.href) {
@@ -284,7 +284,7 @@ export class Router {
284
284
  }
285
285
 
286
286
  /**
287
- * Hold the navigation while the blockers run and, if they allow it, reload the current entry —
287
+ * Hold the navigation while the blockers run and, if they allow it, reload the current entry,
288
288
  * which is already the navigation's destination, because an intercepted navigation commits before
289
289
  * its handler runs.
290
290
  */
@@ -309,7 +309,7 @@ export class Router {
309
309
  }
310
310
 
311
311
  /**
312
- * Hand one navigation to the browser instead of intercepting it, for a URL the SERVER owns —
312
+ * Hand one navigation to the browser instead of intercepting it, for a URL the SERVER owns:
313
313
  * an auth handoff, a file download, a server-rendered page that happens to share this origin.
314
314
  *
315
315
  * The Navigation API offers no way for a caller to mark a navigation un-interceptable:
@@ -319,7 +319,7 @@ export class Router {
319
319
  *
320
320
  * The release is recorded BEFORE the navigation is requested and is keyed to the resolved URL, so
321
321
  * it cannot race the event or release some other navigation. Unlike `navigate`, the URL is passed
322
- * to the browser as given — no base path is prepended, because the target is outside the app.
322
+ * to the browser as given: no base path is prepended, because the target is outside the app.
323
323
  */
324
324
  leaveApp(url: string): void {
325
325
  this.releasedURL = new URL(url, this.adapter.getCurrentURL()).href
@@ -328,7 +328,7 @@ export class Router {
328
328
 
329
329
  /**
330
330
  * Navigate programmatically.
331
- * The `to` path should not include the base path — it is prepended automatically.
331
+ * The `to` path should not include the base path. It is prepended automatically.
332
332
  */
333
333
  navigate(to: string, options?: NavigateOptions): void {
334
334
  if (options?.resetScroll === false) {
@@ -409,7 +409,7 @@ export class Router {
409
409
  missing.push(paramName)
410
410
  } else {
411
411
  if (isCatchAll) {
412
- // Catch-all values may contain slashes — insert raw
412
+ // Catch-all values may contain slashes: insert raw
413
413
  result.push(value)
414
414
  } else {
415
415
  result.push(encodeURIComponent(value))
@@ -533,7 +533,7 @@ export class Router {
533
533
  }
534
534
 
535
535
  /**
536
- * Dispose the router — clear all subscribers and reset state.
536
+ * Dispose the router: clear all subscribers and reset state.
537
537
  */
538
538
  dispose(): void {
539
539
  this.stopFn?.()
@@ -29,7 +29,7 @@ export type RegisteredPage = keyof BuzolaPageMap & string
29
29
  export type PageParams<P extends keyof BuzolaPageMap> = BuzolaPageMap[P]
30
30
 
31
31
  /**
32
- * Effective params for a page — persistent params become optional.
32
+ * Effective params for a page: persistent params become optional.
33
33
  * When BuzolaPersistentParams is empty (default), collapses to BuzolaPageMap[P].
34
34
  */
35
35
  export type EffectivePageParams<P extends keyof BuzolaPageMap> =
@@ -50,7 +50,7 @@ export interface StandardSchema<T = unknown> {
50
50
  }
51
51
  }
52
52
 
53
- /** Route component — either a regular component or a lazy-loaded one. */
53
+ /** Route component: either a regular component or a lazy-loaded one. */
54
54
  export type RouteComponent = ComponentType<Record<string, never>> | LazyExoticComponent<ComponentType<Record<string, never>>>
55
55
 
56
56
  /** Configuration for a single route. */
@@ -63,7 +63,7 @@ export interface RouteConfig {
63
63
  component?: RouteComponent
64
64
  /** Schema for validating search params (Standard Schema compatible). */
65
65
  searchSchema?: StandardSchema
66
- /** Preload function — triggers lazy component import ahead of navigation. */
66
+ /** Preload function: triggers lazy component import ahead of navigation. */
67
67
  preload?: () => void
68
68
  /** Child routes. */
69
69
  children?: RouteConfig[]
@@ -71,7 +71,7 @@ export interface RouteConfig {
71
71
  isLayout?: boolean
72
72
  /** Whether this is an index route (renders at parent's exact path). */
73
73
  isIndex?: boolean
74
- /** Whether this is a pathless group (e.g., (auth) — no URL segment). */
74
+ /** Whether this is a pathless group (e.g., (auth), with no URL segment). */
75
75
  isPathlessGroup?: boolean
76
76
  }
77
77
 
@@ -101,7 +101,7 @@ export interface RouteNode {
101
101
  component?: RouteComponent
102
102
  /** Search params schema. */
103
103
  searchSchema?: StandardSchema
104
- /** Preload function — triggers lazy component import ahead of navigation. */
104
+ /** Preload function: triggers lazy component import ahead of navigation. */
105
105
  preload?: () => void
106
106
  /** Whether this is a layout node (renders children via Outlet). */
107
107
  isLayout: boolean
@@ -113,7 +113,7 @@ export interface RouteNode {
113
113
 
114
114
  /** A node in the segment trie used for URL matching. */
115
115
  export interface TrieNode {
116
- /** Static children — exact segment match via Map lookup (O(1)). */
116
+ /** Static children: exact segment match via Map lookup (O(1)). */
117
117
  staticChildren: Map<string, TrieNode>
118
118
  /**
119
119
  * Dynamic child: matches any single segment. It carries no param name, because routes sharing this
@@ -174,8 +174,8 @@ export interface NavigateOptions {
174
174
  resetScroll?: boolean
175
175
  /**
176
176
  * Whether the browser moves focus after navigation.
177
- * Defaults to `manual` when only the search string changes — so search boxes, filters and
178
- * pagination controls keep the caret — and to `after-transition` when the path or the hash
177
+ * Defaults to `manual` when only the search string changes (so search boxes, filters and
178
+ * pagination controls keep the caret), and to `after-transition` when the path or the hash
179
179
  * changes, so fragment links move focus to the section they target.
180
180
  */
181
181
  focusReset?: 'after-transition' | 'manual'
@@ -24,12 +24,12 @@ export function extractParamNames(pattern: string): string[] {
24
24
  }
25
25
 
26
26
  /**
27
- * Whether two URLs address the same page — i.e. only search/hash differ.
27
+ * Whether two URLs address the same page, i.e. only search/hash differ.
28
28
  * Same-path navigations (filters, sorting, pagination, search) keep the page
29
29
  * on screen and keep its loader data as stale; path changes do not.
30
30
  *
31
- * Note this ignores the hash. Callers that care about fragment changes — focus
32
- * handling, for one — have to compare `hash` themselves.
31
+ * Note this ignores the hash. Callers that care about fragment changes (focus
32
+ * handling, for one) have to compare `hash` themselves.
33
33
  */
34
34
  export function isSamePath(a: string | URL, b: string | URL): boolean {
35
35
  const urlA = typeof a === 'string' ? new URL(a) : a
@@ -29,7 +29,7 @@ function useRouteContext() {
29
29
  /**
30
30
  * Type-safe navigation function.
31
31
  * Uses page IDs instead of URL patterns.
32
- * Persistent params are optional — resolved from current URL or fallback.
32
+ * Persistent params are optional: resolved from current URL or fallback.
33
33
  */
34
34
  type NavigateFn = <P extends RegisteredPage>(
35
35
  to: P,
@@ -41,7 +41,7 @@ type NavigateFn = <P extends RegisteredPage>(
41
41
 
42
42
  /**
43
43
  * Hook to get a type-safe navigate function.
44
- * Navigates using page IDs — the router looks up the route pattern from the page registry.
44
+ * Navigates using page IDs: the router looks up the route pattern from the page registry.
45
45
  */
46
46
  export function useNavigate(): NavigateFn {
47
47
  const router = useRouter()
@@ -2,7 +2,7 @@ import React, { useCallback, useEffect, useRef } from 'react'
2
2
  import type { EffectivePageParams, NavigateOptions, RegisteredPage } from '../engine/types.js'
3
3
  import { useRouter, useRouterState } from './hooks.js'
4
4
 
5
- // ─── Link props type — always type-safe via page ID ──────────────────────────
5
+ // ─── Link props type: always type-safe via page ID ───────────────────────────
6
6
 
7
7
  type LinkPropsBase = Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, 'href'> & {
8
8
  /** Replace the current history entry instead of pushing. */
@@ -29,9 +29,9 @@ type LinkPropsBase = Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, 'href'>
29
29
  asChild?: boolean
30
30
  /**
31
31
  * Prefetch strategy for lazy-loaded route code.
32
- * - `'intent'` — preload on mouseEnter/focus (default)
33
- * - `'render'` — preload as soon as the Link renders
34
- * - `'none'` — disable prefetching
32
+ * - `'intent'`: preload on mouseEnter/focus (default)
33
+ * - `'render'`: preload as soon as the Link renders
34
+ * - `'none'`: disable prefetching
35
35
  */
36
36
  prefetch?: 'intent' | 'render' | 'none'
37
37
  }
@@ -44,7 +44,7 @@ export type LinkProps<P extends RegisteredPage = RegisteredPage> = [keyof Effect
44
44
 
45
45
  /**
46
46
  * Type-safe link component.
47
- * Uses page IDs for navigation — the router looks up the route pattern from the page registry.
47
+ * Uses page IDs for navigation: the router looks up the route pattern from the page registry.
48
48
  * For simple navigations, renders a native <a> and lets the Navigation API handle it.
49
49
  * Uses programmatic navigation when state, replace, resetScroll, or viewTransition is needed.
50
50
  *
@@ -12,7 +12,7 @@ function DefaultNotFound(): React.ReactElement {
12
12
  },
13
13
  isDev
14
14
  ? [
15
- React.createElement('h1', { key: 'h' }, '404 — Page Not Found'),
15
+ React.createElement('h1', { key: 'h' }, '404: Page Not Found'),
16
16
  React.createElement('p', { key: 'p1' }, `No route matches "${typeof window !== 'undefined' ? window.location.pathname : ''}".`),
17
17
  React.createElement('p', {
18
18
  key: 'p2',
@@ -74,7 +74,7 @@ export function Outlet({ fallback, errorFallback, notFound }: OutletProps): Reac
74
74
  }, [state, depth, effectiveDepth, matches, match, routeContext.params])
75
75
 
76
76
  if (!match) {
77
- // At root depth with no matches — show 404
77
+ // At root depth with no matches: show 404
78
78
  if (depth === 0 && matches.length === 0) {
79
79
  if (notFound === null) return null
80
80
  return (notFound ?? React.createElement(DefaultNotFound, null)) as React.ReactElement