@iyulab/modern-app 0.2.2 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,14 +1,18 @@
1
- # Changelog
2
-
3
- ## 0.2.2 (2025-11-17)
4
- - added `fallback` config in `AppConfig` type
5
- - improved route-progress handling in layout component
6
-
7
- ## 0.2.1 (2025-11-13)
8
- - Fixed few component and sidebar styles
9
- - removed `theme` setter property in `app` instance
10
- - changed `progress` property to function in `app` instance
11
- - changed name `locales` option to `localization` option in `AppConfig` type
12
-
13
- ## 0.2.0 (2025-11-12)
1
+ # Changelog
2
+
3
+ ## 0.2.3 (2025-12-19)
4
+ - added `root` option in `AppConfig` type to set application root element
5
+ - update `@iyulab/components` to v0.1.10
6
+
7
+ ## 0.2.2 (2025-11-17)
8
+ - added `fallback` config in `AppConfig` type
9
+ - improved route-progress handling in layout component
10
+
11
+ ## 0.2.1 (2025-11-13)
12
+ - Fixed few component and sidebar styles
13
+ - removed `theme` setter property in `app` instance
14
+ - changed `progress` property to function in `app` instance
15
+ - changed name `locales` option to `localization` option in `AppConfig` type
16
+
17
+ ## 0.2.0 (2025-11-12)
14
18
  - Initial library version release
package/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2025 Iyulab, Inc.
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Iyulab, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
21
  SOFTWARE.
