@esmx/router-vue 3.0.0-rc.103

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 (49) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +570 -0
  3. package/README.zh-CN.md +570 -0
  4. package/dist/index.d.ts +6 -0
  5. package/dist/index.mjs +13 -0
  6. package/dist/index.test.d.ts +1 -0
  7. package/dist/index.test.mjs +216 -0
  8. package/dist/plugin.d.ts +61 -0
  9. package/dist/plugin.mjs +41 -0
  10. package/dist/plugin.test.d.ts +1 -0
  11. package/dist/plugin.test.mjs +631 -0
  12. package/dist/router-link.d.ts +220 -0
  13. package/dist/router-link.mjs +119 -0
  14. package/dist/router-link.test.d.ts +1 -0
  15. package/dist/router-link.test.mjs +663 -0
  16. package/dist/router-view.d.ts +31 -0
  17. package/dist/router-view.mjs +15 -0
  18. package/dist/router-view.test.d.ts +1 -0
  19. package/dist/router-view.test.mjs +676 -0
  20. package/dist/run-with-context.test.d.ts +1 -0
  21. package/dist/run-with-context.test.mjs +57 -0
  22. package/dist/use.d.ts +260 -0
  23. package/dist/use.mjs +125 -0
  24. package/dist/use.test.d.ts +1 -0
  25. package/dist/use.test.mjs +381 -0
  26. package/dist/util.d.ts +20 -0
  27. package/dist/util.mjs +49 -0
  28. package/dist/util.test.d.ts +4 -0
  29. package/dist/util.test.mjs +604 -0
  30. package/dist/vue2.d.ts +15 -0
  31. package/dist/vue2.mjs +0 -0
  32. package/dist/vue3.d.ts +13 -0
  33. package/dist/vue3.mjs +0 -0
  34. package/package.json +85 -0
  35. package/src/index.test.ts +273 -0
  36. package/src/index.ts +15 -0
  37. package/src/plugin.test.ts +812 -0
  38. package/src/plugin.ts +107 -0
  39. package/src/router-link.test.ts +830 -0
  40. package/src/router-link.ts +172 -0
  41. package/src/router-view.test.ts +840 -0
  42. package/src/router-view.ts +59 -0
  43. package/src/run-with-context.test.ts +64 -0
  44. package/src/use.test.ts +484 -0
  45. package/src/use.ts +416 -0
  46. package/src/util.test.ts +760 -0
  47. package/src/util.ts +85 -0
  48. package/src/vue2.ts +18 -0
  49. package/src/vue3.ts +15 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2020 Esmx Team
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,570 @@
1
+ <div align="center">
2
+ <img src="https://esmx.dev/logo.svg?t=2025" width="120" alt="Esmx Logo" />
3
+ <h1>@esmx/router-vue</h1>
4
+
5
+ <div>
6
+ <a href="https://www.npmjs.com/package/@esmx/router-vue">
7
+ <img src="https://img.shields.io/npm/v/@esmx/router-vue.svg" alt="npm version" />
8
+ </a>
9
+ <a href="https://github.com/esmnext/esmx/actions/workflows/build.yml">
10
+ <img src="https://github.com/esmnext/esmx/actions/workflows/build.yml/badge.svg" alt="Build" />
11
+ </a>
12
+ <a href="https://esmx.dev/coverage/">
13
+ <img src="https://img.shields.io/badge/coverage-live%20report-brightgreen" alt="Coverage Report" />
14
+ </a>
15
+ <a href="https://nodejs.org/">
16
+ <img src="https://img.shields.io/node/v/@esmx/router-vue.svg" alt="node version" />
17
+ </a>
18
+ <a href="https://bundlephobia.com/package/@esmx/router-vue">
19
+ <img src="https://img.shields.io/bundlephobia/minzip/@esmx/router-vue" alt="size" />
20
+ </a>
21
+ </div>
22
+
23
+ <p>Vue integration for <a href="https://github.com/esmnext/esmx/tree/master/packages/router">@esmx/router</a> - A universal router that works seamlessly with both Vue 2.7+ and Vue 3.</p>
24
+
25
+ <p>
26
+ English | <a href="https://github.com/esmnext/esmx/blob/master/packages/router-vue/README.zh-CN.md">δΈ­ζ–‡</a>
27
+ </p>
28
+ </div>
29
+
30
+
31
+
32
+ ## πŸš€ Features
33
+
34
+ ✨ **Universal Vue Support** - Works with both Vue 2.7+ and Vue 3
35
+ 🎯 **Composition API First** - Built for modern Vue development
36
+ πŸ”— **Seamless Integration** - Drop-in replacement for Vue Router
37
+ πŸš€ **TypeScript Ready** - Full TypeScript support with excellent DX
38
+ ⚑ **High Performance** - Optimized for production use
39
+ πŸ”„ **SSR Compatible** - Server-side rendering support
40
+
41
+ ## πŸ“¦ Installation
42
+
43
+ ```bash
44
+ # npm
45
+ npm install @esmx/router @esmx/router-vue
46
+
47
+ # pnpm
48
+ pnpm add @esmx/router @esmx/router-vue
49
+
50
+ # yarn
51
+ yarn add @esmx/router @esmx/router-vue
52
+ ```
53
+
54
+ ## πŸš€ Quick Start
55
+
56
+ ### Vue 3
57
+
58
+ ```typescript
59
+ import { createApp, h } from 'vue';
60
+ import { Router, RouterMode } from '@esmx/router';
61
+ import { RouterPlugin, useProvideRouter } from '@esmx/router-vue';
62
+ import App from './App.vue';
63
+
64
+ const routes = [
65
+ { path: '/', component: () => import('./views/Home.vue') },
66
+ { path: '/about', component: () => import('./views/About.vue') }
67
+ ];
68
+
69
+ const router = new Router({
70
+ routes,
71
+ mode: RouterMode.history
72
+ });
73
+
74
+ const app = createApp({
75
+ setup() {
76
+ useProvideRouter(router);
77
+ return {};
78
+ },
79
+ render: () => h(App)
80
+ });
81
+
82
+ // Install the plugin
83
+ app.use(RouterPlugin);
84
+
85
+ app.mount('#app');
86
+ ```
87
+
88
+ ### Vue 2.7+
89
+
90
+ ```typescript
91
+ import Vue from 'vue';
92
+ import { Router, RouterMode } from '@esmx/router';
93
+ import { RouterPlugin, useProvideRouter } from '@esmx/router-vue';
94
+ import App from './App.vue';
95
+
96
+ const routes = [
97
+ { path: '/', component: () => import('./views/Home.vue') },
98
+ { path: '/about', component: () => import('./views/About.vue') }
99
+ ];
100
+
101
+ const router = new Router({
102
+ routes,
103
+ mode: RouterMode.history
104
+ });
105
+
106
+ // Install the plugin
107
+ Vue.use(RouterPlugin);
108
+
109
+ new Vue({
110
+ setup() {
111
+ useProvideRouter(router);
112
+ },
113
+ render: h => h(App)
114
+ }).$mount('#app');
115
+ ```
116
+
117
+ ## Basic Usage
118
+
119
+ ### Template Usage
120
+
121
+ ```vue
122
+ <template>
123
+ <div id="app">
124
+ <nav>
125
+ <RouterLink to="/">Home</RouterLink>
126
+ <RouterLink to="/about">About</RouterLink>
127
+ <RouterLink to="/users/123">User Profile</RouterLink>
128
+ </nav>
129
+
130
+ <!-- Route components will be rendered here -->
131
+ <RouterView />
132
+ </div>
133
+ </template>
134
+ ```
135
+
136
+ ### Composition API
137
+
138
+ ```vue
139
+ <script setup lang="ts">
140
+ import { useRouter, useRoute } from '@esmx/router-vue';
141
+ import { watch } from 'vue';
142
+
143
+ const router = useRouter();
144
+ const route = useRoute();
145
+
146
+ // Programmatic navigation
147
+ const goToAbout = () => {
148
+ router.push('/about');
149
+ };
150
+
151
+ const goBack = () => {
152
+ router.back();
153
+ };
154
+
155
+ // Watch route changes
156
+ watch(() => route.path, (newPath) => {
157
+ // Handle route change logic here
158
+ });
159
+ </script>
160
+
161
+ <template>
162
+ <div>
163
+ <h1>{{ route.meta?.title || 'Page' }}</h1>
164
+ <p>Current path: {{ route.path }}</p>
165
+ <p>Route params: {{ JSON.stringify(route.params) }}</p>
166
+ <p>Query params: {{ JSON.stringify(route.query) }}</p>
167
+
168
+ <button @click="goToAbout">Go to About Page</button>
169
+ <button @click="goBack">Go Back</button>
170
+ </div>
171
+ </template>
172
+ ```
173
+
174
+ ### Options API
175
+
176
+ ```vue
177
+ <script>
178
+ import { defineComponent } from 'vue';
179
+ import { getRouter, getRoute } from '@esmx/router-vue';
180
+
181
+ export default defineComponent({
182
+ mounted() {
183
+ const router = getRouter(this);
184
+ const route = getRoute(this);
185
+
186
+ // Access current route information
187
+ },
188
+
189
+ methods: {
190
+ navigate() {
191
+ const router = getRouter(this);
192
+ router.push('/dashboard');
193
+ }
194
+ }
195
+ });
196
+ </script>
197
+ ```
198
+
199
+ ## πŸ“š API Reference
200
+
201
+ ### Components
202
+
203
+ #### RouterLink
204
+
205
+ A component for creating navigation links.
206
+
207
+ **Props:**
208
+
209
+ | Prop | Type | Default | Description |
210
+ |------|------|---------|-------------|
211
+ | `to` | `string` \| `RouteLocationInput` | - | Target route location |
212
+ | `type` | `RouterLinkType` | `'push'` | Navigation type (`'push'` \| `'replace'` \| `'pushWindow'` \| `'replaceWindow'` \| `'pushLayer'`) |
213
+ | `exact` | `RouteMatchType` | `'include'` | Active state matching (`'include'` \| `'exact'` \| `'route'`) |
214
+ | `activeClass` | `string` | - | CSS class for active state |
215
+ | `event` | `string` \| `string[]` | `'click'` | Events that trigger navigation |
216
+ | `tag` | `string` | `'a'` | HTML tag to render |
217
+ | `layerOptions` | `RouterLayerOptions` | - | Layer navigation options (used with `type="pushLayer"`) |
218
+
219
+ **Usage:**
220
+
221
+ ```vue
222
+ <template>
223
+ <!-- Basic link -->
224
+ <RouterLink to="/home">Home</RouterLink>
225
+
226
+ <!-- Replace navigation -->
227
+ <RouterLink to="/login" type="replace">Login</RouterLink>
228
+
229
+ <!-- Custom styling -->
230
+ <RouterLink
231
+ to="/dashboard"
232
+ active-class="nav-active"
233
+ exact="exact"
234
+ >
235
+ Dashboard
236
+ </RouterLink>
237
+
238
+ <!-- Custom tag -->
239
+ <RouterLink to="/submit" tag="button" class="btn">
240
+ Submit
241
+ </RouterLink>
242
+ </template>
243
+ ```
244
+
245
+ #### RouterView
246
+
247
+ A component that renders the matched route component.
248
+
249
+ **Usage:**
250
+
251
+ ```vue
252
+ <template>
253
+ <div>
254
+ <!-- Root level routes render here -->
255
+ <RouterView />
256
+
257
+ <!-- Nested routes will render in child RouterView components -->
258
+ <!-- Each RouterView automatically handles the correct depth -->
259
+ </div>
260
+ </template>
261
+ ```
262
+
263
+ ### Composition API
264
+
265
+ #### useRouter()
266
+
267
+ Get the router instance for navigation.
268
+
269
+ ```typescript
270
+ function useRouter(): Router
271
+ ```
272
+
273
+ **Usage:**
274
+
275
+ ```vue
276
+ <script setup>
277
+ import { useRouter } from '@esmx/router-vue';
278
+
279
+ const router = useRouter();
280
+
281
+ const navigate = () => {
282
+ router.push('/about');
283
+ };
284
+ </script>
285
+ ```
286
+
287
+ #### useRoute()
288
+
289
+ Get the current route information (reactive).
290
+
291
+ ```typescript
292
+ function useRoute(): Route
293
+ ```
294
+
295
+ **Usage:**
296
+
297
+ ```vue
298
+ <script setup>
299
+ import { useRoute } from '@esmx/router-vue';
300
+
301
+ const route = useRoute();
302
+
303
+ // Access route properties
304
+ // route.path - Current path
305
+ // route.params - Route parameters
306
+ // route.query - Query parameters
307
+ // route.meta - Route metadata
308
+ </script>
309
+ ```
310
+
311
+ #### useProvideRouter()
312
+
313
+ Provide router context to child components.
314
+
315
+ ```typescript
316
+ function useProvideRouter(router: Router): void
317
+ ```
318
+
319
+ **Usage:**
320
+
321
+ ```typescript
322
+ import { Router, RouterMode } from '@esmx/router';
323
+ import { useProvideRouter } from '@esmx/router-vue';
324
+
325
+ const router = new Router({
326
+ routes,
327
+ mode: RouterMode.history
328
+ });
329
+
330
+ // In your app's setup function
331
+ setup() {
332
+ useProvideRouter(router);
333
+ }
334
+ ```
335
+
336
+ #### useLink()
337
+
338
+ Create reactive link helpers for custom navigation components.
339
+
340
+ ```typescript
341
+ function useLink(props: RouterLinkProps): ComputedRef<RouterLinkResolved>
342
+ ```
343
+
344
+ **Usage:**
345
+
346
+ ```vue
347
+ <script setup>
348
+ import { useLink } from '@esmx/router-vue';
349
+
350
+ const link = useLink({
351
+ to: '/home',
352
+ type: 'push',
353
+ exact: 'include'
354
+ }).value;
355
+ </script>
356
+
357
+ <template>
358
+ <a
359
+ v-bind="link.attributes"
360
+ v-on="link.createEventHandlers()"
361
+ :class="{ active: link.isActive }"
362
+ >
363
+ Custom Link
364
+ </a>
365
+ </template>
366
+ ```
367
+
368
+ ### Options API
369
+
370
+ #### getRouter()
371
+
372
+ Get router instance in Options API components.
373
+
374
+ ```typescript
375
+ function getRouter(instance: VueInstance): Router
376
+ ```
377
+
378
+ #### getRoute()
379
+
380
+ Get current route in Options API components.
381
+
382
+ ```typescript
383
+ function getRoute(instance: VueInstance): Route
384
+ ```
385
+
386
+ ### Plugin
387
+
388
+ #### RouterPlugin
389
+
390
+ Vue plugin that registers RouterLink and RouterView components globally.
391
+
392
+ ```typescript
393
+ const RouterPlugin = {
394
+ install(app: App): void
395
+ }
396
+ ```
397
+
398
+ **Usage:**
399
+
400
+ ```typescript
401
+ // Vue 3
402
+ app.use(RouterPlugin);
403
+
404
+ // Vue 2
405
+ Vue.use(RouterPlugin);
406
+ ```
407
+
408
+ ## TypeScript Support
409
+
410
+ This package provides full TypeScript support for both Vue 2.7+ and Vue 3. For Options API usage, the package automatically augments Vue component instances with `$router` and `$route` properties, allowing you to access them directly in templates and component methods.
411
+
412
+ ```typescript
413
+ // Options API type augmentation (automatic)
414
+ declare module 'vue/types/vue' {
415
+ interface Vue {
416
+ readonly $router: Router;
417
+ readonly $route: Route;
418
+ }
419
+ }
420
+ ```
421
+
422
+ **Options API Usage:**
423
+
424
+ ```vue
425
+ <template>
426
+ <div>
427
+ <!-- Direct access without 'this.' -->
428
+ <p>Current path: {{ $route.path }}</p>
429
+ <button @click="navigate">Navigate to About Page</button>
430
+ </div>
431
+ </template>
432
+
433
+ <script lang="ts">
434
+ import { defineComponent } from 'vue';
435
+
436
+ export default defineComponent({
437
+ methods: {
438
+ navigate() {
439
+ // TypeScript knows about $router and $route
440
+ this.$router.push('/about');
441
+ // Access current route: this.$route.path
442
+ }
443
+ }
444
+ });
445
+ </script>
446
+ ```
447
+
448
+ ## Advanced Usage
449
+
450
+ ### Custom Link Component
451
+
452
+ ```vue
453
+ <script setup lang="ts">
454
+ import { useLink } from '@esmx/router-vue';
455
+ import type { RouterLinkProps } from '@esmx/router';
456
+
457
+ interface Props extends RouterLinkProps {
458
+ icon?: string;
459
+ disabled?: boolean;
460
+ }
461
+
462
+ const props = defineProps<Props>();
463
+
464
+ const link = useLink(props).value;
465
+ </script>
466
+
467
+ <template>
468
+ <button
469
+ v-bind="link.attributes"
470
+ v-on="link.createEventHandlers()"
471
+ :class="{
472
+ active: link.isActive,
473
+ disabled: disabled
474
+ }"
475
+ :disabled="disabled"
476
+ >
477
+ <i v-if="icon" :class="icon" />
478
+ <slot />
479
+ </button>
480
+ </template>
481
+ ```
482
+
483
+ ### Route Guards in Components
484
+
485
+ ```vue
486
+ <script setup>
487
+ import { useRouter, useRoute } from '@esmx/router-vue';
488
+ import { onMounted, onBeforeUnmount } from 'vue';
489
+
490
+ const router = useRouter();
491
+ const route = useRoute();
492
+
493
+ onMounted(() => {
494
+ // Add route guard
495
+ const unregister = router.beforeEach((to, from) => {
496
+ // Check if route requires authentication (isAuthenticated is your auth function)
497
+ if (to.meta?.requiresAuth && !isAuthenticated()) {
498
+ return '/login';
499
+ }
500
+ });
501
+
502
+ // Cleanup on unmount
503
+ onBeforeUnmount(unregister);
504
+ });
505
+ </script>
506
+ ```
507
+
508
+ ## Migration from Vue Router
509
+
510
+ ### Key Differences
511
+
512
+ 1. **Router Creation**: Use `new Router()` constructor from `@esmx/router`
513
+ 2. **Context Provision**: Use `useProvideRouter()` instead of router installation
514
+ 3. **Component Registration**: Use `RouterPlugin` for global components
515
+
516
+ ### Migration Example
517
+
518
+ **Before (Vue Router):**
519
+
520
+ ```typescript
521
+ import { createRouter, createWebHistory } from 'vue-router';
522
+
523
+ const router = createRouter({
524
+ history: createWebHistory(),
525
+ routes
526
+ });
527
+
528
+ app.use(router);
529
+ ```
530
+
531
+ **After (@esmx/router-vue):**
532
+
533
+ ```typescript
534
+ import { Router, RouterMode } from '@esmx/router';
535
+ import { RouterPlugin, useProvideRouter } from '@esmx/router-vue';
536
+ import { createApp, h } from 'vue';
537
+ import App from './App.vue';
538
+
539
+ const router = new Router({
540
+ routes,
541
+ mode: RouterMode.history
542
+ });
543
+
544
+ const app = createApp({
545
+ setup() {
546
+ useProvideRouter(router);
547
+ return {};
548
+ },
549
+ render: () => h(App)
550
+ });
551
+
552
+ app.use(RouterPlugin);
553
+ ```
554
+
555
+ ## Browser Support
556
+
557
+ - **Modern browsers** that support ES modules (`import`/`export`) and dynamic imports (`import()`)
558
+
559
+ ## Contributing
560
+
561
+ We welcome contributions! Please feel free to submit issues and pull requests.
562
+
563
+ ## πŸ“„ License
564
+
565
+ MIT Β© [Esmx Team](https://github.com/esmnext/esmx)
566
+
567
+ ## Related Packages
568
+
569
+ - [@esmx/router](https://github.com/esmnext/esmx/tree/master/packages/router) - Core router package
570
+ - [@esmx/core](https://github.com/esmnext/esmx/tree/master/packages/core) - Esmx core framework