@iyulab/router 0.5.3 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -19
- package/dist/index.d.ts +62 -72
- package/dist/index.js +89 -341
- package/dist/react.d.ts +89 -0
- package/dist/react.js +44 -0
- package/dist/share-ZrQFmsur.js +253 -0
- package/package.json +12 -8
package/README.md
CHANGED
|
@@ -126,38 +126,24 @@ export class AppRoot extends LitElement {
|
|
|
126
126
|
|
|
127
127
|
```tsx
|
|
128
128
|
import React from 'react';
|
|
129
|
-
import {
|
|
129
|
+
import { UOutlet, ULink } from '@iyulab/router/react';
|
|
130
130
|
|
|
131
131
|
export function AppRoot() {
|
|
132
132
|
return (
|
|
133
133
|
<div>
|
|
134
134
|
<nav>
|
|
135
|
-
<
|
|
136
|
-
<
|
|
137
|
-
<
|
|
135
|
+
<ULink href="/">Home</ULink>
|
|
136
|
+
<ULink href="/about">About</ULink>
|
|
137
|
+
<ULink href="/user/123">User Profile</ULink>
|
|
138
138
|
</nav>
|
|
139
139
|
<main>
|
|
140
|
-
<
|
|
140
|
+
<UOutlet />
|
|
141
141
|
</main>
|
|
142
142
|
</div>
|
|
143
143
|
);
|
|
144
144
|
}
|
|
145
145
|
```
|
|
146
146
|
|
|
147
|
-
## Browser Support
|
|
148
|
-
|
|
149
|
-
- **URLPattern API**: Required for routing functionality
|
|
150
|
-
- **Modern browsers**: Chrome 95+, Firefox 106+, Safari 16.4+
|
|
151
|
-
- **Polyfill**: Consider using [urlpattern-polyfill](https://www.npmjs.com/package/urlpattern-polyfill) for older browsers
|
|
152
|
-
|
|
153
|
-
## Contributing
|
|
154
|
-
|
|
155
|
-
1. Fork the repository
|
|
156
|
-
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
157
|
-
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
|
158
|
-
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
159
|
-
5. Open a Pull Request
|
|
160
|
-
|
|
161
147
|
## License
|
|
162
148
|
|
|
163
149
|
MIT License - see [LICENSE](LICENSE) file for details.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { CSSResult } from 'lit';
|
|
2
2
|
import { LitElement } from 'lit';
|
|
3
|
+
import { PropertyValues } from 'lit';
|
|
3
4
|
import { ReactElement } from 'react';
|
|
4
|
-
import { ReactWebComponent } from '@lit/react';
|
|
5
5
|
import { TemplateResult } from 'lit';
|
|
6
6
|
import { TemplateResult as TemplateResult_2 } from 'lit-html';
|
|
7
7
|
|
|
@@ -119,47 +119,6 @@ declare interface IndexRouteConfig extends BaseRouteConfig {
|
|
|
119
119
|
index: true;
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
-
/**
|
|
123
|
-
* - 클라이언트 라우팅을 지원하는 링크 엘리먼트입니다.
|
|
124
|
-
* - 내부 링크는 클라이언트 라우팅을 수행하고, 외부 링크는 새로운 페이지로 이동합니다.
|
|
125
|
-
* - 마우스 중간 버튼 클릭 또는 Ctrl 키를 누르면 새로운 탭에서 엽니다.
|
|
126
|
-
*/
|
|
127
|
-
export declare class Link extends LitElement {
|
|
128
|
-
/** 외부 링크 여부 */
|
|
129
|
-
private isExternal;
|
|
130
|
-
/** a 태그의 href 속성 및 새로운 페이지로 이동할 때 사용될 링크입니다. */
|
|
131
|
-
anchorHref: string;
|
|
132
|
-
/**
|
|
133
|
-
* - 속성을 정의하지 않으면 basepath로 이동합니다.
|
|
134
|
-
* - http 로 시작하면 새로운 페이지를 로드합니다.
|
|
135
|
-
* - 절대경로일 경우 basepath로 시작하면 클라이언트 라우팅을 합니다. 그렇지 않으면 새로운 페이지를 로드합니다.
|
|
136
|
-
* - 상대경로로 시작하면 (현재의 basepath + 상대경로)로 클라이언트 라우팅을 합니다.
|
|
137
|
-
* - ?로 시작하면 현재 경로에 쿼리스트링을 추가하고, 클라이언트 라우팅을 합니다.
|
|
138
|
-
* - #으로 시작하면 현재 경로에 해시를 추가하고, hashchange 이벤트를 발생시킵니다.
|
|
139
|
-
*/
|
|
140
|
-
href?: string;
|
|
141
|
-
connectedCallback(): void;
|
|
142
|
-
disconnectedCallback(): void;
|
|
143
|
-
protected updated(changedProperties: any): Promise<void>;
|
|
144
|
-
render(): TemplateResult_2<1>;
|
|
145
|
-
/**
|
|
146
|
-
* 링크 엘리먼트의 마우스 이벤트 핸들러
|
|
147
|
-
* - 새로운 탭에서 열기: 마우스 중간 버튼 또는 Ctrl 키를 누릅니다.
|
|
148
|
-
* - 새로운 페이지로 이동: http로 시작하거나 절대경로일 경우 새로운 페이지로 이동합니다.
|
|
149
|
-
* - 클라이언트 라우팅: 상대경로로 시작하면 클라이언트 라우팅을 합니다.
|
|
150
|
-
*/
|
|
151
|
-
private handleMouseDown;
|
|
152
|
-
/** 클라이언트 라우팅을 위해 popstate 이벤트를 발생시킵니다. */
|
|
153
|
-
private dispatchPopstate;
|
|
154
|
-
/** 클라이언트 라우팅을 위해 hashchange 이벤트를 발생시킵니다. */
|
|
155
|
-
private dispatchHashchange;
|
|
156
|
-
/** 기본 a 태그의 클릭 이벤트를 막습니다. */
|
|
157
|
-
private preventClickEvent;
|
|
158
|
-
/** a 태그에 주입할 href 값을 계산합니다. */
|
|
159
|
-
private getAnchorHref;
|
|
160
|
-
static styles: CSSResult;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
122
|
declare interface NonIndexRouteConfig extends BaseRouteConfig {
|
|
164
123
|
/**
|
|
165
124
|
* 인덱스 라우트가 아님을 나타냅니다.
|
|
@@ -179,28 +138,6 @@ export declare class NotFoundError extends RouteError {
|
|
|
179
138
|
constructor(path: string, original?: Error | any);
|
|
180
139
|
}
|
|
181
140
|
|
|
182
|
-
/**
|
|
183
|
-
* 라우트 아웃렛 컴포넌트
|
|
184
|
-
* 라우트 설정에 따라 LitElement 또는 React 컴포넌트를 렌더링합니다.
|
|
185
|
-
*/
|
|
186
|
-
export declare class Outlet extends LitElement {
|
|
187
|
-
private routeId?;
|
|
188
|
-
private container?;
|
|
189
|
-
private content?;
|
|
190
|
-
/** 쉐도우를 사용하지 않고, 직접 렌더링합니다. */
|
|
191
|
-
protected createRenderRoot(): this;
|
|
192
|
-
render(): TemplateResult<1>;
|
|
193
|
-
/**
|
|
194
|
-
* render 함수의 결과를 렌더링합니다.
|
|
195
|
-
* - HTMLElement, ReactElement, TemplateResult를 모두 처리할 수 있습니다.
|
|
196
|
-
*/
|
|
197
|
-
renderContent({ id, content, force }: RenderOption): Promise<HTMLDivElement>;
|
|
198
|
-
/**
|
|
199
|
-
* 기존 DOM을 라이프 사이클에 맞게 제거합니다.
|
|
200
|
-
*/
|
|
201
|
-
clear(): void;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
141
|
/**
|
|
205
142
|
* u-outlet 요소를 찾을 수 없을 때 발생하는 에러
|
|
206
143
|
*/
|
|
@@ -360,7 +297,7 @@ export declare class RouteProgressEvent extends RouteEvent {
|
|
|
360
297
|
}
|
|
361
298
|
|
|
362
299
|
/**
|
|
363
|
-
* `lit-element
|
|
300
|
+
* `lit-element`, `react`를 지원하는 클라이언트 사이드 라우터
|
|
364
301
|
*/
|
|
365
302
|
export declare class Router {
|
|
366
303
|
private readonly _rootElement;
|
|
@@ -429,9 +366,67 @@ export declare interface RouterConfig {
|
|
|
429
366
|
initialLoad?: boolean;
|
|
430
367
|
}
|
|
431
368
|
|
|
432
|
-
|
|
369
|
+
/**
|
|
370
|
+
* - 클라이언트 라우팅을 지원하는 링크 엘리먼트입니다.
|
|
371
|
+
* - 내부 링크는 클라이언트 라우팅을 수행하고, 외부 링크는 브라우저 기본 네비게이션을 사용합니다.
|
|
372
|
+
* - Ctrl/Meta/Shift/Alt, 중클릭/우클릭 등은 브라우저 기본 동작(새 탭, 컨텍스트 메뉴 등)을 그대로 유지합니다.
|
|
373
|
+
*/
|
|
374
|
+
export declare class ULink extends LitElement {
|
|
375
|
+
/** 외부 링크 여부 */
|
|
376
|
+
private isExternal;
|
|
377
|
+
/** a 태그에 주입할 href 값 */
|
|
378
|
+
computedHref: string;
|
|
379
|
+
/**
|
|
380
|
+
* a 태그 target을 지원하고 싶으면 열어두는게 좋습니다.
|
|
381
|
+
* - _blank 등을 쓰면 무조건 브라우저 기본 동작을 따르도록 처리합니다.
|
|
382
|
+
*/
|
|
383
|
+
target?: string;
|
|
384
|
+
/**
|
|
385
|
+
* - 속성을 정의하지 않으면 basepath로 이동합니다.
|
|
386
|
+
* - http(s)로 시작하면 외부 링크로 간주하고 브라우저 네비게이션을 사용합니다.
|
|
387
|
+
* - 절대경로(/...)일 경우 basepath로 시작하면 SPA 라우팅 대상이 될 수 있습니다.
|
|
388
|
+
* - 상대경로는 (basepath + 상대경로)로 SPA 라우팅 대상이 될 수 있습니다.
|
|
389
|
+
* - ?로 시작하면 현재 pathname에 쿼리스트링을 붙여 SPA 라우팅합니다.
|
|
390
|
+
* - #으로 시작하면 현재 URL에 해시만 바꾸고(브라우저 기본) 동작합니다.
|
|
391
|
+
*/
|
|
392
|
+
href?: string;
|
|
393
|
+
protected willUpdate(changedProperties: PropertyValues): void;
|
|
394
|
+
render(): TemplateResult_2<1>;
|
|
395
|
+
/** basepath를 state에서 꺼내는 헬퍼 */
|
|
396
|
+
private getBasepath;
|
|
397
|
+
/** a 태그에 주입할 href 값을 계산합니다. */
|
|
398
|
+
private computeHref;
|
|
399
|
+
/**
|
|
400
|
+
* 클릭 가로채기 규칙
|
|
401
|
+
* - 좌클릭(0) + 보조키 없음(ctrl/meta/shift/alt 없음) + target이 _self일 때만 SPA 라우팅 고려
|
|
402
|
+
* - 그 외(중클릭/우클릭/보조키/target=_blank 등)는 브라우저 기본 동작 유지
|
|
403
|
+
*/
|
|
404
|
+
private handleAnchorClick;
|
|
405
|
+
/** 클라이언트 라우팅을 위해 popstate 이벤트를 발생시킵니다. */
|
|
406
|
+
private dispatchPopstate;
|
|
407
|
+
static styles: CSSResult;
|
|
408
|
+
}
|
|
433
409
|
|
|
434
|
-
|
|
410
|
+
/**
|
|
411
|
+
* 라우트 설정에 따라 LitElement 또는 React 컴포넌트를 렌더링합니다.
|
|
412
|
+
*/
|
|
413
|
+
export declare class UOutlet extends LitElement {
|
|
414
|
+
private routeId?;
|
|
415
|
+
private container?;
|
|
416
|
+
private content?;
|
|
417
|
+
/** 외부 스타일을 적용하기 위해 라이트 돔을사용 합니다. */
|
|
418
|
+
protected createRenderRoot(): this;
|
|
419
|
+
render(): TemplateResult<1>;
|
|
420
|
+
/**
|
|
421
|
+
* render 함수의 결과를 렌더링합니다.
|
|
422
|
+
* - HTMLElement, ReactElement, TemplateResult를 모두 처리할 수 있습니다.
|
|
423
|
+
*/
|
|
424
|
+
renderContent({ id, content, force }: RenderOption): Promise<HTMLDivElement>;
|
|
425
|
+
/**
|
|
426
|
+
* 기존 DOM을 라이프 사이클에 맞게 제거합니다.
|
|
427
|
+
*/
|
|
428
|
+
clear(): void;
|
|
429
|
+
}
|
|
435
430
|
|
|
436
431
|
export { }
|
|
437
432
|
|
|
@@ -442,9 +437,4 @@ declare global {
|
|
|
442
437
|
'route-done': RouteDoneEvent;
|
|
443
438
|
'route-error': RouteErrorEvent;
|
|
444
439
|
}
|
|
445
|
-
|
|
446
|
-
interface HTMLElementTagNameMap {
|
|
447
|
-
'u-link': Link;
|
|
448
|
-
'u-outlet': Outlet;
|
|
449
|
-
}
|
|
450
440
|
}
|
package/dist/index.js
CHANGED
|
@@ -1,269 +1,8 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { a as absolutePath, i as isExternalUrl, p as parseUrl } from "./share-ZrQFmsur.js";
|
|
2
|
+
import { b, U } from "./share-ZrQFmsur.js";
|
|
3
|
+
import { css, LitElement, html } from "lit";
|
|
4
|
+
import { property, customElement } from "lit/decorators.js";
|
|
5
5
|
import { unsafeHTML } from "lit-html/directives/unsafe-html.js";
|
|
6
|
-
const e = /* @__PURE__ */ new Set(["children", "localName", "ref", "style", "className"]), n = /* @__PURE__ */ new WeakMap(), t = (e2, t2, o2, l, a) => {
|
|
7
|
-
const s = a?.[t2];
|
|
8
|
-
void 0 === s ? (e2[t2] = o2, null == o2 && t2 in HTMLElement.prototype && e2.removeAttribute(t2)) : o2 !== l && ((e3, t3, o3) => {
|
|
9
|
-
let l2 = n.get(e3);
|
|
10
|
-
void 0 === l2 && n.set(e3, l2 = /* @__PURE__ */ new Map());
|
|
11
|
-
let a2 = l2.get(t3);
|
|
12
|
-
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));
|
|
13
|
-
})(e2, s, o2);
|
|
14
|
-
}, o = ({ react: n2, tagName: o2, elementClass: l, events: a, displayName: s }) => {
|
|
15
|
-
const c = new Set(Object.keys(a ?? {})), r = n2.forwardRef(((s2, r2) => {
|
|
16
|
-
const i = n2.useRef(/* @__PURE__ */ new Map()), d = n2.useRef(null), f = {}, u = {};
|
|
17
|
-
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;
|
|
18
|
-
return n2.useLayoutEffect((() => {
|
|
19
|
-
if (null === d.current) return;
|
|
20
|
-
const e2 = /* @__PURE__ */ new Map();
|
|
21
|
-
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]);
|
|
22
|
-
for (const [e3, n3] of i.current) t(d.current, e3, void 0, n3, a);
|
|
23
|
-
i.current = e2;
|
|
24
|
-
})), n2.useLayoutEffect((() => {
|
|
25
|
-
d.current?.removeAttribute("defer-hydration");
|
|
26
|
-
}), []), f.suppressHydrationWarning = true, n2.createElement(o2, { ...f, ref: n2.useCallback(((e2) => {
|
|
27
|
-
d.current = e2, "function" == typeof r2 ? r2(e2) : null !== r2 && (r2.current = e2);
|
|
28
|
-
}), [r2]) });
|
|
29
|
-
}));
|
|
30
|
-
return r.displayName = s ?? l.name, r;
|
|
31
|
-
};
|
|
32
|
-
function isExternalUrl(url) {
|
|
33
|
-
if (!url) return false;
|
|
34
|
-
const s = url.trim();
|
|
35
|
-
if (/^(?:mailto:|tel:|javascript:)/i.test(s)) return true;
|
|
36
|
-
if (s.startsWith("//")) return true;
|
|
37
|
-
try {
|
|
38
|
-
const base = typeof window !== "undefined" ? window.location.origin : "http://localhost";
|
|
39
|
-
const parsed = new URL(s, base);
|
|
40
|
-
if (/^(?:ftp:|ftps:|data:|ws:|wss:)/i.test(parsed.protocol)) return true;
|
|
41
|
-
return parsed.origin !== new URL(base).origin;
|
|
42
|
-
} catch {
|
|
43
|
-
return false;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
function parseUrl(url, basepath) {
|
|
47
|
-
let urlObj;
|
|
48
|
-
basepath = catchBasePath(basepath);
|
|
49
|
-
if (url.startsWith("http")) {
|
|
50
|
-
urlObj = new URL(url);
|
|
51
|
-
} else if (url.startsWith("/")) {
|
|
52
|
-
urlObj = new URL(url, window.location.origin);
|
|
53
|
-
} else if (url.startsWith("?")) {
|
|
54
|
-
urlObj = new URL(window.location.pathname + url, window.location.origin);
|
|
55
|
-
} else if (url.startsWith("#")) {
|
|
56
|
-
urlObj = new URL(window.location.pathname + window.location.search + url, window.location.origin);
|
|
57
|
-
} else {
|
|
58
|
-
urlObj = new URL(absolutePath(basepath, url), window.location.origin);
|
|
59
|
-
}
|
|
60
|
-
return {
|
|
61
|
-
href: urlObj.href,
|
|
62
|
-
origin: urlObj.origin,
|
|
63
|
-
basepath,
|
|
64
|
-
path: urlObj.href.replace(urlObj.origin, ""),
|
|
65
|
-
pathname: urlObj.pathname,
|
|
66
|
-
query: new URLSearchParams(urlObj.search),
|
|
67
|
-
hash: urlObj.hash,
|
|
68
|
-
params: {},
|
|
69
|
-
progress: () => {
|
|
70
|
-
}
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
function absolutePath(...paths) {
|
|
74
|
-
paths = paths.map((p) => p.replace(/^\/|\/$/g, "")).filter((p) => p.length > 0);
|
|
75
|
-
if (paths.length === 0) return "/";
|
|
76
|
-
return "/" + paths.join("/");
|
|
77
|
-
}
|
|
78
|
-
function catchBasePath(basepath) {
|
|
79
|
-
if (basepath === "/") return basepath;
|
|
80
|
-
let pattern = new URLPattern({ pathname: basepath + "/*" });
|
|
81
|
-
let match = pattern.exec({ pathname: window.location.pathname });
|
|
82
|
-
if (match) {
|
|
83
|
-
const rawPath = match.pathname.input;
|
|
84
|
-
const restPath = match.pathname.groups?.["0"];
|
|
85
|
-
return restPath ? rawPath.replace("/" + restPath, "") : rawPath.slice(0, -1);
|
|
86
|
-
}
|
|
87
|
-
pattern = new URLPattern({ pathname: `${basepath}{/}?` });
|
|
88
|
-
match = pattern.exec({ pathname: window.location.pathname });
|
|
89
|
-
if (match) {
|
|
90
|
-
return match.pathname.input;
|
|
91
|
-
}
|
|
92
|
-
return basepath;
|
|
93
|
-
}
|
|
94
|
-
var __defProp$1 = Object.defineProperty;
|
|
95
|
-
var __decorateClass$1 = (decorators, target, key, kind) => {
|
|
96
|
-
var result = void 0;
|
|
97
|
-
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
98
|
-
if (decorator = decorators[i])
|
|
99
|
-
result = decorator(target, key, result) || result;
|
|
100
|
-
if (result) __defProp$1(target, key, result);
|
|
101
|
-
return result;
|
|
102
|
-
};
|
|
103
|
-
const _Link = class _Link extends LitElement {
|
|
104
|
-
constructor() {
|
|
105
|
-
super(...arguments);
|
|
106
|
-
this.isExternal = false;
|
|
107
|
-
this.anchorHref = "#";
|
|
108
|
-
this.handleMouseDown = (event) => {
|
|
109
|
-
const isNonNavigationClick = event.button === 2 || event.metaKey || event.shiftKey || event.altKey;
|
|
110
|
-
if (event.defaultPrevented || isNonNavigationClick) return;
|
|
111
|
-
event.preventDefault();
|
|
112
|
-
event.stopPropagation();
|
|
113
|
-
const basepath = window.history.state?.basepath || "";
|
|
114
|
-
if (event.button === 1 || event.ctrlKey) {
|
|
115
|
-
window.open(this.anchorHref, "_blank");
|
|
116
|
-
} else if (!this.href) {
|
|
117
|
-
this.dispatchPopstate(basepath, basepath);
|
|
118
|
-
} else if (this.isExternal || this.href.startsWith("/") && !this.href.startsWith(basepath)) {
|
|
119
|
-
window.location.href = this.href;
|
|
120
|
-
} else if (this.href.startsWith("#")) {
|
|
121
|
-
const url = window.location.pathname + window.location.search + this.href;
|
|
122
|
-
this.dispatchHashchange(basepath, url);
|
|
123
|
-
} else if (this.href.startsWith("?")) {
|
|
124
|
-
const url = window.location.pathname + this.href;
|
|
125
|
-
this.dispatchPopstate(basepath, url);
|
|
126
|
-
} else {
|
|
127
|
-
const url = absolutePath(basepath, this.href);
|
|
128
|
-
this.dispatchPopstate(basepath, url);
|
|
129
|
-
}
|
|
130
|
-
};
|
|
131
|
-
this.preventClickEvent = (event) => {
|
|
132
|
-
event.preventDefault();
|
|
133
|
-
event.stopPropagation();
|
|
134
|
-
};
|
|
135
|
-
}
|
|
136
|
-
connectedCallback() {
|
|
137
|
-
super.connectedCallback();
|
|
138
|
-
this.addEventListener("mousedown", this.handleMouseDown);
|
|
139
|
-
}
|
|
140
|
-
disconnectedCallback() {
|
|
141
|
-
this.removeEventListener("mousedown", this.handleMouseDown);
|
|
142
|
-
super.disconnectedCallback();
|
|
143
|
-
}
|
|
144
|
-
async updated(changedProperties) {
|
|
145
|
-
super.updated(changedProperties);
|
|
146
|
-
await this.updateComplete;
|
|
147
|
-
if (changedProperties.has("href")) {
|
|
148
|
-
this.isExternal = isExternalUrl(this.href || "");
|
|
149
|
-
this.anchorHref = this.getAnchorHref(this.href);
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
render() {
|
|
153
|
-
return html`
|
|
154
|
-
<a href=${this.anchorHref} @click=${this.preventClickEvent}>
|
|
155
|
-
<slot></slot>
|
|
156
|
-
</a>
|
|
157
|
-
`;
|
|
158
|
-
}
|
|
159
|
-
/** 클라이언트 라우팅을 위해 popstate 이벤트를 발생시킵니다. */
|
|
160
|
-
dispatchPopstate(basepath, url) {
|
|
161
|
-
window.history.pushState({ basepath }, "", url);
|
|
162
|
-
window.dispatchEvent(new PopStateEvent("popstate"));
|
|
163
|
-
}
|
|
164
|
-
/** 클라이언트 라우팅을 위해 hashchange 이벤트를 발생시킵니다. */
|
|
165
|
-
dispatchHashchange(basepath, url) {
|
|
166
|
-
window.history.pushState({ basepath }, "", url);
|
|
167
|
-
window.dispatchEvent(new HashChangeEvent("hashchange"));
|
|
168
|
-
}
|
|
169
|
-
/** a 태그에 주입할 href 값을 계산합니다. */
|
|
170
|
-
getAnchorHref(href) {
|
|
171
|
-
const basepath = window.history.state?.basepath || "";
|
|
172
|
-
if (!href) {
|
|
173
|
-
return window.location.origin + basepath;
|
|
174
|
-
}
|
|
175
|
-
if (this.isExternal || href.startsWith("/") || href.startsWith("#") || href.startsWith("?")) {
|
|
176
|
-
return href;
|
|
177
|
-
}
|
|
178
|
-
return absolutePath(basepath, href);
|
|
179
|
-
}
|
|
180
|
-
};
|
|
181
|
-
_Link.styles = css`
|
|
182
|
-
:host {
|
|
183
|
-
display: inline-flex;
|
|
184
|
-
cursor: pointer;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
a {
|
|
188
|
-
display: contents;
|
|
189
|
-
text-decoration: none;
|
|
190
|
-
color: inherit;
|
|
191
|
-
}
|
|
192
|
-
`;
|
|
193
|
-
let Link = _Link;
|
|
194
|
-
__decorateClass$1([
|
|
195
|
-
state()
|
|
196
|
-
], Link.prototype, "anchorHref");
|
|
197
|
-
__decorateClass$1([
|
|
198
|
-
property({ type: String })
|
|
199
|
-
], Link.prototype, "href");
|
|
200
|
-
class Outlet extends LitElement {
|
|
201
|
-
/** 쉐도우를 사용하지 않고, 직접 렌더링합니다. */
|
|
202
|
-
createRenderRoot() {
|
|
203
|
-
return this;
|
|
204
|
-
}
|
|
205
|
-
render() {
|
|
206
|
-
return html`${this.container}`;
|
|
207
|
-
}
|
|
208
|
-
/**
|
|
209
|
-
* render 함수의 결과를 렌더링합니다.
|
|
210
|
-
* - HTMLElement, ReactElement, TemplateResult를 모두 처리할 수 있습니다.
|
|
211
|
-
*/
|
|
212
|
-
async renderContent({ id, content, force }) {
|
|
213
|
-
if (this.routeId === id && force === false && this.container) {
|
|
214
|
-
return this.container;
|
|
215
|
-
}
|
|
216
|
-
this.routeId = id;
|
|
217
|
-
this.clear();
|
|
218
|
-
if (!this.container) {
|
|
219
|
-
throw new Error("Outlet container is not initialized.");
|
|
220
|
-
}
|
|
221
|
-
if (typeof content !== "object") {
|
|
222
|
-
throw new Error("Content is not a valid renderable object.");
|
|
223
|
-
}
|
|
224
|
-
if (content instanceof HTMLElement) {
|
|
225
|
-
this.container.appendChild(content);
|
|
226
|
-
} else if ("_$litType$" in content) {
|
|
227
|
-
this.content = render(content, this.container);
|
|
228
|
-
} else if ("$$typeof" in content) {
|
|
229
|
-
this.content = createRoot(this.container);
|
|
230
|
-
this.content.render(content);
|
|
231
|
-
} else {
|
|
232
|
-
throw new Error("not supported content type for Outlet rendering.");
|
|
233
|
-
}
|
|
234
|
-
this.requestUpdate();
|
|
235
|
-
await this.updateComplete;
|
|
236
|
-
return this.container;
|
|
237
|
-
}
|
|
238
|
-
/**
|
|
239
|
-
* 기존 DOM을 라이프 사이클에 맞게 제거합니다.
|
|
240
|
-
*/
|
|
241
|
-
clear() {
|
|
242
|
-
if (this.content) {
|
|
243
|
-
if ("unmount" in this.content) {
|
|
244
|
-
this.content.unmount();
|
|
245
|
-
}
|
|
246
|
-
if ("setConnected" in this.content) {
|
|
247
|
-
this.content.setConnected(false);
|
|
248
|
-
}
|
|
249
|
-
this.content = void 0;
|
|
250
|
-
}
|
|
251
|
-
this.container = document.createElement("div");
|
|
252
|
-
this.container.style.display = "contents";
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
customElements.define("u-link", Link);
|
|
256
|
-
customElements.define("u-outlet", Outlet);
|
|
257
|
-
const ULink = o({
|
|
258
|
-
react: React,
|
|
259
|
-
tagName: "u-link",
|
|
260
|
-
elementClass: Link
|
|
261
|
-
});
|
|
262
|
-
const UOutlet = o({
|
|
263
|
-
react: React,
|
|
264
|
-
tagName: "u-outlet",
|
|
265
|
-
elementClass: Outlet
|
|
266
|
-
});
|
|
267
6
|
class RouteError extends Error {
|
|
268
7
|
constructor(code, message, original) {
|
|
269
8
|
super(message);
|
|
@@ -335,100 +74,51 @@ class RouteErrorEvent extends RouteEvent {
|
|
|
335
74
|
this.error = error;
|
|
336
75
|
}
|
|
337
76
|
}
|
|
338
|
-
const ban = '<svg xmlns="http://www.w3.org/2000/svg"
|
|
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>';
|
|
339
78
|
const __vite_glob_0_0 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
340
79
|
__proto__: null,
|
|
341
80
|
default: ban
|
|
342
81
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
343
|
-
const boxSeam = '<svg xmlns="http://www.w3.org/2000/svg"
|
|
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>';
|
|
344
83
|
const __vite_glob_0_1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
345
84
|
__proto__: null,
|
|
346
85
|
default: boxSeam
|
|
347
86
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
348
|
-
const exclamationTriangle = '<svg xmlns="http://www.w3.org/2000/svg"
|
|
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>';
|
|
349
88
|
const __vite_glob_0_2 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
350
89
|
__proto__: null,
|
|
351
90
|
default: exclamationTriangle
|
|
352
91
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
353
|
-
const palette = '<svg xmlns="http://www.w3.org/2000/svg"
|
|
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>';
|
|
354
93
|
const __vite_glob_0_3 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
355
94
|
__proto__: null,
|
|
356
95
|
default: palette
|
|
357
96
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
358
|
-
const personLock = '<svg xmlns="http://www.w3.org/2000/svg"
|
|
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>';
|
|
359
98
|
const __vite_glob_0_4 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
360
99
|
__proto__: null,
|
|
361
100
|
default: personLock
|
|
362
101
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
363
|
-
const search = '<svg xmlns="http://www.w3.org/2000/svg"
|
|
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>';
|
|
364
103
|
const __vite_glob_0_5 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
365
104
|
__proto__: null,
|
|
366
105
|
default: search
|
|
367
106
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
368
|
-
const stopwatch = '<svg xmlns="http://www.w3.org/2000/svg"
|
|
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>';
|
|
369
108
|
const __vite_glob_0_6 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
370
109
|
__proto__: null,
|
|
371
110
|
default: stopwatch
|
|
372
111
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
373
|
-
const wifiOff = '<svg xmlns="http://www.w3.org/2000/svg"
|
|
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>';
|
|
374
113
|
const __vite_glob_0_7 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
375
114
|
__proto__: null,
|
|
376
115
|
default: wifiOff
|
|
377
116
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
378
|
-
const wrenchAdjustable = '<svg xmlns="http://www.w3.org/2000/svg"
|
|
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>';
|
|
379
118
|
const __vite_glob_0_8 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
380
119
|
__proto__: null,
|
|
381
120
|
default: wrenchAdjustable
|
|
382
121
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
383
|
-
const styles = css`
|
|
384
|
-
:host {
|
|
385
|
-
display: flex;
|
|
386
|
-
flex-direction: column;
|
|
387
|
-
justify-content: center;
|
|
388
|
-
align-items: center;
|
|
389
|
-
min-height: 100vh;
|
|
390
|
-
width: 100%;
|
|
391
|
-
text-align: center;
|
|
392
|
-
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
393
|
-
overflow: auto;
|
|
394
|
-
user-select: none;
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
.icon {
|
|
398
|
-
display: contents;
|
|
399
|
-
font-size: 6rem;
|
|
400
|
-
color: var(--route-error-color, #4a5568);
|
|
401
|
-
opacity: 0.85;
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
.code {
|
|
405
|
-
font-size: 2rem;
|
|
406
|
-
font-weight: 700;
|
|
407
|
-
margin: 1rem 0;
|
|
408
|
-
color: var(--route-error-code-color, #1a202c);
|
|
409
|
-
letter-spacing: -0.5px;
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
.message {
|
|
413
|
-
font-size: 1rem;
|
|
414
|
-
color: var(--route-error-message-color, #718096);
|
|
415
|
-
max-width: 600px;
|
|
416
|
-
line-height: 1.6;
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
@media (prefers-color-scheme: dark) {
|
|
420
|
-
.icon {
|
|
421
|
-
color: var(--route-error-dark-color, #a0aec0);
|
|
422
|
-
opacity: 0.9;
|
|
423
|
-
}
|
|
424
|
-
.code {
|
|
425
|
-
color: var(--route-error-dark-code-color, #f7fafc);
|
|
426
|
-
}
|
|
427
|
-
.message {
|
|
428
|
-
color: var(--route-error-dark-message-color, #cbd5e0);
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
`;
|
|
432
122
|
var __defProp = Object.defineProperty;
|
|
433
123
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
434
124
|
var __decorateClass = (decorators, target, key, kind) => {
|
|
@@ -454,7 +144,7 @@ const icons = Object.entries(/* @__PURE__ */ Object.assign({
|
|
|
454
144
|
acc[name] = content.default;
|
|
455
145
|
return acc;
|
|
456
146
|
}, {});
|
|
457
|
-
let
|
|
147
|
+
let UErrorPage = class extends LitElement {
|
|
458
148
|
render() {
|
|
459
149
|
const error = this.error || this.getDefaultError();
|
|
460
150
|
const icon = this.getErrorIcon(error.code);
|
|
@@ -496,13 +186,73 @@ let ErrorPage = class extends LitElement {
|
|
|
496
186
|
}
|
|
497
187
|
}
|
|
498
188
|
};
|
|
499
|
-
|
|
189
|
+
UErrorPage.styles = css`
|
|
190
|
+
:host {
|
|
191
|
+
--route-icon-color: #4a5568;
|
|
192
|
+
--route-code-color: #1a202c;
|
|
193
|
+
--route-message-color: #718096;
|
|
194
|
+
}
|
|
195
|
+
:host-context([theme="dark"]) {
|
|
196
|
+
--route-icon-color: #a0aec0;
|
|
197
|
+
--route-code-color: #f7fafc;
|
|
198
|
+
--route-message-color: #cbd5e0;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
@media (prefers-color-scheme: dark) {
|
|
202
|
+
:host {
|
|
203
|
+
--route-icon-color: #a0aec0;
|
|
204
|
+
--route-code-color: #f7fafc;
|
|
205
|
+
--route-message-color: #cbd5e0;
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
:host {
|
|
210
|
+
display: flex;
|
|
211
|
+
flex-direction: column;
|
|
212
|
+
justify-content: center;
|
|
213
|
+
align-items: center;
|
|
214
|
+
min-height: 100vh;
|
|
215
|
+
width: 100%;
|
|
216
|
+
text-align: center;
|
|
217
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
218
|
+
overflow: auto;
|
|
219
|
+
user-select: none;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.icon {
|
|
223
|
+
display: contents;
|
|
224
|
+
font-size: 6rem;
|
|
225
|
+
color: var(--route-icon-color);
|
|
226
|
+
opacity: 0.85;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
svg {
|
|
230
|
+
width: 1em;
|
|
231
|
+
height: 1em;
|
|
232
|
+
fill: currentColor;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
.code {
|
|
236
|
+
font-size: 2rem;
|
|
237
|
+
font-weight: 700;
|
|
238
|
+
margin: 1rem 0;
|
|
239
|
+
color: var(--route-code-color);
|
|
240
|
+
letter-spacing: -0.5px;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
.message {
|
|
244
|
+
font-size: 1rem;
|
|
245
|
+
color: var(--route-message-color);
|
|
246
|
+
max-width: 600px;
|
|
247
|
+
line-height: 1.6;
|
|
248
|
+
}
|
|
249
|
+
`;
|
|
500
250
|
__decorateClass([
|
|
501
251
|
property({ type: Object })
|
|
502
|
-
],
|
|
503
|
-
|
|
252
|
+
], UErrorPage.prototype, "error", 2);
|
|
253
|
+
UErrorPage = __decorateClass([
|
|
504
254
|
customElement("u-error-page")
|
|
505
|
-
],
|
|
255
|
+
], UErrorPage);
|
|
506
256
|
function getRandomID() {
|
|
507
257
|
return window.isSecureContext ? window.crypto.randomUUID() : window.crypto.getRandomValues(new Uint32Array(1))[0].toString(16);
|
|
508
258
|
}
|
|
@@ -532,15 +282,15 @@ function findOutletOrThrow(element) {
|
|
|
532
282
|
}
|
|
533
283
|
return outlet;
|
|
534
284
|
}
|
|
535
|
-
function findAnchorFromEvent(
|
|
536
|
-
const targets =
|
|
285
|
+
function findAnchorFromEvent(e) {
|
|
286
|
+
const targets = e.composedPath() || [];
|
|
537
287
|
if (targets && targets.length) {
|
|
538
288
|
for (const node of targets) {
|
|
539
289
|
if (!(node instanceof Element)) continue;
|
|
540
290
|
if (node.tagName === "A") return node;
|
|
541
291
|
}
|
|
542
292
|
}
|
|
543
|
-
const tgt =
|
|
293
|
+
const tgt = e.target;
|
|
544
294
|
if (!tgt) return null;
|
|
545
295
|
const anchor = tgt.closest("a");
|
|
546
296
|
return anchor;
|
|
@@ -600,11 +350,11 @@ class Router {
|
|
|
600
350
|
const href = window.location.href;
|
|
601
351
|
await this.go(href);
|
|
602
352
|
};
|
|
603
|
-
this.handleRootClick = (
|
|
353
|
+
this.handleRootClick = (e) => {
|
|
604
354
|
try {
|
|
605
|
-
if (
|
|
606
|
-
if (
|
|
607
|
-
const anchor = findAnchorFromEvent(
|
|
355
|
+
if (e.defaultPrevented) return;
|
|
356
|
+
if (e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey) return;
|
|
357
|
+
const anchor = findAnchorFromEvent(e);
|
|
608
358
|
if (!anchor) return;
|
|
609
359
|
const href = anchor.getAttribute("href") || anchor.href;
|
|
610
360
|
if (!href) return;
|
|
@@ -612,7 +362,7 @@ class Router {
|
|
|
612
362
|
if (anchor.hasAttribute("download")) return;
|
|
613
363
|
if (anchor.getAttribute("rel") === "external") return;
|
|
614
364
|
if (anchor.target && anchor.target !== "") return;
|
|
615
|
-
|
|
365
|
+
e.preventDefault();
|
|
616
366
|
void this.go(anchor.href);
|
|
617
367
|
} catch {
|
|
618
368
|
}
|
|
@@ -721,7 +471,7 @@ class Router {
|
|
|
721
471
|
outlet.renderContent({ id: "#fallback", content: fallbackContent, force: true });
|
|
722
472
|
document.title = this._fallback.title || document.title;
|
|
723
473
|
} else {
|
|
724
|
-
const errorContent = new
|
|
474
|
+
const errorContent = new UErrorPage();
|
|
725
475
|
errorContent.error = error;
|
|
726
476
|
if (outlet) {
|
|
727
477
|
outlet.renderContent({ id: "#error", content: errorContent, force: true });
|
|
@@ -740,9 +490,7 @@ class Router {
|
|
|
740
490
|
export {
|
|
741
491
|
ContentLoadError,
|
|
742
492
|
ContentRenderError,
|
|
743
|
-
Link,
|
|
744
493
|
NotFoundError,
|
|
745
|
-
Outlet,
|
|
746
494
|
OutletMissingError,
|
|
747
495
|
RouteBeginEvent,
|
|
748
496
|
RouteDoneEvent,
|
|
@@ -750,6 +498,6 @@ export {
|
|
|
750
498
|
RouteErrorEvent,
|
|
751
499
|
RouteProgressEvent,
|
|
752
500
|
Router,
|
|
753
|
-
ULink,
|
|
754
|
-
UOutlet
|
|
501
|
+
b as ULink,
|
|
502
|
+
U as UOutlet
|
|
755
503
|
};
|
package/dist/react.d.ts
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
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
|
+
declare interface RenderOption {
|
|
10
|
+
id?: string;
|
|
11
|
+
force?: boolean;
|
|
12
|
+
content: RenderResult;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
declare type RenderResult = HTMLElement | ReactElement | TemplateResult_2<1> | false;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* `u-link` 웹 컴포넌트를 React에서 사용할 수 있도록 래핑한 컴포넌트입니다.
|
|
19
|
+
*/
|
|
20
|
+
export declare const ULink: ReactWebComponent<ULink_2, {}>;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* - 클라이언트 라우팅을 지원하는 링크 엘리먼트입니다.
|
|
24
|
+
* - 내부 링크는 클라이언트 라우팅을 수행하고, 외부 링크는 브라우저 기본 네비게이션을 사용합니다.
|
|
25
|
+
* - Ctrl/Meta/Shift/Alt, 중클릭/우클릭 등은 브라우저 기본 동작(새 탭, 컨텍스트 메뉴 등)을 그대로 유지합니다.
|
|
26
|
+
*/
|
|
27
|
+
declare class ULink_2 extends LitElement {
|
|
28
|
+
/** 외부 링크 여부 */
|
|
29
|
+
private isExternal;
|
|
30
|
+
/** a 태그에 주입할 href 값 */
|
|
31
|
+
computedHref: string;
|
|
32
|
+
/**
|
|
33
|
+
* a 태그 target을 지원하고 싶으면 열어두는게 좋습니다.
|
|
34
|
+
* - _blank 등을 쓰면 무조건 브라우저 기본 동작을 따르도록 처리합니다.
|
|
35
|
+
*/
|
|
36
|
+
target?: string;
|
|
37
|
+
/**
|
|
38
|
+
* - 속성을 정의하지 않으면 basepath로 이동합니다.
|
|
39
|
+
* - http(s)로 시작하면 외부 링크로 간주하고 브라우저 네비게이션을 사용합니다.
|
|
40
|
+
* - 절대경로(/...)일 경우 basepath로 시작하면 SPA 라우팅 대상이 될 수 있습니다.
|
|
41
|
+
* - 상대경로는 (basepath + 상대경로)로 SPA 라우팅 대상이 될 수 있습니다.
|
|
42
|
+
* - ?로 시작하면 현재 pathname에 쿼리스트링을 붙여 SPA 라우팅합니다.
|
|
43
|
+
* - #으로 시작하면 현재 URL에 해시만 바꾸고(브라우저 기본) 동작합니다.
|
|
44
|
+
*/
|
|
45
|
+
href?: string;
|
|
46
|
+
protected willUpdate(changedProperties: PropertyValues): void;
|
|
47
|
+
render(): TemplateResult<1>;
|
|
48
|
+
/** basepath를 state에서 꺼내는 헬퍼 */
|
|
49
|
+
private getBasepath;
|
|
50
|
+
/** a 태그에 주입할 href 값을 계산합니다. */
|
|
51
|
+
private computeHref;
|
|
52
|
+
/**
|
|
53
|
+
* 클릭 가로채기 규칙
|
|
54
|
+
* - 좌클릭(0) + 보조키 없음(ctrl/meta/shift/alt 없음) + target이 _self일 때만 SPA 라우팅 고려
|
|
55
|
+
* - 그 외(중클릭/우클릭/보조키/target=_blank 등)는 브라우저 기본 동작 유지
|
|
56
|
+
*/
|
|
57
|
+
private handleAnchorClick;
|
|
58
|
+
/** 클라이언트 라우팅을 위해 popstate 이벤트를 발생시킵니다. */
|
|
59
|
+
private dispatchPopstate;
|
|
60
|
+
static styles: CSSResult;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* `u-outlet` 웹 컴포넌트를 React에서 사용할 수 있도록 래핑한 컴포넌트입니다.
|
|
65
|
+
*/
|
|
66
|
+
export declare const UOutlet: ReactWebComponent<UOutlet_2, {}>;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* 라우트 설정에 따라 LitElement 또는 React 컴포넌트를 렌더링합니다.
|
|
70
|
+
*/
|
|
71
|
+
declare class UOutlet_2 extends LitElement {
|
|
72
|
+
private routeId?;
|
|
73
|
+
private container?;
|
|
74
|
+
private content?;
|
|
75
|
+
/** 외부 스타일을 적용하기 위해 라이트 돔을사용 합니다. */
|
|
76
|
+
protected createRenderRoot(): this;
|
|
77
|
+
render(): TemplateResult_2<1>;
|
|
78
|
+
/**
|
|
79
|
+
* render 함수의 결과를 렌더링합니다.
|
|
80
|
+
* - HTMLElement, ReactElement, TemplateResult를 모두 처리할 수 있습니다.
|
|
81
|
+
*/
|
|
82
|
+
renderContent({ id, content, force }: RenderOption): Promise<HTMLDivElement>;
|
|
83
|
+
/**
|
|
84
|
+
* 기존 DOM을 라이프 사이클에 맞게 제거합니다.
|
|
85
|
+
*/
|
|
86
|
+
clear(): void;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export { }
|
package/dist/react.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { b as ULink$1, U as UOutlet$1 } from "./share-ZrQFmsur.js";
|
|
3
|
+
const e = /* @__PURE__ */ new Set(["children", "localName", "ref", "style", "className"]), n = /* @__PURE__ */ new WeakMap(), t = (e2, t2, o2, l, a) => {
|
|
4
|
+
const s = a?.[t2];
|
|
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({
|
|
30
|
+
react: React,
|
|
31
|
+
tagName: "u-link",
|
|
32
|
+
elementClass: ULink$1,
|
|
33
|
+
events: {}
|
|
34
|
+
});
|
|
35
|
+
const UOutlet = o({
|
|
36
|
+
react: React,
|
|
37
|
+
tagName: "u-outlet",
|
|
38
|
+
elementClass: UOutlet$1,
|
|
39
|
+
events: {}
|
|
40
|
+
});
|
|
41
|
+
export {
|
|
42
|
+
ULink,
|
|
43
|
+
UOutlet
|
|
44
|
+
};
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
import { LitElement, html, render, css } from "lit";
|
|
2
|
+
import { customElement, state, property } from "lit/decorators.js";
|
|
3
|
+
import { createRoot } from "react-dom/client";
|
|
4
|
+
var __getOwnPropDesc$1 = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __decorateClass$1 = (decorators, target, key, kind) => {
|
|
6
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$1(target, key) : target;
|
|
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
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* render 함수의 결과를 렌더링합니다.
|
|
22
|
+
* - HTMLElement, ReactElement, TemplateResult를 모두 처리할 수 있습니다.
|
|
23
|
+
*/
|
|
24
|
+
async renderContent({ id, content, force }) {
|
|
25
|
+
if (this.routeId === id && force === false && this.container) {
|
|
26
|
+
return this.container;
|
|
27
|
+
}
|
|
28
|
+
this.routeId = id;
|
|
29
|
+
this.clear();
|
|
30
|
+
if (!this.container) {
|
|
31
|
+
throw new Error("Outlet container is not initialized.");
|
|
32
|
+
}
|
|
33
|
+
if (typeof content !== "object") {
|
|
34
|
+
throw new Error("Content is not a valid renderable object.");
|
|
35
|
+
}
|
|
36
|
+
if (content instanceof HTMLElement) {
|
|
37
|
+
this.container.appendChild(content);
|
|
38
|
+
} else if ("_$litType$" in content) {
|
|
39
|
+
this.content = render(content, this.container);
|
|
40
|
+
} else if ("$$typeof" in content) {
|
|
41
|
+
this.content = createRoot(this.container);
|
|
42
|
+
this.content.render(content);
|
|
43
|
+
} else {
|
|
44
|
+
throw new Error("not supported content type for Outlet rendering.");
|
|
45
|
+
}
|
|
46
|
+
this.requestUpdate();
|
|
47
|
+
await this.updateComplete;
|
|
48
|
+
return this.container;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* 기존 DOM을 라이프 사이클에 맞게 제거합니다.
|
|
52
|
+
*/
|
|
53
|
+
clear() {
|
|
54
|
+
if (this.content) {
|
|
55
|
+
if ("unmount" in this.content) {
|
|
56
|
+
this.content.unmount();
|
|
57
|
+
}
|
|
58
|
+
if ("setConnected" in this.content) {
|
|
59
|
+
this.content.setConnected(false);
|
|
60
|
+
}
|
|
61
|
+
this.content = void 0;
|
|
62
|
+
}
|
|
63
|
+
this.container = document.createElement("div");
|
|
64
|
+
this.container.style.display = "contents";
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
UOutlet = __decorateClass$1([
|
|
68
|
+
customElement("u-outlet")
|
|
69
|
+
], UOutlet);
|
|
70
|
+
function isExternalUrl(url) {
|
|
71
|
+
if (!url) return false;
|
|
72
|
+
const s = url.trim();
|
|
73
|
+
if (/^(?:mailto:|tel:|javascript:)/i.test(s)) return true;
|
|
74
|
+
if (s.startsWith("//")) return true;
|
|
75
|
+
try {
|
|
76
|
+
const base = typeof window !== "undefined" ? window.location.origin : "http://localhost";
|
|
77
|
+
const parsed = new URL(s, base);
|
|
78
|
+
if (/^(?:ftp:|ftps:|data:|ws:|wss:)/i.test(parsed.protocol)) return true;
|
|
79
|
+
return parsed.origin !== new URL(base).origin;
|
|
80
|
+
} catch {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function parseUrl(url, basepath) {
|
|
85
|
+
let urlObj;
|
|
86
|
+
basepath = catchBasePath(basepath);
|
|
87
|
+
if (url.startsWith("http")) {
|
|
88
|
+
urlObj = new URL(url);
|
|
89
|
+
} else if (url.startsWith("/")) {
|
|
90
|
+
urlObj = new URL(url, window.location.origin);
|
|
91
|
+
} else if (url.startsWith("?")) {
|
|
92
|
+
urlObj = new URL(window.location.pathname + url, window.location.origin);
|
|
93
|
+
} else if (url.startsWith("#")) {
|
|
94
|
+
urlObj = new URL(window.location.pathname + window.location.search + url, window.location.origin);
|
|
95
|
+
} else {
|
|
96
|
+
urlObj = new URL(absolutePath(basepath, url), window.location.origin);
|
|
97
|
+
}
|
|
98
|
+
return {
|
|
99
|
+
href: urlObj.href,
|
|
100
|
+
origin: urlObj.origin,
|
|
101
|
+
basepath,
|
|
102
|
+
path: urlObj.href.replace(urlObj.origin, ""),
|
|
103
|
+
pathname: urlObj.pathname,
|
|
104
|
+
query: new URLSearchParams(urlObj.search),
|
|
105
|
+
hash: urlObj.hash,
|
|
106
|
+
params: {},
|
|
107
|
+
progress: () => {
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
function absolutePath(...paths) {
|
|
112
|
+
paths = paths.map((p) => p.replace(/^\/|\/$/g, "")).filter((p) => p.length > 0);
|
|
113
|
+
if (paths.length === 0) return "/";
|
|
114
|
+
return "/" + paths.join("/");
|
|
115
|
+
}
|
|
116
|
+
function catchBasePath(basepath) {
|
|
117
|
+
if (basepath === "/") return basepath;
|
|
118
|
+
let pattern = new URLPattern({ pathname: basepath + "/*" });
|
|
119
|
+
let match = pattern.exec({ pathname: window.location.pathname });
|
|
120
|
+
if (match) {
|
|
121
|
+
const rawPath = match.pathname.input;
|
|
122
|
+
const restPath = match.pathname.groups?.["0"];
|
|
123
|
+
return restPath ? rawPath.replace("/" + restPath, "") : rawPath.slice(0, -1);
|
|
124
|
+
}
|
|
125
|
+
pattern = new URLPattern({ pathname: `${basepath}{/}?` });
|
|
126
|
+
match = pattern.exec({ pathname: window.location.pathname });
|
|
127
|
+
if (match) {
|
|
128
|
+
return match.pathname.input;
|
|
129
|
+
}
|
|
130
|
+
return basepath;
|
|
131
|
+
}
|
|
132
|
+
var __defProp = Object.defineProperty;
|
|
133
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
134
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
135
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
136
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
137
|
+
if (decorator = decorators[i])
|
|
138
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
139
|
+
if (kind && result) __defProp(target, key, result);
|
|
140
|
+
return result;
|
|
141
|
+
};
|
|
142
|
+
let ULink = class extends LitElement {
|
|
143
|
+
constructor() {
|
|
144
|
+
super(...arguments);
|
|
145
|
+
this.isExternal = false;
|
|
146
|
+
this.computedHref = "#";
|
|
147
|
+
this.handleAnchorClick = (event) => {
|
|
148
|
+
if (event.defaultPrevented) return;
|
|
149
|
+
if (event.button !== 0) return;
|
|
150
|
+
if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return;
|
|
151
|
+
const target = (this.target ?? "").trim();
|
|
152
|
+
if (target && target.toLowerCase() !== "_self") return;
|
|
153
|
+
const basepath = this.getBasepath();
|
|
154
|
+
if (!this.href) {
|
|
155
|
+
event.preventDefault();
|
|
156
|
+
this.dispatchPopstate(basepath, basepath);
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
if (this.isExternal) return;
|
|
160
|
+
if (this.href.startsWith("#")) return;
|
|
161
|
+
event.preventDefault();
|
|
162
|
+
if (this.href.startsWith("?")) {
|
|
163
|
+
const url2 = window.location.pathname + this.href;
|
|
164
|
+
this.dispatchPopstate(basepath, url2);
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
if (this.href.startsWith("/")) {
|
|
168
|
+
if (!this.href.startsWith(basepath)) {
|
|
169
|
+
window.location.assign(this.href);
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
this.dispatchPopstate(basepath, this.href);
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
const url = absolutePath(basepath, this.href);
|
|
176
|
+
this.dispatchPopstate(basepath, url);
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
willUpdate(changedProperties) {
|
|
180
|
+
super.willUpdate(changedProperties);
|
|
181
|
+
if (changedProperties.has("href")) {
|
|
182
|
+
this.isExternal = isExternalUrl(this.href || "");
|
|
183
|
+
this.computedHref = this.computeHref(this.href);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
render() {
|
|
187
|
+
return html`
|
|
188
|
+
<a
|
|
189
|
+
target=${this.target ?? "_self"}
|
|
190
|
+
href=${this.computedHref}
|
|
191
|
+
@click=${this.handleAnchorClick}
|
|
192
|
+
>
|
|
193
|
+
<slot></slot>
|
|
194
|
+
</a>
|
|
195
|
+
`;
|
|
196
|
+
}
|
|
197
|
+
/** basepath를 state에서 꺼내는 헬퍼 */
|
|
198
|
+
getBasepath() {
|
|
199
|
+
return window.history.state?.basepath || "";
|
|
200
|
+
}
|
|
201
|
+
/** a 태그에 주입할 href 값을 계산합니다. */
|
|
202
|
+
computeHref(href) {
|
|
203
|
+
const basepath = this.getBasepath();
|
|
204
|
+
if (!href) {
|
|
205
|
+
return window.location.origin + basepath;
|
|
206
|
+
}
|
|
207
|
+
if (this.isExternal) return href;
|
|
208
|
+
if (href.startsWith("#") || href.startsWith("?")) return href;
|
|
209
|
+
if (href.startsWith("/")) return href;
|
|
210
|
+
return absolutePath(basepath, href);
|
|
211
|
+
}
|
|
212
|
+
/** 클라이언트 라우팅을 위해 popstate 이벤트를 발생시킵니다. */
|
|
213
|
+
dispatchPopstate(basepath, url) {
|
|
214
|
+
window.history.pushState({ basepath }, "", url);
|
|
215
|
+
window.dispatchEvent(new PopStateEvent("popstate"));
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
ULink.styles = css`
|
|
219
|
+
:host {
|
|
220
|
+
display: inline-flex;
|
|
221
|
+
cursor: pointer;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
a {
|
|
225
|
+
display: contents;
|
|
226
|
+
text-decoration: none;
|
|
227
|
+
|
|
228
|
+
font-size: inherit;
|
|
229
|
+
font-weight: inherit;
|
|
230
|
+
font-family: inherit;
|
|
231
|
+
color: inherit;
|
|
232
|
+
cursor: inherit;
|
|
233
|
+
}
|
|
234
|
+
`;
|
|
235
|
+
__decorateClass([
|
|
236
|
+
state()
|
|
237
|
+
], ULink.prototype, "computedHref", 2);
|
|
238
|
+
__decorateClass([
|
|
239
|
+
property({ type: String })
|
|
240
|
+
], ULink.prototype, "target", 2);
|
|
241
|
+
__decorateClass([
|
|
242
|
+
property({ type: String })
|
|
243
|
+
], ULink.prototype, "href", 2);
|
|
244
|
+
ULink = __decorateClass([
|
|
245
|
+
customElement("u-link")
|
|
246
|
+
], ULink);
|
|
247
|
+
export {
|
|
248
|
+
UOutlet as U,
|
|
249
|
+
absolutePath as a,
|
|
250
|
+
ULink as b,
|
|
251
|
+
isExternalUrl as i,
|
|
252
|
+
parseUrl as p
|
|
253
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iyulab/router",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "A modern client-side router for web applications with support for Lit and React components",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"lit",
|
|
@@ -29,23 +29,27 @@
|
|
|
29
29
|
".": {
|
|
30
30
|
"types": "./dist/index.d.ts",
|
|
31
31
|
"import": "./dist/index.js"
|
|
32
|
+
},
|
|
33
|
+
"./react": {
|
|
34
|
+
"types": "./dist/react.d.ts",
|
|
35
|
+
"import": "./dist/react.js"
|
|
32
36
|
}
|
|
33
37
|
},
|
|
34
38
|
"scripts": {
|
|
35
39
|
"build": "vite build"
|
|
36
40
|
},
|
|
37
41
|
"dependencies": {
|
|
38
|
-
"lit": "^3.3.
|
|
39
|
-
"react": "^19.2.
|
|
40
|
-
"react-dom": "^19.2.
|
|
42
|
+
"lit": "^3.3.2",
|
|
43
|
+
"react": "^19.2.3",
|
|
44
|
+
"react-dom": "^19.2.3"
|
|
41
45
|
},
|
|
42
46
|
"devDependencies": {
|
|
43
47
|
"@lit/react": "^1.0.8",
|
|
44
|
-
"@types/node": "^
|
|
45
|
-
"@types/react": "^19.2.
|
|
48
|
+
"@types/node": "^25.0.8",
|
|
49
|
+
"@types/react": "^19.2.8",
|
|
46
50
|
"@types/react-dom": "^19.2.3",
|
|
47
51
|
"typescript": "^5.9.3",
|
|
48
|
-
"vite": "^7.
|
|
52
|
+
"vite": "^7.3.1",
|
|
49
53
|
"vite-plugin-dts": "^4.5.4"
|
|
50
54
|
}
|
|
51
|
-
}
|
|
55
|
+
}
|