@iyulab/modern-app 0.2.2 → 0.2.4
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 +20 -13
- package/LICENSE +20 -20
- package/README.md +158 -35
- package/dist/{app.js → App.js} +29 -26
- package/dist/components/SidebarButton.js +5 -6
- package/dist/components/SidebarButton.styles.js +3 -3
- package/dist/components/SidebarGroup.js +3 -3
- package/dist/components/SidebarGroup.styles.js +2 -2
- package/dist/components/SidebarLink.js +3 -4
- package/dist/components/SidebarLink.styles.js +8 -8
- package/dist/components/SidebarLogo.js +2 -3
- package/dist/components/SidebarLogo.styles.js +6 -6
- package/dist/components/SidebarSection.styles.js +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/layouts/SidebarLayout.d.ts +5 -5
- package/dist/layouts/SidebarLayout.js +16 -11
- package/dist/layouts/SidebarLayout.styles.js +3 -3
- package/dist/layouts/SidebarLayout.types.d.ts +5 -5
- package/dist/types/AppConfigs.d.ts +10 -5
- package/package.json +7 -7
- package/dist/app.d.ts +0 -50
package/CHANGELOG.md
CHANGED
|
@@ -1,14 +1,21 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
## 0.2.
|
|
4
|
-
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
-
|
|
12
|
-
|
|
13
|
-
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.2.4 (2025-12-19)
|
|
4
|
+
- fix import path, modified correct case-sensitive paths
|
|
5
|
+
|
|
6
|
+
## 0.2.3 (2025-12-19)
|
|
7
|
+
- added `root` option in `AppConfig` type to set application root element
|
|
8
|
+
- update `@iyulab/components` to v0.1.10
|
|
9
|
+
|
|
10
|
+
## 0.2.2 (2025-11-17)
|
|
11
|
+
- added `fallback` config in `AppConfig` type
|
|
12
|
+
- improved route-progress handling in layout component
|
|
13
|
+
|
|
14
|
+
## 0.2.1 (2025-11-13)
|
|
15
|
+
- Fixed few component and sidebar styles
|
|
16
|
+
- removed `theme` setter property in `app` instance
|
|
17
|
+
- changed `progress` property to function in `app` instance
|
|
18
|
+
- changed name `locales` option to `localization` option in `AppConfig` type
|
|
19
|
+
|
|
20
|
+
## 0.2.0 (2025-11-12)
|
|
14
21
|
- 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
|
-
```
|
|
16
|
-
import { app } from '@iyulab/modern-app';
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
layout: {
|
|
21
|
-
type: 'sidebar',
|
|
22
|
-
// layout configuration
|
|
23
|
-
},
|
|
24
|
-
routes: [
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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
|
package/dist/{app.js → App.js}
RENAMED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { runInAction as
|
|
1
|
+
import { runInAction as l } from "mobx";
|
|
2
2
|
import n from "i18next";
|
|
3
|
-
import { Router as
|
|
4
|
-
import { theme as
|
|
5
|
-
import { notifier as
|
|
6
|
-
import { screen as
|
|
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
|
-
|
|
13
|
-
e < i ?
|
|
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
|
|
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
|
|
40
|
-
for (const
|
|
41
|
-
n.use(
|
|
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"))
|
|
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
|
|
83
|
+
await h.toast({
|
|
92
84
|
type: t,
|
|
93
85
|
content: e,
|
|
94
|
-
|
|
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
|
|
103
|
+
const _ = o.instance;
|
|
101
104
|
export {
|
|
102
|
-
|
|
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 {
|
|
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
|
|
6
|
-
var
|
|
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 &&
|
|
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,
|
|
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-
|
|
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-
|
|
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
|
|
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 {
|
|
4
|
-
import { app as m } from "../
|
|
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-
|
|
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-
|
|
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 {
|
|
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
|
|
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 &&
|
|
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
|
|
2
|
+
const e = o`
|
|
3
3
|
:host {
|
|
4
4
|
display: block;
|
|
5
5
|
border-radius: 8px;
|
|
6
|
-
color: var(--u-
|
|
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-
|
|
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-
|
|
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-
|
|
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
|
-
|
|
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 {
|
|
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
|
|
2
|
-
const
|
|
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-
|
|
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-
|
|
13
|
+
color: var(--u-txt-color-hover);
|
|
14
14
|
}
|
|
15
15
|
:host(:active) {
|
|
16
|
-
color: var(--u-
|
|
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
|
-
|
|
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-
|
|
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-
|
|
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 './
|
|
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 }
|
|
5
|
+
export { app };
|
|
6
6
|
export default app;
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { nothing, PropertyValues } from 'lit';
|
|
2
2
|
import { BaseElement } from '@iyulab/components/dist/components/BaseElement.js';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
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':
|
|
16
|
-
'u-progress-bar':
|
|
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:
|
|
40
|
+
progressBarEl: UProgressBar;
|
|
41
41
|
/** 사이드바 상태 */
|
|
42
42
|
state: SidebarState;
|
|
43
43
|
/** 사이드바 레이아웃 설정 */
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { nothing as
|
|
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 {
|
|
7
|
-
import {
|
|
8
|
-
import { screen as
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
-
` :
|
|
103
|
+
` : p;
|
|
103
104
|
}
|
|
104
105
|
/** 사이드바 아이템 렌더링 */
|
|
105
106
|
renderItem(e) {
|
|
106
|
-
|
|
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
|
-
|
|
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("
|
|
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:
|
|
8
|
-
height:
|
|
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
|
-
/** 사이드바
|
|
12
|
-
export interface
|
|
13
|
-
type: '
|
|
14
|
-
|
|
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 |
|
|
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.
|
|
4
|
+
"version": "0.2.4",
|
|
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.
|
|
42
|
-
"@iyulab/router": "^0.5.
|
|
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.
|
|
45
|
+
"i18next": "^25.7.3"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
|
-
"@types/node": "^
|
|
48
|
+
"@types/node": "^25.0.3",
|
|
49
49
|
"typescript": "^5.9.3",
|
|
50
|
-
"vite": "^7.
|
|
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 {};
|