@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 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.5",
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
+ ```