@iyulab/router 0.5.3 โ†’ 0.6.1

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 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-side Navigation** - History API integration with browser back/forward support
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
- root: document.getElementById('app')!,
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) => html`<my-lit-component .routeInfo=${routeInfo}></my-lit-component>`
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) => React.createElement(MyReactComponent, { 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 Components
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() {
@@ -126,38 +126,24 @@ export class AppRoot extends LitElement {
126
126
 
127
127
  ```tsx
128
128
  import React from 'react';
129
- import { Outlet, Link } from '@iyulab/router';
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
- <Link href="/">Home</Link>
136
- <Link href="/about">About</Link>
137
- <Link href="/user/123">User Profile</Link>
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
- <Outlet />
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
- MIT License - see [LICENSE](LICENSE) file for details.
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`์™€ `react-component` ๊ธฐ๋ฐ˜์˜ ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ ๋ผ์šฐํ„ฐ
300
+ * `lit-element`, `react`๋ฅผ ์ง€์›ํ•˜๋Š” ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ ๋ผ์šฐํ„ฐ
364
301
  */
365
302
  export declare class Router {
366
303
  private readonly _rootElement;
@@ -388,7 +325,7 @@ export declare class Router {
388
325
  /** ๋ธŒ๋ผ์šฐ์ € ํžˆ์Šคํ† ๋ฆฌ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒ์‹œ ๋ผ์šฐํŒ… ์ฒ˜๋ฆฌ */
389
326
  private handleWindowPopstate;
390
327
  /** ํด๋ฆญ ์ด๋ฒคํŠธ์—์„œ ๋ผ์šฐํ„ฐ๋กœ ์ฒ˜๋ฆฌํ•  ์•ต์ปค๋ฅผ ์ฐพ์•„ ํด๋ผ์ด์–ธํŠธ ๋ผ์šฐํŒ… ์ˆ˜ํ–‰ */
391
- private handleRootClick;
328
+ private handleDocumentClick;
392
329
  }
393
330
 
394
331
  /**
@@ -429,9 +366,67 @@ export declare interface RouterConfig {
429
366
  initialLoad?: boolean;
430
367
  }
431
368
 
432
- export declare const ULink: ReactWebComponent<Link, {}>;
369
+ /**
370
+ * - ํด๋ผ์ด์–ธํŠธ ๋ผ์šฐํŒ…์„ ์ง€์›ํ•˜๋Š” ๋งํฌ ์—˜๋ฆฌ๋จผํŠธ์ž…๋‹ˆ๋‹ค.
371
+ * - ๋‚ด๋ถ€ ๋งํฌ๋Š” ํด๋ผ์ด์–ธํŠธ ๋ผ์šฐํŒ…์„ ์ˆ˜ํ–‰ํ•˜๊ณ , ์™ธ๋ถ€ ๋งํฌ๋Š” ๋ธŒ๋ผ์šฐ์ € ๊ธฐ๋ณธ ๋„ค๋น„๊ฒŒ์ด์…˜์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
372
+ * - Ctrl/Meta/Shift/Alt, ์ค‘ํด๋ฆญ/์šฐํด๋ฆญ ๋“ฑ์€ ๋ธŒ๋ผ์šฐ์ € ๊ธฐ๋ณธ ๋™์ž‘(์ƒˆ ํƒญ, ์ปจํ…์ŠคํŠธ ๋ฉ”๋‰ด ๋“ฑ)์„ ๊ทธ๋Œ€๋กœ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค.
373
+ */
374
+ export declare class ULink extends LitElement {
375
+ /** ์™ธ๋ถ€ ๋งํฌ ์—ฌ๋ถ€ */
376
+ private isExternal;
377
+ /**
378
+ * a ํƒœ๊ทธ target์„ ์ง€์›ํ•˜๊ณ  ์‹ถ์œผ๋ฉด ์—ด์–ด๋‘๋Š”๊ฒŒ ์ข‹์Šต๋‹ˆ๋‹ค.
379
+ * - _blank ๋“ฑ์„ ์“ฐ๋ฉด ๋ฌด์กฐ๊ฑด ๋ธŒ๋ผ์šฐ์ € ๊ธฐ๋ณธ ๋™์ž‘์„ ๋”ฐ๋ฅด๋„๋ก ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
380
+ */
381
+ target?: string;
382
+ /**
383
+ * - ์†์„ฑ์„ ์ •์˜ํ•˜์ง€ ์•Š์œผ๋ฉด basepath๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.
384
+ * - http(s)๋กœ ์‹œ์ž‘ํ•˜๋ฉด ์™ธ๋ถ€ ๋งํฌ๋กœ ๊ฐ„์ฃผํ•˜๊ณ  ๋ธŒ๋ผ์šฐ์ € ๋„ค๋น„๊ฒŒ์ด์…˜์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
385
+ * - ์ ˆ๋Œ€๊ฒฝ๋กœ(/...)์ผ ๊ฒฝ์šฐ basepath๋กœ ์‹œ์ž‘ํ•˜๋ฉด SPA ๋ผ์šฐํŒ… ๋Œ€์ƒ์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
386
+ * - ์ƒ๋Œ€๊ฒฝ๋กœ๋Š” (basepath + ์ƒ๋Œ€๊ฒฝ๋กœ)๋กœ SPA ๋ผ์šฐํŒ… ๋Œ€์ƒ์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
387
+ * - ?๋กœ ์‹œ์ž‘ํ•˜๋ฉด ํ˜„์žฌ pathname์— ์ฟผ๋ฆฌ์ŠคํŠธ๋ง์„ ๋ถ™์—ฌ SPA ๋ผ์šฐํŒ…ํ•ฉ๋‹ˆ๋‹ค.
388
+ * - #์œผ๋กœ ์‹œ์ž‘ํ•˜๋ฉด ํ˜„์žฌ URL์— ํ•ด์‹œ๋งŒ ๋ฐ”๊พธ๊ณ (๋ธŒ๋ผ์šฐ์ € ๊ธฐ๋ณธ) ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.
389
+ */
390
+ href?: string;
391
+ protected willUpdate(changedProperties: PropertyValues): void;
392
+ render(): TemplateResult_2<1>;
393
+ /** basepath๋ฅผ state์—์„œ ๊บผ๋‚ด๋Š” ํ—ฌํผ */
394
+ private getBasepath;
395
+ /** a ํƒœ๊ทธ์— ์ฃผ์ž…ํ•  href ๊ฐ’์„ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค. */
396
+ private computeHref;
397
+ /**
398
+ * ํด๋ฆญ ๊ฐ€๋กœ์ฑ„๊ธฐ ๊ทœ์น™
399
+ * - ์ขŒํด๋ฆญ(0) + ๋ณด์กฐํ‚ค ์—†์Œ(ctrl/meta/shift/alt ์—†์Œ) + target์ด _self์ผ ๋•Œ๋งŒ SPA ๋ผ์šฐํŒ… ๊ณ ๋ ค
400
+ * - ๊ทธ ์™ธ(์ค‘ํด๋ฆญ/์šฐํด๋ฆญ/๋ณด์กฐํ‚ค/target=_blank ๋“ฑ)๋Š” ๋ธŒ๋ผ์šฐ์ € ๊ธฐ๋ณธ ๋™์ž‘ ์œ ์ง€
401
+ */
402
+ private handleAnchorClick;
403
+ /** ํด๋ผ์ด์–ธํŠธ ๋ผ์šฐํŒ…์„ ์œ„ํ•ด popstate ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค. */
404
+ private dispatchPopstate;
405
+ static styles: CSSResult;
406
+ }
433
407
 
434
- export declare const UOutlet: ReactWebComponent<Outlet, {}>;
408
+ /**
409
+ * ๋ผ์šฐํŠธ ์„ค์ •์— ๋”ฐ๋ผ LitElement ๋˜๋Š” React ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ Œ๋”๋งํ•ฉ๋‹ˆ๋‹ค.
410
+ */
411
+ export declare class UOutlet extends LitElement {
412
+ private routeId?;
413
+ private container?;
414
+ private content?;
415
+ /** ์™ธ๋ถ€ ์Šคํƒ€์ผ์„ ์ ์šฉํ•˜๊ธฐ ์œ„ํ•ด ๋ผ์ดํŠธ ๋”์„์‚ฌ์šฉ ํ•ฉ๋‹ˆ๋‹ค. */
416
+ protected createRenderRoot(): this;
417
+ /** ์ปดํฌ๋„ŒํŠธ๊ฐ€ DOM์— ์—ฐ๊ฒฐ๋  ๋•Œ ์ดˆ๊ธฐํ™” ์ž‘์—… ์ˆ˜ํ–‰ */
418
+ connectedCallback(): void;
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 React from "react";
2
- import { LitElement, html, css, render } from "lit";
3
- import { state, property, customElement } from "lit/decorators.js";
4
- import { createRoot } from "react-dom/client";
1
+ import { a as absolutePath, i as isExternalUrl, p as parseUrl } from "./share-SPj-xl6y.js";
2
+ import { b, U } from "./share-SPj-xl6y.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" width="1em" height="1em" fill="currentColor" 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>';
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" width="1em" height="1em" fill="currentColor" 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>';
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" width="1em" height="1em" fill="currentColor" 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>';
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" width="1em" height="1em" fill="currentColor" 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>';
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" width="1em" height="1em" fill="currentColor" 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>';
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" width="1em" height="1em" fill="currentColor" 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>';
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" width="1em" height="1em" fill="currentColor" 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>';
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" width="1em" height="1em" fill="currentColor" 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>';
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" width="1em" height="1em" fill="currentColor" 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>';
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 ErrorPage = class extends LitElement {
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
- ErrorPage.styles = styles;
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
- ], ErrorPage.prototype, "error", 2);
503
- ErrorPage = __decorateClass([
252
+ ], UErrorPage.prototype, "error", 2);
253
+ UErrorPage = __decorateClass([
504
254
  customElement("u-error-page")
505
- ], ErrorPage);
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,24 @@ function findOutletOrThrow(element) {
532
282
  }
533
283
  return outlet;
534
284
  }
535
- function findAnchorFromEvent(e2) {
536
- const targets = e2.composedPath() || [];
285
+ async function waitOutlet(element, timeout = 1e4) {
286
+ const start = performance.now();
287
+ while (performance.now() - start < timeout) {
288
+ const outlet = findOutlet(element);
289
+ if (outlet) return outlet;
290
+ await new Promise((r) => setTimeout(r, 50));
291
+ }
292
+ throw new Error("Timed out waiting for u-outlet.");
293
+ }
294
+ function findAnchorFrom(event) {
295
+ const targets = event.composedPath() || [];
537
296
  if (targets && targets.length) {
538
297
  for (const node of targets) {
539
298
  if (!(node instanceof Element)) continue;
540
299
  if (node.tagName === "A") return node;
541
300
  }
542
301
  }
543
- const tgt = e2.target;
302
+ const tgt = event.target;
544
303
  if (!tgt) return null;
545
304
  const anchor = tgt.closest("a");
546
305
  return anchor;
@@ -600,11 +359,11 @@ class Router {
600
359
  const href = window.location.href;
601
360
  await this.go(href);
602
361
  };
603
- this.handleRootClick = (e2) => {
362
+ this.handleDocumentClick = (e) => {
604
363
  try {
605
- if (e2.defaultPrevented) return;
606
- if (e2.button !== 0 || e2.metaKey || e2.ctrlKey || e2.shiftKey) return;
607
- const anchor = findAnchorFromEvent(e2);
364
+ if (e.defaultPrevented) return;
365
+ if (e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey) return;
366
+ const anchor = findAnchorFrom(e);
608
367
  if (!anchor) return;
609
368
  const href = anchor.getAttribute("href") || anchor.href;
610
369
  if (!href) return;
@@ -612,7 +371,7 @@ class Router {
612
371
  if (anchor.hasAttribute("download")) return;
613
372
  if (anchor.getAttribute("rel") === "external") return;
614
373
  if (anchor.target && anchor.target !== "") return;
615
- e2.preventDefault();
374
+ e.preventDefault();
616
375
  void this.go(anchor.href);
617
376
  } catch {
618
377
  }
@@ -624,17 +383,19 @@ class Router {
624
383
  window.removeEventListener("popstate", this.handleWindowPopstate);
625
384
  window.addEventListener("popstate", this.handleWindowPopstate);
626
385
  if (config.useIntercept !== false) {
627
- this._rootElement.removeEventListener("click", this.handleRootClick);
628
- this._rootElement.addEventListener("click", this.handleRootClick);
386
+ document.removeEventListener("click", this.handleDocumentClick);
387
+ document.addEventListener("click", this.handleDocumentClick);
629
388
  }
630
389
  if (config.initialLoad !== false) {
631
- void this.go(window.location.href);
390
+ void waitOutlet(this._rootElement).then(() => {
391
+ this.go(window.location.href);
392
+ });
632
393
  }
633
394
  }
634
395
  /** ๊ฐ์ฒด๋ฅผ ์ •๋ฆฌํ•˜๊ณ  ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ๋ฅผ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค. */
635
396
  destroy() {
636
397
  window.removeEventListener("popstate", this.handleWindowPopstate);
637
- this._rootElement.removeEventListener("click", this.handleRootClick);
398
+ document.removeEventListener("click", this.handleDocumentClick);
638
399
  this._requestID = void 0;
639
400
  this._context = void 0;
640
401
  }
@@ -721,7 +482,7 @@ class Router {
721
482
  outlet.renderContent({ id: "#fallback", content: fallbackContent, force: true });
722
483
  document.title = this._fallback.title || document.title;
723
484
  } else {
724
- const errorContent = new ErrorPage();
485
+ const errorContent = new UErrorPage();
725
486
  errorContent.error = error;
726
487
  if (outlet) {
727
488
  outlet.renderContent({ id: "#error", content: errorContent, force: true });
@@ -740,9 +501,7 @@ class Router {
740
501
  export {
741
502
  ContentLoadError,
742
503
  ContentRenderError,
743
- Link,
744
504
  NotFoundError,
745
- Outlet,
746
505
  OutletMissingError,
747
506
  RouteBeginEvent,
748
507
  RouteDoneEvent,
@@ -750,6 +509,6 @@ export {
750
509
  RouteErrorEvent,
751
510
  RouteProgressEvent,
752
511
  Router,
753
- ULink,
754
- UOutlet
512
+ b as ULink,
513
+ U as UOutlet
755
514
  };
@@ -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
+ /**
31
+ * a ํƒœ๊ทธ target์„ ์ง€์›ํ•˜๊ณ  ์‹ถ์œผ๋ฉด ์—ด์–ด๋‘๋Š”๊ฒŒ ์ข‹์Šต๋‹ˆ๋‹ค.
32
+ * - _blank ๋“ฑ์„ ์“ฐ๋ฉด ๋ฌด์กฐ๊ฑด ๋ธŒ๋ผ์šฐ์ € ๊ธฐ๋ณธ ๋™์ž‘์„ ๋”ฐ๋ฅด๋„๋ก ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
33
+ */
34
+ target?: string;
35
+ /**
36
+ * - ์†์„ฑ์„ ์ •์˜ํ•˜์ง€ ์•Š์œผ๋ฉด basepath๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.
37
+ * - http(s)๋กœ ์‹œ์ž‘ํ•˜๋ฉด ์™ธ๋ถ€ ๋งํฌ๋กœ ๊ฐ„์ฃผํ•˜๊ณ  ๋ธŒ๋ผ์šฐ์ € ๋„ค๋น„๊ฒŒ์ด์…˜์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
38
+ * - ์ ˆ๋Œ€๊ฒฝ๋กœ(/...)์ผ ๊ฒฝ์šฐ basepath๋กœ ์‹œ์ž‘ํ•˜๋ฉด SPA ๋ผ์šฐํŒ… ๋Œ€์ƒ์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
39
+ * - ์ƒ๋Œ€๊ฒฝ๋กœ๋Š” (basepath + ์ƒ๋Œ€๊ฒฝ๋กœ)๋กœ SPA ๋ผ์šฐํŒ… ๋Œ€์ƒ์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
40
+ * - ?๋กœ ์‹œ์ž‘ํ•˜๋ฉด ํ˜„์žฌ pathname์— ์ฟผ๋ฆฌ์ŠคํŠธ๋ง์„ ๋ถ™์—ฌ SPA ๋ผ์šฐํŒ…ํ•ฉ๋‹ˆ๋‹ค.
41
+ * - #์œผ๋กœ ์‹œ์ž‘ํ•˜๋ฉด ํ˜„์žฌ URL์— ํ•ด์‹œ๋งŒ ๋ฐ”๊พธ๊ณ (๋ธŒ๋ผ์šฐ์ € ๊ธฐ๋ณธ) ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.
42
+ */
43
+ href?: string;
44
+ protected willUpdate(changedProperties: PropertyValues): void;
45
+ render(): TemplateResult<1>;
46
+ /** basepath๋ฅผ state์—์„œ ๊บผ๋‚ด๋Š” ํ—ฌํผ */
47
+ private getBasepath;
48
+ /** a ํƒœ๊ทธ์— ์ฃผ์ž…ํ•  href ๊ฐ’์„ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค. */
49
+ private computeHref;
50
+ /**
51
+ * ํด๋ฆญ ๊ฐ€๋กœ์ฑ„๊ธฐ ๊ทœ์น™
52
+ * - ์ขŒํด๋ฆญ(0) + ๋ณด์กฐํ‚ค ์—†์Œ(ctrl/meta/shift/alt ์—†์Œ) + target์ด _self์ผ ๋•Œ๋งŒ SPA ๋ผ์šฐํŒ… ๊ณ ๋ ค
53
+ * - ๊ทธ ์™ธ(์ค‘ํด๋ฆญ/์šฐํด๋ฆญ/๋ณด์กฐํ‚ค/target=_blank ๋“ฑ)๋Š” ๋ธŒ๋ผ์šฐ์ € ๊ธฐ๋ณธ ๋™์ž‘ ์œ ์ง€
54
+ */
55
+ private handleAnchorClick;
56
+ /** ํด๋ผ์ด์–ธํŠธ ๋ผ์šฐํŒ…์„ ์œ„ํ•ด popstate ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค. */
57
+ private dispatchPopstate;
58
+ static styles: CSSResult;
59
+ }
60
+
61
+ /**
62
+ * `u-outlet` ์›น ์ปดํฌ๋„ŒํŠธ๋ฅผ React์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๋ž˜ํ•‘ํ•œ ์ปดํฌ๋„ŒํŠธ์ž…๋‹ˆ๋‹ค.
63
+ */
64
+ export declare const UOutlet: ReactWebComponent<UOutlet_2, {}>;
65
+
66
+ /**
67
+ * ๋ผ์šฐํŠธ ์„ค์ •์— ๋”ฐ๋ผ LitElement ๋˜๋Š” React ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ Œ๋”๋งํ•ฉ๋‹ˆ๋‹ค.
68
+ */
69
+ declare class UOutlet_2 extends LitElement {
70
+ private routeId?;
71
+ private container?;
72
+ private content?;
73
+ /** ์™ธ๋ถ€ ์Šคํƒ€์ผ์„ ์ ์šฉํ•˜๊ธฐ ์œ„ํ•ด ๋ผ์ดํŠธ ๋”์„์‚ฌ์šฉ ํ•ฉ๋‹ˆ๋‹ค. */
74
+ protected createRenderRoot(): this;
75
+ /** ์ปดํฌ๋„ŒํŠธ๊ฐ€ DOM์— ์—ฐ๊ฒฐ๋  ๋•Œ ์ดˆ๊ธฐํ™” ์ž‘์—… ์ˆ˜ํ–‰ */
76
+ connectedCallback(): void;
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-SPj-xl6y.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,255 @@
1
+ import { LitElement, html, render, css } from "lit";
2
+ import { customElement, 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
+ /** ์ปดํฌ๋„ŒํŠธ๊ฐ€ DOM์— ์—ฐ๊ฒฐ๋  ๋•Œ ์ดˆ๊ธฐํ™” ์ž‘์—… ์ˆ˜ํ–‰ */
18
+ connectedCallback() {
19
+ super.connectedCallback();
20
+ this.dispatchEvent(new CustomEvent("outlet-load", {
21
+ bubbles: true,
22
+ composed: true
23
+ }));
24
+ }
25
+ render() {
26
+ return html`${this.container}`;
27
+ }
28
+ /**
29
+ * render ํ•จ์ˆ˜์˜ ๊ฒฐ๊ณผ๋ฅผ ๋ Œ๋”๋งํ•ฉ๋‹ˆ๋‹ค.
30
+ * - HTMLElement, ReactElement, TemplateResult๋ฅผ ๋ชจ๋‘ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
31
+ */
32
+ async renderContent({ id, content, force }) {
33
+ if (this.routeId === id && force === false && this.container) {
34
+ return this.container;
35
+ }
36
+ this.routeId = id;
37
+ this.clear();
38
+ if (!this.container) {
39
+ throw new Error("Outlet container is not initialized.");
40
+ }
41
+ if (typeof content !== "object") {
42
+ throw new Error("Content is not a valid renderable object.");
43
+ }
44
+ if (content instanceof HTMLElement) {
45
+ this.container.appendChild(content);
46
+ } else if ("_$litType$" in content) {
47
+ this.content = render(content, this.container);
48
+ } else if ("$$typeof" in content) {
49
+ this.content = createRoot(this.container);
50
+ this.content.render(content);
51
+ } else {
52
+ throw new Error("not supported content type for Outlet rendering.");
53
+ }
54
+ this.requestUpdate();
55
+ await this.updateComplete;
56
+ return this.container;
57
+ }
58
+ /**
59
+ * ๊ธฐ์กด DOM์„ ๋ผ์ดํ”„ ์‚ฌ์ดํด์— ๋งž๊ฒŒ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค.
60
+ */
61
+ clear() {
62
+ if (this.content) {
63
+ if ("unmount" in this.content) {
64
+ this.content.unmount();
65
+ }
66
+ if ("setConnected" in this.content) {
67
+ this.content.setConnected(false);
68
+ }
69
+ this.content = void 0;
70
+ }
71
+ this.container = document.createElement("div");
72
+ this.container.style.display = "contents";
73
+ }
74
+ };
75
+ UOutlet = __decorateClass$1([
76
+ customElement("u-outlet")
77
+ ], UOutlet);
78
+ function isExternalUrl(url) {
79
+ if (!url) return false;
80
+ const s = url.trim();
81
+ if (/^(?:mailto:|tel:|javascript:)/i.test(s)) return true;
82
+ if (s.startsWith("//")) return true;
83
+ try {
84
+ const base = typeof window !== "undefined" ? window.location.origin : "http://localhost";
85
+ const parsed = new URL(s, base);
86
+ if (/^(?:ftp:|ftps:|data:|ws:|wss:)/i.test(parsed.protocol)) return true;
87
+ return parsed.origin !== new URL(base).origin;
88
+ } catch {
89
+ return false;
90
+ }
91
+ }
92
+ function parseUrl(url, basepath) {
93
+ let urlObj;
94
+ basepath = catchBasePath(basepath);
95
+ if (url.startsWith("http")) {
96
+ urlObj = new URL(url);
97
+ } else if (url.startsWith("/")) {
98
+ urlObj = new URL(url, window.location.origin);
99
+ } else if (url.startsWith("?")) {
100
+ urlObj = new URL(window.location.pathname + url, window.location.origin);
101
+ } else if (url.startsWith("#")) {
102
+ urlObj = new URL(window.location.pathname + window.location.search + url, window.location.origin);
103
+ } else {
104
+ urlObj = new URL(absolutePath(basepath, url), window.location.origin);
105
+ }
106
+ return {
107
+ href: urlObj.href,
108
+ origin: urlObj.origin,
109
+ basepath,
110
+ path: urlObj.href.replace(urlObj.origin, ""),
111
+ pathname: urlObj.pathname,
112
+ query: new URLSearchParams(urlObj.search),
113
+ hash: urlObj.hash,
114
+ params: {},
115
+ progress: () => {
116
+ }
117
+ };
118
+ }
119
+ function absolutePath(...paths) {
120
+ paths = paths.map((p) => p.replace(/^\/|\/$/g, "")).filter((p) => p.length > 0);
121
+ if (paths.length === 0) return "/";
122
+ return "/" + paths.join("/");
123
+ }
124
+ function catchBasePath(basepath) {
125
+ if (basepath === "/") return basepath;
126
+ let pattern = new URLPattern({ pathname: basepath + "/*" });
127
+ let match = pattern.exec({ pathname: window.location.pathname });
128
+ if (match) {
129
+ const rawPath = match.pathname.input;
130
+ const restPath = match.pathname.groups?.["0"];
131
+ return restPath ? rawPath.replace("/" + restPath, "") : rawPath.slice(0, -1);
132
+ }
133
+ pattern = new URLPattern({ pathname: `${basepath}{/}?` });
134
+ match = pattern.exec({ pathname: window.location.pathname });
135
+ if (match) {
136
+ return match.pathname.input;
137
+ }
138
+ return basepath;
139
+ }
140
+ var __defProp = Object.defineProperty;
141
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
142
+ var __decorateClass = (decorators, target, key, kind) => {
143
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
144
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
145
+ if (decorator = decorators[i])
146
+ result = (kind ? decorator(target, key, result) : decorator(result)) || result;
147
+ if (kind && result) __defProp(target, key, result);
148
+ return result;
149
+ };
150
+ let ULink = class extends LitElement {
151
+ constructor() {
152
+ super(...arguments);
153
+ this.isExternal = false;
154
+ this.handleAnchorClick = (event) => {
155
+ if (event.defaultPrevented) return;
156
+ if (event.button !== 0) return;
157
+ if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return;
158
+ const target = (this.target ?? "").trim();
159
+ if (target && target.toLowerCase() !== "_self") return;
160
+ const basepath = this.getBasepath();
161
+ if (!this.href) {
162
+ event.preventDefault();
163
+ this.dispatchPopstate(basepath, basepath);
164
+ return;
165
+ }
166
+ if (this.isExternal) return;
167
+ if (this.href.startsWith("#")) return;
168
+ event.preventDefault();
169
+ if (this.href.startsWith("?")) {
170
+ const url2 = window.location.pathname + this.href;
171
+ this.dispatchPopstate(basepath, url2);
172
+ return;
173
+ }
174
+ if (this.href.startsWith("/")) {
175
+ if (!this.href.startsWith(basepath)) {
176
+ window.location.assign(this.href);
177
+ return;
178
+ }
179
+ this.dispatchPopstate(basepath, this.href);
180
+ return;
181
+ }
182
+ const url = absolutePath(basepath, this.href);
183
+ this.dispatchPopstate(basepath, url);
184
+ };
185
+ }
186
+ willUpdate(changedProperties) {
187
+ super.willUpdate(changedProperties);
188
+ if (changedProperties.has("href")) {
189
+ this.isExternal = isExternalUrl(this.href || "");
190
+ }
191
+ }
192
+ render() {
193
+ return html`
194
+ <a
195
+ target=${this.target ?? "_self"}
196
+ href=${this.computeHref(this.href)}
197
+ @click=${this.handleAnchorClick}>
198
+ <slot></slot>
199
+ </a>
200
+ `;
201
+ }
202
+ /** basepath๋ฅผ state์—์„œ ๊บผ๋‚ด๋Š” ํ—ฌํผ */
203
+ getBasepath() {
204
+ return window.history.state?.basepath || "";
205
+ }
206
+ /** a ํƒœ๊ทธ์— ์ฃผ์ž…ํ•  href ๊ฐ’์„ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค. */
207
+ computeHref(href) {
208
+ const basepath = this.getBasepath();
209
+ if (!href) {
210
+ return window.location.origin + basepath;
211
+ }
212
+ if (this.isExternal) return href;
213
+ if (href.startsWith("#") || href.startsWith("?")) return href;
214
+ if (href.startsWith("/")) return href;
215
+ return absolutePath(basepath, href);
216
+ }
217
+ /** ํด๋ผ์ด์–ธํŠธ ๋ผ์šฐํŒ…์„ ์œ„ํ•ด popstate ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค. */
218
+ dispatchPopstate(basepath, url) {
219
+ window.history.pushState({ basepath }, "", url);
220
+ window.dispatchEvent(new PopStateEvent("popstate"));
221
+ }
222
+ };
223
+ ULink.styles = css`
224
+ :host {
225
+ display: inline-flex;
226
+ cursor: pointer;
227
+ }
228
+
229
+ a {
230
+ display: contents;
231
+ text-decoration: none;
232
+
233
+ font-size: inherit;
234
+ font-weight: inherit;
235
+ font-family: inherit;
236
+ color: inherit;
237
+ cursor: inherit;
238
+ }
239
+ `;
240
+ __decorateClass([
241
+ property({ type: String })
242
+ ], ULink.prototype, "target", 2);
243
+ __decorateClass([
244
+ property({ type: String })
245
+ ], ULink.prototype, "href", 2);
246
+ ULink = __decorateClass([
247
+ customElement("u-link")
248
+ ], ULink);
249
+ export {
250
+ UOutlet as U,
251
+ absolutePath as a,
252
+ ULink as b,
253
+ isExternalUrl as i,
254
+ parseUrl as p
255
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iyulab/router",
3
- "version": "0.5.3",
3
+ "version": "0.6.1",
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,28 @@
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": {
39
+ "test": "vite",
35
40
  "build": "vite build"
36
41
  },
37
42
  "dependencies": {
38
- "lit": "^3.3.1",
39
- "react": "^19.2.1",
40
- "react-dom": "^19.2.1"
43
+ "lit": "^3.3.2",
44
+ "react": "^19.2.3",
45
+ "react-dom": "^19.2.3"
41
46
  },
42
47
  "devDependencies": {
43
48
  "@lit/react": "^1.0.8",
44
- "@types/node": "^24.10.1",
45
- "@types/react": "^19.2.7",
49
+ "@types/node": "^25.0.9",
50
+ "@types/react": "^19.2.8",
46
51
  "@types/react-dom": "^19.2.3",
47
52
  "typescript": "^5.9.3",
48
- "vite": "^7.2.6",
53
+ "vite": "^7.3.1",
49
54
  "vite-plugin-dts": "^4.5.4"
50
55
  }
51
- }
56
+ }