@iyulab/router 0.7.5 → 0.7.6
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/CHANGELOG.md +155 -0
- package/package.json +3 -1
- package/skills/iyulab-router/SKILL.md +123 -0
- package/skills/iyulab-router/references/REFERENCE.md +175 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [0.7.6] - 2026-04-02
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
- Added `skills/` and `CHANGELOG.md` to npm `files` field — both were missing from the published package, making `npx skills add ./node_modules/@iyulab/router` non-functional
|
|
7
|
+
|
|
8
|
+
## [0.7.5] - 2026-04-02
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
- `@lit/react` promoted from optional peer dependency to direct dependency — React integration now works without a separate `@lit/react` install
|
|
12
|
+
- Added Agent Skills definition (`skills/iyulab-router`) for AI agent tooling support
|
|
13
|
+
|
|
14
|
+
## [0.7.4] - 2026-03-05
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
- `findOutlet()` now searches both shadow DOM and light DOM simultaneously
|
|
18
|
+
|
|
19
|
+
## [0.7.3] - 2026-03-05
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
- **Breaking:** Removed `RenderResult` and `FallbackRenderResult` types — `render` function return type is now `unknown`
|
|
23
|
+
- **Breaking:** Moved React dependencies (`react`, `react-dom`, `@lit/react`) to optional peer dependencies — Lit-only projects no longer require a React install
|
|
24
|
+
- Simplified `findOutlet` — removed shadow/light DOM branching and redundant `querySelector` traversal
|
|
25
|
+
|
|
26
|
+
### Fixed
|
|
27
|
+
- `UOutlet` now dynamically imports `react-dom/client` — prevents import failure in React-free environments
|
|
28
|
+
- Corrected `UErrorPage` error code string mismatches (`OUTLET_NOT_FOUND` → `OUTLET_MISSING`, `RENDER_FAILED` → `CONTENT_RENDER_FAILED`)
|
|
29
|
+
- Fixed edge case in `catchBasepath` where an empty `restPath` was treated as falsy, causing trailing slashes to be dropped
|
|
30
|
+
- Changed `ULink.getBasepath()` fallback from `""` to `"/"` to prevent incorrect path generation on initial access
|
|
31
|
+
- Applied optional chaining in `Router.go()` catch block to prevent property access errors when a primitive value is thrown
|
|
32
|
+
|
|
33
|
+
## [0.7.2] - 2026-02-09
|
|
34
|
+
|
|
35
|
+
### Changed
|
|
36
|
+
- Updated dependencies to latest versions
|
|
37
|
+
|
|
38
|
+
## [0.7.1] - 2026-02-09
|
|
39
|
+
|
|
40
|
+
### Fixed
|
|
41
|
+
- Fixed silent failure when passing `<u-outlet>` element directly as `Router` root (#1)
|
|
42
|
+
- `findOutlet()` now recognizes the root element itself as a valid outlet
|
|
43
|
+
- Improved `waitOutlet()` timeout error message with root element context for easier debugging
|
|
44
|
+
|
|
45
|
+
## [0.7.0] - 2026-02-09
|
|
46
|
+
|
|
47
|
+
### Added
|
|
48
|
+
- `meta` field on `RouteConfig` — attach arbitrary key-value data to any route
|
|
49
|
+
- `RouteContext.meta` — populated at navigation time with metadata merged from the full matched route chain (parent → child order, child overrides parent)
|
|
50
|
+
|
|
51
|
+
## [0.6.2] - 2026-01-21
|
|
52
|
+
|
|
53
|
+
### Changed
|
|
54
|
+
- **Breaking:** Refactored `UOutlet` from `LitElement` to native `HTMLElement` for improved performance and reduced bundle size
|
|
55
|
+
- **Breaking:** `UErrorPage` CSS custom properties renamed: `--route-icon-color` → `--error-icon-color`, `--route-code-color` → `--error-code-color`, `--route-message-color` → `--error-message-color`
|
|
56
|
+
- `ULink` click event handling moved to host element level for better encapsulation
|
|
57
|
+
- `@lit/react` moved from devDependency to dependency for proper React integration
|
|
58
|
+
- `UErrorPage` replaced inline SVG icon imports with emoji icons; SVG asset files removed
|
|
59
|
+
|
|
60
|
+
## [0.6.1] - 2026-01-20
|
|
61
|
+
|
|
62
|
+
### Added
|
|
63
|
+
- Added `global.d.ts` import to main entry point
|
|
64
|
+
|
|
65
|
+
### Changed
|
|
66
|
+
- Moved click event listener from root element to document level for more reliable event handling
|
|
67
|
+
|
|
68
|
+
### Fixed
|
|
69
|
+
- Fixed `UErrorPage` CSS syntax error (trailing semicolon in CSS block)
|
|
70
|
+
- Fixed initial route loading to wait for outlet element readiness before navigation
|
|
71
|
+
|
|
72
|
+
### Removed
|
|
73
|
+
- Removed unused `computedHref` reactive state from `ULink`
|
|
74
|
+
|
|
75
|
+
## [0.6.0] - 2026-01-15
|
|
76
|
+
|
|
77
|
+
### Added
|
|
78
|
+
- Dedicated `react.ts` export entry providing React-compatible `UOutlet` and `ULink` wrappers
|
|
79
|
+
- `ULink` now supports the `target` attribute, enabling standard browser behavior (e.g. `_blank`)
|
|
80
|
+
|
|
81
|
+
### Changed
|
|
82
|
+
- Renamed custom elements: `ErrorPage` → `UErrorPage`, `Link` → `ULink`, `Outlet` → `UOutlet`
|
|
83
|
+
- Refactored internal module organization
|
|
84
|
+
|
|
85
|
+
## [0.5.3] - 2025-12-04
|
|
86
|
+
|
|
87
|
+
### Changed
|
|
88
|
+
- Removed restriction that prevented re-navigation to the current URL
|
|
89
|
+
|
|
90
|
+
## [0.5.2] - 2025-11-17
|
|
91
|
+
|
|
92
|
+
### Added
|
|
93
|
+
- `initialLoad` option on `RouterConfig` — controls whether the router navigates to the current URL on initialization
|
|
94
|
+
- `fallback` option on `RouterConfig` — defines a custom render function for error and not-found states
|
|
95
|
+
- `RouteProgressEvent` dispatched during async route loading
|
|
96
|
+
|
|
97
|
+
### Changed
|
|
98
|
+
- Renamed `RouteInfo` to `RouteContext`; added `progress` callback to context for reporting load progress
|
|
99
|
+
- Improved error handling and display in the built-in error page component
|
|
100
|
+
|
|
101
|
+
### Removed
|
|
102
|
+
- Removed `children` from `NonIndexRouteConfig` to simplify the type interface
|
|
103
|
+
- Removed `route` property from the `window` object to reduce global namespace pollution
|
|
104
|
+
|
|
105
|
+
## [0.5.1] - 2025-11-13
|
|
106
|
+
|
|
107
|
+
### Fixed
|
|
108
|
+
- Improved route error handling
|
|
109
|
+
|
|
110
|
+
## [0.5.0] - 2025-11-12
|
|
111
|
+
|
|
112
|
+
### Changed
|
|
113
|
+
- Route `render` functions now support both synchronous and asynchronous return values
|
|
114
|
+
|
|
115
|
+
### Removed
|
|
116
|
+
- Dropped CommonJS build output — ESM only
|
|
117
|
+
|
|
118
|
+
## [0.4.0] - 2025-11-11
|
|
119
|
+
|
|
120
|
+
### Added
|
|
121
|
+
- `destroy()` method on `Router` to cleanly remove event listeners
|
|
122
|
+
- `useIntercept` option on `RouterConfig` — controls whether anchor tag clicks are intercepted for client-side routing
|
|
123
|
+
- Global type declarations (`global.d.ts`)
|
|
124
|
+
|
|
125
|
+
## [0.3.0] - 2025-10-28
|
|
126
|
+
|
|
127
|
+
### Changed
|
|
128
|
+
- **Breaking:** Complete router architecture overhaul
|
|
129
|
+
- **Breaking:** `RouteConfig` split into `IndexRouteConfig` and `PathRouteConfig`
|
|
130
|
+
- **Breaking:** `RouteError` converted to a class; added `NotFoundRouteError`
|
|
131
|
+
- **Breaking:** Route event names changed: `route-start` → `route-begin`, `route-end` → `route-done`
|
|
132
|
+
- Simplified `Outlet` rendering via a unified `renderContent` method
|
|
133
|
+
|
|
134
|
+
### Added
|
|
135
|
+
- Improved `ErrorPage` component styling and usability
|
|
136
|
+
- Unified route rendering using render functions
|
|
137
|
+
|
|
138
|
+
## [0.2.1] - 2025-10-27
|
|
139
|
+
|
|
140
|
+
### Changed
|
|
141
|
+
- Refactored routing mechanism for improved performance
|
|
142
|
+
- Enhanced error handling with custom error pages
|
|
143
|
+
|
|
144
|
+
### Removed
|
|
145
|
+
- Removed `connect()` and `disconnect()` methods from `Router`
|
|
146
|
+
- Removed `notfound` configuration option
|
|
147
|
+
- Removed legacy route progress events
|
|
148
|
+
- added ErrorPage component for error handling
|
|
149
|
+
- added Route events: `route-start`, `route-end`, `route-error`
|
|
150
|
+
- improved TypeScript types and interfaces
|
|
151
|
+
|
|
152
|
+
## [0.1.0] - 2025-04-25
|
|
153
|
+
|
|
154
|
+
### Added
|
|
155
|
+
- Initial release
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iyulab/router",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.6",
|
|
4
4
|
"description": "A modern client-side router for web applications with support for Lit and React components",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"lit",
|
|
@@ -19,8 +19,10 @@
|
|
|
19
19
|
},
|
|
20
20
|
"files": [
|
|
21
21
|
"dist",
|
|
22
|
+
"skills",
|
|
22
23
|
"package.json",
|
|
23
24
|
"README.md",
|
|
25
|
+
"CHANGELOG.md",
|
|
24
26
|
"LICENSE"
|
|
25
27
|
],
|
|
26
28
|
"type": "module",
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: iyulab-router
|
|
3
|
+
description: Client-side SPA router for Lit and React with URLPattern-based matching, nested routes, fallback handling, and route events. Use when working with @iyulab/router — setting up routing, defining routes, handling navigation, nested layouts with <u-outlet>, or listening to route lifecycle events.
|
|
4
|
+
license: MIT
|
|
5
|
+
compatibility: Browser environments only (requires URLPattern and History API)
|
|
6
|
+
metadata:
|
|
7
|
+
author: iyulab
|
|
8
|
+
version: "0.7.4"
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# @iyulab/router
|
|
12
|
+
|
|
13
|
+
Client-side router supporting Lit and React renders, nested routes, and URLPattern-based matching.
|
|
14
|
+
|
|
15
|
+
## Install
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install @iyulab/router
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Core API
|
|
22
|
+
|
|
23
|
+
| Export | Purpose |
|
|
24
|
+
|---|---|
|
|
25
|
+
| `Router` | Main router class |
|
|
26
|
+
| `RouteConfig` | Route definition type |
|
|
27
|
+
| `RouterConfig` | Constructor config type |
|
|
28
|
+
| `RouteContext` | Passed to every `render()` call |
|
|
29
|
+
| `FallbackRouteConfig` | Error/404 fallback definition |
|
|
30
|
+
| `<u-outlet>` | Renders the matched route output |
|
|
31
|
+
| `<u-link>` | Client-side navigation anchor |
|
|
32
|
+
| `UOutlet`, `ULink` | React wrappers (from `@iyulab/router/react`) |
|
|
33
|
+
|
|
34
|
+
## Router Setup
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
import { Router } from '@iyulab/router';
|
|
38
|
+
import { html } from 'lit';
|
|
39
|
+
|
|
40
|
+
const router = new Router({
|
|
41
|
+
root: document.body, // required — mount element containing <u-outlet>
|
|
42
|
+
basepath: '/', // optional
|
|
43
|
+
routes: [
|
|
44
|
+
{ index: true, render: () => html`<home-page></home-page>` },
|
|
45
|
+
{ path: '/user/:id', render: (ctx) => html`<user-page .id=${ctx.params.id}></user-page>` },
|
|
46
|
+
],
|
|
47
|
+
fallback: {
|
|
48
|
+
render: (ctx) => html`<error-page .error=${ctx.error}></error-page>`
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## RouteConfig Fields
|
|
54
|
+
|
|
55
|
+
| Field | Type | Description |
|
|
56
|
+
|---|---|---|
|
|
57
|
+
| `path` | `string \| URLPattern` | URLPattern path; omit when `index: true` |
|
|
58
|
+
| `index` | `true` | Marks route as index of its parent path |
|
|
59
|
+
| `render` | `(ctx) => unknown` | Returns Lit `TemplateResult`, React element, or `HTMLElement` |
|
|
60
|
+
| `children` | `RouteConfig[]` | Nested routes; parent must render `<u-outlet>` |
|
|
61
|
+
| `title` | `string` | Sets `document.title` on match |
|
|
62
|
+
| `meta` | `Record<string, unknown>` | Arbitrary metadata (auth, layout, analytics) |
|
|
63
|
+
| `force` | `boolean` | Force re-render on URL change (default `true` for leaf routes) |
|
|
64
|
+
|
|
65
|
+
## RouteContext Fields
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
ctx.params // URLPattern captured params
|
|
69
|
+
ctx.pathname // path without query/hash
|
|
70
|
+
ctx.path // full path including query + hash
|
|
71
|
+
ctx.query // URLSearchParams
|
|
72
|
+
ctx.meta // merged meta from matched route chain
|
|
73
|
+
ctx.progress // (value: number) => void — report 0–100 loading progress
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Nested Routes
|
|
77
|
+
|
|
78
|
+
Parent must include `<u-outlet>` in its render output:
|
|
79
|
+
|
|
80
|
+
```ts
|
|
81
|
+
{
|
|
82
|
+
path: '/dashboard',
|
|
83
|
+
render: () => html`<dashboard-layout><u-outlet></u-outlet></dashboard-layout>`,
|
|
84
|
+
children: [
|
|
85
|
+
{ index: true, render: () => html`<dashboard-home></dashboard-home>` },
|
|
86
|
+
{ path: 'settings', render: () => html`<dashboard-settings></dashboard-settings>` }
|
|
87
|
+
]
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Navigation
|
|
92
|
+
|
|
93
|
+
```ts
|
|
94
|
+
router.go('/path'); // programmatic navigation
|
|
95
|
+
router.go('relative-path'); // relative to basepath
|
|
96
|
+
router.destroy(); // remove event listeners
|
|
97
|
+
|
|
98
|
+
// From Lit template
|
|
99
|
+
html`<u-link href="/about">About</u-link>`
|
|
100
|
+
|
|
101
|
+
// From React
|
|
102
|
+
import { ULink } from '@iyulab/router/react';
|
|
103
|
+
<ULink href="/about">About</ULink>
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Route Events (window)
|
|
107
|
+
|
|
108
|
+
| Event | Fired when |
|
|
109
|
+
|---|---|
|
|
110
|
+
| `route-begin` | Navigation starts |
|
|
111
|
+
| `route-progress` | Async progress update (0–100) |
|
|
112
|
+
| `route-done` | Navigation completes |
|
|
113
|
+
| `route-error` | Routing error occurs |
|
|
114
|
+
|
|
115
|
+
## Error Types (fallback ctx.error)
|
|
116
|
+
|
|
117
|
+
| Code | Class |
|
|
118
|
+
|---|---|
|
|
119
|
+
| `NOT_FOUND` | `NotFoundError` |
|
|
120
|
+
| `CONTENT_LOAD_ERROR` | `ContentLoadError` |
|
|
121
|
+
| `CONTENT_RENDER_ERROR` | `ContentRenderError` |
|
|
122
|
+
|
|
123
|
+
See [references/REFERENCE.md](references/REFERENCE.md) for URL parameter patterns, React usage, and advanced examples.
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# @iyulab/router — Reference
|
|
2
|
+
|
|
3
|
+
## URL Parameter Patterns
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
// Required
|
|
7
|
+
{ path: '/user/:id' }
|
|
8
|
+
|
|
9
|
+
// Optional
|
|
10
|
+
{ path: '/posts/:category?' }
|
|
11
|
+
|
|
12
|
+
// Wildcard (catch-all)
|
|
13
|
+
{ path: '/docs/:path*' }
|
|
14
|
+
|
|
15
|
+
// Multiple
|
|
16
|
+
{ path: '/org/:orgId/repo/:repoId' }
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Access via `ctx.params.id`, `ctx.params.category`, etc.
|
|
20
|
+
|
|
21
|
+
## Query String
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
// URL: /search?q=hello&page=2
|
|
25
|
+
ctx.query.get('q') // 'hello'
|
|
26
|
+
ctx.query.get('page') // '2'
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Route Meta
|
|
30
|
+
|
|
31
|
+
Meta from the full matched chain is merged (parent → child, child overrides):
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
{
|
|
35
|
+
path: '/admin',
|
|
36
|
+
meta: { requiresAuth: true, layout: 'admin' },
|
|
37
|
+
render: (ctx) => {
|
|
38
|
+
// ctx.meta === { requiresAuth: true, layout: 'admin' }
|
|
39
|
+
return html`<admin-layout><u-outlet></u-outlet></admin-layout>`;
|
|
40
|
+
},
|
|
41
|
+
children: [
|
|
42
|
+
{
|
|
43
|
+
path: 'settings',
|
|
44
|
+
meta: { role: 'superadmin' },
|
|
45
|
+
render: (ctx) => {
|
|
46
|
+
// ctx.meta === { requiresAuth: true, layout: 'admin', role: 'superadmin' }
|
|
47
|
+
return html`<admin-settings></admin-settings>`;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
]
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Async Render with Progress
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
{
|
|
58
|
+
path: '/user/:id',
|
|
59
|
+
render: async (ctx) => {
|
|
60
|
+
ctx.progress(20);
|
|
61
|
+
const user = await fetchUser(ctx.params.id);
|
|
62
|
+
ctx.progress(80);
|
|
63
|
+
return html`<user-profile .data=${user}></user-profile>`;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Route Events
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
window.addEventListener('route-begin', (e) => {
|
|
72
|
+
console.log('navigating to:', e.context.pathname);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
window.addEventListener('route-progress', (e) => {
|
|
76
|
+
progressBar.value = e.progress; // 0–100
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
window.addEventListener('route-done', (e) => {
|
|
80
|
+
analytics.track(e.context.pathname);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
window.addEventListener('route-error', (e) => {
|
|
84
|
+
errorTracker.report(e.error);
|
|
85
|
+
});
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Error Fallback
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
fallback: {
|
|
92
|
+
render: (ctx) => {
|
|
93
|
+
const { code, message } = ctx.error;
|
|
94
|
+
if (code === 'NOT_FOUND') return html`<not-found-page></not-found-page>`;
|
|
95
|
+
return html`<error-page .message=${message}></error-page>`;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## React Usage
|
|
101
|
+
|
|
102
|
+
```tsx
|
|
103
|
+
import { UOutlet, ULink } from '@iyulab/router/react';
|
|
104
|
+
|
|
105
|
+
export function AppRoot() {
|
|
106
|
+
return (
|
|
107
|
+
<div>
|
|
108
|
+
<nav>
|
|
109
|
+
<ULink href="/">Home</ULink>
|
|
110
|
+
<ULink href="/about">About</ULink>
|
|
111
|
+
</nav>
|
|
112
|
+
<main>
|
|
113
|
+
<UOutlet />
|
|
114
|
+
</main>
|
|
115
|
+
</div>
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Mixed Lit + React routes:
|
|
121
|
+
|
|
122
|
+
```ts
|
|
123
|
+
const routes = [
|
|
124
|
+
{
|
|
125
|
+
path: '/lit-page',
|
|
126
|
+
render: () => html`<my-lit-component></my-lit-component>`
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
path: '/react-page',
|
|
130
|
+
render: () => <MyReactComponent />
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
path: '/raw-element',
|
|
134
|
+
render: (ctx) => {
|
|
135
|
+
const el = document.createElement('my-element');
|
|
136
|
+
el.data = ctx.params;
|
|
137
|
+
return el;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
];
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## RouterConfig Options
|
|
144
|
+
|
|
145
|
+
| Option | Default | Description |
|
|
146
|
+
|---|---|---|
|
|
147
|
+
| `root` | — | Mount element (required) |
|
|
148
|
+
| `basepath` | `'/'` | URL base path |
|
|
149
|
+
| `routes` | `[]` | Route definitions |
|
|
150
|
+
| `fallback` | built-in error page | Error/404 handler |
|
|
151
|
+
| `useIntercept` | `true` | Intercept `<a>` clicks for client routing |
|
|
152
|
+
| `initialLoad` | `true` | Auto-navigate to current URL on init |
|
|
153
|
+
|
|
154
|
+
## Lit Element Integration
|
|
155
|
+
|
|
156
|
+
```ts
|
|
157
|
+
import "@iyulab/router"; // registers <u-outlet> and <u-link>
|
|
158
|
+
import { LitElement, html } from 'lit';
|
|
159
|
+
import { customElement } from 'lit/decorators.js';
|
|
160
|
+
|
|
161
|
+
@customElement('app-root')
|
|
162
|
+
export class AppRoot extends LitElement {
|
|
163
|
+
render() {
|
|
164
|
+
return html`
|
|
165
|
+
<nav>
|
|
166
|
+
<u-link href="/">Home</u-link>
|
|
167
|
+
<u-link href="/about">About</u-link>
|
|
168
|
+
</nav>
|
|
169
|
+
<main>
|
|
170
|
+
<u-outlet></u-outlet>
|
|
171
|
+
</main>
|
|
172
|
+
`;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
```
|