@iyulab/router 0.5.2 → 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/LICENSE +20 -20
- package/README.md +148 -162
- package/dist/index.d.ts +74 -80
- package/dist/index.js +105 -352
- package/dist/react.d.ts +89 -0
- package/dist/react.js +44 -0
- package/dist/share-ZrQFmsur.js +253 -0
- package/package.json +55 -51
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,51 +1,55 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@iyulab/router",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "A modern client-side router for web applications with support for Lit and React components",
|
|
5
|
-
"keywords": [
|
|
6
|
-
"lit",
|
|
7
|
-
"react",
|
|
8
|
-
"router",
|
|
9
|
-
"routing",
|
|
10
|
-
"spa",
|
|
11
|
-
"navigation",
|
|
12
|
-
"client-side"
|
|
13
|
-
],
|
|
14
|
-
"license": "MIT",
|
|
15
|
-
"author": "iyulab",
|
|
16
|
-
"repository": {
|
|
17
|
-
"type": "git",
|
|
18
|
-
"url": "https://github.com/iyulab/node-router.git"
|
|
19
|
-
},
|
|
20
|
-
"files": [
|
|
21
|
-
"dist",
|
|
22
|
-
"package.json",
|
|
23
|
-
"README.md",
|
|
24
|
-
"LICENSE"
|
|
25
|
-
],
|
|
26
|
-
"type": "module",
|
|
27
|
-
"types": "dist/index.d.ts",
|
|
28
|
-
"exports": {
|
|
29
|
-
".": {
|
|
30
|
-
"types": "./dist/index.d.ts",
|
|
31
|
-
"import": "./dist/index.js"
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
"
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
|
|
51
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@iyulab/router",
|
|
3
|
+
"version": "0.6.0",
|
|
4
|
+
"description": "A modern client-side router for web applications with support for Lit and React components",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"lit",
|
|
7
|
+
"react",
|
|
8
|
+
"router",
|
|
9
|
+
"routing",
|
|
10
|
+
"spa",
|
|
11
|
+
"navigation",
|
|
12
|
+
"client-side"
|
|
13
|
+
],
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"author": "iyulab",
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "https://github.com/iyulab/node-router.git"
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist",
|
|
22
|
+
"package.json",
|
|
23
|
+
"README.md",
|
|
24
|
+
"LICENSE"
|
|
25
|
+
],
|
|
26
|
+
"type": "module",
|
|
27
|
+
"types": "dist/index.d.ts",
|
|
28
|
+
"exports": {
|
|
29
|
+
".": {
|
|
30
|
+
"types": "./dist/index.d.ts",
|
|
31
|
+
"import": "./dist/index.js"
|
|
32
|
+
},
|
|
33
|
+
"./react": {
|
|
34
|
+
"types": "./dist/react.d.ts",
|
|
35
|
+
"import": "./dist/react.js"
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"scripts": {
|
|
39
|
+
"build": "vite build"
|
|
40
|
+
},
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"lit": "^3.3.2",
|
|
43
|
+
"react": "^19.2.3",
|
|
44
|
+
"react-dom": "^19.2.3"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@lit/react": "^1.0.8",
|
|
48
|
+
"@types/node": "^25.0.8",
|
|
49
|
+
"@types/react": "^19.2.8",
|
|
50
|
+
"@types/react-dom": "^19.2.3",
|
|
51
|
+
"typescript": "^5.9.3",
|
|
52
|
+
"vite": "^7.3.1",
|
|
53
|
+
"vite-plugin-dts": "^4.5.4"
|
|
54
|
+
}
|
|
55
|
+
}
|