package/README.md CHANGED
@@ -1,35 +1,158 @@
1
- # Modern App
2
-
3
- A modern web application framework by iyulab, built on React and Lit Element.
4
-
5
- For complete examples and documentation, visit our demo site: [https://modern-app.iyulab.com](https://modern-app.iyulab.com)
6
-
7
- ## Installation
8
-
9
- ```bash
10
- npm install @iyulab/modern-app
11
- ```
12
-
13
- ## Quick Start
14
-
15
- ```javascript
16
- import { app } from '@iyulab/modern-app';
17
-
18
- // Load your app configuration
19
- await app.load({
20
- layout: {
21
- type: 'sidebar',
22
- // layout configuration
23
- },
24
- routes: [
25
- // your routes
26
- ],
27
- locales: {
28
- // locale configuration
29
- }
30
- });
31
- ```
32
-
33
- ## License
34
-
35
- MIT
1
+ # Modern App
2
+
3
+ A modern web application framework by iyulab, built on React and Lit Element.
4
+
5
+ For complete examples and documentation, visit our demo site: [https://modern-app.iyulab.com](https://modern-app.iyulab.com)
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install @iyulab/modern-app
11
+ ```
12
+
13
+ ## Quick Start
14
+
15
+ ```typescript
16
+ import { app } from '@iyulab/modern-app';
17
+
18
+ await app.load({
19
+ basepath: '/',
20
+ layout: {
21
+ type: 'sidebar',
22
+ // ...layout configuration
23
+ },
24
+ routes: [
25
+ { index: true, render: () => html`<home-page></home-page>` },
26
+ { path: 'about', render: () => html`<about-page></about-page>` },
27
+ ],
28
+ });
29
+ ```
30
+
31
+ ## API Reference
32
+
33
+ ### Navigation
34
+
35
+ ```typescript
36
+ // Navigate to a path
37
+ app.navigate('/path');
38
+
39
+ // Access router instance
40
+ app.router?.go('/path');
41
+ app.router?.basepath; // Get base path
42
+ app.router?.routes; // Get registered routes
43
+ app.router?.context; // Get current route context
44
+ ```
45
+
46
+ ### Theme Management
47
+
48
+ ```typescript
49
+ // Get current theme
50
+ app.theme.get(); // Returns: 'system' | 'light' | 'dark' | undefined
51
+
52
+ // Set theme
53
+ app.theme.set('dark'); // 'system' | 'light' | 'dark'
54
+
55
+ // Check initialization status
56
+ app.theme.isInitialized;
57
+ ```
58
+
59
+ ### Notifications
60
+
61
+ ```typescript
62
+ // Display notifications (returns Promise<void>)
63
+ await app.notice('Notice message');
64
+ await app.info('Info message');
65
+ await app.success('Success message');
66
+ await app.warning('Warning message');
67
+ await app.error('Error message');
68
+
69
+ // With options
70
+ await app.success('Saved!', {
71
+ title: 'Success',
72
+ duration: 5000, // milliseconds (default: 3000)
73
+ position: 'top-right' // 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left'
74
+ });
75
+ ```
76
+
77
+ ### Localization
78
+
79
+ ```typescript
80
+ // Access i18next instance
81
+ app.localizer; // i18next instance
82
+
83
+ // Usage with lit-i18n
84
+ import { translate } from 'lit-i18n';
85
+ html`<p>${translate('namespace::key')}</p>`;
86
+ ```
87
+
88
+ ## Configuration
89
+
90
+ ### AppConfig
91
+
92
+ ```typescript
93
+ interface AppConfig {
94
+ root?: Element; // Root element (default: document.body)
95
+ basepath?: string; // Base path for routing (default: '/')
96
+ routes: RouteConfig[]; // Route definitions
97
+ fallback?: FallbackConfig; // Error fallback route
98
+ theme?: ThemeInitOptions; // Theme configuration
99
+ localization?: i18next.InitOptions; // i18next options
100
+ layout: LayoutConfig; // Layout configuration
101
+ }
102
+ ```
103
+
104
+ ### Theme Options
105
+
106
+ ```typescript
107
+ interface ThemeInitOptions {
108
+ default?: 'system' | 'light' | 'dark'; // Default theme
109
+ debug?: boolean; // Enable debug logging
110
+ store?: false | { // Persist theme preference
111
+ type: 'cookie' | 'localStorage' | 'sessionStorage';
112
+ prefix?: string;
113
+ };
114
+ useBuiltIn?: boolean; // Use built-in styles (default: true)
115
+ }
116
+ ```
117
+
118
+ ### Layout Configuration (Sidebar)
119
+
120
+ ```typescript
121
+ interface SidebarLayoutConfig {
122
+ type: 'sidebar';
123
+ breakpoints?: [number, number]; // [small, medium] (default: [768, 1024])
124
+ logo?: {
125
+ type: 'icon' | 'image';
126
+ icon?: string;
127
+ src?: string;
128
+ label?: string;
129
+ onClick?: () => void;
130
+ };
131
+ menu?: MenuItem[]; // Navigation menu items
132
+ footer?: FooterItem[]; // Footer buttons/items
133
+ }
134
+ ```
135
+
136
+ ### Route Configuration
137
+
138
+ ```typescript
139
+ interface RouteConfig {
140
+ index?: boolean; // Index route
141
+ path?: string; // Route path (supports :param patterns)
142
+ title?: string; // Document title
143
+ force?: boolean; // Force re-render
144
+ render: (context: RouteContext) => RenderResult | Promise<RenderResult>;
145
+ }
146
+
147
+ interface RouteContext {
148
+ href: string; // Full URL
149
+ pathname: string; // Path portion
150
+ basepath: string; // Base path
151
+ params: Record<string, string>; // URL parameters
152
+ progress: (value: number) => void; // Progress callback (0-100)
153
+ }
154
+ ```
155
+
156
+ ## License
157
+
158
+ MIT
@@ -1,16 +1,16 @@
1
- import { runInAction as u } from "mobx";
1
+ import { runInAction as l } from "mobx";
2
2
  import n from "i18next";
3
- import { Router as l } from "@iyulab/router";
4
- import { theme as s } from "@iyulab/components/dist/utilities/theme.js";
5
- import { notifier as d } from "@iyulab/components/dist/utilities/notifier.js";
6
- import { screen as r } from "./internals/observables.js";
3
+ import { Router as d } from "@iyulab/router";
4
+ import { theme as u } from "@iyulab/components/dist/utilities/theme.js";
5
+ import { notifier as h } from "@iyulab/components/dist/utilities/notifier.js";
6
+ import { screen as s } from "./internals/observables.js";
7
7
  class o {
8
8
  // private 생성자로 외부에서 인스턴스 생성 방지
9
9
  constructor() {
10
10
  this.handleWindowResize = (t) => {
11
11
  const e = window.innerWidth, [i, a] = this._config?.layout.breakpoints || [768, 1024];
12
- u(() => {
13
- e < i ? r.set("small") : e < a ? r.set("medium") : r.set("large");
12
+ l(() => {
13
+ e < i ? s.set("small") : e < a ? s.set("medium") : s.set("large");
14
14
  });
15
15
  };
16
16
  }
@@ -28,7 +28,7 @@ class o {
28
28
  }
29
29
  /** 스타일 테마 관리 유틸리티 객체 반환 */
30
30
  get theme() {
31
- return s;
31
+ return u;
32
32
  }
33
33
  /** 다국어 로컬라이저(i18next) 반환 */
34
34
  get localizer() {
@@ -36,12 +36,14 @@ class o {
36
36
  }
37
37
  /** 앱 로드 및 초기화 */
38
38
  async load(t) {
39
- if (this.unload(), this._config = t, await s.init(t.theme), t.localization) {
40
- for (const e of t.localization.plugins || [])
41
- n.use(e);
39
+ if (this.unload(), this._config = t, await u.init(t.theme), t.localization) {
40
+ for (const i of t.localization.plugins || [])
41
+ n.use(i);
42
42
  await n.init(t.localization);
43
43
  }
44
- window.addEventListener("resize", this.handleWindowResize), this.handleWindowResize(new Event("resize")), this._layout = await this.createLayout(t.layout), this._router = new l({
44
+ window.addEventListener("resize", this.handleWindowResize), this.handleWindowResize(new Event("resize"));
45
+ const e = t.root || document.body;
46
+ this._layout = await this.createLayout(e, t.layout), this._router = new d({
45
47
  root: this._layout,
46
48
  basepath: t.basepath,
47
49
  routes: t.routes,
@@ -76,28 +78,29 @@ class o {
76
78
  async error(t, e) {
77
79
  await this.notify("error", t, e);
78
80
  }
79
- /** 레이아웃 생성 */
80
- async createLayout(t) {
81
- let e = document.body.querySelector("[data-layout]");
82
- if (e && document.body.removeChild(e), t.type === "sidebar") {
83
- const { SidebarLayout: i } = await import("./layouts/SidebarLayout.js"), a = new i();
84
- a.config = t, e = a;
85
- } else
86
- throw new Error(`Unsupported layout type: ${t.type}`);
87
- return e.setAttribute("data-layout", "true"), document.body.appendChild(e), "updateComplete" in e && await e.updateComplete, e;
88
- }
89
81
  /** 알림 표시 */
90
82
  async notify(t, e, i) {
91
- await d.toast({
83
+ await h.toast({
92
84
  type: t,
93
85
  content: e,
94
- label: i?.title,
86
+ heading: i?.title,
95
87
  duration: i?.duration || 3e3,
96
88
  position: i?.position || "top-right"
97
89
  });
98
90
  }
91
+ /** 레이아웃 생성 */
92
+ async createLayout(t, e) {
93
+ t === document.body && (document.body.style.margin = "0", document.body.style.width = "100vw", document.body.style.height = "100vh");
94
+ let i = t.querySelector("[data-layout]");
95
+ if (i && t.removeChild(i), e.type === "sidebar") {
96
+ const { SidebarLayout: a } = await import("./layouts/SidebarLayout.js"), r = new a();
97
+ r.config = e, i = r;
98
+ } else
99
+ throw new Error(`Unsupported layout type: ${e.type}`);
100
+ return i.setAttribute("data-layout", "true"), t.appendChild(i), "updateComplete" in i && await i.updateComplete, i;
101
+ }
99
102
  }
100
- const p = o.instance;
103
+ const _ = o.instance;
101
104
  export {
102
- p as app
105
+ _ as app
103
106
  };
@@ -1,19 +1,19 @@
1
1
  import { html as c } from "lit";
2
2
  import { property as o } from "lit/decorators.js";
3
- import { Icon as l } from "@iyulab/components/dist/components/Icon/Icon.js";
3
+ import { UIcon as l } from "@iyulab/components/dist/components/Icon/UIcon.component.js";
4
4
  import { ExtendedBaseElement as m } from "../internals/ExtendedBaseElement.js";
5
- import { styles as u } from "./SidebarButton.styles.js";
6
- var d = Object.defineProperty, n = (e, p, s, f) => {
5
+ import { styles as d } from "./SidebarButton.styles.js";
6
+ var u = Object.defineProperty, n = (e, p, s, f) => {
7
7
  for (var t = void 0, r = e.length - 1, a; r >= 0; r--)
8
8
  (a = e[r]) && (t = a(p, s, t) || t);
9
- return t && d(p, s, t), t;
9
+ return t && u(p, s, t), t;
10
10
  };
11
11
  class i extends m {
12
12
  constructor() {
13
13
  super(...arguments), this.compact = !1;
14
14
  }
15
15
  static {
16
- this.styles = [super.styles, u];
16
+ this.styles = [super.styles, d];
17
17
  }
18
18
  static {
19
19
  this.dependencies = {
@@ -25,7 +25,6 @@ class i extends m {
25
25
  <button part="base">
26
26
  <u-icon part="icon"
27
27
  ?hidden=${!this.icon}
28
- ?remote=${!0}
29
28
  .name=${this.icon}
30
29
  ></u-icon>
31
30
  <span part="label"
@@ -5,7 +5,7 @@ const r = o`
5
5
  width: 100%;
6
6
  padding: 8px 12px;
7
7
  font-size: 14px;
8
- color: var(--u-text-color);
8
+ color: var(--u-txt-color);
9
9
  background: transparent;
10
10
  border: none;
11
11
  border-radius: 8px;
@@ -21,7 +21,7 @@ const r = o`
21
21
  gap: 0;
22
22
  }
23
23
  :host(:hover) {
24
- color: var(--u-text-color-hover);
24
+ color: var(--u-txt-color-hover);
25
25
  background-color: var(--u-bg-color-hover);
26
26
  }
27
27
  :host(:active) {
@@ -38,7 +38,7 @@ const r = o`
38
38
  gap: 12px;
39
39
  }
40
40
  button:focus-visible {
41
- outline: 2px solid var(--u-input-border-focus);
41
+ outline: 2px solid #6666ff;
42
42
  outline-offset: 2px;
43
43
  }
44
44
 
@@ -1,7 +1,7 @@
1
1
  import { html as c } from "lit";
2
2
  import { property as o } from "lit/decorators.js";
3
- import { Icon as d } from "@iyulab/components/dist/components/Icon/Icon.js";
4
- import { app as m } from "../app.js";
3
+ import { UIcon as d } from "@iyulab/components/dist/components/Icon/UIcon.component.js";
4
+ import { app as m } from "../App.js";
5
5
  import { ExtendedBaseElement as u } from "../internals/ExtendedBaseElement.js";
6
6
  import { SidebarLink as h } from "./SidebarLink.js";
7
7
  import { styles as f } from "./SidebarGroup.styles.js";
@@ -35,13 +35,13 @@ class s extends u {
35
35
  @click=${this.handleButtonClick}>
36
36
  <u-icon class="icon" part="icon"
37
37
  ?hidden=${!this.icon}
38
- ?remote=${!0}
39
38
  .name=${this.icon}
40
39
  ></u-icon>
41
40
  <span class="label" part="label">
42
41
  ${this.label}
43
42
  </span>
44
43
  <u-icon class="toggler" part="toggler"
44
+ lib="internal"
45
45
  name="chevron-down"
46
46
  ></u-icon>
47
47
  </button>
@@ -40,7 +40,7 @@ const e = o`
40
40
  gap: 12px;
41
41
  width: 100%;
42
42
  padding: 8px 12px;
43
- color: var(--u-text-color);
43
+ color: var(--u-txt-color);
44
44
  font-family: inherit;
45
45
  background: transparent;
46
46
  border: none;
@@ -50,7 +50,7 @@ const e = o`
50
50
  }
51
51
  button:hover {
52
52
  background-color: var(--u-bg-color-hover);
53
- color: var(--u-text-color-hover);
53
+ color: var(--u-txt-color-hover);
54
54
  }
55
55
 
56
56
  .icon {
@@ -1,12 +1,12 @@
1
1
  import { html as c } from "lit";
2
2
  import { property as e } from "lit/decorators.js";
3
- import { Icon as l } from "@iyulab/components/dist/components/Icon/Icon.js";
3
+ import { UIcon as l } from "@iyulab/components/dist/components/Icon/UIcon.component.js";
4
4
  import { ExtendedBaseElement as h } from "../internals/ExtendedBaseElement.js";
5
5
  import { styles as d } from "./SidebarLink.styles.js";
6
- var m = Object.defineProperty, n = (o, r, a, u) => {
6
+ var f = Object.defineProperty, n = (o, r, a, m) => {
7
7
  for (var t = void 0, s = o.length - 1, p; s >= 0; s--)
8
8
  (p = o[s]) && (t = p(r, a, t) || t);
9
- return t && m(r, a, t), t;
9
+ return t && f(r, a, t), t;
10
10
  };
11
11
  class i extends h {
12
12
  constructor() {
@@ -35,7 +35,6 @@ class i extends h {
35
35
  ?compact=${this.compact}>
36
36
  <u-icon part="icon"
37
37
  ?hidden=${!this.icon}
38
- ?remote=${!0}
39
38
  .name=${this.icon}
40
39
  ></u-icon>
41
40
  <span part="label"
@@ -1,26 +1,26 @@
1
1
  import { css as o } from "lit";
2
- const r = o`
2
+ const e = o`
3
3
  :host {
4
4
  display: block;
5
5
  border-radius: 8px;
6
- color: var(--u-text-color);
6
+ color: var(--u-txt-color);
7
7
  text-decoration: none;
8
8
  transition: all 0.2s ease;
9
9
  cursor: pointer;
10
10
  }
11
11
  :host(:hover) {
12
- color: var(--u-text-color-hover);
12
+ color: var(--u-txt-color-hover);
13
13
  background-color: var(--u-bg-color-hover);
14
14
  }
15
15
  :host([selected]) {
16
- color: var(--u-text-color-inverse);
16
+ color: var(--u-txt-color-inverse);
17
17
  background-color: var(--u-blue-600);
18
- box-shadow: 0 1px 3px var(--u-shadow-weak);
18
+ box-shadow: 0 1px 3px var(--u-shadow-color-weak);
19
19
  }
20
20
  :host([selected]:hover) {
21
- color: var(--u-text-color-inverse);
21
+ color: var(--u-txt-color-inverse);
22
22
  background-color: var(--u-blue-700);
23
- box-shadow: 0 2px 6px var(--u-shadow-normal);
23
+ box-shadow: 0 2px 6px var(--u-shadow-color-normal);
24
24
  }
25
25
 
26
26
  u-link {
@@ -54,5 +54,5 @@ const r = o`
54
54
  }
55
55
  `;
56
56
  export {
57
- r as styles
57
+ e as styles
58
58
  };
@@ -1,6 +1,6 @@
1
1
  import { nothing as m, html as s } from "lit";
2
2
  import { property as e } from "lit/decorators.js";
3
- import { Icon as l } from "@iyulab/components/dist/components/icon/Icon.js";
3
+ import { UIcon as l } from "@iyulab/components/dist/components/icon/UIcon.component.js";
4
4
  import { ExtendedBaseElement as h } from "../internals/ExtendedBaseElement.js";
5
5
  import { styles as y } from "./SidebarLogo.styles.js";
6
6
  var d = Object.defineProperty, i = (r, n, a, g) => {
@@ -29,8 +29,7 @@ class o extends h {
29
29
  src=${this.image}
30
30
  alt="App Logo"
31
31
  />` : this.type === "icon" && this.icon ? s`
32
- <u-icon part="icon"
33
- .remote=${!0}
32
+ <u-icon part="icon"
34
33
  .name=${this.icon}
35
34
  ></u-icon>` : m}
36
35
  <span part="label"
@@ -1,19 +1,19 @@
1
- import { css as e } from "lit";
2
- const t = e`
1
+ import { css as o } from "lit";
2
+ const e = o`
3
3
  :host {
4
4
  display: block;
5
5
  min-width: 0;
6
6
  font-size: 32px;
7
- color: var(--u-text-color);
7
+ color: var(--u-txt-color);
8
8
  user-select: none;
9
9
  cursor: pointer;
10
10
  transition: all 0.2s ease;
11
11
  }
12
12
  :host(:hover) {
13
- color: var(--u-text-color-hover);
13
+ color: var(--u-txt-color-hover);
14
14
  }
15
15
  :host(:active) {
16
- color: var(--u-text-color-active);
16
+ color: var(--u-txt-color-active);
17
17
  }
18
18
 
19
19
  .container {
@@ -53,5 +53,5 @@ const t = e`
53
53
  }
54
54
  `;
55
55
  export {
56
- t as styles
56
+ e as styles
57
57
  };
@@ -21,7 +21,7 @@ const o = e`
21
21
  .title {
22
22
  font-size: 12px;
23
23
  font-weight: 700;
24
- color: var(--u-soft-text-color);
24
+ color: var(--u-txt-color-weak);
25
25
  text-transform: uppercase;
26
26
  letter-spacing: 0.5px;
27
27
  margin: 0;
@@ -29,7 +29,7 @@ const o = e`
29
29
 
30
30
  .subtitle {
31
31
  font-size: 11px;
32
- color: var(--u-text-color-disabled);
32
+ color: var(--u-txt-color-disabled);
33
33
  margin: 0;
34
34
  }
35
35
 
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { app } from './app';
1
+ import { app } from './App.js';
2
2
  export type * from './types/AppConfigs.js';
3
3
  export type * from './types/AppOptions.js';
4
4
  export type * from './types/AppTypes.js';
5
- export { app } from './app';
5
+ export { app };
6
6
  export default app;
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { app as a } from "./app.js";
1
+ import { app as a } from "./App.js";
2
2
  export {
3
3
  a as app,
4
4
  a as default
@@ -1,7 +1,7 @@
1
1
  import { nothing, PropertyValues } from 'lit';
2
2
  import { BaseElement } from '@iyulab/components/dist/components/BaseElement.js';
3
- import { IconButton } from '@iyulab/components/dist/components/icon-button/IconButton.js';
4
- import { ProgressBar } from '@iyulab/components/dist/components/progress-bar/ProgressBar.js';
3
+ import { UIconButton } from '@iyulab/components/dist/components/icon-button/UIconButton.component.js';
4
+ import { UProgressBar } from '@iyulab/components/dist/components/progress-bar/UProgressBar.component.js';
5
5
  import { ExtendedBaseElement } from '../internals/ExtendedBaseElement';
6
6
  import { SidebarLogo } from '../components/SidebarLogo';
7
7
  import { SidebarSection } from '../components/SidebarSection';
@@ -12,8 +12,8 @@ import { SidebarLayoutConfig, SidebarState, SidebarParts } from './SidebarLayout
12
12
  /** 엘리먼트 타입 매핑 (for deveveloper experience) */
13
13
  declare global {
14
14
  interface HTMLElementTagNameMap {
15
- 'u-icon-button': IconButton;
16
- 'u-progress-bar': ProgressBar;
15
+ 'u-icon-button': UIconButton;
16
+ 'u-progress-bar': UProgressBar;
17
17
  'u-sidebar-logo': SidebarLogo;
18
18
  'u-sidebar-section': SidebarSection;
19
19
  'u-sidebar-group': SidebarGroup;
@@ -37,7 +37,7 @@ export declare class SidebarLayout extends ExtendedBaseElement<SidebarParts> {
37
37
  static dependencies: Record<string, typeof BaseElement>;
38
38
  /** 반응형 상태 관리를 위한 MobX 반응 해제 함수들 */
39
39
  private disposers;
40
- progressBarEl: ProgressBar;
40
+ progressBarEl: UProgressBar;
41
41
  /** 사이드바 상태 */
42
42
  state: SidebarState;
43
43
  /** 사이드바 레이아웃 설정 */
@@ -1,11 +1,11 @@
1
- import { nothing as u, html as i } from "lit";
1
+ import { nothing as p, html as i } from "lit";
2
2
  import { query as h, state as g, property as b, customElement as f } from "lit/decorators.js";
3
3
  import { unsafeHTML as m } from "lit/directives/unsafe-html.js";
4
4
  import { repeat as n } from "lit/directives/repeat.js";
5
5
  import { autorun as $ } from "mobx";
6
- import { IconButton as v } from "@iyulab/components/dist/components/icon-button/IconButton.js";
7
- import { ProgressBar as y } from "@iyulab/components/dist/components/progress-bar/ProgressBar.js";
8
- import { screen as p } from "../internals/observables.js";
6
+ import { UIconButton as v } from "@iyulab/components/dist/components/icon-button/UIconButton.component.js";
7
+ import { UProgressBar as y } from "@iyulab/components/dist/components/progress-bar/UProgressBar.component.js";
8
+ import { screen as u } from "../internals/observables.js";
9
9
  import { ExtendedBaseElement as S } from "../internals/ExtendedBaseElement.js";
10
10
  import { SidebarLogo as _ } from "../components/SidebarLogo.js";
11
11
  import { SidebarSection as w } from "../components/SidebarSection.js";
@@ -21,10 +21,10 @@ var R = Object.defineProperty, I = Object.getOwnPropertyDescriptor, P = Object.g
21
21
  let o = class extends S {
22
22
  constructor() {
23
23
  super(...arguments), this.disposers = [], this.state = "docked", this.toggleState = () => {
24
- const e = p.get();
24
+ const e = u.get();
25
25
  e === "large" ? this.state = this.state === "docked" ? "slim" : "docked" : e === "medium" ? this.state = this.state === "slim" ? "modal" : "slim" : e === "small" ? this.state = this.state === "closed" ? "modal" : "closed" : console.warn("Unknown screen size:", e);
26
26
  }, this.toggleStateIfModalState = () => {
27
- const e = p.get();
27
+ const e = u.get();
28
28
  this.state === "modal" && (e === "medium" ? this.state = "slim" : e === "small" && (this.state = "closed"));
29
29
  }, this.handleRouteBegin = (e) => {
30
30
  this.progressBarEl.value = 0, this.toggleStateIfModalState();
@@ -36,7 +36,7 @@ let o = class extends S {
36
36
  }
37
37
  connectedCallback() {
38
38
  super.connectedCallback(), this.disposers.push($(() => {
39
- const e = p.get();
39
+ const e = u.get();
40
40
  this.updateState(e);
41
41
  })), window.addEventListener("route-begin", this.handleRouteBegin), window.addEventListener("route-done", this.handleRouteDone), window.addEventListener("route-progress", this.handleRouteProgress);
42
42
  }
@@ -62,6 +62,7 @@ let o = class extends S {
62
62
  @click="${this.config.logo?.onClick}"
63
63
  ></u-sidebar-logo>
64
64
  <u-icon-button class="sidebar-toggler" part="sidebar-toggler"
65
+ lib="internal"
65
66
  name=${this.state === "closed" ? "chevron-right" : "layout-sidebar"}
66
67
  @click="${this.toggleState}"
67
68
  ></u-icon-button>
@@ -99,11 +100,15 @@ let o = class extends S {
99
100
  ?hidden="${this.state !== "modal"}"
100
101
  @click="${this.toggleStateIfModalState}"
101
102
  ></div>
102
- ` : u;
103
+ ` : p;
103
104
  }
104
105
  /** 사이드바 아이템 렌더링 */
105
106
  renderItem(e) {
106
- return e ? e.type === "content" ? this.state === "slim" ? u : m(e.content) : e.type === "button" ? i`
107
+ if (!e) return p;
108
+ if (e.type === "innerHtml") {
109
+ const t = e.render(this.state);
110
+ return typeof t == "string" ? m(t) : i`${t}`;
111
+ } else return e.type === "button" ? i`
107
112
  <u-sidebar-button
108
113
  ?compact=${this.state === "slim"}
109
114
  .icon="${e.icon}"
@@ -147,7 +152,7 @@ let o = class extends S {
147
152
  .pattern="${e.pattern}"
148
153
  .styles="${e.styles}"
149
154
  ></u-sidebar-link>
150
- ` : u;
155
+ `;
151
156
  }
152
157
  /** 화면 크기 변경에 따른 사이드바 상태 업데이트 */
153
158
  updateState(e) {
@@ -174,7 +179,7 @@ l([
174
179
  b({ type: Object })
175
180
  ], o.prototype, "config", 2);
176
181
  o = l([
177
- f("app-sidebar-layout")
182
+ f("u-sidebar-layout")
178
183
  ], o);
179
184
  export {
180
185
  o as SidebarLayout
@@ -4,8 +4,8 @@ const r = o`
4
4
  position: relative;
5
5
  display: flex;
6
6
  flex-direction: row;
7
- width: 100vw;
8
- height: 100vh;
7
+ width: 100%;
8
+ height: 100%;
9
9
  overflow: hidden;
10
10
  }
11
11
 
@@ -21,7 +21,7 @@ const r = o`
21
21
  height: 100vh;
22
22
  background: var(--u-panel-bg-color);
23
23
  border-right: 1px solid var(--u-border-color);
24
- box-shadow: 0 2px 8px var(--u-shadow-weak);
24
+ box-shadow: 0 2px 8px var(--u-shadow-color-weak);
25
25
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
26
26
  }
27
27
  /* Sidebar states */
@@ -8,13 +8,13 @@ import { SidebarButtonConfig } from '../components/SidebarButton';
8
8
  export type SidebarParts = 'host' | 'sidebar' | 'sidebar-toggler' | 'sidebar-header' | 'sidebar-menu' | 'sidebar-footer' | 'main' | 'progress';
9
9
  /** 사이드바 상태 타입 */
10
10
  export type SidebarState = 'docked' | 'modal' | 'slim' | 'closed';
11
- /** 사이드바 컨텐츠 커스텀 HTML 타입 */
12
- export interface SidebarContentConfig {
13
- type: 'content';
14
- content: string;
11
+ /** 사이드바 안에 HTML 또는 엘리먼트를 직접 렌더링하는 설정 */
12
+ export interface SidebarInnerHtmlConfig {
13
+ type: 'innerHtml';
14
+ render: (state: SidebarState) => HTMLElement | string;
15
15
  }
16
16
  /** union: section | group | link | button */
17
- export type SidebarItem = (SidebarLinkConfig | SidebarSectionConfig | SidebarGroupConfig | SidebarButtonConfig | SidebarContentConfig);
17
+ export type SidebarItem = (SidebarLinkConfig | SidebarSectionConfig | SidebarGroupConfig | SidebarButtonConfig | SidebarInnerHtmlConfig);
18
18
  /** 사이드바 전체 설정 (루트) */
19
19
  export interface SidebarLayoutConfig {
20
20
  type: 'sidebar';
@@ -40,6 +40,16 @@ export interface AppConfig {
40
40
  * 라우팅 실패 시 대체 컨텐츠 설정
41
41
  */
42
42
  fallback?: FallbackRouteConfig;
43
+ /**
44
+ * 애플리케이션이 렌더링될 루트 HTML 요소
45
+ * @description 지정하지 않을 경우 document.body가 사용됩니다.
46
+ */
47
+ root?: Element;
48
+ /**
49
+ * 애플리케이션을 구성하기 위한 레이아웃 설정
50
+ * @description 현재는 사이드바 레이아웃만 지원합니다.
51
+ */
52
+ layout: LayoutConfig;
43
53
  /**
44
54
  * 애플리케이션의 스타일 테마 설정
45
55
  */
@@ -50,9 +60,4 @@ export interface AppConfig {
50
60
  * @see 설정에 대한 자세한 내용은 {@link https://www.i18next.com/overview/configuration-options} 참조하십시오.
51
61
  */
52
62
  localization?: LocalizationInitOptions;
53
- /**
54
- * 애플리케이션을 구성하기 위한 레이아웃 설정
55
- * @description 현재는 사이드바 레이아웃만 지원합니다.
56
- */
57
- layout: LayoutConfig;
58
63
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@iyulab/modern-app",
3
3
  "description": "web-framework by iyulab based on react, lit-element",
4
- "version": "0.2.2",
4
+ "version": "0.2.3",
5
5
  "keywords": [
6
6
  "iyulab",
7
7
  "web-framework",
@@ -38,16 +38,16 @@
38
38
  "build": "vite build"
39
39
  },
40
40
  "dependencies": {
41
- "@iyulab/components": "^0.1.3",
42
- "@iyulab/router": "^0.5.2",
41
+ "@iyulab/components": "^0.1.10",
42
+ "@iyulab/router": "^0.5.3",
43
43
  "lit": "^3.3.1",
44
44
  "mobx": "^6.15.0",
45
- "i18next": "^25.6.2"
45
+ "i18next": "^25.7.3"
46
46
  },
47
47
  "devDependencies": {
48
- "@types/node": "^24.10.1",
48
+ "@types/node": "^25.0.3",
49
49
  "typescript": "^5.9.3",
50
- "vite": "^7.2.2",
50
+ "vite": "^7.3.0",
51
51
  "vite-plugin-dts": "^4.5.4"
52
52
  }
53
- }
53
+ }
package/dist/app.d.ts DELETED
@@ -1,50 +0,0 @@
1
- import { Router } from '@iyulab/router';
2
- import { AppConfig } from './types/AppConfigs.js';
3
- import { NotificationOptions } from './types/AppOptions.js';
4
- /**
5
- * 애플리케이션 전역 상태 및 설정 관리 클래스
6
- */
7
- declare class App {
8
- private static _instance;
9
- private _config?;
10
- private _layout?;
11
- private _router?;
12
- private constructor();
13
- /** 싱글톤 인스턴스 반환 */
14
- static get instance(): App;
15
- /** 현재 앱 설정 반환 */
16
- get config(): AppConfig | undefined;
17
- /** 라우터 인스턴스 반환 */
18
- get router(): Router | undefined;
19
- /** 스타일 테마 관리 유틸리티 객체 반환 */
20
- get theme(): import('@iyulab/components/dist/utilities/theme.js').Theme;
21
- /** 다국어 로컬라이저(i18next) 반환 */
22
- get localizer(): import('i18next').i18n;
23
- /** 앱 로드 및 초기화 */
24
- load(config: AppConfig): Promise<void>;
25
- /** 앱 언로드 */
26
- unload(): void;
27
- /** 페이지 이동 */
28
- navigate(path: string): void;
29
- /** 공지 메시지 */
30
- notice(message: string, options?: NotificationOptions): Promise<void>;
31
- /** 정보 메시지 */
32
- info(message: string, options?: NotificationOptions): Promise<void>;
33
- /** 경고 메시지 */
34
- warning(message: string, options?: NotificationOptions): Promise<void>;
35
- /** 성공 메시지 */
36
- success(message: string, options?: NotificationOptions): Promise<void>;
37
- /** 에러 메시지 */
38
- error(message: string, options?: NotificationOptions): Promise<void>;
39
- /** 레이아웃 생성 */
40
- private createLayout;
41
- /** 알림 표시 */
42
- private notify;
43
- /** 화면 크기 변경 핸들러 */
44
- private handleWindowResize;
45
- }
46
- /**
47
- * 전역 어플리케이션 설정 및 관리 인스턴스
48
- */
49
- export declare const app: App;
50
- export {};