@iyulab/router 0.1.0 → 0.3.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 +83 -160
- package/dist/main.cjs.js +681 -32591
- package/dist/main.d.ts +217 -250
- package/dist/main.es.js +681 -32593
- package/package.json +2 -2
- package/dist/main.umd.js +0 -32729
package/README.md
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
# @iyulab/router
|
|
2
2
|
|
|
3
|
-
A modern client-side router for web applications with support for Lit and React components.
|
|
3
|
+
A modern, lightweight client-side router for web applications with support for both Lit and React components.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
- 🚀 Modern URLPattern-based routing
|
|
8
|
-
- 🔧 Support
|
|
9
|
-
- 📱 Client-side
|
|
10
|
-
- 🎯 Nested
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
7
|
+
- 🚀 **Modern URLPattern-based routing** - Uses native URLPattern API for powerful path matching
|
|
8
|
+
- 🔧 **Unified Framework Support** - Works with both Lit and React components using render functions
|
|
9
|
+
- 📱 **Client-side Navigation** - History API integration with browser back/forward support
|
|
10
|
+
- 🎯 **Nested Routing** - Support for deeply nested route hierarchies with index and path routes
|
|
11
|
+
- 🔗 **Smart Link Component** - Automatic external link detection and handling
|
|
12
|
+
- 📊 **Route Events** - Track navigation progress with route-begin, route-done, and route-error events
|
|
13
|
+
- 🎨 **Flexible Outlet System** - Unified rendering with renderContent method
|
|
14
|
+
- 🌐 **Global Route Access** - Access current route information anywhere via `window.route`
|
|
15
|
+
- 🔄 **Force Re-rendering** - Control component re-rendering on route changes
|
|
16
|
+
- ⚠️ **Enhanced Error Handling** - Built-in ErrorPage component with improved styling
|
|
16
17
|
|
|
17
18
|
## Installation
|
|
18
19
|
|
|
@@ -20,43 +21,89 @@ A modern client-side router for web applications with support for Lit and React
|
|
|
20
21
|
npm install @iyulab/router
|
|
21
22
|
```
|
|
22
23
|
|
|
23
|
-
##
|
|
24
|
+
## Quick Start
|
|
24
25
|
|
|
25
26
|
### Basic Setup
|
|
26
27
|
|
|
27
28
|
```typescript
|
|
28
29
|
import { Router } from '@iyulab/router';
|
|
30
|
+
import { html } from 'lit';
|
|
29
31
|
|
|
30
32
|
const router = new Router({
|
|
31
33
|
root: document.getElementById('app')!,
|
|
32
34
|
basepath: '/app',
|
|
33
35
|
routes: [
|
|
34
36
|
{
|
|
35
|
-
|
|
36
|
-
|
|
37
|
+
index: true,
|
|
38
|
+
render: () => html`<home-page></home-page>`
|
|
37
39
|
},
|
|
38
40
|
{
|
|
39
41
|
path: '/user/:id',
|
|
40
|
-
|
|
41
|
-
loader: async (routeInfo) => {
|
|
42
|
-
const response = await fetch(`/api/user/${routeInfo.params.id}`);
|
|
43
|
-
return response.json();
|
|
44
|
-
}
|
|
42
|
+
render: (routeInfo) => html`<user-page .userId=${routeInfo.params.id}></user-page>`
|
|
45
43
|
}
|
|
46
|
-
]
|
|
47
|
-
notfound: 'not-found-page'
|
|
44
|
+
]
|
|
48
45
|
});
|
|
49
46
|
|
|
50
|
-
//
|
|
51
|
-
router.
|
|
47
|
+
// Start routing
|
|
48
|
+
router.go(window.location.href);
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Nested Routes
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
const routes = [
|
|
55
|
+
{
|
|
56
|
+
path: '/dashboard',
|
|
57
|
+
render: () => html`<dashboard-layout><u-outlet></u-outlet></dashboard-layout>`,
|
|
58
|
+
children: [
|
|
59
|
+
{
|
|
60
|
+
index: true, // Matches /dashboard exactly
|
|
61
|
+
render: () => html`<dashboard-home></dashboard-home>`
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
path: 'settings',
|
|
65
|
+
render: () => html`<dashboard-settings></dashboard-settings>`
|
|
66
|
+
}
|
|
67
|
+
]
|
|
68
|
+
}
|
|
69
|
+
];
|
|
52
70
|
```
|
|
53
71
|
|
|
72
|
+
### Mixed Framework Support
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
import React from 'react';
|
|
76
|
+
|
|
77
|
+
const routes = [
|
|
78
|
+
// Lit component
|
|
79
|
+
{
|
|
80
|
+
path: '/lit-page',
|
|
81
|
+
render: (routeInfo) => html`<my-lit-component .routeInfo=${routeInfo}></my-lit-component>`
|
|
82
|
+
},
|
|
83
|
+
// React component
|
|
84
|
+
{
|
|
85
|
+
path: '/react-page',
|
|
86
|
+
render: (routeInfo) => React.createElement(MyReactComponent, { routeInfo })
|
|
87
|
+
},
|
|
88
|
+
// HTML element
|
|
89
|
+
{
|
|
90
|
+
path: '/element-page',
|
|
91
|
+
render: (routeInfo) => {
|
|
92
|
+
const element = document.createElement('my-element');
|
|
93
|
+
element.data = routeInfo.params;
|
|
94
|
+
return element;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
];
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Usage Examples
|
|
101
|
+
|
|
54
102
|
### Using with Lit Components
|
|
55
103
|
|
|
56
104
|
```typescript
|
|
57
105
|
import { LitElement, html } from 'lit';
|
|
58
106
|
import { customElement } from 'lit/decorators.js';
|
|
59
|
-
import { UOutlet, ULink } from '@iyulab/router';
|
|
60
107
|
|
|
61
108
|
@customElement('app-root')
|
|
62
109
|
export class AppRoot extends LitElement {
|
|
@@ -65,7 +112,7 @@ export class AppRoot extends LitElement {
|
|
|
65
112
|
<nav>
|
|
66
113
|
<u-link href="/">Home</u-link>
|
|
67
114
|
<u-link href="/about">About</u-link>
|
|
68
|
-
<u-link href="/user/123">User</u-link>
|
|
115
|
+
<u-link href="/user/123">User Profile</u-link>
|
|
69
116
|
</nav>
|
|
70
117
|
<main>
|
|
71
118
|
<u-outlet></u-outlet>
|
|
@@ -87,7 +134,7 @@ export function AppRoot() {
|
|
|
87
134
|
<nav>
|
|
88
135
|
<Link href="/">Home</Link>
|
|
89
136
|
<Link href="/about">About</Link>
|
|
90
|
-
<Link href="/user/123">User</Link>
|
|
137
|
+
<Link href="/user/123">User Profile</Link>
|
|
91
138
|
</nav>
|
|
92
139
|
<main>
|
|
93
140
|
<Outlet />
|
|
@@ -97,144 +144,20 @@ export function AppRoot() {
|
|
|
97
144
|
}
|
|
98
145
|
```
|
|
99
146
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
```typescript
|
|
103
|
-
const routes = [
|
|
104
|
-
{
|
|
105
|
-
path: '/dashboard',
|
|
106
|
-
element: 'dashboard-layout',
|
|
107
|
-
children: [
|
|
108
|
-
{
|
|
109
|
-
index: true,
|
|
110
|
-
element: 'dashboard-home'
|
|
111
|
-
},
|
|
112
|
-
{
|
|
113
|
-
path: 'settings',
|
|
114
|
-
element: 'dashboard-settings'
|
|
115
|
-
},
|
|
116
|
-
{
|
|
117
|
-
path: 'profile',
|
|
118
|
-
component: ProfileComponent
|
|
119
|
-
}
|
|
120
|
-
]
|
|
121
|
-
}
|
|
122
|
-
];
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
### Route Information Access
|
|
126
|
-
|
|
127
|
-
You can access current route information globally via `window.route`:
|
|
128
|
-
|
|
129
|
-
```typescript
|
|
130
|
-
// In any component or script
|
|
131
|
-
console.log('Current path:', window.route.pathname);
|
|
132
|
-
console.log('Route params:', window.route.params);
|
|
133
|
-
console.log('Query params:', window.route.search);
|
|
134
|
-
console.log('Route data:', window.route.data);
|
|
135
|
-
|
|
136
|
-
// For Lit components
|
|
137
|
-
import { LitElement, html } from 'lit';
|
|
138
|
-
import { customElement } from 'lit/decorators.js';
|
|
139
|
-
|
|
140
|
-
@customElement('my-component')
|
|
141
|
-
export class MyComponent extends LitElement {
|
|
142
|
-
connectedCallback() {
|
|
143
|
-
super.connectedCallback();
|
|
144
|
-
// Listen for route changes
|
|
145
|
-
document.addEventListener('route-change', this.onRouteChange);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
disconnectedCallback() {
|
|
149
|
-
document.removeEventListener('route-change', this.onRouteChange);
|
|
150
|
-
super.disconnectedCallback();
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
private onRouteChange = () => {
|
|
154
|
-
this.requestUpdate(); // Trigger re-render when route changes
|
|
155
|
-
};
|
|
156
|
-
|
|
157
|
-
render() {
|
|
158
|
-
return html`
|
|
159
|
-
<div>Current path: ${window.route?.pathname}</div>
|
|
160
|
-
<div>Params: ${JSON.stringify(window.route?.params)}</div>
|
|
161
|
-
`;
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
// For React components
|
|
166
|
-
import React, { useState, useEffect } from 'react';
|
|
167
|
-
|
|
168
|
-
export function MyReactComponent() {
|
|
169
|
-
const [routeInfo, setRouteInfo] = useState(window.route);
|
|
170
|
-
|
|
171
|
-
useEffect(() => {
|
|
172
|
-
const handleRouteChange = () => {
|
|
173
|
-
setRouteInfo(window.route);
|
|
174
|
-
};
|
|
175
|
-
|
|
176
|
-
document.addEventListener('route-change', handleRouteChange);
|
|
177
|
-
return () => document.removeEventListener('route-change', handleRouteChange);
|
|
178
|
-
}, []);
|
|
179
|
-
|
|
180
|
-
return (
|
|
181
|
-
<div>
|
|
182
|
-
<div>Current path: {routeInfo?.pathname}</div>
|
|
183
|
-
<div>Params: {JSON.stringify(routeInfo?.params)}</div>
|
|
184
|
-
</div>
|
|
185
|
-
);
|
|
186
|
-
}
|
|
187
|
-
```
|
|
188
|
-
|
|
189
|
-
## API Reference
|
|
190
|
-
|
|
191
|
-
### Router
|
|
192
|
-
|
|
193
|
-
#### Constructor Options
|
|
194
|
-
|
|
195
|
-
- `root`: HTMLElement - The root element where the router will render components
|
|
196
|
-
- `basepath`: string - The base path for the router (optional, defaults to '/')
|
|
197
|
-
- `routes`: Route[] - Array of route configurations
|
|
198
|
-
- `notfound`: LitElement class or string - Component to render when no route matches
|
|
199
|
-
|
|
200
|
-
#### Methods
|
|
201
|
-
|
|
202
|
-
- `connect()`: Connect the router and start listening to navigation events
|
|
203
|
-
- `disconnect()`: Disconnect the router and stop listening to events
|
|
204
|
-
- `go(href: string)`: Navigate to a specific path
|
|
205
|
-
- `goBase()`: Navigate to the base path
|
|
206
|
-
|
|
207
|
-
### Route Configuration
|
|
208
|
-
|
|
209
|
-
```typescript
|
|
210
|
-
type Route = {
|
|
211
|
-
path?: string; // URL pattern (URLPattern syntax)
|
|
212
|
-
index?: boolean; // Index route (matches parent path exactly)
|
|
213
|
-
element?: typeof LitElement | string; // Lit element to render
|
|
214
|
-
component?: ComponentType; // React component to render
|
|
215
|
-
loader?: (routeInfo: RouteInfo) => Promise<any>; // Data loader function
|
|
216
|
-
title?: string; // Page title
|
|
217
|
-
children?: Route[]; // Nested routes
|
|
218
|
-
force?: boolean; // Force re-render on navigation
|
|
219
|
-
};
|
|
220
|
-
```
|
|
221
|
-
|
|
222
|
-
### Components
|
|
223
|
-
|
|
224
|
-
- `UOutlet` / `Outlet`: Outlet component for rendering route components
|
|
225
|
-
- `ULink` / `Link`: Smart link component with client-side navigation
|
|
226
|
-
|
|
227
|
-
### Global Route Access
|
|
228
|
-
|
|
229
|
-
- `window.route`: Global access to current route information (RouteInfo object)
|
|
147
|
+
## Browser Support
|
|
230
148
|
|
|
231
|
-
|
|
149
|
+
- **URLPattern API**: Required for routing functionality
|
|
150
|
+
- **Modern browsers**: Chrome 95+, Firefox 106+, Safari 16.4+
|
|
151
|
+
- **Polyfill**: Consider using [urlpattern-polyfill](https://www.npmjs.com/package/urlpattern-polyfill) for older browsers
|
|
232
152
|
|
|
233
|
-
|
|
153
|
+
## Contributing
|
|
234
154
|
|
|
235
|
-
|
|
236
|
-
|
|
155
|
+
1. Fork the repository
|
|
156
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
157
|
+
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
|
158
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
159
|
+
5. Open a Pull Request
|
|
237
160
|
|
|
238
161
|
## License
|
|
239
162
|
|
|
240
|
-
MIT
|
|
163
|
+
MIT License - see [LICENSE](LICENSE) file for details.
|