@iyulab/components 0.1.4 → 0.1.6
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 +18 -18
- package/LICENSE +20 -20
- package/README.md +33 -33
- package/dist/assets/icons/arrow-clockwise.svg.js +1 -1
- package/dist/assets/icons/arrow-down.svg.js +1 -1
- package/dist/assets/icons/arrow-up.svg.js +1 -1
- package/dist/assets/icons/ban.svg.js +1 -1
- package/dist/assets/icons/bell-fill.svg.js +1 -1
- package/dist/assets/icons/check-circle-fill.svg.js +1 -1
- package/dist/assets/icons/check-lg.svg.js +1 -1
- package/dist/assets/icons/chevron-down.svg.js +1 -1
- package/dist/assets/icons/chevron-left.svg.js +1 -1
- package/dist/assets/icons/chevron-right.svg.js +1 -1
- package/dist/assets/icons/chevron-up.svg.js +1 -1
- package/dist/assets/icons/copy.svg.js +1 -1
- package/dist/assets/icons/dash-lg.svg.js +1 -1
- package/dist/assets/icons/exclamation-circle-fill.svg.js +1 -1
- package/dist/assets/icons/exclamation-triangle-fill.svg.js +1 -1
- package/dist/assets/icons/eye-slash.svg.js +1 -1
- package/dist/assets/icons/eye.svg.js +1 -1
- package/dist/assets/icons/info-circle-fill.svg.js +1 -1
- package/dist/assets/icons/layout-sidebar.svg.js +1 -1
- package/dist/assets/icons/lightbulb-fill.svg.js +1 -1
- package/dist/assets/icons/lightbulb-off.svg.js +1 -1
- package/dist/assets/icons/lightbulb.svg.js +1 -1
- package/dist/assets/icons/mic-fill.svg.js +1 -1
- package/dist/assets/icons/mic-mute-fill.svg.js +1 -1
- package/dist/assets/icons/paperclip.svg.js +1 -1
- package/dist/assets/icons/pencil-square.svg.js +1 -1
- package/dist/assets/icons/plus-lg.svg.js +1 -1
- package/dist/assets/icons/search.svg.js +1 -1
- package/dist/assets/icons/speedometer.svg.js +1 -1
- package/dist/assets/icons/x-lg.svg.js +1 -1
- package/dist/assets/styles/dark.css +129 -125
- package/dist/assets/styles/dark.css.js +1 -1
- package/dist/assets/styles/light.css +129 -126
- package/dist/assets/styles/light.css.js +1 -1
- package/dist/components/BaseElement.styles.js +2 -2
- package/dist/components/FloatingElement.d.ts +84 -0
- package/dist/components/FloatingElement.js +166 -0
- package/dist/components/FloatingElement.styles.js +26 -0
- package/dist/components/alert/Alert.d.ts +8 -4
- package/dist/components/alert/Alert.js +24 -15
- package/dist/components/alert/Alert.styles.js +32 -39
- package/dist/components/alert/index.js +5 -0
- package/dist/components/button/Button.js +4 -2
- package/dist/components/button/Button.styles.js +13 -20
- package/dist/components/button/index.js +5 -0
- package/dist/components/context-menu/ContextMenu.d.ts +20 -39
- package/dist/components/context-menu/ContextMenu.js +92 -137
- package/dist/components/context-menu/ContextMenu.styles.js +3 -28
- package/dist/components/context-menu/index.d.ts +1 -1
- package/dist/components/context-menu/index.js +5 -0
- package/dist/components/copy-button/CopyButton.d.ts +7 -3
- package/dist/components/copy-button/CopyButton.js +69 -0
- package/dist/components/copy-button/CopyButton.styles.js +17 -0
- package/dist/components/copy-button/index.js +5 -0
- package/dist/components/dialog/Dialog.d.ts +14 -7
- package/dist/components/dialog/Dialog.js +88 -27
- package/dist/components/dialog/Dialog.styles.js +60 -11
- package/dist/components/dialog/index.js +5 -0
- package/dist/components/divider/Divider.d.ts +10 -10
- package/dist/components/divider/Divider.js +32 -32
- package/dist/components/divider/Divider.styles.js +10 -10
- package/dist/components/divider/index.js +5 -0
- package/dist/components/dropdown-menu/DropdownMenu.d.ts +27 -0
- package/dist/components/dropdown-menu/DropdownMenu.js +135 -0
- package/dist/components/dropdown-menu/DropdownMenu.styles.d.ts +1 -0
- package/dist/components/dropdown-menu/DropdownMenu.styles.js +15 -0
- package/dist/components/dropdown-menu/index.d.ts +7 -0
- package/dist/components/dropdown-menu/index.js +5 -0
- package/dist/components/form/Form.d.ts +3 -1
- package/dist/components/form/Form.js +3 -1
- package/dist/components/form/Form.styles.js +1 -0
- package/dist/components/form/index.js +5 -0
- package/dist/components/icon/Icon.d.ts +6 -12
- package/dist/components/icon/Icon.js +15 -30
- package/dist/components/icon/Icon.styles.js +1 -1
- package/dist/components/icon/index.js +5 -0
- package/dist/components/icon-button/IconButton.d.ts +3 -3
- package/dist/components/icon-button/IconButton.js +6 -6
- package/dist/components/icon-button/IconButton.styles.js +14 -29
- package/dist/components/icon-button/index.js +5 -0
- package/dist/components/index.d.ts +3 -1
- package/dist/components/input/Input.d.ts +14 -13
- package/dist/components/input/Input.js +57 -56
- package/dist/components/input/Input.styles.js +54 -56
- package/dist/components/input/index.js +5 -0
- package/dist/components/menu/Menu.d.ts +4 -15
- package/dist/components/menu/Menu.js +43 -28
- package/dist/components/menu/Menu.styles.js +7 -19
- package/dist/components/menu/index.js +5 -0
- package/dist/components/menu-item/MenuItem.d.ts +21 -12
- package/dist/components/menu-item/MenuItem.js +184 -15
- package/dist/components/menu-item/MenuItem.styles.js +6 -0
- package/dist/components/menu-item/index.js +5 -0
- package/dist/components/progress-bar/ProgressBar.d.ts +1 -1
- package/dist/components/progress-bar/ProgressBar.js +2 -2
- package/dist/components/progress-bar/ProgressBar.styles.js +10 -10
- package/dist/components/progress-bar/index.js +5 -0
- package/dist/components/progress-ring/ProgressRing.d.ts +2 -2
- package/dist/components/progress-ring/ProgressRing.js +7 -6
- package/dist/components/progress-ring/ProgressRing.styles.js +8 -9
- package/dist/components/progress-ring/index.js +5 -0
- package/dist/components/spinner/Spinner.styles.js +5 -3
- package/dist/components/spinner/index.js +5 -0
- package/dist/components/split-panel/SplitPanel.d.ts +11 -3
- package/dist/components/split-panel/SplitPanel.js +44 -27
- package/dist/components/split-panel/SplitPanel.styles.js +1 -16
- package/dist/components/split-panel/index.js +5 -0
- package/dist/components/tooltip/Tooltip.d.ts +9 -29
- package/dist/components/tooltip/Tooltip.js +27 -149
- package/dist/components/tooltip/Tooltip.styles.js +9 -23
- package/dist/components/tooltip/index.js +5 -0
- package/dist/components/tree/index.js +5 -0
- package/dist/components/tree-item/index.js +5 -0
- package/dist/index.js +28 -5
- package/dist/integrations/react/UDropdownMenu.d.ts +8 -0
- package/dist/integrations/react/UDropdownMenu.js +10 -0
- package/dist/integrations/react/index.d.ts +1 -1
- package/dist/integrations/react/index.js +1 -1
- package/dist/internals/index.d.ts +0 -1
- package/dist/internals/node-helpers.d.ts +6 -1
- package/dist/internals/node-helpers.js +5 -6
- package/dist/utilities/decorators.js +2 -0
- package/dist/utilities/icons.d.ts +46 -0
- package/dist/utilities/icons.js +114 -0
- package/dist/utilities/index.d.ts +1 -0
- package/dist/utilities/notifier.d.ts +17 -7
- package/dist/utilities/notifier.js +51 -41
- package/dist/utilities/theme.d.ts +15 -20
- package/dist/utilities/theme.js +24 -20
- package/package.json +59 -58
- package/dist/components/panel/Panel.d.ts +0 -9
- package/dist/components/panel/Panel.js +0 -17
- package/dist/components/panel/Panel.styles.js +0 -12
- package/dist/components/panel/index.d.ts +0 -7
- package/dist/integrations/react/UPanel.d.ts +0 -8
- package/dist/integrations/react/UPanel.js +0 -10
- package/dist/internals/icon-helpers.d.ts +0 -32
- package/dist/internals/icon-helpers.js +0 -48
- /package/dist/components/{panel/Panel.styles.d.ts → FloatingElement.styles.d.ts} +0 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import * as arrowClockwise from '../assets/icons/arrow-clockwise.svg.js';
|
|
2
|
+
import * as arrowDown from '../assets/icons/arrow-down.svg.js';
|
|
3
|
+
import * as arrowUp from '../assets/icons/arrow-up.svg.js';
|
|
4
|
+
import * as ban from '../assets/icons/ban.svg.js';
|
|
5
|
+
import * as bellFill from '../assets/icons/bell-fill.svg.js';
|
|
6
|
+
import * as checkCircleFill from '../assets/icons/check-circle-fill.svg.js';
|
|
7
|
+
import * as checkLg from '../assets/icons/check-lg.svg.js';
|
|
8
|
+
import * as chevronDown from '../assets/icons/chevron-down.svg.js';
|
|
9
|
+
import * as chevronLeft from '../assets/icons/chevron-left.svg.js';
|
|
10
|
+
import * as chevronRight from '../assets/icons/chevron-right.svg.js';
|
|
11
|
+
import * as chevronUp from '../assets/icons/chevron-up.svg.js';
|
|
12
|
+
import * as copy from '../assets/icons/copy.svg.js';
|
|
13
|
+
import * as dashLg from '../assets/icons/dash-lg.svg.js';
|
|
14
|
+
import * as exclamationCircleFill from '../assets/icons/exclamation-circle-fill.svg.js';
|
|
15
|
+
import * as exclamationTriangleFill from '../assets/icons/exclamation-triangle-fill.svg.js';
|
|
16
|
+
import * as eyeSlash from '../assets/icons/eye-slash.svg.js';
|
|
17
|
+
import * as eye from '../assets/icons/eye.svg.js';
|
|
18
|
+
import * as infoCircleFill from '../assets/icons/info-circle-fill.svg.js';
|
|
19
|
+
import * as layoutSidebar from '../assets/icons/layout-sidebar.svg.js';
|
|
20
|
+
import * as lightbulbFill from '../assets/icons/lightbulb-fill.svg.js';
|
|
21
|
+
import * as lightbulbOff from '../assets/icons/lightbulb-off.svg.js';
|
|
22
|
+
import * as lightbulb from '../assets/icons/lightbulb.svg.js';
|
|
23
|
+
import * as micFill from '../assets/icons/mic-fill.svg.js';
|
|
24
|
+
import * as micMuteFill from '../assets/icons/mic-mute-fill.svg.js';
|
|
25
|
+
import * as paperclip from '../assets/icons/paperclip.svg.js';
|
|
26
|
+
import * as pencilSquare from '../assets/icons/pencil-square.svg.js';
|
|
27
|
+
import * as plusLg from '../assets/icons/plus-lg.svg.js';
|
|
28
|
+
import * as search from '../assets/icons/search.svg.js';
|
|
29
|
+
import * as speedometer from '../assets/icons/speedometer.svg.js';
|
|
30
|
+
import * as xLg from '../assets/icons/x-lg.svg.js';
|
|
31
|
+
|
|
32
|
+
let defaultIconBaseUrl = "/assets/icons/";
|
|
33
|
+
const defaultIconCache = /* @__PURE__ */ new Map();
|
|
34
|
+
const internalIconBundle = new Map(
|
|
35
|
+
Object.entries(/* #__PURE__ */ Object.assign({"../assets/icons/arrow-clockwise.svg": arrowClockwise,"../assets/icons/arrow-down.svg": arrowDown,"../assets/icons/arrow-up.svg": arrowUp,"../assets/icons/ban.svg": ban,"../assets/icons/bell-fill.svg": bellFill,"../assets/icons/check-circle-fill.svg": checkCircleFill,"../assets/icons/check-lg.svg": checkLg,"../assets/icons/chevron-down.svg": chevronDown,"../assets/icons/chevron-left.svg": chevronLeft,"../assets/icons/chevron-right.svg": chevronRight,"../assets/icons/chevron-up.svg": chevronUp,"../assets/icons/copy.svg": copy,"../assets/icons/dash-lg.svg": dashLg,"../assets/icons/exclamation-circle-fill.svg": exclamationCircleFill,"../assets/icons/exclamation-triangle-fill.svg": exclamationTriangleFill,"../assets/icons/eye-slash.svg": eyeSlash,"../assets/icons/eye.svg": eye,"../assets/icons/info-circle-fill.svg": infoCircleFill,"../assets/icons/layout-sidebar.svg": layoutSidebar,"../assets/icons/lightbulb-fill.svg": lightbulbFill,"../assets/icons/lightbulb-off.svg": lightbulbOff,"../assets/icons/lightbulb.svg": lightbulb,"../assets/icons/mic-fill.svg": micFill,"../assets/icons/mic-mute-fill.svg": micMuteFill,"../assets/icons/paperclip.svg": paperclip,"../assets/icons/pencil-square.svg": pencilSquare,"../assets/icons/plus-lg.svg": plusLg,"../assets/icons/search.svg": search,"../assets/icons/speedometer.svg": speedometer,"../assets/icons/x-lg.svg": xLg
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
})).map(([path, module]) => {
|
|
39
|
+
const name = path.split("/").pop()?.replace(".svg", "") || "";
|
|
40
|
+
return [name, module.default];
|
|
41
|
+
}).filter(([name]) => name !== "")
|
|
42
|
+
);
|
|
43
|
+
class IconRegistry {
|
|
44
|
+
constructor() {
|
|
45
|
+
this.libs = /* @__PURE__ */ new Map();
|
|
46
|
+
}
|
|
47
|
+
static get instance() {
|
|
48
|
+
if (!this._instance) {
|
|
49
|
+
this._instance = new IconRegistry();
|
|
50
|
+
}
|
|
51
|
+
return this._instance;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* 지정된 아이콘 라이브러리가 등록되었는지 확인합니다.
|
|
55
|
+
*/
|
|
56
|
+
has(lib) {
|
|
57
|
+
return this.libs.has(lib);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* 지정된 아이콘 라이브러리를 등록합니다.
|
|
61
|
+
* 이미 등록된 라이브러리 이름인 경우, 경고 메시지를 출력합니다.
|
|
62
|
+
*/
|
|
63
|
+
register(lib, resolver) {
|
|
64
|
+
if (this.libs.has(lib)) {
|
|
65
|
+
console.warn(`Icon library "${lib}" is already registered`);
|
|
66
|
+
} else {
|
|
67
|
+
this.libs.set(lib, resolver);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* 지정된 아이콘 라이브러리를 등록 해제합니다.
|
|
72
|
+
*/
|
|
73
|
+
unregister(lib) {
|
|
74
|
+
this.libs.delete(lib);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* 지정된 아이콘 라이브러리의 svg 아이콘 소스를 가져옵니다.
|
|
78
|
+
*/
|
|
79
|
+
async resolve(lib, name) {
|
|
80
|
+
const resolver = this.libs.get(lib);
|
|
81
|
+
if (!resolver) return void 0;
|
|
82
|
+
const svg = await resolver(name);
|
|
83
|
+
return svg?.trim();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
IconRegistry.instance.register("internal", (name) => {
|
|
87
|
+
return internalIconBundle.get(name);
|
|
88
|
+
});
|
|
89
|
+
IconRegistry.instance.register("default", async (name) => {
|
|
90
|
+
if (defaultIconCache.has(name)) {
|
|
91
|
+
return defaultIconCache.get(name);
|
|
92
|
+
}
|
|
93
|
+
const baseUrl = getDefaultBaseUrl();
|
|
94
|
+
const remoteUrl = baseUrl.endsWith("/") ? `${baseUrl}${name}.svg` : `${baseUrl}/${name}.svg`;
|
|
95
|
+
try {
|
|
96
|
+
const response = await fetch(remoteUrl);
|
|
97
|
+
if (!response.ok) return void 0;
|
|
98
|
+
const svg = await response.text();
|
|
99
|
+
defaultIconCache.set(name, svg);
|
|
100
|
+
return svg;
|
|
101
|
+
} catch (error) {
|
|
102
|
+
console.error(error);
|
|
103
|
+
return void 0;
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
const icons = IconRegistry.instance;
|
|
107
|
+
function getDefaultBaseUrl() {
|
|
108
|
+
return defaultIconBaseUrl;
|
|
109
|
+
}
|
|
110
|
+
function setDefaultBaseUrl(url) {
|
|
111
|
+
defaultIconBaseUrl = url;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export { getDefaultBaseUrl, icons, setDefaultBaseUrl };
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AlertType } from '../components/alert/Alert.js';
|
|
2
2
|
export type ScreenPosition = "top-left" | "top-center" | "top-right" | "middle-left" | "middle-center" | "middle-right" | "bottom-left" | "bottom-center" | "bottom-right";
|
|
3
3
|
/** 토스트 알림 옵션 */
|
|
4
4
|
export interface ToastOptions {
|
|
5
5
|
/** 알림 유형 */
|
|
6
6
|
type: AlertType;
|
|
7
7
|
/** 알림 제목 */
|
|
8
|
-
|
|
8
|
+
heading?: string;
|
|
9
9
|
/** 알림 내용 */
|
|
10
10
|
content?: string;
|
|
11
11
|
/** 알림 표시 시간 (밀리초 단위) */
|
|
@@ -14,13 +14,23 @@ export interface ToastOptions {
|
|
|
14
14
|
position?: ScreenPosition;
|
|
15
15
|
}
|
|
16
16
|
/**
|
|
17
|
-
*
|
|
17
|
+
* Notifier 클래스 — 싱글톤 패턴으로 사용합니다.
|
|
18
18
|
*/
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
declare class Notifier {
|
|
20
|
+
private static _instance;
|
|
21
|
+
private containers;
|
|
22
|
+
private toasts;
|
|
23
|
+
private constructor();
|
|
24
|
+
static get instance(): Notifier;
|
|
22
25
|
/**
|
|
23
26
|
* 토스트 알림을 생성합니다.
|
|
24
27
|
*/
|
|
25
28
|
toast(options: ToastOptions): Promise<void>;
|
|
26
|
-
|
|
29
|
+
/** 위치에 맞는 컨테이너 엘리먼트를 가져오거나, 생성합니다. */
|
|
30
|
+
private getOrCreateContainer;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* 알림 유틸리티 싱글톤 인스턴스입니다.
|
|
34
|
+
*/
|
|
35
|
+
export declare const notifier: Notifier;
|
|
36
|
+
export {};
|
|
@@ -1,20 +1,28 @@
|
|
|
1
1
|
import { Alert } from '../components/alert/Alert.js';
|
|
2
2
|
|
|
3
3
|
Alert.define("u-alert");
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
class Notifier {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.containers = /* @__PURE__ */ new Map();
|
|
7
|
+
this.toasts = /* @__PURE__ */ new Set();
|
|
8
|
+
}
|
|
9
|
+
static get instance() {
|
|
10
|
+
if (!this._instance) {
|
|
11
|
+
this._instance = new Notifier();
|
|
12
|
+
}
|
|
13
|
+
return this._instance;
|
|
14
|
+
}
|
|
7
15
|
/**
|
|
8
16
|
* 토스트 알림을 생성합니다.
|
|
9
17
|
*/
|
|
10
18
|
async toast(options) {
|
|
11
19
|
const el = new Alert();
|
|
12
20
|
el.type = options.type;
|
|
13
|
-
el.
|
|
21
|
+
el.heading = options.heading;
|
|
14
22
|
el.content = options.content;
|
|
15
23
|
this.toasts.add(el);
|
|
16
24
|
const position = options.position || "top-right";
|
|
17
|
-
const container = getOrCreateContainer(position);
|
|
25
|
+
const container = this.getOrCreateContainer(position);
|
|
18
26
|
container.appendChild(el);
|
|
19
27
|
await el.updateComplete;
|
|
20
28
|
el.show();
|
|
@@ -26,46 +34,48 @@ const notifier = {
|
|
|
26
34
|
this.toasts.delete(el);
|
|
27
35
|
if (!container.hasChildNodes()) {
|
|
28
36
|
container.remove();
|
|
29
|
-
this.
|
|
37
|
+
this.containers.delete(position);
|
|
30
38
|
}
|
|
31
39
|
}, duration);
|
|
32
40
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
41
|
+
/** 위치에 맞는 컨테이너 엘리먼트를 가져오거나, 생성합니다. */
|
|
42
|
+
getOrCreateContainer(position) {
|
|
43
|
+
let container = this.containers.get(position);
|
|
44
|
+
if (container) return container;
|
|
45
|
+
container = document.createElement("div");
|
|
46
|
+
container.style.position = "fixed";
|
|
47
|
+
container.style.zIndex = "9999";
|
|
48
|
+
container.style.display = "flex";
|
|
49
|
+
container.style.gap = "10px";
|
|
50
|
+
const transformParts = [];
|
|
51
|
+
if (position.startsWith("top")) {
|
|
52
|
+
container.style.top = "20px";
|
|
53
|
+
container.style.flexDirection = "column";
|
|
54
|
+
} else if (position.startsWith("bottom")) {
|
|
55
|
+
container.style.bottom = "20px";
|
|
56
|
+
container.style.flexDirection = "column-reverse";
|
|
57
|
+
} else {
|
|
58
|
+
container.style.top = "50%";
|
|
59
|
+
container.style.flexDirection = "column";
|
|
60
|
+
transformParts.push("translateY(-50%)");
|
|
61
|
+
}
|
|
62
|
+
if (position.endsWith("left")) {
|
|
63
|
+
container.style.left = "20px";
|
|
64
|
+
container.style.alignItems = "flex-start";
|
|
65
|
+
} else if (position.endsWith("right")) {
|
|
66
|
+
container.style.right = "20px";
|
|
67
|
+
container.style.alignItems = "flex-end";
|
|
68
|
+
} else {
|
|
69
|
+
container.style.left = "50%";
|
|
70
|
+
container.style.alignItems = "center";
|
|
71
|
+
transformParts.unshift("translateX(-50%)");
|
|
72
|
+
}
|
|
73
|
+
container.style.transform = transformParts.length ? transformParts.join(" ") : "";
|
|
74
|
+
document.body.appendChild(container);
|
|
75
|
+
this.containers.set(position, container);
|
|
76
|
+
return container;
|
|
64
77
|
}
|
|
65
|
-
container.style.transform = transformParts.length ? transformParts.join(" ") : "";
|
|
66
|
-
document.body.appendChild(container);
|
|
67
|
-
notifier.container.set(position, container);
|
|
68
|
-
return container;
|
|
69
78
|
}
|
|
79
|
+
const notifier = Notifier.instance;
|
|
70
80
|
|
|
71
81
|
export { notifier };
|
|
@@ -8,11 +8,6 @@ export interface ThemeInitOptions {
|
|
|
8
8
|
* @default false
|
|
9
9
|
*/
|
|
10
10
|
debug?: boolean;
|
|
11
|
-
/**
|
|
12
|
-
* 내부적으로 제공되는 스타일 시트를 사용할지 여부
|
|
13
|
-
* @default true
|
|
14
|
-
*/
|
|
15
|
-
useBuiltIn?: boolean;
|
|
16
11
|
/**
|
|
17
12
|
* 테마 설정을 브라우저 스토리지에 영구 저장할지 여부 또는 옵션
|
|
18
13
|
* @default false
|
|
@@ -23,24 +18,27 @@ export interface ThemeInitOptions {
|
|
|
23
18
|
* @default 'system'
|
|
24
19
|
*/
|
|
25
20
|
default?: ThemeType;
|
|
21
|
+
/**
|
|
22
|
+
* 내부적으로 제공되는 스타일 시트를 사용할지 여부
|
|
23
|
+
* @default true
|
|
24
|
+
*/
|
|
25
|
+
useBuiltIn?: boolean;
|
|
26
26
|
}
|
|
27
27
|
/**
|
|
28
|
-
*
|
|
28
|
+
* 현재 문서에 테마를 적용하고 관리하는 유틸리티 클래스입니다.
|
|
29
29
|
*/
|
|
30
|
-
|
|
30
|
+
declare class Theme {
|
|
31
31
|
private static _instance;
|
|
32
|
-
private readonly
|
|
32
|
+
private readonly STORAGE_THEME_KEY;
|
|
33
33
|
private storage;
|
|
34
34
|
private _isInitialized;
|
|
35
35
|
private _isDebugMode;
|
|
36
|
-
/** private 생성자 — 외부에서 new Theme()를 할 수 없게 함 */
|
|
37
36
|
private constructor();
|
|
38
|
-
/** 싱글톤 인스턴스 접근자 */
|
|
39
37
|
static get instance(): Theme;
|
|
40
|
-
/** 외부에서 현재 초기화 상태를 확인할 수 있게 getter 제공 */
|
|
41
38
|
get isInitialized(): boolean;
|
|
39
|
+
get isDebugMode(): boolean;
|
|
42
40
|
/**
|
|
43
|
-
* 테마
|
|
41
|
+
* 테마 유틸리티를 초기화합니다.
|
|
44
42
|
*/
|
|
45
43
|
init(options?: ThemeInitOptions): Promise<void>;
|
|
46
44
|
/**
|
|
@@ -48,19 +46,16 @@ export declare class Theme {
|
|
|
48
46
|
*/
|
|
49
47
|
get(): ThemeType | undefined;
|
|
50
48
|
/**
|
|
51
|
-
* 현재
|
|
49
|
+
* 현재 문서에 적용할 테마를 설정합니다.
|
|
52
50
|
*/
|
|
53
51
|
set(theme: ThemeType): void;
|
|
54
|
-
/**
|
|
55
|
-
* 시스템 테마 변경을 처리하는 메서드
|
|
56
|
-
*/
|
|
52
|
+
/** 시스템 테마 변경을 처리하는 메서드 */
|
|
57
53
|
private handleSystemThemeChanged;
|
|
58
|
-
/**
|
|
59
|
-
* 디버그 모드시 로그 출력 함수 (인스턴스 스코프)
|
|
60
|
-
*/
|
|
54
|
+
/** 디버그 모드시 로그 출력 함수 (인스턴스 스코프) */
|
|
61
55
|
private log;
|
|
62
56
|
}
|
|
63
57
|
/**
|
|
64
|
-
* 테마
|
|
58
|
+
* 테마 유틸리티의 싱글톤 인스턴스입니다.
|
|
65
59
|
*/
|
|
66
60
|
export declare const theme: Theme;
|
|
61
|
+
export {};
|
package/dist/utilities/theme.js
CHANGED
|
@@ -2,7 +2,7 @@ import * as dark from '../assets/styles/dark.css.js';
|
|
|
2
2
|
import * as light from '../assets/styles/light.css.js';
|
|
3
3
|
import { BrowserStorage } from './BrowserStorage.js';
|
|
4
4
|
|
|
5
|
-
const
|
|
5
|
+
const styleBundle = Object.entries(/* #__PURE__ */ Object.assign({"../assets/styles/dark.css": dark,"../assets/styles/light.css": light
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
})).map(([path, module]) => {
|
|
@@ -10,61 +10,67 @@ const styleAssets = Object.entries(/* #__PURE__ */ Object.assign({"../assets/sty
|
|
|
10
10
|
return [name, module.default];
|
|
11
11
|
}).filter(([name]) => name !== "");
|
|
12
12
|
class Theme {
|
|
13
|
-
/** private 생성자 — 외부에서 new Theme()를 할 수 없게 함 */
|
|
14
13
|
constructor() {
|
|
15
|
-
this.
|
|
14
|
+
this.STORAGE_THEME_KEY = "theme";
|
|
16
15
|
this.storage = null;
|
|
17
16
|
this._isInitialized = false;
|
|
18
17
|
this._isDebugMode = false;
|
|
19
|
-
/**
|
|
20
|
-
* 시스템 테마 변경을 처리하는 메서드
|
|
21
|
-
*/
|
|
18
|
+
/** 시스템 테마 변경을 처리하는 메서드 */
|
|
22
19
|
this.handleSystemThemeChanged = (_) => {
|
|
23
20
|
if (document.documentElement.getAttribute("data-theme") === "system") {
|
|
24
21
|
const isDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
|
|
25
22
|
document.documentElement.setAttribute("theme", isDark ? "dark" : "light");
|
|
23
|
+
this.log("system theme changed, applied", isDark ? "dark" : "light");
|
|
26
24
|
}
|
|
27
25
|
};
|
|
28
26
|
}
|
|
29
|
-
/** 싱글톤 인스턴스 접근자 */
|
|
30
27
|
static get instance() {
|
|
31
28
|
if (!this._instance) {
|
|
32
29
|
this._instance = new Theme();
|
|
33
30
|
}
|
|
34
31
|
return this._instance;
|
|
35
32
|
}
|
|
36
|
-
/** 외부에서 현재 초기화 상태를 확인할 수 있게 getter 제공 */
|
|
37
33
|
get isInitialized() {
|
|
38
34
|
return this._isInitialized;
|
|
39
35
|
}
|
|
36
|
+
get isDebugMode() {
|
|
37
|
+
return this._isDebugMode;
|
|
38
|
+
}
|
|
40
39
|
/**
|
|
41
|
-
* 테마
|
|
40
|
+
* 테마 유틸리티를 초기화합니다.
|
|
42
41
|
*/
|
|
43
42
|
async init(options) {
|
|
44
43
|
this._isDebugMode = options?.debug || false;
|
|
45
44
|
this.log("init called", { options });
|
|
46
45
|
if (options?.store) {
|
|
47
|
-
this.log("store option provided, initializing BrowserStorage");
|
|
48
46
|
this.storage = new BrowserStorage(options.store);
|
|
47
|
+
this.log("store option provided, initializing BrowserStorage");
|
|
48
|
+
} else {
|
|
49
|
+
this.storage = null;
|
|
50
|
+
this.log("no store option provided, skipping BrowserStorage initialization");
|
|
49
51
|
}
|
|
50
52
|
const useBuiltIn = options?.useBuiltIn ?? true;
|
|
51
53
|
if (useBuiltIn) {
|
|
52
54
|
this.log("Import enabled: loading styles via internal assets");
|
|
53
|
-
for (let [name, module] of
|
|
55
|
+
for (let [name, module] of styleBundle) {
|
|
54
56
|
const style = document.createElement("style");
|
|
55
|
-
style.setAttribute("data-
|
|
57
|
+
style.setAttribute("data-name", name);
|
|
56
58
|
style.textContent = module;
|
|
57
|
-
if (document.head.querySelector(`style[data-
|
|
59
|
+
if (document.head.querySelector(`style[data-name="${name}"]`)) {
|
|
58
60
|
this.log("style already present, skipping", name);
|
|
59
61
|
continue;
|
|
60
62
|
}
|
|
61
63
|
document.head.appendChild(style);
|
|
62
64
|
this.log("appended style to head", name);
|
|
63
65
|
}
|
|
66
|
+
} else {
|
|
67
|
+
const styleHead = document.head.querySelectorAll("style[data-name]");
|
|
68
|
+
styleHead.forEach((el) => el.remove());
|
|
69
|
+
this.log("Import disabled: removed internal styles from head");
|
|
64
70
|
}
|
|
65
71
|
let theme2 = options?.default ?? "system";
|
|
66
72
|
if (this.storage !== null) {
|
|
67
|
-
const savedTheme = await this.storage.get(this.
|
|
73
|
+
const savedTheme = await this.storage.get(this.STORAGE_THEME_KEY);
|
|
68
74
|
if (savedTheme) {
|
|
69
75
|
theme2 = savedTheme;
|
|
70
76
|
this.log("loaded theme from storage", theme2);
|
|
@@ -93,7 +99,7 @@ class Theme {
|
|
|
93
99
|
}
|
|
94
100
|
}
|
|
95
101
|
/**
|
|
96
|
-
* 현재
|
|
102
|
+
* 현재 문서에 적용할 테마를 설정합니다.
|
|
97
103
|
*/
|
|
98
104
|
set(theme2) {
|
|
99
105
|
try {
|
|
@@ -120,17 +126,15 @@ class Theme {
|
|
|
120
126
|
this.log("Error applying theme:", e);
|
|
121
127
|
}
|
|
122
128
|
if (this.storage !== null) {
|
|
123
|
-
this.storage.set(this.
|
|
129
|
+
this.storage.set(this.STORAGE_THEME_KEY, theme2);
|
|
124
130
|
this.log("saved theme to storage", theme2);
|
|
125
131
|
}
|
|
126
132
|
}
|
|
127
|
-
/**
|
|
128
|
-
* 디버그 모드시 로그 출력 함수 (인스턴스 스코프)
|
|
129
|
-
*/
|
|
133
|
+
/** 디버그 모드시 로그 출력 함수 (인스턴스 스코프) */
|
|
130
134
|
log(...args) {
|
|
131
135
|
if (this._isDebugMode) console.log("[theme]", ...args);
|
|
132
136
|
}
|
|
133
137
|
}
|
|
134
138
|
const theme = Theme.instance;
|
|
135
139
|
|
|
136
|
-
export {
|
|
140
|
+
export { theme };
|
package/package.json
CHANGED
|
@@ -1,58 +1,59 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@iyulab/components",
|
|
3
|
-
"description": "web-components library
|
|
4
|
-
"version": "0.1.
|
|
5
|
-
"keywords": [
|
|
6
|
-
"iyulab",
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
|
|
14
|
-
"
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
"
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
"
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
"
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
"@
|
|
48
|
-
"@
|
|
49
|
-
"
|
|
50
|
-
"eslint
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"typescript
|
|
54
|
-
"
|
|
55
|
-
"vite
|
|
56
|
-
"vite-plugin-
|
|
57
|
-
|
|
58
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@iyulab/components",
|
|
3
|
+
"description": "web-components library based on lit-element made by iyulab",
|
|
4
|
+
"version": "0.1.6",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"iyulab",
|
|
7
|
+
"components",
|
|
8
|
+
"web-components",
|
|
9
|
+
"lit-element"
|
|
10
|
+
],
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"author": "iyulab",
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "https://github.com/iyulab/node-components.git"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist",
|
|
19
|
+
"LICENSE",
|
|
20
|
+
"README.md",
|
|
21
|
+
"CHANGELOG.md",
|
|
22
|
+
"package.json"
|
|
23
|
+
],
|
|
24
|
+
"type": "module",
|
|
25
|
+
"types": "./dist/index.d.ts",
|
|
26
|
+
"exports": {
|
|
27
|
+
".": {
|
|
28
|
+
"types": "./src/index.d.ts",
|
|
29
|
+
"import": "./src/index.js"
|
|
30
|
+
},
|
|
31
|
+
"./dist/*": {
|
|
32
|
+
"types": "./src/*.d.ts",
|
|
33
|
+
"import": "./src/*"
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"scripts": {
|
|
37
|
+
"start": "vite --force",
|
|
38
|
+
"build": "eslint && vite build"
|
|
39
|
+
},
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"@floating-ui/dom": "^1.7.4",
|
|
42
|
+
"lit": "^3.3.1",
|
|
43
|
+
"react": "^19.2.3",
|
|
44
|
+
"reflect-metadata": "^0.2.2"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@lit/react": "^1.0.8",
|
|
48
|
+
"@eslint/js": "^9.39.1",
|
|
49
|
+
"@types/node": "^25.0.1",
|
|
50
|
+
"eslint": "^9.39.1",
|
|
51
|
+
"eslint-plugin-lit": "^2.1.1",
|
|
52
|
+
"globals": "^16.5.0",
|
|
53
|
+
"typescript": "^5.9.3",
|
|
54
|
+
"typescript-eslint": "^8.49.0",
|
|
55
|
+
"vite": "^7.2.7",
|
|
56
|
+
"vite-plugin-dts": "^4.5.4",
|
|
57
|
+
"vite-plugin-static-copy": "^3.1.4"
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { BaseElement } from '../BaseElement.js';
|
|
2
|
-
/**
|
|
3
|
-
* 각 패널은 독립적인 크기와 콘텐츠를 가질 수 있습니다.
|
|
4
|
-
*/
|
|
5
|
-
export declare class Panel extends BaseElement {
|
|
6
|
-
static styles: import('lit').CSSResultGroup[];
|
|
7
|
-
static dependencies: Record<string, typeof BaseElement>;
|
|
8
|
-
render(): import('lit-html').TemplateResult<1>;
|
|
9
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { html } from 'lit';
|
|
2
|
-
import { BaseElement } from '../BaseElement.js';
|
|
3
|
-
import { styles } from './Panel.styles.js';
|
|
4
|
-
|
|
5
|
-
class Panel extends BaseElement {
|
|
6
|
-
static {
|
|
7
|
-
this.styles = [super.styles, styles];
|
|
8
|
-
}
|
|
9
|
-
static {
|
|
10
|
-
this.dependencies = {};
|
|
11
|
-
}
|
|
12
|
-
render() {
|
|
13
|
-
return html`<slot></slot>`;
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export { Panel };
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { Panel } from '../../components/panel/index';
|
|
3
|
-
|
|
4
|
-
export declare const UPanel: React.ForwardRefExoticComponent<
|
|
5
|
-
Partial<Panel> & React.HTMLAttributes<Panel>
|
|
6
|
-
>;
|
|
7
|
-
|
|
8
|
-
export type UPanelProps = React.ComponentProps<typeof UPanel>;
|