@iyulab/modern-app 0.2.1 → 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 +17 -9
- package/LICENSE +20 -20
- package/README.md +158 -35
- package/dist/{app.js → App.js} +33 -39
- 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 +4 -5
- 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/internals/observables.d.ts +0 -4
- package/dist/internals/observables.js +3 -4
- package/dist/layouts/SidebarLayout.d.ts +12 -4
- package/dist/layouts/SidebarLayout.js +60 -52
- package/dist/layouts/SidebarLayout.styles.js +22 -12
- package/dist/layouts/SidebarLayout.types.d.ts +6 -6
- package/dist/types/AppConfigs.d.ts +17 -8
- package/package.json +7 -7
- package/dist/app.d.ts +0 -54
- package/dist/components/ProgressBar.d.ts +0 -22
- package/dist/components/ProgressBar.js +0 -54
- package/dist/components/ProgressBar.styles.d.ts +0 -1
- package/dist/components/ProgressBar.styles.js +0 -31
package/CHANGELOG.md
CHANGED
|
@@ -1,10 +1,18 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
## 0.2.
|
|
4
|
-
-
|
|
5
|
-
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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)
|
|
10
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
|
-
```
|
|
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,15 +1,15 @@
|
|
|
1
|
-
import { runInAction as
|
|
1
|
+
import { runInAction as l } from "mobx";
|
|
2
2
|
import n from "i18next";
|
|
3
|
-
import { Router as
|
|
4
|
-
import { notifier as c } from "@iyulab/components/dist/utilities/notifier.js";
|
|
3
|
+
import { Router as d } from "@iyulab/router";
|
|
5
4
|
import { theme as u } from "@iyulab/components/dist/utilities/theme.js";
|
|
6
|
-
import {
|
|
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
|
-
|
|
12
|
+
l(() => {
|
|
13
13
|
e < i ? s.set("small") : e < a ? s.set("medium") : s.set("large");
|
|
14
14
|
});
|
|
15
15
|
};
|
|
@@ -30,41 +30,34 @@ class o {
|
|
|
30
30
|
get theme() {
|
|
31
31
|
return u;
|
|
32
32
|
}
|
|
33
|
-
/**
|
|
34
|
-
get
|
|
35
|
-
return n
|
|
33
|
+
/** 다국어 로컬라이저(i18next) 반환 */
|
|
34
|
+
get localizer() {
|
|
35
|
+
return n;
|
|
36
36
|
}
|
|
37
37
|
/** 앱 로드 및 초기화 */
|
|
38
38
|
async load(t) {
|
|
39
39
|
if (this.unload(), this._config = t, await u.init(t.theme), t.localization) {
|
|
40
|
-
for (const
|
|
41
|
-
n.use(
|
|
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"))
|
|
45
|
-
|
|
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({
|
|
47
|
+
root: this._layout,
|
|
46
48
|
basepath: t.basepath,
|
|
47
|
-
routes: t.routes
|
|
48
|
-
|
|
49
|
+
routes: t.routes,
|
|
50
|
+
fallback: t.fallback
|
|
51
|
+
});
|
|
49
52
|
}
|
|
50
53
|
/** 앱 언로드 */
|
|
51
54
|
unload() {
|
|
52
|
-
window.removeEventListener("resize", this.handleWindowResize), this.
|
|
55
|
+
window.removeEventListener("resize", this.handleWindowResize), this._layout && (this._layout.remove(), this._layout = void 0), this._router && (this._router.destroy(), this._router = void 0), this._config && (this._config = void 0);
|
|
53
56
|
}
|
|
54
57
|
/** 페이지 이동 */
|
|
55
58
|
navigate(t) {
|
|
56
59
|
this._router?.go(t);
|
|
57
60
|
}
|
|
58
|
-
/** 언어 설정 변경(i18next.changeLanguage 호출) */
|
|
59
|
-
async setLanguage(t) {
|
|
60
|
-
await n.changeLanguage(t);
|
|
61
|
-
}
|
|
62
|
-
/** 레이아웃 진행바 설정 */
|
|
63
|
-
progress(t) {
|
|
64
|
-
r(() => {
|
|
65
|
-
d.set(t);
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
61
|
/** 공지 메시지 */
|
|
69
62
|
async notice(t, e) {
|
|
70
63
|
await this.notify("notice", t, e);
|
|
@@ -85,28 +78,29 @@ class o {
|
|
|
85
78
|
async error(t, e) {
|
|
86
79
|
await this.notify("error", t, e);
|
|
87
80
|
}
|
|
88
|
-
/** 레이아웃 생성 */
|
|
89
|
-
async createLayout(t) {
|
|
90
|
-
let e = document.body.querySelector("[data-layout]");
|
|
91
|
-
if (e && document.body.removeChild(e), t.type === "sidebar") {
|
|
92
|
-
const { SidebarLayout: i } = await import("./layouts/SidebarLayout.js"), a = new i();
|
|
93
|
-
a.config = t, e = a;
|
|
94
|
-
} else
|
|
95
|
-
throw new Error(`Unsupported layout type: ${t.type}`);
|
|
96
|
-
return e.setAttribute("data-layout", "true"), document.body.appendChild(e), "updateComplete" in e && await e.updateComplete, e;
|
|
97
|
-
}
|
|
98
81
|
/** 알림 표시 */
|
|
99
82
|
async notify(t, e, i) {
|
|
100
|
-
await
|
|
83
|
+
await h.toast({
|
|
101
84
|
type: t,
|
|
102
85
|
content: e,
|
|
103
|
-
|
|
86
|
+
heading: i?.title,
|
|
104
87
|
duration: i?.duration || 3e3,
|
|
105
88
|
position: i?.position || "top-right"
|
|
106
89
|
});
|
|
107
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
|
+
}
|
|
108
102
|
}
|
|
109
|
-
const
|
|
103
|
+
const _ = o.instance;
|
|
110
104
|
export {
|
|
111
|
-
|
|
105
|
+
_ as app
|
|
112
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,17 +1,17 @@
|
|
|
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() {
|
|
13
13
|
super(...arguments), this.selected = !1, this.compact = !1, this.handleRouteBegin = (r) => {
|
|
14
|
-
this.pattern ||= this.href, this.pattern ? (this.pattern = typeof this.pattern == "string" ? new URLPattern(this.pattern, window.location.origin) : this.pattern, this.selected = this.pattern.test(r.
|
|
14
|
+
this.pattern ||= this.href, this.pattern ? (this.pattern = typeof this.pattern == "string" ? new URLPattern(this.pattern, window.location.origin) : this.pattern, this.selected = this.pattern.test(r.context.path, window.location.origin)) : this.selected = !1;
|
|
15
15
|
};
|
|
16
16
|
}
|
|
17
17
|
static {
|
|
@@ -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,17 +1,19 @@
|
|
|
1
1
|
import { nothing, PropertyValues } from 'lit';
|
|
2
2
|
import { BaseElement } from '@iyulab/components/dist/components/BaseElement.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';
|
|
3
5
|
import { ExtendedBaseElement } from '../internals/ExtendedBaseElement';
|
|
4
|
-
import { ProgressBar } from '../components/ProgressBar';
|
|
5
6
|
import { SidebarLogo } from '../components/SidebarLogo';
|
|
6
7
|
import { SidebarSection } from '../components/SidebarSection';
|
|
7
8
|
import { SidebarGroup } from '../components/SidebarGroup';
|
|
8
9
|
import { SidebarLink } from '../components/SidebarLink';
|
|
9
10
|
import { SidebarButton } from '../components/SidebarButton';
|
|
10
11
|
import { SidebarLayoutConfig, SidebarState, SidebarParts } from './SidebarLayout.types';
|
|
11
|
-
/** 엘리먼트 타입 매핑 */
|
|
12
|
+
/** 엘리먼트 타입 매핑 (for deveveloper experience) */
|
|
12
13
|
declare global {
|
|
13
14
|
interface HTMLElementTagNameMap {
|
|
14
|
-
'u-
|
|
15
|
+
'u-icon-button': UIconButton;
|
|
16
|
+
'u-progress-bar': UProgressBar;
|
|
15
17
|
'u-sidebar-logo': SidebarLogo;
|
|
16
18
|
'u-sidebar-section': SidebarSection;
|
|
17
19
|
'u-sidebar-group': SidebarGroup;
|
|
@@ -35,7 +37,7 @@ export declare class SidebarLayout extends ExtendedBaseElement<SidebarParts> {
|
|
|
35
37
|
static dependencies: Record<string, typeof BaseElement>;
|
|
36
38
|
/** 반응형 상태 관리를 위한 MobX 반응 해제 함수들 */
|
|
37
39
|
private disposers;
|
|
38
|
-
|
|
40
|
+
progressBarEl: UProgressBar;
|
|
39
41
|
/** 사이드바 상태 */
|
|
40
42
|
state: SidebarState;
|
|
41
43
|
/** 사이드바 레이아웃 설정 */
|
|
@@ -55,4 +57,10 @@ export declare class SidebarLayout extends ExtendedBaseElement<SidebarParts> {
|
|
|
55
57
|
* 백드롭 클릭 or 라우트 변경 시
|
|
56
58
|
*/
|
|
57
59
|
private toggleStateIfModalState;
|
|
60
|
+
/** 라우트 변경 시작 핸들러 */
|
|
61
|
+
private handleRouteBegin;
|
|
62
|
+
/** 라우트 변경 진행 핸들러 */
|
|
63
|
+
private handleRouteProgress;
|
|
64
|
+
/** 라우트 변경 완료 핸들러 */
|
|
65
|
+
private handleRouteDone;
|
|
58
66
|
}
|
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
import { nothing as p, html as i } from "lit";
|
|
2
|
-
import { query as
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
2
|
+
import { query as h, state as g, property as b, customElement as f } from "lit/decorators.js";
|
|
3
|
+
import { unsafeHTML as m } from "lit/directives/unsafe-html.js";
|
|
4
|
+
import { repeat as n } from "lit/directives/repeat.js";
|
|
5
|
+
import { autorun as $ } from "mobx";
|
|
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
|
+
import { ExtendedBaseElement as S } from "../internals/ExtendedBaseElement.js";
|
|
9
10
|
import { SidebarLogo as _ } from "../components/SidebarLogo.js";
|
|
10
|
-
import { SidebarSection as
|
|
11
|
-
import { SidebarGroup as
|
|
12
|
-
import { SidebarLink as
|
|
13
|
-
import { SidebarButton as
|
|
14
|
-
import { styles as
|
|
15
|
-
|
|
16
|
-
var
|
|
17
|
-
for (var r = a > 1 ? void 0 : a ? L(t, s) : t, d = e.length - 1, c; d >= 0; d--)
|
|
11
|
+
import { SidebarSection as w } from "../components/SidebarSection.js";
|
|
12
|
+
import { SidebarGroup as k } from "../components/SidebarGroup.js";
|
|
13
|
+
import { SidebarLink as E } from "../components/SidebarLink.js";
|
|
14
|
+
import { SidebarButton as B } from "../components/SidebarButton.js";
|
|
15
|
+
import { styles as L } from "./SidebarLayout.styles.js";
|
|
16
|
+
var R = Object.defineProperty, I = Object.getOwnPropertyDescriptor, P = Object.getPrototypeOf, C = Reflect.get, l = (e, t, s, a) => {
|
|
17
|
+
for (var r = a > 1 ? void 0 : a ? I(t, s) : t, d = e.length - 1, c; d >= 0; d--)
|
|
18
18
|
(c = e[d]) && (r = (a ? c(t, s, r) : c(r)) || r);
|
|
19
|
-
return a && r &&
|
|
20
|
-
},
|
|
21
|
-
let o = class extends
|
|
19
|
+
return a && r && R(t, s, r), r;
|
|
20
|
+
}, O = (e, t, s) => C(P(e), s, t);
|
|
21
|
+
let o = class extends S {
|
|
22
22
|
constructor() {
|
|
23
23
|
super(...arguments), this.disposers = [], this.state = "docked", this.toggleState = () => {
|
|
24
24
|
const e = u.get();
|
|
@@ -26,19 +26,22 @@ let o = class extends v {
|
|
|
26
26
|
}, this.toggleStateIfModalState = () => {
|
|
27
27
|
const e = u.get();
|
|
28
28
|
this.state === "modal" && (e === "medium" ? this.state = "slim" : e === "small" && (this.state = "closed"));
|
|
29
|
+
}, this.handleRouteBegin = (e) => {
|
|
30
|
+
this.progressBarEl.value = 0, this.toggleStateIfModalState();
|
|
31
|
+
}, this.handleRouteProgress = (e) => {
|
|
32
|
+
this.progressBarEl.value = e.progress;
|
|
33
|
+
}, this.handleRouteDone = (e) => {
|
|
34
|
+
this.progressBarEl.value = 100;
|
|
29
35
|
};
|
|
30
36
|
}
|
|
31
37
|
connectedCallback() {
|
|
32
|
-
super.connectedCallback(), this.disposers.push(
|
|
38
|
+
super.connectedCallback(), this.disposers.push($(() => {
|
|
33
39
|
const e = u.get();
|
|
34
40
|
this.updateState(e);
|
|
35
|
-
})), this.
|
|
36
|
-
const e = y.get();
|
|
37
|
-
this.progressEl && (this.progressEl.value = e);
|
|
38
|
-
})), window.addEventListener("route-begin", this.toggleStateIfModalState);
|
|
41
|
+
})), window.addEventListener("route-begin", this.handleRouteBegin), window.addEventListener("route-done", this.handleRouteDone), window.addEventListener("route-progress", this.handleRouteProgress);
|
|
39
42
|
}
|
|
40
43
|
disconnectedCallback() {
|
|
41
|
-
this.disposers.forEach((e) => e()), window.removeEventListener("route-begin", this.
|
|
44
|
+
this.disposers.forEach((e) => e()), window.removeEventListener("route-begin", this.handleRouteBegin), window.removeEventListener("route-done", this.handleRouteDone), window.removeEventListener("route-progress", this.handleRouteProgress), super.disconnectedCallback();
|
|
42
45
|
}
|
|
43
46
|
updated(e) {
|
|
44
47
|
super.updated(e), e.has("config") && (this.styles = this.config?.styles);
|
|
@@ -51,14 +54,15 @@ let o = class extends v {
|
|
|
51
54
|
<div class="sidebar-header" part="sidebar-header">
|
|
52
55
|
<u-sidebar-logo
|
|
53
56
|
.compact="${this.state === "slim"}"
|
|
54
|
-
.type=${this.config.logo
|
|
55
|
-
.image="${this.config.logo
|
|
56
|
-
.icon="${this.config.logo
|
|
57
|
-
.label="${this.config.logo
|
|
58
|
-
.styles="${this.config.logo
|
|
59
|
-
@click="${this.config.logo
|
|
57
|
+
.type=${this.config.logo?.type || "icon"}
|
|
58
|
+
.image="${this.config.logo?.image}"
|
|
59
|
+
.icon="${this.config.logo?.icon}"
|
|
60
|
+
.label="${this.config.logo?.label}"
|
|
61
|
+
.styles="${this.config.logo?.styles}"
|
|
62
|
+
@click="${this.config.logo?.onClick}"
|
|
60
63
|
></u-sidebar-logo>
|
|
61
64
|
<u-icon-button class="sidebar-toggler" part="sidebar-toggler"
|
|
65
|
+
lib="internal"
|
|
62
66
|
name=${this.state === "closed" ? "chevron-right" : "layout-sidebar"}
|
|
63
67
|
@click="${this.toggleState}"
|
|
64
68
|
></u-icon-button>
|
|
@@ -66,7 +70,7 @@ let o = class extends v {
|
|
|
66
70
|
|
|
67
71
|
<!-- Sidebar Navigation Menu -->
|
|
68
72
|
<nav class="sidebar-menu" part="sidebar-menu">
|
|
69
|
-
${
|
|
73
|
+
${n(
|
|
70
74
|
this.config.menu ?? [],
|
|
71
75
|
(e, t) => t,
|
|
72
76
|
(e, t) => this.renderItem(e)
|
|
@@ -76,7 +80,7 @@ let o = class extends v {
|
|
|
76
80
|
<!-- Sidebar Footer -->
|
|
77
81
|
<div class="sidebar-footer" part="sidebar-footer"
|
|
78
82
|
?hidden="${!this.config.footer || this.config.footer.length === 0}">
|
|
79
|
-
${
|
|
83
|
+
${n(
|
|
80
84
|
this.config.footer ?? [],
|
|
81
85
|
(e, t) => t,
|
|
82
86
|
(e, t) => this.renderItem(e)
|
|
@@ -100,7 +104,11 @@ let o = class extends v {
|
|
|
100
104
|
}
|
|
101
105
|
/** 사이드바 아이템 렌더링 */
|
|
102
106
|
renderItem(e) {
|
|
103
|
-
|
|
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`
|
|
104
112
|
<u-sidebar-button
|
|
105
113
|
?compact=${this.state === "slim"}
|
|
106
114
|
.icon="${e.icon}"
|
|
@@ -115,7 +123,7 @@ let o = class extends v {
|
|
|
115
123
|
.subTitle="${e.subTitle}"
|
|
116
124
|
.items="${e.items}"
|
|
117
125
|
.styles="${e.styles}">
|
|
118
|
-
${
|
|
126
|
+
${n(
|
|
119
127
|
e.items,
|
|
120
128
|
(t, s) => s,
|
|
121
129
|
(t, s) => this.renderItem(t)
|
|
@@ -129,7 +137,7 @@ let o = class extends v {
|
|
|
129
137
|
.label="${e.label}"
|
|
130
138
|
.items="${e.items}"
|
|
131
139
|
.styles="${e.styles}">
|
|
132
|
-
${
|
|
140
|
+
${n(
|
|
133
141
|
e.items,
|
|
134
142
|
(t, s) => s,
|
|
135
143
|
(t, s) => this.renderItem(t)
|
|
@@ -144,34 +152,34 @@ let o = class extends v {
|
|
|
144
152
|
.pattern="${e.pattern}"
|
|
145
153
|
.styles="${e.styles}"
|
|
146
154
|
></u-sidebar-link>
|
|
147
|
-
|
|
155
|
+
`;
|
|
148
156
|
}
|
|
149
157
|
/** 화면 크기 변경에 따른 사이드바 상태 업데이트 */
|
|
150
158
|
updateState(e) {
|
|
151
159
|
e === "large" ? this.state = "docked" : e === "medium" ? this.state = "slim" : e === "small" ? this.state = "closed" : console.warn("Unknown screen size:", e);
|
|
152
160
|
}
|
|
153
161
|
};
|
|
154
|
-
o.styles = [
|
|
162
|
+
o.styles = [O(o, o, "styles"), L];
|
|
155
163
|
o.dependencies = {
|
|
156
|
-
"u-icon-button":
|
|
157
|
-
"u-progress-bar":
|
|
164
|
+
"u-icon-button": v,
|
|
165
|
+
"u-progress-bar": y,
|
|
158
166
|
"u-sidebar-logo": _,
|
|
159
|
-
"u-sidebar-section":
|
|
160
|
-
"u-sidebar-group":
|
|
161
|
-
"u-sidebar-link":
|
|
162
|
-
"u-sidebar-button":
|
|
167
|
+
"u-sidebar-section": w,
|
|
168
|
+
"u-sidebar-group": k,
|
|
169
|
+
"u-sidebar-link": E,
|
|
170
|
+
"u-sidebar-button": B
|
|
163
171
|
};
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
], o.prototype, "
|
|
167
|
-
|
|
168
|
-
|
|
172
|
+
l([
|
|
173
|
+
h("u-progress-bar")
|
|
174
|
+
], o.prototype, "progressBarEl", 2);
|
|
175
|
+
l([
|
|
176
|
+
g()
|
|
169
177
|
], o.prototype, "state", 2);
|
|
170
|
-
|
|
171
|
-
|
|
178
|
+
l([
|
|
179
|
+
b({ type: Object })
|
|
172
180
|
], o.prototype, "config", 2);
|
|
173
|
-
o =
|
|
174
|
-
|
|
181
|
+
o = l([
|
|
182
|
+
f("u-sidebar-layout")
|
|
175
183
|
], o);
|
|
176
184
|
export {
|
|
177
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 */
|
|
@@ -100,6 +100,25 @@ const r = o`
|
|
|
100
100
|
border-top: 1px solid var(--u-border-color-weak);
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
+
/* Main Content */
|
|
104
|
+
.main {
|
|
105
|
+
position: relative;
|
|
106
|
+
flex: 1;
|
|
107
|
+
display: block;
|
|
108
|
+
overflow: hidden;
|
|
109
|
+
background: var(--u-bg-color);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.main u-progress-bar {
|
|
113
|
+
position: absolute;
|
|
114
|
+
z-index: 100;
|
|
115
|
+
top: 0;
|
|
116
|
+
left: 0;
|
|
117
|
+
height: 4px;
|
|
118
|
+
border-radius: 0;
|
|
119
|
+
background-color: transparent;
|
|
120
|
+
}
|
|
121
|
+
|
|
103
122
|
/* Backdrop for modal mode */
|
|
104
123
|
.backdrop {
|
|
105
124
|
content: '';
|
|
@@ -111,15 +130,6 @@ const r = o`
|
|
|
111
130
|
bottom: 0;
|
|
112
131
|
background: var(--u-overlay-bg-color);
|
|
113
132
|
}
|
|
114
|
-
|
|
115
|
-
/* Main Content */
|
|
116
|
-
.main {
|
|
117
|
-
position: relative;
|
|
118
|
-
flex: 1;
|
|
119
|
-
display: block;
|
|
120
|
-
overflow: hidden;
|
|
121
|
-
background: var(--u-bg-color);
|
|
122
|
-
}
|
|
123
133
|
`;
|
|
124
134
|
export {
|
|
125
135
|
r as styles
|
|
@@ -8,18 +8,18 @@ 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';
|
|
21
21
|
/** 최상단 앱 로고 */
|
|
22
|
-
logo
|
|
22
|
+
logo?: SidebarLogoConfig;
|
|
23
23
|
/** 상단/메인 메뉴 항목들 */
|
|
24
24
|
menu?: SidebarItem[];
|
|
25
25
|
/** 하단(footer)에 고정해서 렌더할 항목들 */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { InitOptions, Module, Newable, NewableModule } from 'i18next';
|
|
2
|
-
import { RouteConfig } from '@iyulab/router';
|
|
2
|
+
import { RouteConfig, FallbackRouteConfig } from '@iyulab/router';
|
|
3
3
|
import { ThemeInitOptions } from '@iyulab/components/dist/utilities/theme.js';
|
|
4
4
|
import { SidebarLayoutConfig } from '../layouts/SidebarLayout.types';
|
|
5
5
|
/**
|
|
@@ -8,7 +8,7 @@ import { SidebarLayoutConfig } from '../layouts/SidebarLayout.types';
|
|
|
8
8
|
export type LocalizationInitOptions = InitOptions & {
|
|
9
9
|
/**
|
|
10
10
|
* i18next 플러그인 배열
|
|
11
|
-
* @description i18next.use() 메서드에
|
|
11
|
+
* @description i18next.use() 메서드에 전달되는 플러그인들의 배열입니다.
|
|
12
12
|
*/
|
|
13
13
|
plugins?: (Module | NewableModule<Module> | Newable<Module>)[];
|
|
14
14
|
};
|
|
@@ -35,7 +35,21 @@ export interface AppConfig {
|
|
|
35
35
|
/**
|
|
36
36
|
* 클라이언트 사이드 라우팅을 위한 설정 배열
|
|
37
37
|
*/
|
|
38
|
-
routes
|
|
38
|
+
routes?: RouteConfig[];
|
|
39
|
+
/**
|
|
40
|
+
* 라우팅 실패 시 대체 컨텐츠 설정
|
|
41
|
+
*/
|
|
42
|
+
fallback?: FallbackRouteConfig;
|
|
43
|
+
/**
|
|
44
|
+
* 애플리케이션이 렌더링될 루트 HTML 요소
|
|
45
|
+
* @description 지정하지 않을 경우 document.body가 사용됩니다.
|
|
46
|
+
*/
|
|
47
|
+
root?: Element;
|
|
48
|
+
/**
|
|
49
|
+
* 애플리케이션을 구성하기 위한 레이아웃 설정
|
|
50
|
+
* @description 현재는 사이드바 레이아웃만 지원합니다.
|
|
51
|
+
*/
|
|
52
|
+
layout: LayoutConfig;
|
|
39
53
|
/**
|
|
40
54
|
* 애플리케이션의 스타일 테마 설정
|
|
41
55
|
*/
|
|
@@ -46,9 +60,4 @@ export interface AppConfig {
|
|
|
46
60
|
* @see 설정에 대한 자세한 내용은 {@link https://www.i18next.com/overview/configuration-options} 참조하십시오.
|
|
47
61
|
*/
|
|
48
62
|
localization?: LocalizationInitOptions;
|
|
49
|
-
/**
|
|
50
|
-
* 애플리케이션을 구성하기 위한 레이아웃 설정
|
|
51
|
-
* @description 현재는 사이드바 레이아웃만 지원합니다.
|
|
52
|
-
*/
|
|
53
|
-
layout: LayoutConfig;
|
|
54
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.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.
|
|
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,54 +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 _router?;
|
|
11
|
-
private _root?;
|
|
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.language) */
|
|
22
|
-
get language(): string;
|
|
23
|
-
/** 앱 로드 및 초기화 */
|
|
24
|
-
load(config: AppConfig): Promise<void>;
|
|
25
|
-
/** 앱 언로드 */
|
|
26
|
-
unload(): void;
|
|
27
|
-
/** 페이지 이동 */
|
|
28
|
-
navigate(path: string): void;
|
|
29
|
-
/** 언어 설정 변경(i18next.changeLanguage 호출) */
|
|
30
|
-
setLanguage(lang: string): Promise<void>;
|
|
31
|
-
/** 레이아웃 진행바 설정 */
|
|
32
|
-
progress(value: number): void;
|
|
33
|
-
/** 공지 메시지 */
|
|
34
|
-
notice(message: string, options?: NotificationOptions): Promise<void>;
|
|
35
|
-
/** 정보 메시지 */
|
|
36
|
-
info(message: string, options?: NotificationOptions): Promise<void>;
|
|
37
|
-
/** 경고 메시지 */
|
|
38
|
-
warning(message: string, options?: NotificationOptions): Promise<void>;
|
|
39
|
-
/** 성공 메시지 */
|
|
40
|
-
success(message: string, options?: NotificationOptions): Promise<void>;
|
|
41
|
-
/** 에러 메시지 */
|
|
42
|
-
error(message: string, options?: NotificationOptions): Promise<void>;
|
|
43
|
-
/** 레이아웃 생성 */
|
|
44
|
-
private createLayout;
|
|
45
|
-
/** 알림 표시 */
|
|
46
|
-
private notify;
|
|
47
|
-
/** 화면 크기 변경 핸들러 */
|
|
48
|
-
private handleWindowResize;
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* 전역 어플리케이션 설정 및 관리 인스턴스
|
|
52
|
-
*/
|
|
53
|
-
export declare const app: App;
|
|
54
|
-
export {};
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { BaseElement } from '@iyulab/components/dist/components/BaseElement.js';
|
|
2
|
-
/**
|
|
3
|
-
* ProgressBar 컴포넌트는 진행 상태를 시각적으로 표시합니다.
|
|
4
|
-
* 로딩 상태나 작업 진행률을 표시하는데 사용됩니다.
|
|
5
|
-
*/
|
|
6
|
-
export declare class ProgressBar extends BaseElement {
|
|
7
|
-
static styles: import('lit').CSSResultGroup[];
|
|
8
|
-
static dependencies: Record<string, typeof BaseElement>;
|
|
9
|
-
/** 불확정 상태 (로딩 애니메이션 표시) */
|
|
10
|
-
indeterminate: boolean;
|
|
11
|
-
/** 최소값 (기본값: 0) */
|
|
12
|
-
minValue: number;
|
|
13
|
-
/** 최대값 (기본값: 100) */
|
|
14
|
-
maxValue: number;
|
|
15
|
-
/** 현재값 */
|
|
16
|
-
value: number;
|
|
17
|
-
connectedCallback(): void;
|
|
18
|
-
protected updated(changedProperties: Map<string, unknown>): void;
|
|
19
|
-
render(): import('lit-html').TemplateResult<1>;
|
|
20
|
-
/** 진행 상태 업데이트 */
|
|
21
|
-
private updateProgress;
|
|
22
|
-
}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { html as h } from "lit";
|
|
2
|
-
import { property as i } from "lit/decorators.js";
|
|
3
|
-
import { BaseElement as n } from "@iyulab/components/dist/components/BaseElement.js";
|
|
4
|
-
import { styles as p } from "./ProgressBar.styles.js";
|
|
5
|
-
var v = Object.defineProperty, a = (u, t, s, o) => {
|
|
6
|
-
for (var e = void 0, l = u.length - 1, m; l >= 0; l--)
|
|
7
|
-
(m = u[l]) && (e = m(t, s, e) || e);
|
|
8
|
-
return e && v(t, s, e), e;
|
|
9
|
-
};
|
|
10
|
-
class r extends n {
|
|
11
|
-
constructor() {
|
|
12
|
-
super(...arguments), this.indeterminate = !1, this.minValue = 0, this.maxValue = 100, this.value = 0;
|
|
13
|
-
}
|
|
14
|
-
static {
|
|
15
|
-
this.styles = [super.styles, p];
|
|
16
|
-
}
|
|
17
|
-
static {
|
|
18
|
-
this.dependencies = {};
|
|
19
|
-
}
|
|
20
|
-
connectedCallback() {
|
|
21
|
-
super.connectedCallback(), this.setAttribute("role", "progressbar");
|
|
22
|
-
}
|
|
23
|
-
updated(t) {
|
|
24
|
-
super.updated(t), t.has("value") && (this.updateProgress(t.get("value"), this.value), this.setAttribute("aria-valuenow", this.value.toString())), t.has("minValue") && (this.updateProgress(this.value, this.value), this.setAttribute("aria-valuemax", this.maxValue.toString())), t.has("maxValue") && (this.updateProgress(this.value, this.value), this.setAttribute("aria-valuemin", this.minValue.toString())), t.has("indeterminate") && (this.updateProgress(this.value, this.value), this.indeterminate ? (this.removeAttribute("aria-valuenow"), this.setAttribute("aria-busy", "true")) : this.removeAttribute("aria-busy"));
|
|
25
|
-
}
|
|
26
|
-
render() {
|
|
27
|
-
return h`<slot></slot>`;
|
|
28
|
-
}
|
|
29
|
-
/** 진행 상태 업데이트 */
|
|
30
|
-
updateProgress(t, s) {
|
|
31
|
-
if (this.indeterminate) return;
|
|
32
|
-
const e = (Math.min(Math.max(s, this.minValue), this.maxValue) - this.minValue) / (this.maxValue - this.minValue);
|
|
33
|
-
t < s ? (this.style.transform = `scaleX(${e})`, s >= this.maxValue && setTimeout(() => {
|
|
34
|
-
this.style.opacity = "0";
|
|
35
|
-
}, 300)) : (this.style.opacity = "0", this.style.transform = "scaleX(0)", setTimeout(() => {
|
|
36
|
-
this.style.opacity = "1", this.style.transform = `scaleX(${e})`;
|
|
37
|
-
}, 300));
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
a([
|
|
41
|
-
i({ type: Boolean, reflect: !0 })
|
|
42
|
-
], r.prototype, "indeterminate");
|
|
43
|
-
a([
|
|
44
|
-
i({ type: Number })
|
|
45
|
-
], r.prototype, "minValue");
|
|
46
|
-
a([
|
|
47
|
-
i({ type: Number })
|
|
48
|
-
], r.prototype, "maxValue");
|
|
49
|
-
a([
|
|
50
|
-
i({ type: Number })
|
|
51
|
-
], r.prototype, "value");
|
|
52
|
-
export {
|
|
53
|
-
r as ProgressBar
|
|
54
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const styles: import('lit').CSSResult;
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { css as t } from "lit";
|
|
2
|
-
const a = t`
|
|
3
|
-
:host {
|
|
4
|
-
display: block;
|
|
5
|
-
position: absolute;
|
|
6
|
-
z-index: 9999;
|
|
7
|
-
top: 0;
|
|
8
|
-
left: 0;
|
|
9
|
-
right: 0;
|
|
10
|
-
height: 4px;
|
|
11
|
-
background-color: var(--u-blue-600);
|
|
12
|
-
transform-origin: left;
|
|
13
|
-
transition: all 0.3s ease-out;
|
|
14
|
-
box-shadow: 0 2px 4px var(--u-shadow-weak);
|
|
15
|
-
}
|
|
16
|
-
:host([indeterminate]) {
|
|
17
|
-
animation: indeterminate 1.5s cubic-bezier(0.65, 0.815, 0.735, 0.395) infinite;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
@keyframes indeterminate {
|
|
21
|
-
0% {
|
|
22
|
-
transform: translateX(-100%);
|
|
23
|
-
}
|
|
24
|
-
100% {
|
|
25
|
-
transform: translateX(100%);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
`;
|
|
29
|
-
export {
|
|
30
|
-
a as styles
|
|
31
|
-
};
|