@iyulab/router 0.6.0 โ 0.6.2
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 +37 -37
- package/dist/index.d.ts +36 -29
- package/dist/index.js +59 -118
- package/dist/react.d.ts +34 -27
- package/dist/react.js +4 -29
- package/dist/{share-ZrQFmsur.js โ share-6Zs4TunA.js} +53 -86
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -6,13 +6,9 @@ A modern, lightweight client-side router for web applications with support for b
|
|
|
6
6
|
|
|
7
7
|
- ๐ **Modern URLPattern-based routing** - Uses native URLPattern API for powerful path matching
|
|
8
8
|
- ๐ง **Unified Framework Support** - Works with both Lit and React components using render functions
|
|
9
|
-
- ๐ฑ **Client-
|
|
9
|
+
- ๐ฑ **Client-Side Navigation** - History API integration with browser back/forward support
|
|
10
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
11
|
- ๐ **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
12
|
- โ ๏ธ **Enhanced Error Handling** - Built-in ErrorPage component with improved styling
|
|
17
13
|
|
|
18
14
|
## Installation
|
|
@@ -30,43 +26,18 @@ import { Router } from '@iyulab/router';
|
|
|
30
26
|
import { html } from 'lit';
|
|
31
27
|
|
|
32
28
|
const router = new Router({
|
|
33
|
-
|
|
34
|
-
basepath: '/app',
|
|
29
|
+
basepath: '/',
|
|
35
30
|
routes: [
|
|
36
31
|
{
|
|
37
32
|
index: true,
|
|
38
33
|
render: () => html`<home-page></home-page>`
|
|
39
34
|
},
|
|
40
35
|
{
|
|
41
|
-
path: '/user/:id',
|
|
36
|
+
path: '/user/:id', // URLPattern route
|
|
42
37
|
render: (routeInfo) => html`<user-page .userId=${routeInfo.params.id}></user-page>`
|
|
43
38
|
}
|
|
44
|
-
]
|
|
39
|
+
],
|
|
45
40
|
});
|
|
46
|
-
|
|
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
|
-
];
|
|
70
41
|
```
|
|
71
42
|
|
|
72
43
|
### Mixed Framework Support
|
|
@@ -78,12 +49,16 @@ const routes = [
|
|
|
78
49
|
// Lit component
|
|
79
50
|
{
|
|
80
51
|
path: '/lit-page',
|
|
81
|
-
render: (routeInfo) =>
|
|
52
|
+
render: (routeInfo) => {
|
|
53
|
+
return html`<my-lit-component .routeInfo=${routeInfo}></my-lit-component>`
|
|
54
|
+
}
|
|
82
55
|
},
|
|
83
56
|
// React component
|
|
84
57
|
{
|
|
85
58
|
path: '/react-page',
|
|
86
|
-
render: (routeInfo) =>
|
|
59
|
+
render: (routeInfo) => {
|
|
60
|
+
return ( <MyComponent></MyComponent> )
|
|
61
|
+
}
|
|
87
62
|
},
|
|
88
63
|
// HTML element
|
|
89
64
|
{
|
|
@@ -97,14 +72,39 @@ const routes = [
|
|
|
97
72
|
];
|
|
98
73
|
```
|
|
99
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
|
+
|
|
100
98
|
## Usage Examples
|
|
101
99
|
|
|
102
|
-
### Using with Lit
|
|
100
|
+
### Using with Lit Elements
|
|
103
101
|
|
|
104
102
|
```typescript
|
|
105
103
|
import { LitElement, html } from 'lit';
|
|
106
104
|
import { customElement } from 'lit/decorators.js';
|
|
107
105
|
|
|
106
|
+
import "@iyulab/router";
|
|
107
|
+
|
|
108
108
|
@customElement('app-root')
|
|
109
109
|
export class AppRoot extends LitElement {
|
|
110
110
|
render() {
|
|
@@ -146,4 +146,4 @@ export function AppRoot() {
|
|
|
146
146
|
|
|
147
147
|
## License
|
|
148
148
|
|
|
149
|
-
MIT License - see [LICENSE](LICENSE) file for details.
|
|
149
|
+
MIT License - see [LICENSE](LICENSE) file for details.
|
package/dist/index.d.ts
CHANGED
|
@@ -145,10 +145,14 @@ export declare class OutletMissingError extends RouteError {
|
|
|
145
145
|
constructor();
|
|
146
146
|
}
|
|
147
147
|
|
|
148
|
+
/** ๋ ๋๋ง ์ต์
*/
|
|
148
149
|
declare interface RenderOption {
|
|
150
|
+
/** ๊ต์ฐจ ๋ ๋๋ง ๋ฐฉ์ง ID */
|
|
149
151
|
id?: string;
|
|
152
|
+
/** ๊ฐ์ ๋ ๋๋ง ์ฌ๋ถ */
|
|
150
153
|
force?: boolean;
|
|
151
|
-
|
|
154
|
+
/** ๋ ๋๋งํ ๊ฐ */
|
|
155
|
+
value: RenderResult;
|
|
152
156
|
}
|
|
153
157
|
|
|
154
158
|
export declare type RenderResult = HTMLElement | ReactElement | TemplateResult<1> | false;
|
|
@@ -297,7 +301,7 @@ export declare class RouteProgressEvent extends RouteEvent {
|
|
|
297
301
|
}
|
|
298
302
|
|
|
299
303
|
/**
|
|
300
|
-
* `lit-element`, `react`๋ฅผ ์ง์ํ๋ ํด๋ผ์ด์ธํธ
|
|
304
|
+
* `lit-element`, `react`๋ฅผ ์ง์ํ๋ SPA ํด๋ผ์ด์ธํธ ๋ผ์ฐํฐ ๊ฐ์ฒด์
๋๋ค.
|
|
301
305
|
*/
|
|
302
306
|
export declare class Router {
|
|
303
307
|
private readonly _rootElement;
|
|
@@ -325,7 +329,7 @@ export declare class Router {
|
|
|
325
329
|
/** ๋ธ๋ผ์ฐ์ ํ์คํ ๋ฆฌ ์ด๋ฒคํธ๊ฐ ๋ฐ์์ ๋ผ์ฐํ
์ฒ๋ฆฌ */
|
|
326
330
|
private handleWindowPopstate;
|
|
327
331
|
/** ํด๋ฆญ ์ด๋ฒคํธ์์ ๋ผ์ฐํฐ๋ก ์ฒ๋ฆฌํ ์ต์ปค๋ฅผ ์ฐพ์ ํด๋ผ์ด์ธํธ ๋ผ์ฐํ
์ํ */
|
|
328
|
-
private
|
|
332
|
+
private handleDocumentClick;
|
|
329
333
|
}
|
|
330
334
|
|
|
331
335
|
/**
|
|
@@ -374,58 +378,61 @@ export declare interface RouterConfig {
|
|
|
374
378
|
export declare class ULink extends LitElement {
|
|
375
379
|
/** ์ธ๋ถ ๋งํฌ ์ฌ๋ถ */
|
|
376
380
|
private isExternal;
|
|
377
|
-
/** a ํ๊ทธ์ ์ฃผ์
ํ href ๊ฐ */
|
|
378
|
-
computedHref: string;
|
|
379
381
|
/**
|
|
380
|
-
*
|
|
381
|
-
*
|
|
382
|
+
* ๋งํฌ ๋์ target ์์ฑ
|
|
383
|
+
*
|
|
384
|
+
* - `_self`: ํ์ฌ ์ฐฝ์์ ๋งํฌ ์ด๊ธฐ (๊ธฐ๋ณธ๊ฐ)
|
|
385
|
+
* - `_blank`: ์ ํญ/์ฐฝ์์ ๋งํฌ ์ด๊ธฐ
|
|
386
|
+
* - `_parent`: ๋ถ๋ชจ ํ๋ ์์์ ๋งํฌ ์ด๊ธฐ
|
|
387
|
+
* - `_top`: ์ต์์ ํ๋ ์์์ ๋งํฌ ์ด๊ธฐ
|
|
382
388
|
*/
|
|
383
389
|
target?: string;
|
|
384
390
|
/**
|
|
385
|
-
*
|
|
391
|
+
* ๋งํฌ ๋์ URL, ๋ค์ ์ฌํญ์ ๋ฐ๋ผ SPA ๋ผ์ฐํ
๋๋ ๋ธ๋ผ์ฐ์ ๋ค๋น๊ฒ์ด์
์ด ๊ฒฐ์ ๋ฉ๋๋ค.
|
|
392
|
+
*
|
|
393
|
+
* - ์์ฑ์ ์ ์ํ์ง ์์ผ๋ฉด ์ค์ ์์ ์ง์ ํ `basepath`๋ก SPA ๋ผ์ฐํ
ํฉ๋๋ค.
|
|
386
394
|
* - http(s)๋ก ์์ํ๋ฉด ์ธ๋ถ ๋งํฌ๋ก ๊ฐ์ฃผํ๊ณ ๋ธ๋ผ์ฐ์ ๋ค๋น๊ฒ์ด์
์ ์ฌ์ฉํฉ๋๋ค.
|
|
387
|
-
* - ์ ๋๊ฒฝ๋ก(/...)
|
|
388
|
-
* - ์๋๊ฒฝ๋ก๋ (basepath + ์๋๊ฒฝ๋ก)๋ก SPA
|
|
389
|
-
* - ?๋ก ์์ํ๋ฉด ํ์ฌ
|
|
390
|
-
* - #์ผ๋ก ์์ํ๋ฉด
|
|
395
|
+
* - ์ ๋๊ฒฝ๋ก(/...)์ ๊ฒฝ์ฐ `basepath`๋ก ์์ํ๋ฉด SPA ๋ผ์ฐํ
ํฉ๋๋ค, ์ด์ธ ๋ธ๋ผ์ฐ์ ๋ค๋น๊ฒ์ด์
์ ์ฌ์ฉํฉ๋๋ค.
|
|
396
|
+
* - ์๋๊ฒฝ๋ก๋ (basepath + ์๋๊ฒฝ๋ก)๋ก ๊ฒฐํฉํ์ฌ SPA ๋ผ์ฐํ
ํฉ๋๋ค.
|
|
397
|
+
* - ?๋ก ์์ํ๋ฉด ํ์ฌ ๊ฒฝ๋ก์ ์ฟผ๋ฆฌ์คํธ๋ง์ ์ถ๊ฐํ์ฌ SPA ๋ผ์ฐํ
ํฉ๋๋ค.
|
|
398
|
+
* - #์ผ๋ก ์์ํ๋ฉด ๋ธ๋ผ์ฐ์ ๊ธฐ๋ณธ ๋์์ ์ฌ์ฉํฉ๋๋ค.
|
|
391
399
|
*/
|
|
392
400
|
href?: string;
|
|
401
|
+
connectedCallback(): void;
|
|
402
|
+
disconnectedCallback(): void;
|
|
393
403
|
protected willUpdate(changedProperties: PropertyValues): void;
|
|
394
404
|
render(): TemplateResult_2<1>;
|
|
395
|
-
/** basepath๋ฅผ state์์ ๊บผ๋ด๋ ํฌํผ */
|
|
396
|
-
private getBasepath;
|
|
397
405
|
/** a ํ๊ทธ์ ์ฃผ์
ํ href ๊ฐ์ ๊ณ์ฐํฉ๋๋ค. */
|
|
398
|
-
private
|
|
406
|
+
private compute;
|
|
399
407
|
/**
|
|
400
|
-
* ํด๋ฆญ ๊ฐ๋ก์ฑ๊ธฐ
|
|
408
|
+
* ํด๋ฆญ ๊ฐ๋ก์ฑ๊ธฐ ํธ๋ค๋ฌ
|
|
401
409
|
* - ์ขํด๋ฆญ(0) + ๋ณด์กฐํค ์์(ctrl/meta/shift/alt ์์) + target์ด _self์ผ ๋๋ง SPA ๋ผ์ฐํ
๊ณ ๋ ค
|
|
402
410
|
* - ๊ทธ ์ธ(์คํด๋ฆญ/์ฐํด๋ฆญ/๋ณด์กฐํค/target=_blank ๋ฑ)๋ ๋ธ๋ผ์ฐ์ ๊ธฐ๋ณธ ๋์ ์ ์ง
|
|
403
411
|
*/
|
|
404
|
-
private
|
|
412
|
+
private handleClick;
|
|
405
413
|
/** ํด๋ผ์ด์ธํธ ๋ผ์ฐํ
์ ์ํด popstate ์ด๋ฒคํธ๋ฅผ ๋ฐ์์ํต๋๋ค. */
|
|
406
414
|
private dispatchPopstate;
|
|
415
|
+
/** basepath๋ฅผ state์์ ๊บผ๋ด๋ ํฌํผ */
|
|
416
|
+
private getBasepath;
|
|
407
417
|
static styles: CSSResult;
|
|
408
418
|
}
|
|
409
419
|
|
|
410
420
|
/**
|
|
411
|
-
*
|
|
421
|
+
* LitElement ๋๋ React ์ปดํฌ๋ํธ๋ฅผ ๋ ๋๋งํด์ฃผ๋ ์น์ปดํฌ๋ํธ ์
๋๋ค.
|
|
412
422
|
*/
|
|
413
|
-
export declare class UOutlet extends
|
|
423
|
+
export declare class UOutlet extends HTMLElement {
|
|
424
|
+
/** ๊ต์ฐจ ๋ ๋๋ง ๋ฐฉ์ง id */
|
|
414
425
|
private routeId?;
|
|
415
|
-
|
|
416
|
-
private
|
|
417
|
-
/** ์ธ๋ถ ์คํ์ผ์ ์ ์ฉํ๊ธฐ ์ํด ๋ผ์ดํธ ๋์์ฌ์ฉ ํฉ๋๋ค. */
|
|
418
|
-
protected createRenderRoot(): this;
|
|
419
|
-
render(): TemplateResult<1>;
|
|
426
|
+
/** ์ค์ ๋ ๋๋ง ์ปจํ
์ธ */
|
|
427
|
+
private root?;
|
|
420
428
|
/**
|
|
421
|
-
*
|
|
422
|
-
* - HTMLElement, ReactElement, TemplateResult๋ฅผ ๋ชจ๋ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.
|
|
429
|
+
* ์ฃผ์ด์ง ๋ ๋๋ง ์ต์
์ ๋ฐ๋ผ ์ปจํ
์ธ ๋ฅผ ๋ ๋๋งํฉ๋๋ค.
|
|
423
430
|
*/
|
|
424
|
-
|
|
431
|
+
render({ id, value, force }: RenderOption): void;
|
|
425
432
|
/**
|
|
426
|
-
* ๊ธฐ์กด DOM์
|
|
433
|
+
* ๊ธฐ์กด DOM์ ์ญ์ ํ์ฌ, ์ด๊ธฐ ์ํ๋ก ๋๋๋ฆฝ๋๋ค.
|
|
427
434
|
*/
|
|
428
|
-
|
|
435
|
+
reset(): void;
|
|
429
436
|
}
|
|
430
437
|
|
|
431
438
|
export { }
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { a as absolutePath, i as isExternalUrl, p as parseUrl } from "./share-
|
|
2
|
-
import { b, U } from "./share-
|
|
1
|
+
import { a as absolutePath, i as isExternalUrl, p as parseUrl } from "./share-6Zs4TunA.js";
|
|
2
|
+
import { b, U } from "./share-6Zs4TunA.js";
|
|
3
3
|
import { css, LitElement, html } from "lit";
|
|
4
4
|
import { property, customElement } from "lit/decorators.js";
|
|
5
|
-
import { unsafeHTML } from "lit-html/directives/unsafe-html.js";
|
|
6
5
|
class RouteError extends Error {
|
|
7
6
|
constructor(code, message, original) {
|
|
8
7
|
super(message);
|
|
@@ -74,51 +73,6 @@ class RouteErrorEvent extends RouteEvent {
|
|
|
74
73
|
this.error = error;
|
|
75
74
|
}
|
|
76
75
|
}
|
|
77
|
-
const ban = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">\n <path d="M15 8a6.97 6.97 0 0 0-1.71-4.584l-9.874 9.875A7 7 0 0 0 15 8M2.71 12.584l9.874-9.875a7 7 0 0 0-9.874 9.874ZM16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0"/>\n</svg>';
|
|
78
|
-
const __vite_glob_0_0 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
79
|
-
__proto__: null,
|
|
80
|
-
default: ban
|
|
81
|
-
}, Symbol.toStringTag, { value: "Module" }));
|
|
82
|
-
const boxSeam = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">\n <path d="M8.186 1.113a.5.5 0 0 0-.372 0L1.846 3.5l2.404.961L10.404 2zm3.564 1.426L5.596 5 8 5.961 14.154 3.5zm3.25 1.7-6.5 2.6v7.922l6.5-2.6V4.24zM7.5 14.762V6.838L1 4.239v7.923zM7.443.184a1.5 1.5 0 0 1 1.114 0l7.129 2.852A.5.5 0 0 1 16 3.5v8.662a1 1 0 0 1-.629.928l-7.185 2.874a.5.5 0 0 1-.372 0L.63 13.09a1 1 0 0 1-.63-.928V3.5a.5.5 0 0 1 .314-.464z"/>\n</svg>';
|
|
83
|
-
const __vite_glob_0_1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
84
|
-
__proto__: null,
|
|
85
|
-
default: boxSeam
|
|
86
|
-
}, Symbol.toStringTag, { value: "Module" }));
|
|
87
|
-
const exclamationTriangle = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">\n <path d="M7.938 2.016A.13.13 0 0 1 8.002 2a.13.13 0 0 1 .063.016.15.15 0 0 1 .054.057l6.857 11.667c.036.06.035.124.002.183a.2.2 0 0 1-.054.06.1.1 0 0 1-.066.017H1.146a.1.1 0 0 1-.066-.017.2.2 0 0 1-.054-.06.18.18 0 0 1 .002-.183L7.884 2.073a.15.15 0 0 1 .054-.057m1.044-.45a1.13 1.13 0 0 0-1.96 0L.165 13.233c-.457.778.091 1.767.98 1.767h13.713c.889 0 1.438-.99.98-1.767z"/>\n <path d="M7.002 12a1 1 0 1 1 2 0 1 1 0 0 1-2 0M7.1 5.995a.905.905 0 1 1 1.8 0l-.35 3.507a.552.552 0 0 1-1.1 0z"/>\n</svg>';
|
|
88
|
-
const __vite_glob_0_2 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
89
|
-
__proto__: null,
|
|
90
|
-
default: exclamationTriangle
|
|
91
|
-
}, Symbol.toStringTag, { value: "Module" }));
|
|
92
|
-
const palette = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">\n <path d="M8 5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3m4 3a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3M5.5 7a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0m.5 6a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3"/>\n <path d="M16 8c0 3.15-1.866 2.585-3.567 2.07C11.42 9.763 10.465 9.473 10 10c-.603.683-.475 1.819-.351 2.92C9.826 14.495 9.996 16 8 16a8 8 0 1 1 8-8m-8 7c.611 0 .654-.171.655-.176.078-.146.124-.464.07-1.119-.014-.168-.037-.37-.061-.591-.052-.464-.112-1.005-.118-1.462-.01-.707.083-1.61.704-2.314.369-.417.845-.578 1.272-.618.404-.038.812.026 1.16.104.343.077.702.186 1.025.284l.028.008c.346.105.658.199.953.266.653.148.904.083.991.024C14.717 9.38 15 9.161 15 8a7 7 0 1 0-7 7"/>\n</svg>';
|
|
93
|
-
const __vite_glob_0_3 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
94
|
-
__proto__: null,
|
|
95
|
-
default: palette
|
|
96
|
-
}, Symbol.toStringTag, { value: "Module" }));
|
|
97
|
-
const personLock = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">\n <path d="M11 5a3 3 0 1 1-6 0 3 3 0 0 1 6 0M8 7a2 2 0 1 0 0-4 2 2 0 0 0 0 4m0 5.996V14H3s-1 0-1-1 1-4 6-4q.845.002 1.544.107a4.5 4.5 0 0 0-.803.918A11 11 0 0 0 8 10c-2.29 0-3.516.68-4.168 1.332-.678.678-.83 1.418-.832 1.664zM9 13a1 1 0 0 1 1-1v-1a2 2 0 1 1 4 0v1a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1h-4a1 1 0 0 1-1-1zm3-3a1 1 0 0 0-1 1v1h2v-1a1 1 0 0 0-1-1"/>\n</svg>';
|
|
98
|
-
const __vite_glob_0_4 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
99
|
-
__proto__: null,
|
|
100
|
-
default: personLock
|
|
101
|
-
}, Symbol.toStringTag, { value: "Module" }));
|
|
102
|
-
const search = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">\n <path d="M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001q.044.06.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1 1 0 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0"/>\n</svg>';
|
|
103
|
-
const __vite_glob_0_5 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
104
|
-
__proto__: null,
|
|
105
|
-
default: search
|
|
106
|
-
}, Symbol.toStringTag, { value: "Module" }));
|
|
107
|
-
const stopwatch = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">\n <path d="M8.5 5.6a.5.5 0 1 0-1 0v2.9h-3a.5.5 0 0 0 0 1H8a.5.5 0 0 0 .5-.5z"/>\n <path d="M6.5 1A.5.5 0 0 1 7 .5h2a.5.5 0 0 1 0 1v.57c1.36.196 2.594.78 3.584 1.64l.012-.013.354-.354-.354-.353a.5.5 0 0 1 .707-.708l1.414 1.415a.5.5 0 1 1-.707.707l-.353-.354-.354.354-.013.012A7 7 0 1 1 7 2.071V1.5a.5.5 0 0 1-.5-.5M8 3a6 6 0 1 0 .001 12A6 6 0 0 0 8 3"/>\n</svg>';
|
|
108
|
-
const __vite_glob_0_6 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
109
|
-
__proto__: null,
|
|
110
|
-
default: stopwatch
|
|
111
|
-
}, Symbol.toStringTag, { value: "Module" }));
|
|
112
|
-
const wifiOff = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">\n <path d="M10.706 3.294A12.6 12.6 0 0 0 8 3C5.259 3 2.723 3.882.663 5.379a.485.485 0 0 0-.048.736.52.52 0 0 0 .668.05A11.45 11.45 0 0 1 8 4q.946 0 1.852.148zM8 6c-1.905 0-3.68.56-5.166 1.526a.48.48 0 0 0-.063.745.525.525 0 0 0 .652.065 8.45 8.45 0 0 1 3.51-1.27zm2.596 1.404.785-.785q.947.362 1.785.907a.482.482 0 0 1 .063.745.525.525 0 0 1-.652.065 8.5 8.5 0 0 0-1.98-.932zM8 10l.933-.933a6.5 6.5 0 0 1 2.013.637c.285.145.326.524.1.75l-.015.015a.53.53 0 0 1-.611.09A5.5 5.5 0 0 0 8 10m4.905-4.905.747-.747q.886.451 1.685 1.03a.485.485 0 0 1 .047.737.52.52 0 0 1-.668.05 11.5 11.5 0 0 0-1.811-1.07M9.02 11.78c.238.14.236.464.04.66l-.707.706a.5.5 0 0 1-.707 0l-.707-.707c-.195-.195-.197-.518.04-.66A2 2 0 0 1 8 11.5c.374 0 .723.102 1.021.28zm4.355-9.905a.53.53 0 0 1 .75.75l-10.75 10.75a.53.53 0 0 1-.75-.75z"/>\n</svg>';
|
|
113
|
-
const __vite_glob_0_7 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
114
|
-
__proto__: null,
|
|
115
|
-
default: wifiOff
|
|
116
|
-
}, Symbol.toStringTag, { value: "Module" }));
|
|
117
|
-
const wrenchAdjustable = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">\n <path d="M16 4.5a4.5 4.5 0 0 1-1.703 3.526L13 5l2.959-1.11q.04.3.041.61"/>\n <path d="M11.5 9c.653 0 1.273-.139 1.833-.39L12 5.5 11 3l3.826-1.53A4.5 4.5 0 0 0 7.29 6.092l-6.116 5.096a2.583 2.583 0 1 0 3.638 3.638L9.908 8.71A4.5 4.5 0 0 0 11.5 9m-1.292-4.361-.596.893.809-.27a.25.25 0 0 1 .287.377l-.596.893.809-.27.158.475-1.5.5a.25.25 0 0 1-.287-.376l.596-.893-.809.27a.25.25 0 0 1-.287-.377l.596-.893-.809.27-.158-.475 1.5-.5a.25.25 0 0 1 .287.376M3 14a1 1 0 1 1 0-2 1 1 0 0 1 0 2"/>\n</svg>';
|
|
118
|
-
const __vite_glob_0_8 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
119
|
-
__proto__: null,
|
|
120
|
-
default: wrenchAdjustable
|
|
121
|
-
}, Symbol.toStringTag, { value: "Module" }));
|
|
122
76
|
var __defProp = Object.defineProperty;
|
|
123
77
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
124
78
|
var __decorateClass = (decorators, target, key, kind) => {
|
|
@@ -129,27 +83,12 @@ var __decorateClass = (decorators, target, key, kind) => {
|
|
|
129
83
|
if (kind && result) __defProp(target, key, result);
|
|
130
84
|
return result;
|
|
131
85
|
};
|
|
132
|
-
const icons = Object.entries(/* @__PURE__ */ Object.assign({
|
|
133
|
-
"../assets/ban.svg": __vite_glob_0_0,
|
|
134
|
-
"../assets/box-seam.svg": __vite_glob_0_1,
|
|
135
|
-
"../assets/exclamation-triangle.svg": __vite_glob_0_2,
|
|
136
|
-
"../assets/palette.svg": __vite_glob_0_3,
|
|
137
|
-
"../assets/person-lock.svg": __vite_glob_0_4,
|
|
138
|
-
"../assets/search.svg": __vite_glob_0_5,
|
|
139
|
-
"../assets/stopwatch.svg": __vite_glob_0_6,
|
|
140
|
-
"../assets/wifi-off.svg": __vite_glob_0_7,
|
|
141
|
-
"../assets/wrench-adjustable.svg": __vite_glob_0_8
|
|
142
|
-
})).reduce((acc, [path, content]) => {
|
|
143
|
-
const name = path.split("/").pop()?.replace(".svg", "") || "";
|
|
144
|
-
acc[name] = content.default;
|
|
145
|
-
return acc;
|
|
146
|
-
}, {});
|
|
147
86
|
let UErrorPage = class extends LitElement {
|
|
148
87
|
render() {
|
|
149
88
|
const error = this.error || this.getDefaultError();
|
|
150
89
|
const icon = this.getErrorIcon(error.code);
|
|
151
90
|
return html`
|
|
152
|
-
<div class="icon">${
|
|
91
|
+
<div class="icon">${icon}</div>
|
|
153
92
|
<div class="code">${error.code}</div>
|
|
154
93
|
<div class="message">${error.message}</div>
|
|
155
94
|
`;
|
|
@@ -164,55 +103,55 @@ let UErrorPage = class extends LitElement {
|
|
|
164
103
|
const numericCode = typeof code === "string" ? parseInt(code) : code;
|
|
165
104
|
switch (codeStr) {
|
|
166
105
|
case "OUTLET_NOT_FOUND":
|
|
167
|
-
return
|
|
106
|
+
return "๐ฆ";
|
|
168
107
|
case "CONTENT_LOAD_FAILED":
|
|
169
|
-
return
|
|
108
|
+
return "๐ก";
|
|
170
109
|
case "RENDER_FAILED":
|
|
171
|
-
return
|
|
110
|
+
return "๐จ";
|
|
172
111
|
}
|
|
173
112
|
switch (numericCode) {
|
|
174
113
|
case 404:
|
|
175
|
-
return
|
|
114
|
+
return "๐";
|
|
176
115
|
case 403:
|
|
177
|
-
return
|
|
116
|
+
return "๐ซ";
|
|
178
117
|
case 401:
|
|
179
|
-
return
|
|
118
|
+
return "๐";
|
|
180
119
|
case 429:
|
|
181
|
-
return
|
|
120
|
+
return "โฑ๏ธ";
|
|
182
121
|
case 503:
|
|
183
|
-
return
|
|
122
|
+
return "๐ ๏ธ";
|
|
184
123
|
default:
|
|
185
|
-
return
|
|
124
|
+
return "โ ๏ธ";
|
|
186
125
|
}
|
|
187
126
|
}
|
|
188
127
|
};
|
|
189
128
|
UErrorPage.styles = css`
|
|
190
129
|
:host {
|
|
191
|
-
--
|
|
192
|
-
--
|
|
193
|
-
--
|
|
130
|
+
--error-icon-color: #4a5568;
|
|
131
|
+
--error-code-color: #1a202c;
|
|
132
|
+
--error-message-color: #718096;
|
|
194
133
|
}
|
|
195
134
|
:host-context([theme="dark"]) {
|
|
196
|
-
--
|
|
197
|
-
--
|
|
198
|
-
--
|
|
135
|
+
--error-icon-color: #a0aec0;
|
|
136
|
+
--error-code-color: #f7fafc;
|
|
137
|
+
--error-message-color: #cbd5e0;
|
|
199
138
|
}
|
|
200
139
|
|
|
201
140
|
@media (prefers-color-scheme: dark) {
|
|
202
141
|
:host {
|
|
203
|
-
--
|
|
204
|
-
--
|
|
205
|
-
--
|
|
142
|
+
--error-icon-color: #a0aec0;
|
|
143
|
+
--error-code-color: #f7fafc;
|
|
144
|
+
--error-message-color: #cbd5e0;
|
|
206
145
|
}
|
|
207
|
-
}
|
|
146
|
+
}
|
|
208
147
|
|
|
209
148
|
:host {
|
|
210
149
|
display: flex;
|
|
211
150
|
flex-direction: column;
|
|
212
151
|
justify-content: center;
|
|
213
152
|
align-items: center;
|
|
214
|
-
min-height: 100vh;
|
|
215
153
|
width: 100%;
|
|
154
|
+
height: 100%;
|
|
216
155
|
text-align: center;
|
|
217
156
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
218
157
|
overflow: auto;
|
|
@@ -220,31 +159,24 @@ UErrorPage.styles = css`
|
|
|
220
159
|
}
|
|
221
160
|
|
|
222
161
|
.icon {
|
|
223
|
-
|
|
162
|
+
color: var(--error-icon-color);
|
|
224
163
|
font-size: 6rem;
|
|
225
|
-
color: var(--route-icon-color);
|
|
226
164
|
opacity: 0.85;
|
|
227
165
|
}
|
|
228
166
|
|
|
229
|
-
svg {
|
|
230
|
-
width: 1em;
|
|
231
|
-
height: 1em;
|
|
232
|
-
fill: currentColor;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
167
|
.code {
|
|
168
|
+
color: var(--error-code-color);
|
|
236
169
|
font-size: 2rem;
|
|
237
170
|
font-weight: 700;
|
|
238
|
-
margin: 1rem 0;
|
|
239
|
-
color: var(--route-code-color);
|
|
240
171
|
letter-spacing: -0.5px;
|
|
172
|
+
margin: 1rem 0;
|
|
241
173
|
}
|
|
242
174
|
|
|
243
175
|
.message {
|
|
176
|
+
color: var(--error-message-color);
|
|
244
177
|
font-size: 1rem;
|
|
245
|
-
color: var(--route-message-color);
|
|
246
|
-
max-width: 600px;
|
|
247
178
|
line-height: 1.6;
|
|
179
|
+
max-width: 600px;
|
|
248
180
|
}
|
|
249
181
|
`;
|
|
250
182
|
__decorateClass([
|
|
@@ -257,6 +189,7 @@ function getRandomID() {
|
|
|
257
189
|
return window.isSecureContext ? window.crypto.randomUUID() : window.crypto.getRandomValues(new Uint32Array(1))[0].toString(16);
|
|
258
190
|
}
|
|
259
191
|
function findOutlet(element) {
|
|
192
|
+
if (!element) return void 0;
|
|
260
193
|
let outlet = void 0;
|
|
261
194
|
if (element.shadowRoot) {
|
|
262
195
|
outlet = element.shadowRoot.querySelector("u-outlet");
|
|
@@ -282,18 +215,26 @@ function findOutletOrThrow(element) {
|
|
|
282
215
|
}
|
|
283
216
|
return outlet;
|
|
284
217
|
}
|
|
285
|
-
function
|
|
286
|
-
const
|
|
218
|
+
async function waitOutlet(element, timeout = 1e4) {
|
|
219
|
+
const start = performance.now();
|
|
220
|
+
while (performance.now() - start < timeout) {
|
|
221
|
+
const outlet = findOutlet(element);
|
|
222
|
+
if (outlet) return outlet;
|
|
223
|
+
await new Promise((r) => setTimeout(r, 50));
|
|
224
|
+
}
|
|
225
|
+
throw new Error("Timed out waiting for u-outlet.");
|
|
226
|
+
}
|
|
227
|
+
function findAnchorFrom(event) {
|
|
228
|
+
const targets = event.composedPath() || [];
|
|
287
229
|
if (targets && targets.length) {
|
|
288
230
|
for (const node of targets) {
|
|
289
231
|
if (!(node instanceof Element)) continue;
|
|
290
232
|
if (node.tagName === "A") return node;
|
|
291
233
|
}
|
|
292
234
|
}
|
|
293
|
-
const tgt =
|
|
235
|
+
const tgt = event.target;
|
|
294
236
|
if (!tgt) return null;
|
|
295
|
-
|
|
296
|
-
return anchor;
|
|
237
|
+
return tgt.closest("a");
|
|
297
238
|
}
|
|
298
239
|
function setRoutes(routes, basepath) {
|
|
299
240
|
for (const route of routes) {
|
|
@@ -327,10 +268,10 @@ function setRoutes(routes, basepath) {
|
|
|
327
268
|
}
|
|
328
269
|
return routes;
|
|
329
270
|
}
|
|
330
|
-
function getRoutes(
|
|
271
|
+
function getRoutes(routes, pathname) {
|
|
331
272
|
for (const route of routes) {
|
|
332
273
|
if (route.index !== true && route.children && route.children.length > 0) {
|
|
333
|
-
const childRoutes = getRoutes(
|
|
274
|
+
const childRoutes = getRoutes(route.children, pathname);
|
|
334
275
|
if (childRoutes.length > 0) {
|
|
335
276
|
return [route, ...childRoutes];
|
|
336
277
|
}
|
|
@@ -346,15 +287,15 @@ function getRoutes(pathname, routes) {
|
|
|
346
287
|
}
|
|
347
288
|
class Router {
|
|
348
289
|
constructor(config) {
|
|
349
|
-
this.handleWindowPopstate = async () => {
|
|
290
|
+
this.handleWindowPopstate = async (_) => {
|
|
350
291
|
const href = window.location.href;
|
|
351
292
|
await this.go(href);
|
|
352
293
|
};
|
|
353
|
-
this.
|
|
294
|
+
this.handleDocumentClick = async (e) => {
|
|
354
295
|
try {
|
|
355
296
|
if (e.defaultPrevented) return;
|
|
356
297
|
if (e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey) return;
|
|
357
|
-
const anchor =
|
|
298
|
+
const anchor = findAnchorFrom(e);
|
|
358
299
|
if (!anchor) return;
|
|
359
300
|
const href = anchor.getAttribute("href") || anchor.href;
|
|
360
301
|
if (!href) return;
|
|
@@ -363,28 +304,29 @@ class Router {
|
|
|
363
304
|
if (anchor.getAttribute("rel") === "external") return;
|
|
364
305
|
if (anchor.target && anchor.target !== "") return;
|
|
365
306
|
e.preventDefault();
|
|
366
|
-
|
|
307
|
+
await this.go(anchor.href);
|
|
367
308
|
} catch {
|
|
368
309
|
}
|
|
369
310
|
};
|
|
311
|
+
this.destroy();
|
|
370
312
|
this._rootElement = config.root;
|
|
371
313
|
this._basepath = absolutePath(config.basepath || "/");
|
|
372
314
|
this._routes = setRoutes(config.routes || [], this._basepath);
|
|
373
315
|
this._fallback = config.fallback;
|
|
374
|
-
window.removeEventListener("popstate", this.handleWindowPopstate);
|
|
375
316
|
window.addEventListener("popstate", this.handleWindowPopstate);
|
|
376
317
|
if (config.useIntercept !== false) {
|
|
377
|
-
|
|
378
|
-
this._rootElement.addEventListener("click", this.handleRootClick);
|
|
318
|
+
document.addEventListener("click", this.handleDocumentClick);
|
|
379
319
|
}
|
|
380
320
|
if (config.initialLoad !== false) {
|
|
381
|
-
void this.
|
|
321
|
+
void waitOutlet(this._rootElement).then(() => {
|
|
322
|
+
this.go(window.location.href);
|
|
323
|
+
});
|
|
382
324
|
}
|
|
383
325
|
}
|
|
384
326
|
/** ๊ฐ์ฒด๋ฅผ ์ ๋ฆฌํ๊ณ ์ด๋ฒคํธ ๋ฆฌ์ค๋๋ฅผ ์ ๊ฑฐํฉ๋๋ค. */
|
|
385
327
|
destroy() {
|
|
386
328
|
window.removeEventListener("popstate", this.handleWindowPopstate);
|
|
387
|
-
|
|
329
|
+
document.removeEventListener("click", this.handleDocumentClick);
|
|
388
330
|
this._requestID = void 0;
|
|
389
331
|
this._context = void 0;
|
|
390
332
|
}
|
|
@@ -423,7 +365,7 @@ class Router {
|
|
|
423
365
|
try {
|
|
424
366
|
if (this._requestID !== requestID) return;
|
|
425
367
|
window.dispatchEvent(new RouteBeginEvent(context));
|
|
426
|
-
const routes = getRoutes(
|
|
368
|
+
const routes = getRoutes(this._routes, context.pathname);
|
|
427
369
|
const lastRoute = routes[routes.length - 1];
|
|
428
370
|
if (lastRoute && lastRoute.path instanceof URLPattern) {
|
|
429
371
|
context.params = lastRoute.path.exec({ pathname: context.pathname })?.pathname.groups || {};
|
|
@@ -432,7 +374,6 @@ class Router {
|
|
|
432
374
|
outlet = findOutletOrThrow(this._rootElement);
|
|
433
375
|
let title = void 0;
|
|
434
376
|
let content = null;
|
|
435
|
-
let element = null;
|
|
436
377
|
if (routes.length === 0) {
|
|
437
378
|
throw new NotFoundError(context.href);
|
|
438
379
|
}
|
|
@@ -448,11 +389,11 @@ class Router {
|
|
|
448
389
|
throw new ContentLoadError(LoadError);
|
|
449
390
|
}
|
|
450
391
|
try {
|
|
451
|
-
|
|
392
|
+
outlet.render({ id: route.id, value: content, force: route.force });
|
|
452
393
|
} catch (renderError) {
|
|
453
394
|
throw new ContentRenderError(renderError);
|
|
454
395
|
}
|
|
455
|
-
outlet = findOutlet(
|
|
396
|
+
outlet = findOutlet(outlet) || outlet;
|
|
456
397
|
title = route.title || title;
|
|
457
398
|
}
|
|
458
399
|
document.title = title || document.title;
|
|
@@ -468,13 +409,13 @@ class Router {
|
|
|
468
409
|
try {
|
|
469
410
|
if (this._fallback && this._fallback.render && outlet) {
|
|
470
411
|
const fallbackContent = await this._fallback.render({ ...context, error: routeError });
|
|
471
|
-
outlet.
|
|
412
|
+
outlet.render({ id: "#fallback", value: fallbackContent, force: true });
|
|
472
413
|
document.title = this._fallback.title || document.title;
|
|
473
414
|
} else {
|
|
474
415
|
const errorContent = new UErrorPage();
|
|
475
416
|
errorContent.error = error;
|
|
476
417
|
if (outlet) {
|
|
477
|
-
outlet.
|
|
418
|
+
outlet.render({ id: "#error", value: errorContent, force: true });
|
|
478
419
|
} else {
|
|
479
420
|
document.body.innerHTML = "";
|
|
480
421
|
document.body.appendChild(errorContent);
|
package/dist/react.d.ts
CHANGED
|
@@ -6,10 +6,14 @@ import { ReactWebComponent } from '@lit/react';
|
|
|
6
6
|
import { TemplateResult } from 'lit-html';
|
|
7
7
|
import { TemplateResult as TemplateResult_2 } from 'lit';
|
|
8
8
|
|
|
9
|
+
/** ๋ ๋๋ง ์ต์
*/
|
|
9
10
|
declare interface RenderOption {
|
|
11
|
+
/** ๊ต์ฐจ ๋ ๋๋ง ๋ฐฉ์ง ID */
|
|
10
12
|
id?: string;
|
|
13
|
+
/** ๊ฐ์ ๋ ๋๋ง ์ฌ๋ถ */
|
|
11
14
|
force?: boolean;
|
|
12
|
-
|
|
15
|
+
/** ๋ ๋๋งํ ๊ฐ */
|
|
16
|
+
value: RenderResult;
|
|
13
17
|
}
|
|
14
18
|
|
|
15
19
|
declare type RenderResult = HTMLElement | ReactElement | TemplateResult_2<1> | false;
|
|
@@ -27,36 +31,42 @@ export declare const ULink: ReactWebComponent<ULink_2, {}>;
|
|
|
27
31
|
declare class ULink_2 extends LitElement {
|
|
28
32
|
/** ์ธ๋ถ ๋งํฌ ์ฌ๋ถ */
|
|
29
33
|
private isExternal;
|
|
30
|
-
/** a ํ๊ทธ์ ์ฃผ์
ํ href ๊ฐ */
|
|
31
|
-
computedHref: string;
|
|
32
34
|
/**
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
+
* ๋งํฌ ๋์ target ์์ฑ
|
|
36
|
+
*
|
|
37
|
+
* - `_self`: ํ์ฌ ์ฐฝ์์ ๋งํฌ ์ด๊ธฐ (๊ธฐ๋ณธ๊ฐ)
|
|
38
|
+
* - `_blank`: ์ ํญ/์ฐฝ์์ ๋งํฌ ์ด๊ธฐ
|
|
39
|
+
* - `_parent`: ๋ถ๋ชจ ํ๋ ์์์ ๋งํฌ ์ด๊ธฐ
|
|
40
|
+
* - `_top`: ์ต์์ ํ๋ ์์์ ๋งํฌ ์ด๊ธฐ
|
|
35
41
|
*/
|
|
36
42
|
target?: string;
|
|
37
43
|
/**
|
|
38
|
-
*
|
|
44
|
+
* ๋งํฌ ๋์ URL, ๋ค์ ์ฌํญ์ ๋ฐ๋ผ SPA ๋ผ์ฐํ
๋๋ ๋ธ๋ผ์ฐ์ ๋ค๋น๊ฒ์ด์
์ด ๊ฒฐ์ ๋ฉ๋๋ค.
|
|
45
|
+
*
|
|
46
|
+
* - ์์ฑ์ ์ ์ํ์ง ์์ผ๋ฉด ์ค์ ์์ ์ง์ ํ `basepath`๋ก SPA ๋ผ์ฐํ
ํฉ๋๋ค.
|
|
39
47
|
* - http(s)๋ก ์์ํ๋ฉด ์ธ๋ถ ๋งํฌ๋ก ๊ฐ์ฃผํ๊ณ ๋ธ๋ผ์ฐ์ ๋ค๋น๊ฒ์ด์
์ ์ฌ์ฉํฉ๋๋ค.
|
|
40
|
-
* - ์ ๋๊ฒฝ๋ก(/...)
|
|
41
|
-
* - ์๋๊ฒฝ๋ก๋ (basepath + ์๋๊ฒฝ๋ก)๋ก SPA
|
|
42
|
-
* - ?๋ก ์์ํ๋ฉด ํ์ฌ
|
|
43
|
-
* - #์ผ๋ก ์์ํ๋ฉด
|
|
48
|
+
* - ์ ๋๊ฒฝ๋ก(/...)์ ๊ฒฝ์ฐ `basepath`๋ก ์์ํ๋ฉด SPA ๋ผ์ฐํ
ํฉ๋๋ค, ์ด์ธ ๋ธ๋ผ์ฐ์ ๋ค๋น๊ฒ์ด์
์ ์ฌ์ฉํฉ๋๋ค.
|
|
49
|
+
* - ์๋๊ฒฝ๋ก๋ (basepath + ์๋๊ฒฝ๋ก)๋ก ๊ฒฐํฉํ์ฌ SPA ๋ผ์ฐํ
ํฉ๋๋ค.
|
|
50
|
+
* - ?๋ก ์์ํ๋ฉด ํ์ฌ ๊ฒฝ๋ก์ ์ฟผ๋ฆฌ์คํธ๋ง์ ์ถ๊ฐํ์ฌ SPA ๋ผ์ฐํ
ํฉ๋๋ค.
|
|
51
|
+
* - #์ผ๋ก ์์ํ๋ฉด ๋ธ๋ผ์ฐ์ ๊ธฐ๋ณธ ๋์์ ์ฌ์ฉํฉ๋๋ค.
|
|
44
52
|
*/
|
|
45
53
|
href?: string;
|
|
54
|
+
connectedCallback(): void;
|
|
55
|
+
disconnectedCallback(): void;
|
|
46
56
|
protected willUpdate(changedProperties: PropertyValues): void;
|
|
47
57
|
render(): TemplateResult<1>;
|
|
48
|
-
/** basepath๋ฅผ state์์ ๊บผ๋ด๋ ํฌํผ */
|
|
49
|
-
private getBasepath;
|
|
50
58
|
/** a ํ๊ทธ์ ์ฃผ์
ํ href ๊ฐ์ ๊ณ์ฐํฉ๋๋ค. */
|
|
51
|
-
private
|
|
59
|
+
private compute;
|
|
52
60
|
/**
|
|
53
|
-
* ํด๋ฆญ ๊ฐ๋ก์ฑ๊ธฐ
|
|
61
|
+
* ํด๋ฆญ ๊ฐ๋ก์ฑ๊ธฐ ํธ๋ค๋ฌ
|
|
54
62
|
* - ์ขํด๋ฆญ(0) + ๋ณด์กฐํค ์์(ctrl/meta/shift/alt ์์) + target์ด _self์ผ ๋๋ง SPA ๋ผ์ฐํ
๊ณ ๋ ค
|
|
55
63
|
* - ๊ทธ ์ธ(์คํด๋ฆญ/์ฐํด๋ฆญ/๋ณด์กฐํค/target=_blank ๋ฑ)๋ ๋ธ๋ผ์ฐ์ ๊ธฐ๋ณธ ๋์ ์ ์ง
|
|
56
64
|
*/
|
|
57
|
-
private
|
|
65
|
+
private handleClick;
|
|
58
66
|
/** ํด๋ผ์ด์ธํธ ๋ผ์ฐํ
์ ์ํด popstate ์ด๋ฒคํธ๋ฅผ ๋ฐ์์ํต๋๋ค. */
|
|
59
67
|
private dispatchPopstate;
|
|
68
|
+
/** basepath๋ฅผ state์์ ๊บผ๋ด๋ ํฌํผ */
|
|
69
|
+
private getBasepath;
|
|
60
70
|
static styles: CSSResult;
|
|
61
71
|
}
|
|
62
72
|
|
|
@@ -66,24 +76,21 @@ declare class ULink_2 extends LitElement {
|
|
|
66
76
|
export declare const UOutlet: ReactWebComponent<UOutlet_2, {}>;
|
|
67
77
|
|
|
68
78
|
/**
|
|
69
|
-
*
|
|
79
|
+
* LitElement ๋๋ React ์ปดํฌ๋ํธ๋ฅผ ๋ ๋๋งํด์ฃผ๋ ์น์ปดํฌ๋ํธ ์
๋๋ค.
|
|
70
80
|
*/
|
|
71
|
-
declare class UOutlet_2 extends
|
|
81
|
+
declare class UOutlet_2 extends HTMLElement {
|
|
82
|
+
/** ๊ต์ฐจ ๋ ๋๋ง ๋ฐฉ์ง id */
|
|
72
83
|
private routeId?;
|
|
73
|
-
|
|
74
|
-
private
|
|
75
|
-
/** ์ธ๋ถ ์คํ์ผ์ ์ ์ฉํ๊ธฐ ์ํด ๋ผ์ดํธ ๋์์ฌ์ฉ ํฉ๋๋ค. */
|
|
76
|
-
protected createRenderRoot(): this;
|
|
77
|
-
render(): TemplateResult_2<1>;
|
|
84
|
+
/** ์ค์ ๋ ๋๋ง ์ปจํ
์ธ */
|
|
85
|
+
private root?;
|
|
78
86
|
/**
|
|
79
|
-
*
|
|
80
|
-
* - HTMLElement, ReactElement, TemplateResult๋ฅผ ๋ชจ๋ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.
|
|
87
|
+
* ์ฃผ์ด์ง ๋ ๋๋ง ์ต์
์ ๋ฐ๋ผ ์ปจํ
์ธ ๋ฅผ ๋ ๋๋งํฉ๋๋ค.
|
|
81
88
|
*/
|
|
82
|
-
|
|
89
|
+
render({ id, value, force }: RenderOption): void;
|
|
83
90
|
/**
|
|
84
|
-
* ๊ธฐ์กด DOM์
|
|
91
|
+
* ๊ธฐ์กด DOM์ ์ญ์ ํ์ฌ, ์ด๊ธฐ ์ํ๋ก ๋๋๋ฆฝ๋๋ค.
|
|
85
92
|
*/
|
|
86
|
-
|
|
93
|
+
reset(): void;
|
|
87
94
|
}
|
|
88
95
|
|
|
89
96
|
export { }
|
package/dist/react.js
CHANGED
|
@@ -1,38 +1,13 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
void 0 === s ? (e2[t2] = o2, null == o2 && t2 in HTMLElement.prototype && e2.removeAttribute(t2)) : o2 !== l && ((e3, t3, o3) => {
|
|
6
|
-
let l2 = n.get(e3);
|
|
7
|
-
void 0 === l2 && n.set(e3, l2 = /* @__PURE__ */ new Map());
|
|
8
|
-
let a2 = l2.get(t3);
|
|
9
|
-
void 0 !== o3 ? void 0 === a2 ? (l2.set(t3, a2 = { handleEvent: o3 }), e3.addEventListener(t3, a2)) : a2.handleEvent = o3 : void 0 !== a2 && (l2.delete(t3), e3.removeEventListener(t3, a2));
|
|
10
|
-
})(e2, s, o2);
|
|
11
|
-
}, o = ({ react: n2, tagName: o2, elementClass: l, events: a, displayName: s }) => {
|
|
12
|
-
const c = new Set(Object.keys(a ?? {})), r = n2.forwardRef(((s2, r2) => {
|
|
13
|
-
const i = n2.useRef(/* @__PURE__ */ new Map()), d = n2.useRef(null), f = {}, u = {};
|
|
14
|
-
for (const [n3, t2] of Object.entries(s2)) e.has(n3) ? f["className" === n3 ? "class" : n3] = t2 : c.has(n3) || n3 in l.prototype ? u[n3] = t2 : f[n3] = t2;
|
|
15
|
-
return n2.useLayoutEffect((() => {
|
|
16
|
-
if (null === d.current) return;
|
|
17
|
-
const e2 = /* @__PURE__ */ new Map();
|
|
18
|
-
for (const n3 in u) t(d.current, n3, s2[n3], i.current.get(n3), a), i.current.delete(n3), e2.set(n3, s2[n3]);
|
|
19
|
-
for (const [e3, n3] of i.current) t(d.current, e3, void 0, n3, a);
|
|
20
|
-
i.current = e2;
|
|
21
|
-
})), n2.useLayoutEffect((() => {
|
|
22
|
-
d.current?.removeAttribute("defer-hydration");
|
|
23
|
-
}), []), f.suppressHydrationWarning = true, n2.createElement(o2, { ...f, ref: n2.useCallback(((e2) => {
|
|
24
|
-
d.current = e2, "function" == typeof r2 ? r2(e2) : null !== r2 && (r2.current = e2);
|
|
25
|
-
}), [r2]) });
|
|
26
|
-
}));
|
|
27
|
-
return r.displayName = s ?? l.name, r;
|
|
28
|
-
};
|
|
29
|
-
const ULink = o({
|
|
2
|
+
import { createComponent } from "@lit/react";
|
|
3
|
+
import { b as ULink$1, U as UOutlet$1 } from "./share-6Zs4TunA.js";
|
|
4
|
+
const ULink = createComponent({
|
|
30
5
|
react: React,
|
|
31
6
|
tagName: "u-link",
|
|
32
7
|
elementClass: ULink$1,
|
|
33
8
|
events: {}
|
|
34
9
|
});
|
|
35
|
-
const UOutlet =
|
|
10
|
+
const UOutlet = createComponent({
|
|
36
11
|
react: React,
|
|
37
12
|
tagName: "u-outlet",
|
|
38
13
|
elementClass: UOutlet$1,
|
|
@@ -1,81 +1,54 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { customElement, state, property } from "lit/decorators.js";
|
|
1
|
+
import { render, css, LitElement, html } from "lit";
|
|
3
2
|
import { createRoot } from "react-dom/client";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
8
|
-
if (decorator = decorators[i])
|
|
9
|
-
result = decorator(result) || result;
|
|
10
|
-
return result;
|
|
11
|
-
};
|
|
12
|
-
let UOutlet = class extends LitElement {
|
|
13
|
-
/** ์ธ๋ถ ์คํ์ผ์ ์ ์ฉํ๊ธฐ ์ํด ๋ผ์ดํธ ๋์์ฌ์ฉ ํฉ๋๋ค. */
|
|
14
|
-
createRenderRoot() {
|
|
15
|
-
return this;
|
|
16
|
-
}
|
|
17
|
-
render() {
|
|
18
|
-
return html`${this.container}`;
|
|
19
|
-
}
|
|
3
|
+
import { property, customElement } from "lit/decorators.js";
|
|
4
|
+
import { ifDefined } from "lit/directives/if-defined.js";
|
|
5
|
+
class UOutlet extends HTMLElement {
|
|
20
6
|
/**
|
|
21
|
-
*
|
|
22
|
-
* - HTMLElement, ReactElement, TemplateResult๋ฅผ ๋ชจ๋ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.
|
|
7
|
+
* ์ฃผ์ด์ง ๋ ๋๋ง ์ต์
์ ๋ฐ๋ผ ์ปจํ
์ธ ๋ฅผ ๋ ๋๋งํฉ๋๋ค.
|
|
23
8
|
*/
|
|
24
|
-
|
|
25
|
-
if (this.routeId === id && force === false
|
|
26
|
-
return this.container;
|
|
27
|
-
}
|
|
9
|
+
render({ id, value, force }) {
|
|
10
|
+
if (this.routeId === id && force === false) return;
|
|
28
11
|
this.routeId = id;
|
|
29
|
-
this.
|
|
30
|
-
if (
|
|
31
|
-
throw new Error("Outlet container is not initialized.");
|
|
32
|
-
}
|
|
33
|
-
if (typeof content !== "object") {
|
|
12
|
+
this.reset();
|
|
13
|
+
if (typeof value !== "object") {
|
|
34
14
|
throw new Error("Content is not a valid renderable object.");
|
|
35
15
|
}
|
|
36
|
-
if (
|
|
37
|
-
this.
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
this.
|
|
16
|
+
if (value instanceof HTMLElement) {
|
|
17
|
+
this.replaceChildren(value);
|
|
18
|
+
this.root = void 0;
|
|
19
|
+
} else if ("_$litType$" in value) {
|
|
20
|
+
this.root = render(value, this);
|
|
21
|
+
} else if ("$$typeof" in value) {
|
|
22
|
+
this.root = createRoot(this);
|
|
23
|
+
this.root.render(value);
|
|
43
24
|
} else {
|
|
44
25
|
throw new Error("not supported content type for Outlet rendering.");
|
|
45
26
|
}
|
|
46
|
-
this.requestUpdate();
|
|
47
|
-
await this.updateComplete;
|
|
48
|
-
return this.container;
|
|
49
27
|
}
|
|
50
28
|
/**
|
|
51
|
-
* ๊ธฐ์กด DOM์
|
|
29
|
+
* ๊ธฐ์กด DOM์ ์ญ์ ํ์ฌ, ์ด๊ธฐ ์ํ๋ก ๋๋๋ฆฝ๋๋ค.
|
|
52
30
|
*/
|
|
53
|
-
|
|
54
|
-
if (this.
|
|
55
|
-
|
|
56
|
-
this.content.unmount();
|
|
57
|
-
}
|
|
58
|
-
if ("setConnected" in this.content) {
|
|
59
|
-
this.content.setConnected(false);
|
|
60
|
-
}
|
|
61
|
-
this.content = void 0;
|
|
31
|
+
reset() {
|
|
32
|
+
if (this.root && "_$litPart$" in this) {
|
|
33
|
+
delete this._$litPart$;
|
|
62
34
|
}
|
|
63
|
-
this.
|
|
64
|
-
|
|
35
|
+
if (this.root && "unmount" in this.root) {
|
|
36
|
+
this.root.unmount();
|
|
37
|
+
}
|
|
38
|
+
this.root = void 0;
|
|
39
|
+
this.innerHTML = "";
|
|
65
40
|
}
|
|
66
|
-
}
|
|
67
|
-
UOutlet
|
|
68
|
-
customElement("u-outlet")
|
|
69
|
-
], UOutlet);
|
|
41
|
+
}
|
|
42
|
+
customElements.define("u-outlet", UOutlet);
|
|
70
43
|
function isExternalUrl(url) {
|
|
71
44
|
if (!url) return false;
|
|
72
|
-
|
|
73
|
-
if (/^(?:mailto:|tel:|javascript:)/i.test(
|
|
74
|
-
if (
|
|
45
|
+
url = url.trim();
|
|
46
|
+
if (/^(?:mailto:|tel:|javascript:)/i.test(url)) return true;
|
|
47
|
+
if (url.startsWith("//")) return true;
|
|
75
48
|
try {
|
|
76
49
|
const base = typeof window !== "undefined" ? window.location.origin : "http://localhost";
|
|
77
|
-
const parsed = new URL(
|
|
78
|
-
if (/^(?:ftp:|ftps:|
|
|
50
|
+
const parsed = new URL(url, base);
|
|
51
|
+
if (/^(?:ftp:|ftps:|ws:|wss:)/i.test(parsed.protocol)) return true;
|
|
79
52
|
return parsed.origin !== new URL(base).origin;
|
|
80
53
|
} catch {
|
|
81
54
|
return false;
|
|
@@ -83,7 +56,7 @@ function isExternalUrl(url) {
|
|
|
83
56
|
}
|
|
84
57
|
function parseUrl(url, basepath) {
|
|
85
58
|
let urlObj;
|
|
86
|
-
basepath =
|
|
59
|
+
basepath = catchBasepath(basepath);
|
|
87
60
|
if (url.startsWith("http")) {
|
|
88
61
|
urlObj = new URL(url);
|
|
89
62
|
} else if (url.startsWith("/")) {
|
|
@@ -113,7 +86,7 @@ function absolutePath(...paths) {
|
|
|
113
86
|
if (paths.length === 0) return "/";
|
|
114
87
|
return "/" + paths.join("/");
|
|
115
88
|
}
|
|
116
|
-
function
|
|
89
|
+
function catchBasepath(basepath) {
|
|
117
90
|
if (basepath === "/") return basepath;
|
|
118
91
|
let pattern = new URLPattern({ pathname: basepath + "/*" });
|
|
119
92
|
let match = pattern.exec({ pathname: window.location.pathname });
|
|
@@ -143,13 +116,11 @@ let ULink = class extends LitElement {
|
|
|
143
116
|
constructor() {
|
|
144
117
|
super(...arguments);
|
|
145
118
|
this.isExternal = false;
|
|
146
|
-
this.
|
|
147
|
-
this.handleAnchorClick = (event) => {
|
|
119
|
+
this.handleClick = (event) => {
|
|
148
120
|
if (event.defaultPrevented) return;
|
|
149
121
|
if (event.button !== 0) return;
|
|
150
122
|
if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return;
|
|
151
|
-
|
|
152
|
-
if (target && target.toLowerCase() !== "_self") return;
|
|
123
|
+
if (this.target && this.target.toLowerCase() !== "_self") return;
|
|
153
124
|
const basepath = this.getBasepath();
|
|
154
125
|
if (!this.href) {
|
|
155
126
|
event.preventDefault();
|
|
@@ -176,37 +147,34 @@ let ULink = class extends LitElement {
|
|
|
176
147
|
this.dispatchPopstate(basepath, url);
|
|
177
148
|
};
|
|
178
149
|
}
|
|
150
|
+
connectedCallback() {
|
|
151
|
+
super.connectedCallback();
|
|
152
|
+
this.addEventListener("click", this.handleClick);
|
|
153
|
+
}
|
|
154
|
+
disconnectedCallback() {
|
|
155
|
+
this.removeEventListener("click", this.handleClick);
|
|
156
|
+
super.disconnectedCallback();
|
|
157
|
+
}
|
|
179
158
|
willUpdate(changedProperties) {
|
|
180
159
|
super.willUpdate(changedProperties);
|
|
181
160
|
if (changedProperties.has("href")) {
|
|
182
161
|
this.isExternal = isExternalUrl(this.href || "");
|
|
183
|
-
this.computedHref = this.computeHref(this.href);
|
|
184
162
|
}
|
|
185
163
|
}
|
|
186
164
|
render() {
|
|
187
165
|
return html`
|
|
188
|
-
<a
|
|
189
|
-
target=${this.target ?? "_self"}
|
|
190
|
-
href=${this.computedHref}
|
|
191
|
-
@click=${this.handleAnchorClick}
|
|
192
|
-
>
|
|
166
|
+
<a target=${ifDefined(this.target)} href=${this.compute(this.href)}>
|
|
193
167
|
<slot></slot>
|
|
194
168
|
</a>
|
|
195
169
|
`;
|
|
196
170
|
}
|
|
197
|
-
/** basepath๋ฅผ state์์ ๊บผ๋ด๋ ํฌํผ */
|
|
198
|
-
getBasepath() {
|
|
199
|
-
return window.history.state?.basepath || "";
|
|
200
|
-
}
|
|
201
171
|
/** a ํ๊ทธ์ ์ฃผ์
ํ href ๊ฐ์ ๊ณ์ฐํฉ๋๋ค. */
|
|
202
|
-
|
|
172
|
+
compute(href) {
|
|
203
173
|
const basepath = this.getBasepath();
|
|
204
|
-
if (!href)
|
|
205
|
-
return window.location.origin + basepath;
|
|
206
|
-
}
|
|
174
|
+
if (!href) return window.location.origin + basepath;
|
|
207
175
|
if (this.isExternal) return href;
|
|
208
|
-
if (href.startsWith("#") || href.startsWith("?")) return href;
|
|
209
176
|
if (href.startsWith("/")) return href;
|
|
177
|
+
if (href.startsWith("#") || href.startsWith("?")) return href;
|
|
210
178
|
return absolutePath(basepath, href);
|
|
211
179
|
}
|
|
212
180
|
/** ํด๋ผ์ด์ธํธ ๋ผ์ฐํ
์ ์ํด popstate ์ด๋ฒคํธ๋ฅผ ๋ฐ์์ํต๋๋ค. */
|
|
@@ -214,15 +182,17 @@ let ULink = class extends LitElement {
|
|
|
214
182
|
window.history.pushState({ basepath }, "", url);
|
|
215
183
|
window.dispatchEvent(new PopStateEvent("popstate"));
|
|
216
184
|
}
|
|
185
|
+
/** basepath๋ฅผ state์์ ๊บผ๋ด๋ ํฌํผ */
|
|
186
|
+
getBasepath() {
|
|
187
|
+
return window.history.state?.basepath || "";
|
|
188
|
+
}
|
|
217
189
|
};
|
|
218
190
|
ULink.styles = css`
|
|
219
191
|
:host {
|
|
220
|
-
display: inline-flex;
|
|
221
192
|
cursor: pointer;
|
|
222
193
|
}
|
|
223
194
|
|
|
224
195
|
a {
|
|
225
|
-
display: contents;
|
|
226
196
|
text-decoration: none;
|
|
227
197
|
|
|
228
198
|
font-size: inherit;
|
|
@@ -232,9 +202,6 @@ ULink.styles = css`
|
|
|
232
202
|
cursor: inherit;
|
|
233
203
|
}
|
|
234
204
|
`;
|
|
235
|
-
__decorateClass([
|
|
236
|
-
state()
|
|
237
|
-
], ULink.prototype, "computedHref", 2);
|
|
238
205
|
__decorateClass([
|
|
239
206
|
property({ type: String })
|
|
240
207
|
], ULink.prototype, "target", 2);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iyulab/router",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.2",
|
|
4
4
|
"description": "A modern client-side router for web applications with support for Lit and React components",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"lit",
|
|
@@ -36,17 +36,18 @@
|
|
|
36
36
|
}
|
|
37
37
|
},
|
|
38
38
|
"scripts": {
|
|
39
|
+
"test": "vite",
|
|
39
40
|
"build": "vite build"
|
|
40
41
|
},
|
|
41
42
|
"dependencies": {
|
|
43
|
+
"@lit/react": "^1.0.8",
|
|
42
44
|
"lit": "^3.3.2",
|
|
43
45
|
"react": "^19.2.3",
|
|
44
46
|
"react-dom": "^19.2.3"
|
|
45
47
|
},
|
|
46
48
|
"devDependencies": {
|
|
47
|
-
"@
|
|
48
|
-
"@types/
|
|
49
|
-
"@types/react": "^19.2.8",
|
|
49
|
+
"@types/node": "^25.0.9",
|
|
50
|
+
"@types/react": "^19.2.9",
|
|
50
51
|
"@types/react-dom": "^19.2.3",
|
|
51
52
|
"typescript": "^5.9.3",
|
|
52
53
|
"vite": "^7.3.1",
|