@flight-framework/router 0.0.6 → 0.0.7

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.
@@ -0,0 +1,359 @@
1
+ /**
2
+ * Type definitions for @flight-framework/router
3
+ */
4
+ /**
5
+ * Router context value provided to all components
6
+ */
7
+ interface RouterContextValue {
8
+ /** Current pathname (e.g., '/docs/routing') */
9
+ path: string;
10
+ /** URL search params as object */
11
+ searchParams: URLSearchParams;
12
+ /** Navigate to a new path */
13
+ navigate: (to: string, options?: NavigateOptions) => void;
14
+ /** Go back in history */
15
+ back: () => void;
16
+ /** Go forward in history */
17
+ forward: () => void;
18
+ }
19
+ /**
20
+ * Props for RouterProvider component
21
+ */
22
+ interface RouterProviderProps {
23
+ /** Child components */
24
+ children: unknown;
25
+ /** Initial path for SSR (server passes request URL) */
26
+ initialPath?: string;
27
+ /** Base path for the router (e.g., '/app') */
28
+ basePath?: string;
29
+ }
30
+ /**
31
+ * Prefetch strategy for Link component
32
+ *
33
+ * - 'none': No prefetching (default)
34
+ * - 'intent': Prefetch on hover or focus (recommended for most cases)
35
+ * - 'render': Prefetch immediately when link renders
36
+ * - 'viewport': Prefetch when link enters the viewport (good for mobile)
37
+ */
38
+ type PrefetchStrategy = 'none' | 'intent' | 'render' | 'viewport';
39
+ /**
40
+ * Priority level for prefetch requests
41
+ */
42
+ type PrefetchPriority = 'high' | 'low' | 'auto';
43
+ /**
44
+ * Options for programmatic prefetching
45
+ */
46
+ interface PrefetchOptions {
47
+ /** Priority of the prefetch request */
48
+ priority?: PrefetchPriority;
49
+ /** Include data prefetch (loaders) */
50
+ includeData?: boolean;
51
+ /** Include module prefetch (JS chunks) */
52
+ includeModules?: boolean;
53
+ }
54
+ /**
55
+ * Props for Link component
56
+ */
57
+ interface LinkProps {
58
+ /** Target URL path */
59
+ href: string;
60
+ /** Child content */
61
+ children: unknown;
62
+ /** CSS class name */
63
+ className?: string;
64
+ /** Open in new tab */
65
+ target?: string;
66
+ /** Link relationship */
67
+ rel?: string;
68
+ /**
69
+ * Prefetch strategy for the target page.
70
+ *
71
+ * - `true` or `'intent'`: Prefetch on hover/focus
72
+ * - `'render'`: Prefetch when link renders
73
+ * - `'viewport'`: Prefetch when link enters viewport
74
+ * - `false` or `'none'`: No prefetching (default)
75
+ *
76
+ * @default 'none'
77
+ */
78
+ prefetch?: boolean | PrefetchStrategy;
79
+ /** Replace current history entry instead of pushing */
80
+ replace?: boolean;
81
+ /** Scroll to top after navigation */
82
+ scroll?: boolean;
83
+ /** Aria label for accessibility */
84
+ 'aria-label'?: string;
85
+ /** Click handler */
86
+ onClick?: (event: MouseEvent) => void;
87
+ }
88
+ /**
89
+ * Options for programmatic navigation
90
+ */
91
+ interface NavigateOptions {
92
+ /** Replace current history entry instead of pushing */
93
+ replace?: boolean;
94
+ /** Scroll to top after navigation */
95
+ scroll?: boolean;
96
+ /** State data to pass to the new route */
97
+ state?: unknown;
98
+ }
99
+ /**
100
+ * Dynamic route parameters extracted from URL
101
+ */
102
+ type RouteParams<T extends string = string> = Record<T, string>;
103
+ /**
104
+ * Search params as key-value pairs
105
+ */
106
+ type SearchParams = Record<string, string | string[]>;
107
+ /**
108
+ * Route definition for automatic route generation
109
+ */
110
+ interface RouteDefinition {
111
+ /** Route path pattern (e.g., '/docs/:slug') */
112
+ path: string;
113
+ /** Dynamic import for component */
114
+ component: () => Promise<{
115
+ default: unknown;
116
+ }>;
117
+ /** Dynamic imports for layouts (in order, root first) */
118
+ layouts?: Array<() => Promise<{
119
+ default: unknown;
120
+ }>>;
121
+ /** Dynamic import for loader function */
122
+ loader?: () => Promise<{
123
+ loader: LoaderFunction;
124
+ }>;
125
+ }
126
+ /**
127
+ * Loader function signature
128
+ */
129
+ type LoaderFunction = (context: LoaderContext) => Promise<unknown> | unknown;
130
+ /**
131
+ * Context passed to loader functions
132
+ */
133
+ interface LoaderContext {
134
+ /** Route parameters */
135
+ params: RouteParams;
136
+ /** Request object (available on server) */
137
+ request?: Request;
138
+ /** URL search params */
139
+ searchParams: URLSearchParams;
140
+ }
141
+ /**
142
+ * Route match result
143
+ */
144
+ interface RouteMatch {
145
+ /** Matched route definition */
146
+ route: RouteDefinition;
147
+ /** Extracted parameters */
148
+ params: RouteParams;
149
+ /** Matched path */
150
+ pathname: string;
151
+ }
152
+
153
+ /**
154
+ * Router Context and Provider
155
+ *
156
+ * Provides routing state to the component tree.
157
+ * SSR-safe: works on both server and client.
158
+ */
159
+
160
+ /**
161
+ * Subscribe to router context changes
162
+ */
163
+ declare function subscribe(callback: (ctx: RouterContextValue) => void): () => void;
164
+ /**
165
+ * Get current router context value
166
+ */
167
+ declare function getRouterContext(): RouterContextValue;
168
+ /**
169
+ * Initialize router (call once at app start)
170
+ */
171
+ declare function initRouter(options?: {
172
+ initialPath?: string;
173
+ basePath?: string;
174
+ }): void;
175
+ /**
176
+ * React Context for router
177
+ * Only used if React is available
178
+ */
179
+ declare let RouterContext: unknown;
180
+ declare let RouterProvider: unknown;
181
+ declare let useRouter: () => RouterContextValue;
182
+
183
+ /**
184
+ * @flight-framework/router - PrefetchPageLinks Component
185
+ *
186
+ * Renders prefetch link tags for a page. Useful for proactively
187
+ * prefetching pages based on user behavior (e.g., search results).
188
+ *
189
+ * This is the Flight equivalent of React Router's PrefetchPageLinks.
190
+ */
191
+
192
+ declare let PrefetchPageLinks: unknown;
193
+ /**
194
+ * Prefetch multiple pages at once.
195
+ *
196
+ * Useful for prefetching a list of search results or related pages.
197
+ *
198
+ * @example
199
+ * ```typescript
200
+ * // Prefetch top 5 search results
201
+ * prefetchPages([
202
+ * '/products/1',
203
+ * '/products/2',
204
+ * '/products/3',
205
+ * ]);
206
+ * ```
207
+ */
208
+ declare function prefetchPages(pages: string[], options?: PrefetchOptions): void;
209
+ /**
210
+ * Prefetch a page when idle.
211
+ *
212
+ * Uses requestIdleCallback if available, otherwise falls back
213
+ * to setTimeout.
214
+ *
215
+ * @example
216
+ * ```typescript
217
+ * // Prefetch after initial render settles
218
+ * prefetchWhenIdle('/dashboard');
219
+ * ```
220
+ */
221
+ declare function prefetchWhenIdle(page: string, options?: PrefetchOptions): void;
222
+
223
+ /**
224
+ * Navigation Utilities
225
+ *
226
+ * Programmatic navigation and route matching utilities.
227
+ */
228
+
229
+ /**
230
+ * Navigate programmatically to a new path
231
+ *
232
+ * @example
233
+ * ```ts
234
+ * navigate('/docs');
235
+ * navigate('/login', { replace: true });
236
+ * navigate('/dashboard', { scroll: false, state: { from: '/home' } });
237
+ * ```
238
+ */
239
+ declare function navigate(to: string, options?: NavigateOptions): void;
240
+ /**
241
+ * Match a pathname against a route pattern
242
+ *
243
+ * @example
244
+ * ```ts
245
+ * matchRoute('/docs/routing', '/docs/:slug');
246
+ * // Returns: { params: { slug: 'routing' }, matched: true }
247
+ * ```
248
+ */
249
+ declare function matchRoute(pathname: string, pattern: string): {
250
+ matched: boolean;
251
+ params: RouteParams;
252
+ };
253
+ /**
254
+ * Parse parameters from a matched route
255
+ *
256
+ * @example
257
+ * ```ts
258
+ * parseParams('/blog/2024/my-post', '/blog/:year/:slug');
259
+ * // Returns: { year: '2024', slug: 'my-post' }
260
+ * ```
261
+ */
262
+ declare function parseParams(pathname: string, pattern: string): RouteParams;
263
+ /**
264
+ * Find the best matching route from a list of route definitions
265
+ */
266
+ declare function findRoute(pathname: string, routes: RouteDefinition[]): RouteMatch | null;
267
+ /**
268
+ * Generate a URL from a route pattern and params
269
+ *
270
+ * @example
271
+ * ```ts
272
+ * generatePath('/docs/:slug', { slug: 'routing' });
273
+ * // Returns: '/docs/routing'
274
+ * ```
275
+ */
276
+ declare function generatePath(pattern: string, params?: RouteParams): string;
277
+ /**
278
+ * Check if current path matches a pattern
279
+ */
280
+ declare function isActive(pattern: string): boolean;
281
+ /**
282
+ * Redirect to a new URL (full page navigation)
283
+ * Use this for external redirects or when you need to break out of SPA
284
+ */
285
+ declare function redirect(url: string): never;
286
+
287
+ /**
288
+ * @flight-framework/router - Prefetch Utilities
289
+ *
290
+ * Universal prefetch system for Flight Framework.
291
+ * Works across all UI frameworks and runtimes.
292
+ *
293
+ * Features:
294
+ * - Multiple prefetch strategies (intent, render, viewport)
295
+ * - Priority-based prefetching
296
+ * - Module and data prefetching
297
+ * - IntersectionObserver for viewport detection
298
+ * - SSR-safe implementation
299
+ */
300
+
301
+ /**
302
+ * Prefetch a URL with the specified options.
303
+ *
304
+ * This is the main programmatic prefetch API for Flight Framework.
305
+ * It creates appropriate link elements for prefetching resources.
306
+ *
307
+ * @param href - The URL to prefetch
308
+ * @param options - Prefetch configuration options
309
+ *
310
+ * @example
311
+ * ```typescript
312
+ * // Basic prefetch
313
+ * prefetch('/docs');
314
+ *
315
+ * // High priority prefetch (for critical navigation paths)
316
+ * prefetch('/checkout', { priority: 'high' });
317
+ *
318
+ * // Prefetch with data loaders
319
+ * prefetch('/products', { includeData: true });
320
+ * ```
321
+ */
322
+ declare function prefetch(href: string, options?: PrefetchOptions): void;
323
+ /**
324
+ * Prefetch multiple URLs at once.
325
+ *
326
+ * @param hrefs - Array of URLs to prefetch
327
+ * @param options - Prefetch configuration options
328
+ */
329
+ declare function prefetchAll(hrefs: string[], options?: PrefetchOptions): void;
330
+ /**
331
+ * Check if a URL has been prefetched.
332
+ *
333
+ * @param href - The URL to check
334
+ * @returns True if the URL has been prefetched
335
+ */
336
+ declare function isPrefetched(href: string): boolean;
337
+ /**
338
+ * Clear all prefetch state (useful for testing or memory management).
339
+ */
340
+ declare function clearPrefetchCache(): void;
341
+ /**
342
+ * Observe an element for viewport entry and trigger prefetch.
343
+ *
344
+ * @param element - The link element to observe
345
+ * @param href - The URL to prefetch when visible
346
+ * @returns Cleanup function to stop observing
347
+ */
348
+ declare function observeForPrefetch(element: Element, href: string): () => void;
349
+ /**
350
+ * Setup intent-based prefetching for an element.
351
+ * Prefetches on mouseenter or focus.
352
+ *
353
+ * @param element - The link element
354
+ * @param href - The URL to prefetch
355
+ * @returns Cleanup function to remove listeners
356
+ */
357
+ declare function setupIntentPrefetch(element: HTMLElement, href: string): () => void;
358
+
359
+ export { prefetchWhenIdle as A, getRouterContext as B, subscribe as C, initRouter as D, type LinkProps as L, type NavigateOptions as N, type PrefetchStrategy as P, type RouteParams as R, type SearchParams as S, type RouterContextValue as a, type RouterProviderProps as b, type PrefetchPriority as c, type PrefetchOptions as d, type RouteDefinition as e, type LoaderFunction as f, type LoaderContext as g, type RouteMatch as h, RouterContext as i, RouterProvider as j, PrefetchPageLinks as k, findRoute as l, matchRoute as m, navigate as n, generatePath as o, parseParams as p, isActive as q, redirect as r, prefetch as s, prefetchAll as t, useRouter as u, isPrefetched as v, clearPrefetchCache as w, observeForPrefetch as x, setupIntentPrefetch as y, prefetchPages as z };
@@ -0,0 +1,113 @@
1
+ import { L as LinkProps, b as RouterProviderProps, a as RouterContextValue, R as RouteParams } from '../prefetch-CMmeei6-.js';
2
+ export { g as LoaderContext, f as LoaderFunction, N as NavigateOptions, d as PrefetchOptions, c as PrefetchPriority, P as PrefetchStrategy, e as RouteDefinition, h as RouteMatch, S as SearchParams, w as clearPrefetchCache, l as findRoute, o as generatePath, B as getRouterContext, D as initRouter, q as isActive, v as isPrefetched, m as matchRoute, n as navigate, x as observeForPrefetch, p as parseParams, s as prefetch, t as prefetchAll, z as prefetchPages, A as prefetchWhenIdle, r as redirect, y as setupIntentPrefetch, C as subscribe } from '../prefetch-CMmeei6-.js';
3
+ import React from 'react';
4
+
5
+ /**
6
+ * React Link Component
7
+ *
8
+ * Provides client-side navigation with prefetching support.
9
+ * Properly imports React for SSR compatibility.
10
+ */
11
+
12
+ /**
13
+ * Flight Link Component for React
14
+ *
15
+ * A drop-in replacement for `<a>` that enables SPA navigation
16
+ * with optional prefetching strategies.
17
+ *
18
+ * @example
19
+ * ```tsx
20
+ * // Basic usage
21
+ * <Link href="/docs">Documentation</Link>
22
+ *
23
+ * // With prefetch on hover/focus (recommended)
24
+ * <Link href="/docs" prefetch="intent">Docs</Link>
25
+ *
26
+ * // Prefetch immediately when link renders
27
+ * <Link href="/checkout" prefetch="render">Checkout</Link>
28
+ *
29
+ * // Prefetch when link enters viewport (good for mobile)
30
+ * <Link href="/products" prefetch="viewport">Products</Link>
31
+ * ```
32
+ */
33
+ declare function Link({ href, children, className, target, rel, prefetch: prefetchProp, replace, scroll, onClick, 'aria-label': ariaLabel, ...props }: LinkProps): React.ReactElement;
34
+
35
+ /**
36
+ * React Router Provider
37
+ *
38
+ * Provides routing context to React component tree.
39
+ * Properly imports React for SSR compatibility.
40
+ */
41
+
42
+ /**
43
+ * React Context for router
44
+ */
45
+ declare const RouterContext: React.Context<RouterContextValue>;
46
+ /**
47
+ * Hook to access router context
48
+ */
49
+ declare function useRouter(): RouterContextValue;
50
+ /**
51
+ * React Router Provider
52
+ *
53
+ * Wraps your app to provide routing context.
54
+ *
55
+ * @example
56
+ * ```tsx
57
+ * import { RouterProvider } from '@flight-framework/router/react';
58
+ *
59
+ * function App() {
60
+ * return (
61
+ * <RouterProvider initialPath="/">
62
+ * <YourApp />
63
+ * </RouterProvider>
64
+ * );
65
+ * }
66
+ * ```
67
+ */
68
+ declare function RouterProvider({ children, initialPath, basePath }: RouterProviderProps): React.ReactElement;
69
+
70
+ /**
71
+ * Hook to get current pathname
72
+ *
73
+ * Uses React 18+ useSyncExternalStore for optimal performance.
74
+ *
75
+ * @example
76
+ * ```tsx
77
+ * function Component() {
78
+ * const pathname = usePathname();
79
+ * return <div>Current path: {pathname}</div>;
80
+ * }
81
+ * ```
82
+ */
83
+ declare function usePathname(): string;
84
+ /**
85
+ * Hook to get current search params
86
+ *
87
+ * @example
88
+ * ```tsx
89
+ * function Component() {
90
+ * const searchParams = useSearchParams();
91
+ * const page = searchParams.get('page') || '1';
92
+ * return <div>Page: {page}</div>;
93
+ * }
94
+ * ```
95
+ */
96
+ declare function useSearchParams(): URLSearchParams;
97
+ /**
98
+ * Hook to get route params
99
+ *
100
+ * Note: For dynamic routes like /blog/[slug], the params
101
+ * must be extracted from the pathname using pattern matching.
102
+ *
103
+ * @example
104
+ * ```tsx
105
+ * function BlogPost() {
106
+ * const params = useParams();
107
+ * return <div>Post: {params.slug}</div>;
108
+ * }
109
+ * ```
110
+ */
111
+ declare function useParams(): RouteParams;
112
+
113
+ export { Link, LinkProps, RouteParams, RouterContext, RouterContextValue, RouterProvider, RouterProviderProps, useParams, usePathname, useRouter, useSearchParams };
@@ -0,0 +1,245 @@
1
+ import {
2
+ clearPrefetchCache,
3
+ findRoute,
4
+ generatePath,
5
+ getRouterContext,
6
+ initRouter,
7
+ isActive,
8
+ isPrefetched,
9
+ matchRoute,
10
+ navigate,
11
+ observeForPrefetch,
12
+ parseParams,
13
+ prefetch,
14
+ prefetchAll,
15
+ prefetchPages,
16
+ prefetchWhenIdle,
17
+ redirect,
18
+ setupIntentPrefetch,
19
+ subscribe
20
+ } from "../chunk-MO2HMSZH.js";
21
+
22
+ // src/react/Link.tsx
23
+ import { useCallback, useEffect, useRef } from "react";
24
+ import { jsx } from "react/jsx-runtime";
25
+ var isBrowser = typeof window !== "undefined";
26
+ function isExternalUrl(href) {
27
+ if (!href) return false;
28
+ return href.startsWith("http://") || href.startsWith("https://") || href.startsWith("//") || href.startsWith("mailto:") || href.startsWith("tel:") || href.startsWith("javascript:") || href.startsWith("#");
29
+ }
30
+ function normalizePrefetchStrategy(prefetchProp) {
31
+ if (prefetchProp === true) return "intent";
32
+ if (prefetchProp === false || prefetchProp === void 0) return "none";
33
+ return prefetchProp;
34
+ }
35
+ function handleLinkClick(href, options, event) {
36
+ if (event && (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey)) {
37
+ return;
38
+ }
39
+ if (event && event.button !== 0) {
40
+ return;
41
+ }
42
+ event?.preventDefault();
43
+ const { navigate: navigate2 } = getRouterContext();
44
+ navigate2(href, options);
45
+ }
46
+ function Link({
47
+ href,
48
+ children,
49
+ className,
50
+ target,
51
+ rel,
52
+ prefetch: prefetchProp = "none",
53
+ replace = false,
54
+ scroll = true,
55
+ onClick,
56
+ "aria-label": ariaLabel,
57
+ ...props
58
+ }) {
59
+ const linkRef = useRef(null);
60
+ const isExternal = isExternalUrl(href);
61
+ const prefetchStrategy = normalizePrefetchStrategy(prefetchProp);
62
+ const handleClick = useCallback(
63
+ (e) => {
64
+ if (onClick) {
65
+ onClick(e);
66
+ if (e.defaultPrevented) return;
67
+ }
68
+ if (isExternal || target === "_blank") return;
69
+ handleLinkClick(href, { replace, scroll }, e);
70
+ },
71
+ [href, isExternal, target, replace, scroll, onClick]
72
+ );
73
+ useEffect(() => {
74
+ if (isExternal || !isBrowser || prefetchStrategy === "none") {
75
+ return;
76
+ }
77
+ const link = linkRef.current;
78
+ if (!link) return;
79
+ switch (prefetchStrategy) {
80
+ case "render":
81
+ prefetch(href, { priority: "low" });
82
+ break;
83
+ case "viewport":
84
+ return observeForPrefetch(link, href);
85
+ case "intent":
86
+ default:
87
+ return setupIntentPrefetch(link, href);
88
+ }
89
+ }, [href, prefetchStrategy, isExternal]);
90
+ const computedRel = isExternal && target === "_blank" ? rel || "noopener noreferrer" : rel;
91
+ return /* @__PURE__ */ jsx(
92
+ "a",
93
+ {
94
+ ref: linkRef,
95
+ href,
96
+ className,
97
+ target,
98
+ rel: computedRel,
99
+ "aria-label": ariaLabel,
100
+ onClick: handleClick,
101
+ ...props,
102
+ children
103
+ }
104
+ );
105
+ }
106
+
107
+ // src/react/RouterProvider.tsx
108
+ import { createContext, useContext, useState, useEffect as useEffect2 } from "react";
109
+ import { jsx as jsx2 } from "react/jsx-runtime";
110
+ var isBrowser2 = typeof window !== "undefined";
111
+ function navigateTo(to, options = {}) {
112
+ if (!isBrowser2) return;
113
+ const { replace = false, scroll = true, state } = options;
114
+ if (replace) {
115
+ window.history.replaceState(state ?? null, "", to);
116
+ } else {
117
+ window.history.pushState(state ?? null, "", to);
118
+ }
119
+ if (scroll) {
120
+ window.scrollTo({ top: 0, left: 0, behavior: "instant" });
121
+ }
122
+ }
123
+ var defaultContext = {
124
+ path: "/",
125
+ searchParams: new URLSearchParams(),
126
+ navigate: navigateTo,
127
+ back: () => isBrowser2 && window.history.back(),
128
+ forward: () => isBrowser2 && window.history.forward()
129
+ };
130
+ var RouterContext = createContext(defaultContext);
131
+ function useRouter() {
132
+ return useContext(RouterContext);
133
+ }
134
+ function RouterProvider({
135
+ children,
136
+ initialPath,
137
+ basePath = ""
138
+ }) {
139
+ const [routerState, setRouterState] = useState(() => {
140
+ const path = isBrowser2 ? window.location.pathname : initialPath || "/";
141
+ const searchParams = isBrowser2 ? new URLSearchParams(window.location.search) : new URLSearchParams();
142
+ let normalizedPath = path;
143
+ if (basePath && path.startsWith(basePath)) {
144
+ normalizedPath = path.slice(basePath.length) || "/";
145
+ }
146
+ return {
147
+ path: normalizedPath,
148
+ searchParams,
149
+ navigate: navigateTo,
150
+ back: () => isBrowser2 && window.history.back(),
151
+ forward: () => isBrowser2 && window.history.forward()
152
+ };
153
+ });
154
+ useEffect2(() => {
155
+ if (!isBrowser2) return;
156
+ const handlePopState = () => {
157
+ let path = window.location.pathname;
158
+ if (basePath && path.startsWith(basePath)) {
159
+ path = path.slice(basePath.length) || "/";
160
+ }
161
+ setRouterState((prev) => ({
162
+ ...prev,
163
+ path,
164
+ searchParams: new URLSearchParams(window.location.search)
165
+ }));
166
+ };
167
+ window.addEventListener("popstate", handlePopState);
168
+ return () => window.removeEventListener("popstate", handlePopState);
169
+ }, [basePath]);
170
+ useEffect2(() => {
171
+ return subscribe((ctx) => {
172
+ let path = ctx.path;
173
+ if (basePath && path.startsWith(basePath)) {
174
+ path = path.slice(basePath.length) || "/";
175
+ }
176
+ setRouterState((prev) => ({
177
+ ...prev,
178
+ path,
179
+ searchParams: ctx.searchParams
180
+ }));
181
+ });
182
+ }, [basePath]);
183
+ return /* @__PURE__ */ jsx2(RouterContext.Provider, { value: routerState, children });
184
+ }
185
+
186
+ // src/react/hooks.ts
187
+ import { useContext as useContext2, useSyncExternalStore } from "react";
188
+ var isBrowser3 = typeof window !== "undefined";
189
+ function getPathnameSnapshot() {
190
+ return isBrowser3 ? window.location.pathname : "/";
191
+ }
192
+ function getPathnameServerSnapshot() {
193
+ return "/";
194
+ }
195
+ function subscribeToPathname(callback) {
196
+ if (!isBrowser3) return () => {
197
+ };
198
+ window.addEventListener("popstate", callback);
199
+ const unsubscribe = subscribe(callback);
200
+ return () => {
201
+ window.removeEventListener("popstate", callback);
202
+ unsubscribe();
203
+ };
204
+ }
205
+ function usePathname() {
206
+ return useSyncExternalStore(
207
+ subscribeToPathname,
208
+ getPathnameSnapshot,
209
+ getPathnameServerSnapshot
210
+ );
211
+ }
212
+ function useSearchParams() {
213
+ const { searchParams } = useContext2(RouterContext);
214
+ return searchParams;
215
+ }
216
+ function useParams() {
217
+ return {};
218
+ }
219
+ export {
220
+ Link,
221
+ RouterContext,
222
+ RouterProvider,
223
+ clearPrefetchCache,
224
+ findRoute,
225
+ generatePath,
226
+ getRouterContext,
227
+ initRouter,
228
+ isActive,
229
+ isPrefetched,
230
+ matchRoute,
231
+ navigate,
232
+ observeForPrefetch,
233
+ parseParams,
234
+ prefetch,
235
+ prefetchAll,
236
+ prefetchPages,
237
+ prefetchWhenIdle,
238
+ redirect,
239
+ setupIntentPrefetch,
240
+ subscribe,
241
+ useParams,
242
+ usePathname,
243
+ useRouter,
244
+ useSearchParams
245
+ };