@flightdev/router 0.4.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/LICENSE +21 -0
- package/README.md +488 -0
- package/dist/index.d.ts +95 -0
- package/dist/index.js +765 -0
- package/dist/preact/index.d.ts +77 -0
- package/dist/preact/index.js +654 -0
- package/dist/prefetch-DRp54Q7z.d.ts +373 -0
- package/dist/react/index.d.ts +116 -0
- package/dist/react/index.js +696 -0
- package/dist/solid/index.d.ts +107 -0
- package/dist/solid/index.js +625 -0
- package/dist/svelte/index.d.ts +118 -0
- package/dist/svelte/index.js +595 -0
- package/dist/vue/index.d.ts +147 -0
- package/dist/vue/index.js +658 -0
- package/package.json +95 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024-2026 Flight Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,488 @@
|
|
|
1
|
+
# @flight-framework/router
|
|
2
|
+
|
|
3
|
+
Universal client-side routing primitives for Flight Framework. Zero external dependencies. Works with any UI framework.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Features](#features)
|
|
8
|
+
- [Installation](#installation)
|
|
9
|
+
- [Quick Start](#quick-start)
|
|
10
|
+
- [Prefetch Strategies](#prefetch-strategies)
|
|
11
|
+
- [Smart Prefetching](#smart-prefetching)
|
|
12
|
+
- [Intercepting Routes](#intercepting-routes)
|
|
13
|
+
- [Programmatic Prefetching](#programmatic-prefetching)
|
|
14
|
+
- [Prefetch Queue](#prefetch-queue)
|
|
15
|
+
- [React Hooks](#react-hooks)
|
|
16
|
+
- [Programmatic Navigation](#programmatic-navigation)
|
|
17
|
+
- [Route Matching](#route-matching)
|
|
18
|
+
- [Link Component](#link-component)
|
|
19
|
+
- [Framework Integration](#framework-integration)
|
|
20
|
+
- [SSR Support](#ssr-support)
|
|
21
|
+
- [Browser Support](#browser-support)
|
|
22
|
+
- [License](#license)
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Features
|
|
27
|
+
|
|
28
|
+
- Multiple prefetch strategies (none, intent, render, viewport, idle)
|
|
29
|
+
- Network-aware smart prefetching (respects Save-Data and connection speed)
|
|
30
|
+
- Intercepting routes with modal support
|
|
31
|
+
- Prefetch queue with concurrency control
|
|
32
|
+
- SSR-safe implementation
|
|
33
|
+
- Framework-agnostic with React adapters
|
|
34
|
+
- TypeScript-first design
|
|
35
|
+
- IntersectionObserver for viewport prefetching
|
|
36
|
+
- Zero external dependencies
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Installation
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
npm install @flight-framework/router
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Quick Start
|
|
49
|
+
|
|
50
|
+
### With React
|
|
51
|
+
|
|
52
|
+
```tsx
|
|
53
|
+
import { RouterProvider, Link, useRouter } from '@flight-framework/router';
|
|
54
|
+
|
|
55
|
+
function App() {
|
|
56
|
+
return (
|
|
57
|
+
<RouterProvider initialPath={url}>
|
|
58
|
+
<Navigation />
|
|
59
|
+
<Content />
|
|
60
|
+
</RouterProvider>
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function Navigation() {
|
|
65
|
+
return (
|
|
66
|
+
<nav>
|
|
67
|
+
<Link href="/">Home</Link>
|
|
68
|
+
<Link href="/docs" prefetch="intent">Docs</Link>
|
|
69
|
+
<Link href="/about">About</Link>
|
|
70
|
+
</nav>
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function Content() {
|
|
75
|
+
const { path, navigate } = useRouter();
|
|
76
|
+
|
|
77
|
+
return (
|
|
78
|
+
<main>
|
|
79
|
+
<p>Current path: {path}</p>
|
|
80
|
+
<button onClick={() => navigate('/dashboard')}>
|
|
81
|
+
Go to Dashboard
|
|
82
|
+
</button>
|
|
83
|
+
</main>
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Prefetch Strategies
|
|
91
|
+
|
|
92
|
+
Flight Router supports multiple prefetch strategies to optimize navigation performance:
|
|
93
|
+
|
|
94
|
+
| Strategy | Behavior | Best For |
|
|
95
|
+
|----------|----------|----------|
|
|
96
|
+
| `'none'` | No prefetching (default) | Low-priority links |
|
|
97
|
+
| `'intent'` | Prefetch on hover/focus | Most navigation links |
|
|
98
|
+
| `'render'` | Prefetch immediately | Critical paths (checkout) |
|
|
99
|
+
| `'viewport'` | Prefetch when visible | Mobile, infinite scroll |
|
|
100
|
+
| `'idle'` | Prefetch when browser is idle | Background preloading |
|
|
101
|
+
|
|
102
|
+
### Usage Examples
|
|
103
|
+
|
|
104
|
+
```tsx
|
|
105
|
+
// No prefetching (default)
|
|
106
|
+
<Link href="/docs">Docs</Link>
|
|
107
|
+
<Link href="/docs" prefetch="none">Docs</Link>
|
|
108
|
+
|
|
109
|
+
// Prefetch on hover/focus (recommended for most cases)
|
|
110
|
+
<Link href="/docs" prefetch="intent">Docs</Link>
|
|
111
|
+
<Link href="/docs" prefetch>Docs</Link> // boolean true = "intent"
|
|
112
|
+
|
|
113
|
+
// Prefetch immediately when link renders
|
|
114
|
+
<Link href="/checkout" prefetch="render">Checkout</Link>
|
|
115
|
+
|
|
116
|
+
// Prefetch when link enters viewport (good for mobile)
|
|
117
|
+
<Link href="/products" prefetch="viewport">Products</Link>
|
|
118
|
+
|
|
119
|
+
// Prefetch when browser is idle
|
|
120
|
+
<Link href="/settings" prefetch="idle">Settings</Link>
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## Smart Prefetching
|
|
126
|
+
|
|
127
|
+
Network-aware prefetching that respects user preferences and connection quality.
|
|
128
|
+
|
|
129
|
+
### Features
|
|
130
|
+
|
|
131
|
+
- Respects `Save-Data` header (users on limited data plans)
|
|
132
|
+
- Detects connection type (2G, 3G, 4G)
|
|
133
|
+
- Configurable minimum network requirements
|
|
134
|
+
- Automatic throttling on slow connections
|
|
135
|
+
|
|
136
|
+
### API
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
import {
|
|
140
|
+
smartPrefetch,
|
|
141
|
+
shouldSkipPrefetch,
|
|
142
|
+
canPrefetchOnNetwork,
|
|
143
|
+
} from '@flight-framework/router';
|
|
144
|
+
|
|
145
|
+
// Respects network conditions automatically
|
|
146
|
+
smartPrefetch('/dashboard');
|
|
147
|
+
|
|
148
|
+
// Check if prefetching should be skipped
|
|
149
|
+
if (shouldSkipPrefetch()) {
|
|
150
|
+
console.log('Skipping due to network conditions');
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Custom network requirements
|
|
154
|
+
const canPrefetch = canPrefetchOnNetwork({
|
|
155
|
+
respectSaveData: true, // Skip if Save-Data enabled
|
|
156
|
+
respectSlowNetwork: true, // Skip on 2G/slow-2G
|
|
157
|
+
minEffectiveType: '3g', // Minimum 3G required
|
|
158
|
+
});
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Configuration
|
|
162
|
+
|
|
163
|
+
```typescript
|
|
164
|
+
smartPrefetch('/page', {
|
|
165
|
+
respectSaveData: true, // Default: true
|
|
166
|
+
respectSlowNetwork: true, // Default: true
|
|
167
|
+
minEffectiveType: '3g', // Default: '3g'
|
|
168
|
+
priority: 'high', // Optional priority override
|
|
169
|
+
});
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
## Intercepting Routes
|
|
175
|
+
|
|
176
|
+
Render routes in modals while preserving URL state. Perfect for photo galleries, user profiles, and detail views.
|
|
177
|
+
|
|
178
|
+
### React Integration
|
|
179
|
+
|
|
180
|
+
```tsx
|
|
181
|
+
import {
|
|
182
|
+
InterceptedRouteProvider,
|
|
183
|
+
useInterceptedRoute,
|
|
184
|
+
} from '@flight-framework/router';
|
|
185
|
+
|
|
186
|
+
// Wrap your layout
|
|
187
|
+
function RootLayout({ children }) {
|
|
188
|
+
return (
|
|
189
|
+
<InterceptedRouteProvider>
|
|
190
|
+
{children}
|
|
191
|
+
<ModalRenderer />
|
|
192
|
+
</InterceptedRouteProvider>
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Render intercepted content in a modal
|
|
197
|
+
function ModalRenderer() {
|
|
198
|
+
const intercepted = useInterceptedRoute();
|
|
199
|
+
|
|
200
|
+
if (!intercepted) return null;
|
|
201
|
+
|
|
202
|
+
return (
|
|
203
|
+
<Dialog open onClose={intercepted.dismiss}>
|
|
204
|
+
<intercepted.Component />
|
|
205
|
+
<button onClick={intercepted.navigateToPage}>
|
|
206
|
+
View Full Page
|
|
207
|
+
</button>
|
|
208
|
+
</Dialog>
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Intercepted Route State
|
|
214
|
+
|
|
215
|
+
| Property | Type | Description |
|
|
216
|
+
|----------|------|-------------|
|
|
217
|
+
| `Component` | `() => unknown` | The component to render |
|
|
218
|
+
| `pathname` | `string` | The intercepted URL path |
|
|
219
|
+
| `params` | `Record<string, string>` | Route parameters |
|
|
220
|
+
| `dismiss()` | `() => void` | Go back (close modal) |
|
|
221
|
+
| `navigateToPage()` | `() => void` | Navigate to actual page |
|
|
222
|
+
|
|
223
|
+
### Additional Hooks
|
|
224
|
+
|
|
225
|
+
```typescript
|
|
226
|
+
import {
|
|
227
|
+
useInterceptedRoute,
|
|
228
|
+
useSetInterceptedRoute,
|
|
229
|
+
useIsIntercepting,
|
|
230
|
+
} from '@flight-framework/router';
|
|
231
|
+
|
|
232
|
+
// Check if currently intercepting
|
|
233
|
+
const isIntercepting = useIsIntercepting();
|
|
234
|
+
|
|
235
|
+
// Programmatically set intercepted state (for router integration)
|
|
236
|
+
const setIntercepted = useSetInterceptedRoute();
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
## Programmatic Prefetching
|
|
242
|
+
|
|
243
|
+
```typescript
|
|
244
|
+
import {
|
|
245
|
+
prefetch,
|
|
246
|
+
prefetchAll,
|
|
247
|
+
prefetchWhenIdle,
|
|
248
|
+
isPrefetched,
|
|
249
|
+
clearPrefetchCache,
|
|
250
|
+
} from '@flight-framework/router';
|
|
251
|
+
|
|
252
|
+
// Basic prefetch
|
|
253
|
+
prefetch('/docs');
|
|
254
|
+
|
|
255
|
+
// High priority prefetch
|
|
256
|
+
prefetch('/checkout', { priority: 'high' });
|
|
257
|
+
|
|
258
|
+
// Prefetch with data loaders
|
|
259
|
+
prefetch('/products', { includeData: true });
|
|
260
|
+
|
|
261
|
+
// Prefetch multiple pages
|
|
262
|
+
prefetchAll(['/page1', '/page2', '/page3']);
|
|
263
|
+
|
|
264
|
+
// Prefetch when browser is idle
|
|
265
|
+
prefetchWhenIdle('/dashboard');
|
|
266
|
+
|
|
267
|
+
// Check if already prefetched
|
|
268
|
+
if (!isPrefetched('/docs')) {
|
|
269
|
+
prefetch('/docs');
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// Clear prefetch cache (useful for testing)
|
|
273
|
+
clearPrefetchCache();
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
---
|
|
277
|
+
|
|
278
|
+
## Prefetch Queue
|
|
279
|
+
|
|
280
|
+
Control concurrent prefetch requests to avoid overwhelming the network:
|
|
281
|
+
|
|
282
|
+
```typescript
|
|
283
|
+
import { PrefetchQueue } from '@flight-framework/router';
|
|
284
|
+
|
|
285
|
+
// Create queue with max 3 concurrent prefetches
|
|
286
|
+
const queue = new PrefetchQueue(3);
|
|
287
|
+
|
|
288
|
+
// Add URLs to queue
|
|
289
|
+
queue.add('/page1');
|
|
290
|
+
queue.add('/page2', { priority: 'high' });
|
|
291
|
+
queue.addAll(['/page3', '/page4', '/page5']);
|
|
292
|
+
|
|
293
|
+
// Control queue
|
|
294
|
+
queue.pause(); // Stop processing
|
|
295
|
+
queue.resume(); // Continue processing
|
|
296
|
+
queue.clear(); // Remove pending items
|
|
297
|
+
|
|
298
|
+
// Check state
|
|
299
|
+
console.log(queue.pending); // Items waiting
|
|
300
|
+
console.log(queue.activeCount); // Currently prefetching
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
---
|
|
304
|
+
|
|
305
|
+
## React Hooks
|
|
306
|
+
|
|
307
|
+
```tsx
|
|
308
|
+
import {
|
|
309
|
+
useRouter,
|
|
310
|
+
useParams,
|
|
311
|
+
useSearchParams,
|
|
312
|
+
usePathname,
|
|
313
|
+
} from '@flight-framework/router';
|
|
314
|
+
|
|
315
|
+
// Get current path and navigation functions
|
|
316
|
+
const { path, searchParams, navigate, back, forward } = useRouter();
|
|
317
|
+
|
|
318
|
+
// Get route parameters (from dynamic routes like [slug])
|
|
319
|
+
const { slug } = useParams<{ slug: string }>();
|
|
320
|
+
|
|
321
|
+
// Get and set search params
|
|
322
|
+
const [searchParams, setSearchParams] = useSearchParams();
|
|
323
|
+
|
|
324
|
+
// Get current pathname
|
|
325
|
+
const pathname = usePathname();
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
---
|
|
329
|
+
|
|
330
|
+
## Programmatic Navigation
|
|
331
|
+
|
|
332
|
+
```typescript
|
|
333
|
+
import { navigate, prefetch } from '@flight-framework/router';
|
|
334
|
+
|
|
335
|
+
// Navigate to a path
|
|
336
|
+
navigate('/docs');
|
|
337
|
+
|
|
338
|
+
// Replace history instead of push
|
|
339
|
+
navigate('/login', { replace: true });
|
|
340
|
+
|
|
341
|
+
// Navigate without scrolling to top
|
|
342
|
+
navigate('/next-page', { scroll: false });
|
|
343
|
+
|
|
344
|
+
// Pass state data
|
|
345
|
+
navigate('/dashboard', { state: { from: '/login' } });
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
---
|
|
349
|
+
|
|
350
|
+
## Route Matching
|
|
351
|
+
|
|
352
|
+
```typescript
|
|
353
|
+
import { matchRoute, parseParams, generatePath } from '@flight-framework/router';
|
|
354
|
+
|
|
355
|
+
// Check if a path matches a pattern
|
|
356
|
+
const { matched, params } = matchRoute('/docs/routing', '/docs/:slug');
|
|
357
|
+
// matched: true, params: { slug: 'routing' }
|
|
358
|
+
|
|
359
|
+
// Parse params from a path
|
|
360
|
+
const params = parseParams('/blog/2024/my-post', '/blog/:year/:slug');
|
|
361
|
+
// { year: '2024', slug: 'my-post' }
|
|
362
|
+
|
|
363
|
+
// Generate a path from pattern and params
|
|
364
|
+
const path = generatePath('/docs/:slug', { slug: 'api-routes' });
|
|
365
|
+
// '/docs/api-routes'
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
---
|
|
369
|
+
|
|
370
|
+
## Link Component
|
|
371
|
+
|
|
372
|
+
### Props
|
|
373
|
+
|
|
374
|
+
| Prop | Type | Default | Description |
|
|
375
|
+
|------|------|---------|-------------|
|
|
376
|
+
| `href` | `string` | required | Target URL path |
|
|
377
|
+
| `prefetch` | `boolean \| PrefetchStrategy` | `'none'` | Prefetch strategy |
|
|
378
|
+
| `replace` | `boolean` | `false` | Replace history entry |
|
|
379
|
+
| `scroll` | `boolean` | `true` | Scroll to top on navigate |
|
|
380
|
+
| `target` | `string` | - | Link target (_blank, etc) |
|
|
381
|
+
| `className` | `string` | - | CSS class |
|
|
382
|
+
| `aria-label` | `string` | - | Accessibility label |
|
|
383
|
+
|
|
384
|
+
### PrefetchPageLinks Component
|
|
385
|
+
|
|
386
|
+
For proactive prefetching based on user behavior:
|
|
387
|
+
|
|
388
|
+
```tsx
|
|
389
|
+
import { PrefetchPageLinks } from '@flight-framework/router';
|
|
390
|
+
|
|
391
|
+
function SearchResults({ results }) {
|
|
392
|
+
return (
|
|
393
|
+
<>
|
|
394
|
+
{results.map(result => (
|
|
395
|
+
<div key={result.id}>
|
|
396
|
+
<PrefetchPageLinks page={result.url} />
|
|
397
|
+
<Link href={result.url}>{result.title}</Link>
|
|
398
|
+
</div>
|
|
399
|
+
))}
|
|
400
|
+
</>
|
|
401
|
+
);
|
|
402
|
+
}
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
---
|
|
406
|
+
|
|
407
|
+
## Framework Integration
|
|
408
|
+
|
|
409
|
+
### Vue
|
|
410
|
+
|
|
411
|
+
```vue
|
|
412
|
+
<script setup>
|
|
413
|
+
import { useLinkProps } from '@flight-framework/router';
|
|
414
|
+
|
|
415
|
+
const docsLink = useLinkProps('/docs', { prefetch: 'intent' });
|
|
416
|
+
</script>
|
|
417
|
+
|
|
418
|
+
<template>
|
|
419
|
+
<a v-bind="docsLink">Documentation</a>
|
|
420
|
+
</template>
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
### Vanilla JavaScript
|
|
424
|
+
|
|
425
|
+
```typescript
|
|
426
|
+
import { createLink, prefetch } from '@flight-framework/router';
|
|
427
|
+
|
|
428
|
+
const link = createLink({
|
|
429
|
+
href: '/docs',
|
|
430
|
+
children: 'Documentation',
|
|
431
|
+
prefetch: 'intent',
|
|
432
|
+
});
|
|
433
|
+
|
|
434
|
+
document.body.appendChild(link);
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
---
|
|
438
|
+
|
|
439
|
+
## SSR Support
|
|
440
|
+
|
|
441
|
+
The router is SSR-safe. Pass the initial path from your server:
|
|
442
|
+
|
|
443
|
+
```tsx
|
|
444
|
+
// entry-server.tsx
|
|
445
|
+
export function render(url: string) {
|
|
446
|
+
return renderToString(
|
|
447
|
+
<RouterProvider initialPath={url}>
|
|
448
|
+
<App />
|
|
449
|
+
</RouterProvider>
|
|
450
|
+
);
|
|
451
|
+
}
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
---
|
|
455
|
+
|
|
456
|
+
## Browser Support
|
|
457
|
+
|
|
458
|
+
| Feature | Chrome | Firefox | Safari | Edge |
|
|
459
|
+
|---------|--------|---------|--------|------|
|
|
460
|
+
| Prefetch | All | All | All | All |
|
|
461
|
+
| Viewport (IntersectionObserver) | 51+ | 55+ | 12.1+ | 15+ |
|
|
462
|
+
| Network Information API | 61+ | No | No | 79+ |
|
|
463
|
+
| requestIdleCallback | 47+ | 55+ | No | 79+ |
|
|
464
|
+
| fetchPriority | 101+ | No | No | 101+ |
|
|
465
|
+
|
|
466
|
+
Features gracefully degrade when APIs are unavailable.
|
|
467
|
+
|
|
468
|
+
---
|
|
469
|
+
|
|
470
|
+
## TypeScript
|
|
471
|
+
|
|
472
|
+
Full TypeScript support with exported types:
|
|
473
|
+
|
|
474
|
+
```typescript
|
|
475
|
+
import type {
|
|
476
|
+
PrefetchStrategy,
|
|
477
|
+
PrefetchOptions,
|
|
478
|
+
SmartPrefetchOptions,
|
|
479
|
+
InterceptedRouteState,
|
|
480
|
+
InterceptedRouteContextValue,
|
|
481
|
+
} from '@flight-framework/router';
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
---
|
|
485
|
+
|
|
486
|
+
## License
|
|
487
|
+
|
|
488
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { L as LinkProps, R as RouteParams, S as SearchParams } from './prefetch-DRp54Q7z.js';
|
|
2
|
+
export { g as LoaderContext, f as LoaderFunction, N as NavigateOptions, d as PrefetchOptions, k as PrefetchPageLinks, c as PrefetchPriority, P as PrefetchStrategy, e as RouteDefinition, h as RouteMatch, i as RouterContext, a as RouterContextValue, j as RouterProvider, b as RouterProviderProps, w as clearPrefetchCache, l as findRoute, o as generatePath, 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, u as useRouter } from './prefetch-DRp54Q7z.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @flightdev/router - Link Component
|
|
6
|
+
*
|
|
7
|
+
* Universal client-side navigation link with advanced prefetching support.
|
|
8
|
+
* Works with React, Vue, Svelte, Solid, and vanilla JavaScript.
|
|
9
|
+
*
|
|
10
|
+
* Features:
|
|
11
|
+
* - Multiple prefetch strategies (none, intent, render, viewport)
|
|
12
|
+
* - SSR-safe implementation
|
|
13
|
+
* - Accessibility compliant
|
|
14
|
+
* - Framework-agnostic core with React adapter
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @deprecated Use `prefetch` from '@flightdev/router' instead.
|
|
19
|
+
*/
|
|
20
|
+
declare function prefetchRoute(href: string): void;
|
|
21
|
+
declare let Link: unknown;
|
|
22
|
+
/**
|
|
23
|
+
* Create a link element with SPA navigation support (vanilla JS).
|
|
24
|
+
*
|
|
25
|
+
* For Vue, Svelte, Solid, and other frameworks, use this function
|
|
26
|
+
* or implement framework-specific wrappers.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```typescript
|
|
30
|
+
* const link = createLink({
|
|
31
|
+
* href: '/docs',
|
|
32
|
+
* children: 'Documentation',
|
|
33
|
+
* prefetch: 'intent',
|
|
34
|
+
* });
|
|
35
|
+
* document.body.appendChild(link);
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
declare function createLink(props: LinkProps): HTMLAnchorElement;
|
|
39
|
+
/**
|
|
40
|
+
* Get link props for Vue template usage.
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```vue
|
|
44
|
+
* <script setup>
|
|
45
|
+
* import { useLinkProps } from '@flightdev/router';
|
|
46
|
+
* const linkProps = useLinkProps('/docs', { prefetch: 'intent' });
|
|
47
|
+
* </script>
|
|
48
|
+
*
|
|
49
|
+
* <template>
|
|
50
|
+
* <a v-bind="linkProps">Documentation</a>
|
|
51
|
+
* </template>
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
declare function useLinkProps(href: string, options?: Partial<Omit<LinkProps, 'href' | 'children'>>): {
|
|
55
|
+
href: string;
|
|
56
|
+
onClick: (e: MouseEvent) => void;
|
|
57
|
+
onMouseenter?: () => void;
|
|
58
|
+
onFocus?: () => void;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Router Hooks
|
|
63
|
+
*
|
|
64
|
+
* React hooks for accessing router state.
|
|
65
|
+
* Uses useSyncExternalStore for concurrent-safe external state (2026 best practice).
|
|
66
|
+
*/
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Subscribe to pathname changes - for useSyncExternalStore
|
|
70
|
+
*/
|
|
71
|
+
declare function subscribeToPathname(callback: () => void): () => void;
|
|
72
|
+
/**
|
|
73
|
+
* Get current pathname snapshot - for useSyncExternalStore
|
|
74
|
+
*/
|
|
75
|
+
declare function getPathnameSnapshot(): string;
|
|
76
|
+
/**
|
|
77
|
+
* Get server snapshot - for useSyncExternalStore SSR
|
|
78
|
+
*/
|
|
79
|
+
declare function getPathnameServerSnapshot(): string;
|
|
80
|
+
/**
|
|
81
|
+
* Create usePathname hook with provided React instance
|
|
82
|
+
* This pattern ensures proper bundler support for React hooks
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* import { useSyncExternalStore } from 'react';
|
|
86
|
+
* import { createUsePathname } from '@flightdev/router';
|
|
87
|
+
*
|
|
88
|
+
* const usePathname = createUsePathname(useSyncExternalStore);
|
|
89
|
+
*/
|
|
90
|
+
declare function createUsePathname(useSyncExternalStore: <T>(subscribe: (onStoreChange: () => void) => () => void, getSnapshot: () => T, getServerSnapshot?: () => T) => T): () => string;
|
|
91
|
+
declare let useParams: <T extends RouteParams = RouteParams>() => T;
|
|
92
|
+
declare let useSearchParams: () => [URLSearchParams, (params: SearchParams | URLSearchParams) => void];
|
|
93
|
+
declare let usePathname: () => string;
|
|
94
|
+
|
|
95
|
+
export { Link, LinkProps, RouteParams, SearchParams, createLink, createUsePathname, getPathnameServerSnapshot, getPathnameSnapshot, prefetchRoute, subscribeToPathname, useLinkProps, useParams, usePathname, useSearchParams };
|