@iyulab/router 0.7.1 → 0.7.3
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 +20 -20
- package/README.md +272 -272
- package/dist/index.d.ts +13 -19
- package/dist/index.js +12 -24
- package/dist/react.d.ts +2 -87
- package/dist/react.js +1 -1
- package/dist/{share-B5lysqp2.js → share-CG-3Tbuy.js} +9 -6
- package/package.json +69 -56
package/LICENSE
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2025 iyulab
|
|
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
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 iyulab
|
|
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
21
|
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,272 +1,272 @@
|
|
|
1
|
-
# @iyulab/router
|
|
2
|
-
|
|
3
|
-
A modern, lightweight client-side router for web applications with support for both Lit and React components.
|
|
4
|
-
|
|
5
|
-
## Features
|
|
6
|
-
|
|
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
|
-
- 📊 **Route Events** - Track navigation progress with route-begin, route-done, and route-error events
|
|
12
|
-
- ⚠️ **Enhanced Error Handling** - Built-in ErrorPage component with improved styling
|
|
13
|
-
|
|
14
|
-
## Installation
|
|
15
|
-
|
|
16
|
-
```bash
|
|
17
|
-
npm install @iyulab/router
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
## Quick Start
|
|
21
|
-
|
|
22
|
-
### Basic Setup
|
|
23
|
-
|
|
24
|
-
```typescript
|
|
25
|
-
import { Router } from '@iyulab/router';
|
|
26
|
-
import { html } from 'lit';
|
|
27
|
-
|
|
28
|
-
const router = new Router({
|
|
29
|
-
basepath: '/',
|
|
30
|
-
routes: [
|
|
31
|
-
{
|
|
32
|
-
index: true,
|
|
33
|
-
render: () => html`<home-page></home-page>`
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
path: '/user/:id', // URLPattern route
|
|
37
|
-
render: (routeInfo) => html`<user-page .userId=${routeInfo.params.id}></user-page>`
|
|
38
|
-
}
|
|
39
|
-
],
|
|
40
|
-
});
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
### Mixed Framework Support
|
|
44
|
-
|
|
45
|
-
```typescript
|
|
46
|
-
import React from 'react';
|
|
47
|
-
|
|
48
|
-
const routes = [
|
|
49
|
-
// Lit component
|
|
50
|
-
{
|
|
51
|
-
path: '/lit-page',
|
|
52
|
-
render: (routeInfo) => {
|
|
53
|
-
return html`<my-lit-component .routeInfo=${routeInfo}></my-lit-component>`
|
|
54
|
-
}
|
|
55
|
-
},
|
|
56
|
-
// React component
|
|
57
|
-
{
|
|
58
|
-
path: '/react-page',
|
|
59
|
-
render: (routeInfo) => {
|
|
60
|
-
return ( <MyComponent></MyComponent> )
|
|
61
|
-
}
|
|
62
|
-
},
|
|
63
|
-
// HTML element
|
|
64
|
-
{
|
|
65
|
-
path: '/element-page',
|
|
66
|
-
render: (routeInfo) => {
|
|
67
|
-
const element = document.createElement('my-element');
|
|
68
|
-
element.data = routeInfo.params;
|
|
69
|
-
return element;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
];
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
### Nested Routes
|
|
76
|
-
|
|
77
|
-
```typescript
|
|
78
|
-
import { RouteConfig } from '@iyulab/router';
|
|
79
|
-
|
|
80
|
-
const routes: RouteConfig[] = [
|
|
81
|
-
{
|
|
82
|
-
path: '/dashboard',
|
|
83
|
-
render: () => html`<dashboard-layout><u-outlet></u-outlet></dashboard-layout>`,
|
|
84
|
-
children: [
|
|
85
|
-
{
|
|
86
|
-
index: true, // Matches '/dashboard'
|
|
87
|
-
render: () => html`<dashboard-home></dashboard-home>`
|
|
88
|
-
},
|
|
89
|
-
{
|
|
90
|
-
path: 'settings', // Matches '/dashboard/settings'
|
|
91
|
-
render: () => html`<dashboard-settings></dashboard-settings>`
|
|
92
|
-
}
|
|
93
|
-
]
|
|
94
|
-
}
|
|
95
|
-
];
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
## Usage Examples
|
|
99
|
-
|
|
100
|
-
### Using with Lit Elements
|
|
101
|
-
|
|
102
|
-
```typescript
|
|
103
|
-
import { LitElement, html } from 'lit';
|
|
104
|
-
import { customElement } from 'lit/decorators.js';
|
|
105
|
-
|
|
106
|
-
import "@iyulab/router";
|
|
107
|
-
|
|
108
|
-
@customElement('app-root')
|
|
109
|
-
export class AppRoot extends LitElement {
|
|
110
|
-
render() {
|
|
111
|
-
return html`
|
|
112
|
-
<nav>
|
|
113
|
-
<u-link href="/">Home</u-link>
|
|
114
|
-
<u-link href="/about">About</u-link>
|
|
115
|
-
<u-link href="/user/123">User Profile</u-link>
|
|
116
|
-
</nav>
|
|
117
|
-
<main>
|
|
118
|
-
<u-outlet></u-outlet>
|
|
119
|
-
</main>
|
|
120
|
-
`;
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
### Using with React Components
|
|
126
|
-
|
|
127
|
-
```tsx
|
|
128
|
-
import React from 'react';
|
|
129
|
-
import { UOutlet, ULink } from '@iyulab/router/react';
|
|
130
|
-
|
|
131
|
-
export function AppRoot() {
|
|
132
|
-
return (
|
|
133
|
-
<div>
|
|
134
|
-
<nav>
|
|
135
|
-
<ULink href="/">Home</ULink>
|
|
136
|
-
<ULink href="/about">About</ULink>
|
|
137
|
-
<ULink href="/user/123">User Profile</ULink>
|
|
138
|
-
</nav>
|
|
139
|
-
<main>
|
|
140
|
-
<UOutlet />
|
|
141
|
-
</main>
|
|
142
|
-
</div>
|
|
143
|
-
);
|
|
144
|
-
}
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
## Error Handling
|
|
148
|
-
|
|
149
|
-
The router provides comprehensive error handling through `FallbackRouteContext`. When a routing error occurs, the fallback render function receives a context with full error information:
|
|
150
|
-
|
|
151
|
-
```typescript
|
|
152
|
-
const router = new Router({
|
|
153
|
-
root: document.body,
|
|
154
|
-
basepath: '/',
|
|
155
|
-
routes: [...],
|
|
156
|
-
fallback: {
|
|
157
|
-
title: 'Error',
|
|
158
|
-
render: (ctx) => {
|
|
159
|
-
// ctx.error contains RouteError with code, message, and original error
|
|
160
|
-
const { code, message, original } = ctx.error;
|
|
161
|
-
|
|
162
|
-
if (code === 'NOT_FOUND') {
|
|
163
|
-
return html`<not-found-page .path=${ctx.pathname}></not-found-page>`;
|
|
164
|
-
}
|
|
165
|
-
if (code === 'CONTENT_LOAD_ERROR') {
|
|
166
|
-
return html`<error-page .message=${message}></error-page>`;
|
|
167
|
-
}
|
|
168
|
-
return html`<error-page .error=${ctx.error}></error-page>`;
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
});
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
Error types:
|
|
175
|
-
- `NotFoundError` — No matching route found (code: `NOT_FOUND`)
|
|
176
|
-
- `ContentLoadError` — Route render function threw an error (code: `CONTENT_LOAD_ERROR`)
|
|
177
|
-
- `ContentRenderError` — Outlet rendering failed (code: `CONTENT_RENDER_ERROR`)
|
|
178
|
-
|
|
179
|
-
## Route Metadata
|
|
180
|
-
|
|
181
|
-
Routes can carry arbitrary metadata via the `meta` field. When a route matches, metadata from the entire matched route chain is merged (parent → child order, child overrides parent):
|
|
182
|
-
|
|
183
|
-
```typescript
|
|
184
|
-
const router = new Router({
|
|
185
|
-
root: document.body,
|
|
186
|
-
basepath: '/',
|
|
187
|
-
routes: [
|
|
188
|
-
{
|
|
189
|
-
path: '/admin',
|
|
190
|
-
meta: { requiresAuth: true, layout: 'admin' },
|
|
191
|
-
render: (ctx) => {
|
|
192
|
-
// ctx.meta === { requiresAuth: true, layout: 'admin' }
|
|
193
|
-
return html`<admin-layout><u-outlet></u-outlet></admin-layout>`;
|
|
194
|
-
},
|
|
195
|
-
children: [
|
|
196
|
-
{
|
|
197
|
-
path: 'settings',
|
|
198
|
-
meta: { requiresAuth: true, role: 'superadmin' },
|
|
199
|
-
render: (ctx) => {
|
|
200
|
-
// ctx.meta === { requiresAuth: true, layout: 'admin', role: 'superadmin' }
|
|
201
|
-
return html`<admin-settings></admin-settings>`;
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
]
|
|
205
|
-
}
|
|
206
|
-
]
|
|
207
|
-
});
|
|
208
|
-
```
|
|
209
|
-
|
|
210
|
-
Use cases: authentication guards, SEO tags, analytics tracking, layout selection, and more.
|
|
211
|
-
|
|
212
|
-
## Route Events
|
|
213
|
-
|
|
214
|
-
The router dispatches events on the `window` object during navigation:
|
|
215
|
-
|
|
216
|
-
| Event | Type | Description |
|
|
217
|
-
|-------|------|-------------|
|
|
218
|
-
| `route-begin` | `RouteBeginEvent` | Fired when navigation starts |
|
|
219
|
-
| `route-progress` | `RouteProgressEvent` | Fired during async loading (0–100) |
|
|
220
|
-
| `route-done` | `RouteDoneEvent` | Fired when navigation completes successfully |
|
|
221
|
-
| `route-error` | `RouteErrorEvent` | Fired when a routing error occurs |
|
|
222
|
-
|
|
223
|
-
```typescript
|
|
224
|
-
// Track navigation progress
|
|
225
|
-
window.addEventListener('route-progress', (e: RouteProgressEvent) => {
|
|
226
|
-
progressBar.value = e.progress;
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
// Log navigation events
|
|
230
|
-
window.addEventListener('route-begin', (e: RouteBeginEvent) => {
|
|
231
|
-
console.log('Navigating to:', e.context.pathname);
|
|
232
|
-
});
|
|
233
|
-
|
|
234
|
-
window.addEventListener('route-done', (e: RouteDoneEvent) => {
|
|
235
|
-
analytics.trackPageView(e.context.pathname);
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
window.addEventListener('route-error', (e: RouteErrorEvent) => {
|
|
239
|
-
errorTracker.report(e.error);
|
|
240
|
-
});
|
|
241
|
-
```
|
|
242
|
-
|
|
243
|
-
## URL Parameters
|
|
244
|
-
|
|
245
|
-
The router supports URLPattern-based parameter matching:
|
|
246
|
-
|
|
247
|
-
```typescript
|
|
248
|
-
const routes: RouteConfig[] = [
|
|
249
|
-
// Required parameter
|
|
250
|
-
{ path: '/user/:id', render: (ctx) => html`<user-page .id=${ctx.params.id}></user-page>` },
|
|
251
|
-
|
|
252
|
-
// Optional parameter
|
|
253
|
-
{ path: '/posts/:category?', render: (ctx) => {
|
|
254
|
-
const category = ctx.params.category || 'all';
|
|
255
|
-
return html`<posts-page .category=${category}></posts-page>`;
|
|
256
|
-
}},
|
|
257
|
-
|
|
258
|
-
// Wildcard (catch-all)
|
|
259
|
-
{ path: '/docs/:path*', render: (ctx) => html`<docs-page .path=${ctx.params.path}></docs-page>` },
|
|
260
|
-
|
|
261
|
-
// Multiple parameters
|
|
262
|
-
{ path: '/org/:orgId/repo/:repoId', render: (ctx) => {
|
|
263
|
-
return html`<repo-page .orgId=${ctx.params.orgId} .repoId=${ctx.params.repoId}></repo-page>`;
|
|
264
|
-
}}
|
|
265
|
-
];
|
|
266
|
-
```
|
|
267
|
-
|
|
268
|
-
When URL parameters change (e.g., navigating from `/user/1` to `/user/2`), leaf routes (without children) automatically re-render since `force` defaults to `true`. For parent routes with children, set `force: true` explicitly if re-rendering is needed on parameter changes.
|
|
269
|
-
|
|
270
|
-
## License
|
|
271
|
-
|
|
272
|
-
MIT License - see [LICENSE](LICENSE) file for details.
|
|
1
|
+
# @iyulab/router
|
|
2
|
+
|
|
3
|
+
A modern, lightweight client-side router for web applications with support for both Lit and React components.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
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
|
+
- 📊 **Route Events** - Track navigation progress with route-begin, route-done, and route-error events
|
|
12
|
+
- ⚠️ **Enhanced Error Handling** - Built-in ErrorPage component with improved styling
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install @iyulab/router
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Quick Start
|
|
21
|
+
|
|
22
|
+
### Basic Setup
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
import { Router } from '@iyulab/router';
|
|
26
|
+
import { html } from 'lit';
|
|
27
|
+
|
|
28
|
+
const router = new Router({
|
|
29
|
+
basepath: '/',
|
|
30
|
+
routes: [
|
|
31
|
+
{
|
|
32
|
+
index: true,
|
|
33
|
+
render: () => html`<home-page></home-page>`
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
path: '/user/:id', // URLPattern route
|
|
37
|
+
render: (routeInfo) => html`<user-page .userId=${routeInfo.params.id}></user-page>`
|
|
38
|
+
}
|
|
39
|
+
],
|
|
40
|
+
});
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Mixed Framework Support
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
import React from 'react';
|
|
47
|
+
|
|
48
|
+
const routes = [
|
|
49
|
+
// Lit component
|
|
50
|
+
{
|
|
51
|
+
path: '/lit-page',
|
|
52
|
+
render: (routeInfo) => {
|
|
53
|
+
return html`<my-lit-component .routeInfo=${routeInfo}></my-lit-component>`
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
// React component
|
|
57
|
+
{
|
|
58
|
+
path: '/react-page',
|
|
59
|
+
render: (routeInfo) => {
|
|
60
|
+
return ( <MyComponent></MyComponent> )
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
// HTML element
|
|
64
|
+
{
|
|
65
|
+
path: '/element-page',
|
|
66
|
+
render: (routeInfo) => {
|
|
67
|
+
const element = document.createElement('my-element');
|
|
68
|
+
element.data = routeInfo.params;
|
|
69
|
+
return element;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
];
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Nested Routes
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
import { RouteConfig } from '@iyulab/router';
|
|
79
|
+
|
|
80
|
+
const routes: RouteConfig[] = [
|
|
81
|
+
{
|
|
82
|
+
path: '/dashboard',
|
|
83
|
+
render: () => html`<dashboard-layout><u-outlet></u-outlet></dashboard-layout>`,
|
|
84
|
+
children: [
|
|
85
|
+
{
|
|
86
|
+
index: true, // Matches '/dashboard'
|
|
87
|
+
render: () => html`<dashboard-home></dashboard-home>`
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
path: 'settings', // Matches '/dashboard/settings'
|
|
91
|
+
render: () => html`<dashboard-settings></dashboard-settings>`
|
|
92
|
+
}
|
|
93
|
+
]
|
|
94
|
+
}
|
|
95
|
+
];
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Usage Examples
|
|
99
|
+
|
|
100
|
+
### Using with Lit Elements
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
import { LitElement, html } from 'lit';
|
|
104
|
+
import { customElement } from 'lit/decorators.js';
|
|
105
|
+
|
|
106
|
+
import "@iyulab/router";
|
|
107
|
+
|
|
108
|
+
@customElement('app-root')
|
|
109
|
+
export class AppRoot extends LitElement {
|
|
110
|
+
render() {
|
|
111
|
+
return html`
|
|
112
|
+
<nav>
|
|
113
|
+
<u-link href="/">Home</u-link>
|
|
114
|
+
<u-link href="/about">About</u-link>
|
|
115
|
+
<u-link href="/user/123">User Profile</u-link>
|
|
116
|
+
</nav>
|
|
117
|
+
<main>
|
|
118
|
+
<u-outlet></u-outlet>
|
|
119
|
+
</main>
|
|
120
|
+
`;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Using with React Components
|
|
126
|
+
|
|
127
|
+
```tsx
|
|
128
|
+
import React from 'react';
|
|
129
|
+
import { UOutlet, ULink } from '@iyulab/router/react';
|
|
130
|
+
|
|
131
|
+
export function AppRoot() {
|
|
132
|
+
return (
|
|
133
|
+
<div>
|
|
134
|
+
<nav>
|
|
135
|
+
<ULink href="/">Home</ULink>
|
|
136
|
+
<ULink href="/about">About</ULink>
|
|
137
|
+
<ULink href="/user/123">User Profile</ULink>
|
|
138
|
+
</nav>
|
|
139
|
+
<main>
|
|
140
|
+
<UOutlet />
|
|
141
|
+
</main>
|
|
142
|
+
</div>
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Error Handling
|
|
148
|
+
|
|
149
|
+
The router provides comprehensive error handling through `FallbackRouteContext`. When a routing error occurs, the fallback render function receives a context with full error information:
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
const router = new Router({
|
|
153
|
+
root: document.body,
|
|
154
|
+
basepath: '/',
|
|
155
|
+
routes: [...],
|
|
156
|
+
fallback: {
|
|
157
|
+
title: 'Error',
|
|
158
|
+
render: (ctx) => {
|
|
159
|
+
// ctx.error contains RouteError with code, message, and original error
|
|
160
|
+
const { code, message, original } = ctx.error;
|
|
161
|
+
|
|
162
|
+
if (code === 'NOT_FOUND') {
|
|
163
|
+
return html`<not-found-page .path=${ctx.pathname}></not-found-page>`;
|
|
164
|
+
}
|
|
165
|
+
if (code === 'CONTENT_LOAD_ERROR') {
|
|
166
|
+
return html`<error-page .message=${message}></error-page>`;
|
|
167
|
+
}
|
|
168
|
+
return html`<error-page .error=${ctx.error}></error-page>`;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Error types:
|
|
175
|
+
- `NotFoundError` — No matching route found (code: `NOT_FOUND`)
|
|
176
|
+
- `ContentLoadError` — Route render function threw an error (code: `CONTENT_LOAD_ERROR`)
|
|
177
|
+
- `ContentRenderError` — Outlet rendering failed (code: `CONTENT_RENDER_ERROR`)
|
|
178
|
+
|
|
179
|
+
## Route Metadata
|
|
180
|
+
|
|
181
|
+
Routes can carry arbitrary metadata via the `meta` field. When a route matches, metadata from the entire matched route chain is merged (parent → child order, child overrides parent):
|
|
182
|
+
|
|
183
|
+
```typescript
|
|
184
|
+
const router = new Router({
|
|
185
|
+
root: document.body,
|
|
186
|
+
basepath: '/',
|
|
187
|
+
routes: [
|
|
188
|
+
{
|
|
189
|
+
path: '/admin',
|
|
190
|
+
meta: { requiresAuth: true, layout: 'admin' },
|
|
191
|
+
render: (ctx) => {
|
|
192
|
+
// ctx.meta === { requiresAuth: true, layout: 'admin' }
|
|
193
|
+
return html`<admin-layout><u-outlet></u-outlet></admin-layout>`;
|
|
194
|
+
},
|
|
195
|
+
children: [
|
|
196
|
+
{
|
|
197
|
+
path: 'settings',
|
|
198
|
+
meta: { requiresAuth: true, role: 'superadmin' },
|
|
199
|
+
render: (ctx) => {
|
|
200
|
+
// ctx.meta === { requiresAuth: true, layout: 'admin', role: 'superadmin' }
|
|
201
|
+
return html`<admin-settings></admin-settings>`;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
]
|
|
205
|
+
}
|
|
206
|
+
]
|
|
207
|
+
});
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
Use cases: authentication guards, SEO tags, analytics tracking, layout selection, and more.
|
|
211
|
+
|
|
212
|
+
## Route Events
|
|
213
|
+
|
|
214
|
+
The router dispatches events on the `window` object during navigation:
|
|
215
|
+
|
|
216
|
+
| Event | Type | Description |
|
|
217
|
+
|-------|------|-------------|
|
|
218
|
+
| `route-begin` | `RouteBeginEvent` | Fired when navigation starts |
|
|
219
|
+
| `route-progress` | `RouteProgressEvent` | Fired during async loading (0–100) |
|
|
220
|
+
| `route-done` | `RouteDoneEvent` | Fired when navigation completes successfully |
|
|
221
|
+
| `route-error` | `RouteErrorEvent` | Fired when a routing error occurs |
|
|
222
|
+
|
|
223
|
+
```typescript
|
|
224
|
+
// Track navigation progress
|
|
225
|
+
window.addEventListener('route-progress', (e: RouteProgressEvent) => {
|
|
226
|
+
progressBar.value = e.progress;
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
// Log navigation events
|
|
230
|
+
window.addEventListener('route-begin', (e: RouteBeginEvent) => {
|
|
231
|
+
console.log('Navigating to:', e.context.pathname);
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
window.addEventListener('route-done', (e: RouteDoneEvent) => {
|
|
235
|
+
analytics.trackPageView(e.context.pathname);
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
window.addEventListener('route-error', (e: RouteErrorEvent) => {
|
|
239
|
+
errorTracker.report(e.error);
|
|
240
|
+
});
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
## URL Parameters
|
|
244
|
+
|
|
245
|
+
The router supports URLPattern-based parameter matching:
|
|
246
|
+
|
|
247
|
+
```typescript
|
|
248
|
+
const routes: RouteConfig[] = [
|
|
249
|
+
// Required parameter
|
|
250
|
+
{ path: '/user/:id', render: (ctx) => html`<user-page .id=${ctx.params.id}></user-page>` },
|
|
251
|
+
|
|
252
|
+
// Optional parameter
|
|
253
|
+
{ path: '/posts/:category?', render: (ctx) => {
|
|
254
|
+
const category = ctx.params.category || 'all';
|
|
255
|
+
return html`<posts-page .category=${category}></posts-page>`;
|
|
256
|
+
}},
|
|
257
|
+
|
|
258
|
+
// Wildcard (catch-all)
|
|
259
|
+
{ path: '/docs/:path*', render: (ctx) => html`<docs-page .path=${ctx.params.path}></docs-page>` },
|
|
260
|
+
|
|
261
|
+
// Multiple parameters
|
|
262
|
+
{ path: '/org/:orgId/repo/:repoId', render: (ctx) => {
|
|
263
|
+
return html`<repo-page .orgId=${ctx.params.orgId} .repoId=${ctx.params.repoId}></repo-page>`;
|
|
264
|
+
}}
|
|
265
|
+
];
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
When URL parameters change (e.g., navigating from `/user/1` to `/user/2`), leaf routes (without children) automatically re-render since `force` defaults to `true`. For parent routes with children, set `force: true` explicitly if re-rendering is needed on parameter changes.
|
|
269
|
+
|
|
270
|
+
## License
|
|
271
|
+
|
|
272
|
+
MIT License - see [LICENSE](LICENSE) file for details.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { CSSResult } from 'lit';
|
|
2
2
|
import { LitElement } from 'lit';
|
|
3
3
|
import { PropertyValues } from 'lit';
|
|
4
|
-
import {
|
|
5
|
-
import { TemplateResult } from 'lit';
|
|
6
|
-
import { TemplateResult as TemplateResult_2 } from 'lit-html';
|
|
4
|
+
import { TemplateResult } from 'lit-html';
|
|
7
5
|
|
|
8
6
|
/**
|
|
9
7
|
* 공통 라우트 속성
|
|
@@ -48,7 +46,7 @@ declare interface BaseRouteConfig {
|
|
|
48
46
|
* }
|
|
49
47
|
* ```
|
|
50
48
|
*/
|
|
51
|
-
render?: (ctx: RouteContext) => Promise<
|
|
49
|
+
render?: (ctx: RouteContext) => Promise<unknown> | unknown;
|
|
52
50
|
/**
|
|
53
51
|
* 라우터 URL 변경시 렌더링을 강제할지 여부
|
|
54
52
|
* - 기본값으로 children을 가질때 false로 설정되며, children이 없을 경우 true로 설정됩니다.
|
|
@@ -85,8 +83,6 @@ export declare class ContentRenderError extends RouteError {
|
|
|
85
83
|
constructor(original?: Error | any);
|
|
86
84
|
}
|
|
87
85
|
|
|
88
|
-
export declare type FallbackRenderResult = HTMLElement | ReactElement | TemplateResult<1>;
|
|
89
|
-
|
|
90
86
|
export declare interface FallbackRouteConfig {
|
|
91
87
|
/**
|
|
92
88
|
* 브라우저의 타이틀이 설정에 따라 변경됩니다.
|
|
@@ -109,7 +105,7 @@ export declare interface FallbackRouteConfig {
|
|
|
109
105
|
* }
|
|
110
106
|
* ```
|
|
111
107
|
*/
|
|
112
|
-
render?: (ctx: FallbackRouteContext) => Promise<
|
|
108
|
+
render?: (ctx: FallbackRouteContext) => Promise<unknown> | unknown;
|
|
113
109
|
}
|
|
114
110
|
|
|
115
111
|
export declare interface FallbackRouteContext extends RouteContext {
|
|
@@ -161,11 +157,9 @@ declare interface RenderOption {
|
|
|
161
157
|
/** 강제 렌더링 여부 */
|
|
162
158
|
force?: boolean;
|
|
163
159
|
/** 렌더링할 값 */
|
|
164
|
-
value:
|
|
160
|
+
value: unknown;
|
|
165
161
|
}
|
|
166
162
|
|
|
167
|
-
export declare type RenderResult = HTMLElement | ReactElement | TemplateResult<1> | false;
|
|
168
|
-
|
|
169
163
|
/**
|
|
170
164
|
* 라우트 시작 이벤트
|
|
171
165
|
*/
|
|
@@ -415,7 +409,7 @@ export declare class ULink extends LitElement {
|
|
|
415
409
|
connectedCallback(): void;
|
|
416
410
|
disconnectedCallback(): void;
|
|
417
411
|
protected willUpdate(changedProperties: PropertyValues): void;
|
|
418
|
-
render():
|
|
412
|
+
render(): TemplateResult<1>;
|
|
419
413
|
/** a 태그에 주입할 href 값을 계산합니다. */
|
|
420
414
|
private compute;
|
|
421
415
|
/**
|
|
@@ -442,7 +436,7 @@ export declare class UOutlet extends HTMLElement {
|
|
|
442
436
|
/**
|
|
443
437
|
* 주어진 렌더링 옵션에 따라 컨텐츠를 렌더링합니다.
|
|
444
438
|
*/
|
|
445
|
-
render({ id, value, force }: RenderOption): void
|
|
439
|
+
render({ id, value, force }: RenderOption): Promise<void>;
|
|
446
440
|
/**
|
|
447
441
|
* 기존 DOM을 삭제하여, 초기 상태로 되돌립니다.
|
|
448
442
|
*/
|
|
@@ -451,11 +445,11 @@ export declare class UOutlet extends HTMLElement {
|
|
|
451
445
|
|
|
452
446
|
export { }
|
|
453
447
|
|
|
454
|
-
declare global {
|
|
455
|
-
interface WindowEventMap {
|
|
456
|
-
'route-begin': RouteBeginEvent;
|
|
457
|
-
'route-progress': RouteProgressEvent;
|
|
458
|
-
'route-done': RouteDoneEvent;
|
|
459
|
-
'route-error': RouteErrorEvent;
|
|
460
|
-
}
|
|
448
|
+
declare global {
|
|
449
|
+
interface WindowEventMap {
|
|
450
|
+
'route-begin': RouteBeginEvent;
|
|
451
|
+
'route-progress': RouteProgressEvent;
|
|
452
|
+
'route-done': RouteDoneEvent;
|
|
453
|
+
'route-error': RouteErrorEvent;
|
|
454
|
+
}
|
|
461
455
|
}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as absolutePath, i as isExternalUrl, p as parseUrl } from "./share-
|
|
2
|
-
import {
|
|
1
|
+
import { a as absolutePath, i as isExternalUrl, p as parseUrl } from "./share-CG-3Tbuy.js";
|
|
2
|
+
import { U, b } from "./share-CG-3Tbuy.js";
|
|
3
3
|
import { css, LitElement, html } from "lit";
|
|
4
4
|
import { property, customElement } from "lit/decorators.js";
|
|
5
5
|
class RouteError extends Error {
|
|
@@ -102,11 +102,11 @@ let UErrorPage = class extends LitElement {
|
|
|
102
102
|
const codeStr = String(code);
|
|
103
103
|
const numericCode = typeof code === "string" ? parseInt(code) : code;
|
|
104
104
|
switch (codeStr) {
|
|
105
|
-
case "
|
|
105
|
+
case "OUTLET_MISSING":
|
|
106
106
|
return "📦";
|
|
107
107
|
case "CONTENT_LOAD_FAILED":
|
|
108
108
|
return "📡";
|
|
109
|
-
case "
|
|
109
|
+
case "CONTENT_RENDER_FAILED":
|
|
110
110
|
return "🎨";
|
|
111
111
|
}
|
|
112
112
|
switch (numericCode) {
|
|
@@ -189,23 +189,11 @@ function getRandomID() {
|
|
|
189
189
|
return window.isSecureContext ? window.crypto.randomUUID() : window.crypto.getRandomValues(new Uint32Array(1))[0].toString(16);
|
|
190
190
|
}
|
|
191
191
|
function findOutlet(element) {
|
|
192
|
-
if (!element) return void 0;
|
|
193
192
|
if (element.tagName === "U-OUTLET") return element;
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
if (
|
|
198
|
-
for (const child of Array.from(element.shadowRoot.children)) {
|
|
199
|
-
outlet = findOutlet(child);
|
|
200
|
-
if (outlet) return outlet;
|
|
201
|
-
}
|
|
202
|
-
} else {
|
|
203
|
-
outlet = element.querySelector("u-outlet");
|
|
204
|
-
if (outlet) return outlet;
|
|
205
|
-
for (const child of Array.from(element.children)) {
|
|
206
|
-
outlet = findOutlet(child);
|
|
207
|
-
if (outlet) return outlet;
|
|
208
|
-
}
|
|
193
|
+
const root = element.shadowRoot ?? element;
|
|
194
|
+
for (const child of Array.from(root.children)) {
|
|
195
|
+
const result = findOutlet(child);
|
|
196
|
+
if (result) return result;
|
|
209
197
|
}
|
|
210
198
|
return void 0;
|
|
211
199
|
}
|
|
@@ -408,8 +396,8 @@ class Router {
|
|
|
408
396
|
window.dispatchEvent(new RouteDoneEvent(context));
|
|
409
397
|
} catch (error) {
|
|
410
398
|
const routeError = error instanceof RouteError ? error : new RouteError(
|
|
411
|
-
error
|
|
412
|
-
error
|
|
399
|
+
error?.status || error?.code || "UNKNOWN_ERROR",
|
|
400
|
+
error?.message || "An unexpected error occurred",
|
|
413
401
|
error
|
|
414
402
|
);
|
|
415
403
|
window.dispatchEvent(new RouteErrorEvent(context, routeError));
|
|
@@ -447,6 +435,6 @@ export {
|
|
|
447
435
|
RouteErrorEvent,
|
|
448
436
|
RouteProgressEvent,
|
|
449
437
|
Router,
|
|
450
|
-
|
|
451
|
-
|
|
438
|
+
U as ULink,
|
|
439
|
+
b as UOutlet
|
|
452
440
|
};
|
package/dist/react.d.ts
CHANGED
|
@@ -1,96 +1,11 @@
|
|
|
1
|
-
import { CSSResult } from 'lit';
|
|
2
|
-
import { LitElement } from 'lit';
|
|
3
|
-
import { PropertyValues } from 'lit';
|
|
4
|
-
import { ReactElement } from 'react';
|
|
5
|
-
import { ReactWebComponent } from '@lit/react';
|
|
6
|
-
import { TemplateResult } from 'lit-html';
|
|
7
|
-
import { TemplateResult as TemplateResult_2 } from 'lit';
|
|
8
|
-
|
|
9
|
-
/** 렌더링 옵션 */
|
|
10
|
-
declare interface RenderOption {
|
|
11
|
-
/** 교차 렌더링 방지 ID */
|
|
12
|
-
id?: string;
|
|
13
|
-
/** 강제 렌더링 여부 */
|
|
14
|
-
force?: boolean;
|
|
15
|
-
/** 렌더링할 값 */
|
|
16
|
-
value: RenderResult;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
declare type RenderResult = HTMLElement | ReactElement | TemplateResult_2<1> | false;
|
|
20
|
-
|
|
21
1
|
/**
|
|
22
2
|
* `u-link` 웹 컴포넌트를 React에서 사용할 수 있도록 래핑한 컴포넌트입니다.
|
|
23
3
|
*/
|
|
24
|
-
export declare const ULink:
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* - 클라이언트 라우팅을 지원하는 링크 엘리먼트입니다.
|
|
28
|
-
* - 내부 링크는 클라이언트 라우팅을 수행하고, 외부 링크는 브라우저 기본 네비게이션을 사용합니다.
|
|
29
|
-
* - Ctrl/Meta/Shift/Alt, 중클릭/우클릭 등은 브라우저 기본 동작(새 탭, 컨텍스트 메뉴 등)을 그대로 유지합니다.
|
|
30
|
-
*/
|
|
31
|
-
declare class ULink_2 extends LitElement {
|
|
32
|
-
/** 외부 링크 여부 */
|
|
33
|
-
private isExternal;
|
|
34
|
-
/**
|
|
35
|
-
* 링크 대상 target 속성
|
|
36
|
-
*
|
|
37
|
-
* - `_self`: 현재 창에서 링크 열기 (기본값)
|
|
38
|
-
* - `_blank`: 새 탭/창에서 링크 열기
|
|
39
|
-
* - `_parent`: 부모 프레임에서 링크 열기
|
|
40
|
-
* - `_top`: 최상위 프레임에서 링크 열기
|
|
41
|
-
*/
|
|
42
|
-
target?: string;
|
|
43
|
-
/**
|
|
44
|
-
* 링크 대상 URL, 다음 사항에 따라 SPA 라우팅 또는 브라우저 네비게이션이 결정됩니다.
|
|
45
|
-
*
|
|
46
|
-
* - 속성을 정의하지 않으면 설정에서 지정한 `basepath`로 SPA 라우팅합니다.
|
|
47
|
-
* - http(s)로 시작하면 외부 링크로 간주하고 브라우저 네비게이션을 사용합니다.
|
|
48
|
-
* - 절대경로(/...)의 경우 `basepath`로 시작하면 SPA 라우팅합니다, 이외 브라우저 네비게이션을 사용합니다.
|
|
49
|
-
* - 상대경로는 (basepath + 상대경로)로 결합하여 SPA 라우팅합니다.
|
|
50
|
-
* - ?로 시작하면 현재 경로에 쿼리스트링을 추가하여 SPA 라우팅합니다.
|
|
51
|
-
* - #으로 시작하면 브라우저 기본 동작을 사용합니다.
|
|
52
|
-
*/
|
|
53
|
-
href?: string;
|
|
54
|
-
connectedCallback(): void;
|
|
55
|
-
disconnectedCallback(): void;
|
|
56
|
-
protected willUpdate(changedProperties: PropertyValues): void;
|
|
57
|
-
render(): TemplateResult<1>;
|
|
58
|
-
/** a 태그에 주입할 href 값을 계산합니다. */
|
|
59
|
-
private compute;
|
|
60
|
-
/**
|
|
61
|
-
* 클릭 가로채기 핸들러
|
|
62
|
-
* - 좌클릭(0) + 보조키 없음(ctrl/meta/shift/alt 없음) + target이 _self일 때만 SPA 라우팅 고려
|
|
63
|
-
* - 그 외(중클릭/우클릭/보조키/target=_blank 등)는 브라우저 기본 동작 유지
|
|
64
|
-
*/
|
|
65
|
-
private handleClick;
|
|
66
|
-
/** 클라이언트 라우팅을 위해 popstate 이벤트를 발생시킵니다. */
|
|
67
|
-
private dispatchPopstate;
|
|
68
|
-
/** basepath를 state에서 꺼내는 헬퍼 */
|
|
69
|
-
private getBasepath;
|
|
70
|
-
static styles: CSSResult;
|
|
71
|
-
}
|
|
4
|
+
export declare const ULink: any;
|
|
72
5
|
|
|
73
6
|
/**
|
|
74
7
|
* `u-outlet` 웹 컴포넌트를 React에서 사용할 수 있도록 래핑한 컴포넌트입니다.
|
|
75
8
|
*/
|
|
76
|
-
export declare const UOutlet:
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* LitElement 또는 React 컴포넌트를 렌더링해주는 웹컴포넌트 입니다.
|
|
80
|
-
*/
|
|
81
|
-
declare class UOutlet_2 extends HTMLElement {
|
|
82
|
-
/** 교차 렌더링 방지 id */
|
|
83
|
-
private routeId?;
|
|
84
|
-
/** 실제 렌더링 컨텐츠 */
|
|
85
|
-
private root?;
|
|
86
|
-
/**
|
|
87
|
-
* 주어진 렌더링 옵션에 따라 컨텐츠를 렌더링합니다.
|
|
88
|
-
*/
|
|
89
|
-
render({ id, value, force }: RenderOption): void;
|
|
90
|
-
/**
|
|
91
|
-
* 기존 DOM을 삭제하여, 초기 상태로 되돌립니다.
|
|
92
|
-
*/
|
|
93
|
-
reset(): void;
|
|
94
|
-
}
|
|
9
|
+
export declare const UOutlet: any;
|
|
95
10
|
|
|
96
11
|
export { }
|
package/dist/react.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { createComponent } from "@lit/react";
|
|
3
|
-
import {
|
|
3
|
+
import { U as ULink$1, b as UOutlet$1 } from "./share-CG-3Tbuy.js";
|
|
4
4
|
const ULink = createComponent({
|
|
5
5
|
react: React,
|
|
6
6
|
tagName: "u-link",
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import { render, css, LitElement, html } from "lit";
|
|
2
|
-
import { createRoot } from "react-dom/client";
|
|
3
2
|
import { property, customElement } from "lit/decorators.js";
|
|
4
3
|
import { ifDefined } from "lit/directives/if-defined.js";
|
|
5
4
|
class UOutlet extends HTMLElement {
|
|
6
5
|
/**
|
|
7
6
|
* 주어진 렌더링 옵션에 따라 컨텐츠를 렌더링합니다.
|
|
8
7
|
*/
|
|
9
|
-
render({ id, value, force }) {
|
|
8
|
+
async render({ id, value, force }) {
|
|
10
9
|
if (this.routeId === id && force === false) return;
|
|
11
10
|
this.routeId = id;
|
|
12
11
|
this.reset();
|
|
12
|
+
if (value === null) {
|
|
13
|
+
throw new Error("Content is null and cannot be rendered.");
|
|
14
|
+
}
|
|
13
15
|
if (typeof value !== "object") {
|
|
14
16
|
throw new Error("Content is not a valid renderable object.");
|
|
15
17
|
}
|
|
@@ -19,6 +21,7 @@ class UOutlet extends HTMLElement {
|
|
|
19
21
|
} else if ("_$litType$" in value) {
|
|
20
22
|
this.root = render(value, this);
|
|
21
23
|
} else if ("$$typeof" in value) {
|
|
24
|
+
const { createRoot } = await import("react-dom/client");
|
|
22
25
|
this.root = createRoot(this);
|
|
23
26
|
this.root.render(value);
|
|
24
27
|
} else {
|
|
@@ -94,7 +97,7 @@ function catchBasepath(basepath) {
|
|
|
94
97
|
if (match) {
|
|
95
98
|
const rawPath = match.pathname.input;
|
|
96
99
|
const restPath = match.pathname.groups?.["0"];
|
|
97
|
-
return restPath ? rawPath.replace("/" + restPath, "") : rawPath.
|
|
100
|
+
return restPath !== void 0 && restPath !== "" ? rawPath.replace("/" + restPath, "") : rawPath.replace(/\/$/, "");
|
|
98
101
|
}
|
|
99
102
|
pattern = new URLPattern({ pathname: `${basepath}{/}?` });
|
|
100
103
|
match = pattern.exec({ pathname: window.location.pathname });
|
|
@@ -185,7 +188,7 @@ let ULink = class extends LitElement {
|
|
|
185
188
|
}
|
|
186
189
|
/** basepath를 state에서 꺼내는 헬퍼 */
|
|
187
190
|
getBasepath() {
|
|
188
|
-
return window.history.state?.basepath || "";
|
|
191
|
+
return window.history.state?.basepath || "/";
|
|
189
192
|
}
|
|
190
193
|
};
|
|
191
194
|
ULink.styles = css`
|
|
@@ -213,9 +216,9 @@ ULink = __decorateClass([
|
|
|
213
216
|
customElement("u-link")
|
|
214
217
|
], ULink);
|
|
215
218
|
export {
|
|
216
|
-
|
|
219
|
+
ULink as U,
|
|
217
220
|
absolutePath as a,
|
|
218
|
-
|
|
221
|
+
UOutlet as b,
|
|
219
222
|
isExternalUrl as i,
|
|
220
223
|
parseUrl as p
|
|
221
224
|
};
|
package/package.json
CHANGED
|
@@ -1,56 +1,69 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@iyulab/router",
|
|
3
|
-
"version": "0.7.
|
|
4
|
-
"description": "A modern client-side router for web applications with support for Lit and React components",
|
|
5
|
-
"keywords": [
|
|
6
|
-
"lit",
|
|
7
|
-
"react",
|
|
8
|
-
"router",
|
|
9
|
-
"routing",
|
|
10
|
-
"spa",
|
|
11
|
-
"navigation",
|
|
12
|
-
"client-side"
|
|
13
|
-
],
|
|
14
|
-
"license": "MIT",
|
|
15
|
-
"author": "iyulab",
|
|
16
|
-
"repository": {
|
|
17
|
-
"type": "git",
|
|
18
|
-
"url": "https://github.com/iyulab/node-router.git"
|
|
19
|
-
},
|
|
20
|
-
"files": [
|
|
21
|
-
"dist",
|
|
22
|
-
"package.json",
|
|
23
|
-
"README.md",
|
|
24
|
-
"LICENSE"
|
|
25
|
-
],
|
|
26
|
-
"type": "module",
|
|
27
|
-
"types": "dist/index.d.ts",
|
|
28
|
-
"exports": {
|
|
29
|
-
".": {
|
|
30
|
-
"types": "./
|
|
31
|
-
"import": "./
|
|
32
|
-
},
|
|
33
|
-
"./react": {
|
|
34
|
-
"types": "./dist/react.d.ts",
|
|
35
|
-
"import": "./dist/react.js"
|
|
36
|
-
}
|
|
37
|
-
},
|
|
38
|
-
"scripts": {
|
|
39
|
-
"test": "vite",
|
|
40
|
-
"build": "vite build"
|
|
41
|
-
},
|
|
42
|
-
"dependencies": {
|
|
43
|
-
"
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
"react
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
"
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
"
|
|
55
|
-
|
|
56
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@iyulab/router",
|
|
3
|
+
"version": "0.7.3",
|
|
4
|
+
"description": "A modern client-side router for web applications with support for Lit and React components",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"lit",
|
|
7
|
+
"react",
|
|
8
|
+
"router",
|
|
9
|
+
"routing",
|
|
10
|
+
"spa",
|
|
11
|
+
"navigation",
|
|
12
|
+
"client-side"
|
|
13
|
+
],
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"author": "iyulab",
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "https://github.com/iyulab/node-router.git"
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist",
|
|
22
|
+
"package.json",
|
|
23
|
+
"README.md",
|
|
24
|
+
"LICENSE"
|
|
25
|
+
],
|
|
26
|
+
"type": "module",
|
|
27
|
+
"types": "dist/index.d.ts",
|
|
28
|
+
"exports": {
|
|
29
|
+
".": {
|
|
30
|
+
"types": "./dist/index.d.ts",
|
|
31
|
+
"import": "./dist/index.js"
|
|
32
|
+
},
|
|
33
|
+
"./react": {
|
|
34
|
+
"types": "./dist/react.d.ts",
|
|
35
|
+
"import": "./dist/react.js"
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"scripts": {
|
|
39
|
+
"test": "vite",
|
|
40
|
+
"build": "vite build"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"lit": "^3.3.2"
|
|
44
|
+
},
|
|
45
|
+
"peerDependencies": {
|
|
46
|
+
"@lit/react": ">=1.0.0",
|
|
47
|
+
"react": ">=18.0.0",
|
|
48
|
+
"react-dom": ">=18.0.0"
|
|
49
|
+
},
|
|
50
|
+
"peerDependenciesMeta": {
|
|
51
|
+
"react": {
|
|
52
|
+
"optional": true
|
|
53
|
+
},
|
|
54
|
+
"react-dom": {
|
|
55
|
+
"optional": true
|
|
56
|
+
},
|
|
57
|
+
"@lit/react": {
|
|
58
|
+
"optional": true
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
"devDependencies": {
|
|
62
|
+
"@types/node": "^25.3.2",
|
|
63
|
+
"@types/react": "^19.2.14",
|
|
64
|
+
"@types/react-dom": "^19.2.3",
|
|
65
|
+
"typescript": "^5.9.3",
|
|
66
|
+
"vite": "^7.3.1",
|
|
67
|
+
"vite-plugin-dts": "^4.5.4"
|
|
68
|
+
}
|
|
69
|
+
}
|