@iyulab/components 0.1.3 → 0.1.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.
Files changed (73) hide show
  1. package/CHANGELOG.md +18 -15
  2. package/LICENSE +20 -20
  3. package/README.md +33 -33
  4. package/dist/assets/icons/arrow-clockwise.svg.js +1 -1
  5. package/dist/assets/icons/arrow-down.svg.js +1 -1
  6. package/dist/assets/icons/arrow-up.svg.js +1 -1
  7. package/dist/assets/icons/ban.svg.js +1 -1
  8. package/dist/assets/icons/check-circle-fill.svg.js +1 -1
  9. package/dist/assets/icons/check-lg.svg.js +1 -1
  10. package/dist/assets/icons/chevron-down.svg.js +1 -1
  11. package/dist/assets/icons/chevron-left.svg.js +1 -1
  12. package/dist/assets/icons/chevron-right.svg.js +1 -1
  13. package/dist/assets/icons/chevron-up.svg.js +1 -1
  14. package/dist/assets/icons/copy.svg.js +1 -1
  15. package/dist/assets/icons/dash-lg.svg.js +1 -1
  16. package/dist/assets/icons/exclamation-circle-fill.svg.js +1 -1
  17. package/dist/assets/icons/exclamation-triangle-fill.svg.js +1 -1
  18. package/dist/assets/icons/info-circle-fill.svg.js +1 -1
  19. package/dist/assets/icons/layout-sidebar.svg.js +1 -1
  20. package/dist/assets/icons/lightbulb-fill.svg.js +1 -1
  21. package/dist/assets/icons/lightbulb-off.svg.js +1 -1
  22. package/dist/assets/icons/lightbulb.svg.js +1 -1
  23. package/dist/assets/icons/mic-fill.svg.js +1 -1
  24. package/dist/assets/icons/mic-mute-fill.svg.js +1 -1
  25. package/dist/assets/icons/paperclip.svg.js +1 -1
  26. package/dist/assets/icons/pencil-square.svg.js +1 -1
  27. package/dist/assets/icons/plus-lg.svg.js +1 -1
  28. package/dist/assets/icons/search.svg.js +1 -1
  29. package/dist/assets/icons/speedometer.svg.js +1 -1
  30. package/dist/assets/icons/x-lg.svg.js +1 -1
  31. package/dist/assets/styles/dark.css +125 -125
  32. package/dist/assets/styles/dark.css.js +1 -1
  33. package/dist/assets/styles/light.css +126 -126
  34. package/dist/assets/styles/light.css.js +1 -1
  35. package/dist/components/BaseElement.styles.js +0 -1
  36. package/dist/components/divider/Divider.d.ts +25 -0
  37. package/dist/components/divider/Divider.js +89 -0
  38. package/dist/components/{split-panel/Splitter.styles.js → divider/Divider.styles.js} +20 -10
  39. package/dist/components/divider/index.d.ts +7 -0
  40. package/dist/components/icon/Icon.d.ts +3 -7
  41. package/dist/components/icon/Icon.js +8 -15
  42. package/dist/components/index.d.ts +1 -0
  43. package/dist/components/panel/Panel.d.ts +0 -1
  44. package/dist/components/panel/Panel.js +0 -4
  45. package/dist/components/progress-bar/ProgressBar.d.ts +1 -1
  46. package/dist/components/progress-ring/ProgressRing.js +3 -1
  47. package/dist/components/split-panel/SplitPanel.d.ts +8 -12
  48. package/dist/components/split-panel/SplitPanel.js +63 -88
  49. package/dist/components/split-panel/SplitPanel.styles.js +16 -1
  50. package/dist/components/tooltip/Tooltip.d.ts +8 -12
  51. package/dist/components/tooltip/Tooltip.js +39 -38
  52. package/dist/components/tooltip/Tooltip.styles.js +4 -4
  53. package/dist/components/tree/Tree.d.ts +2 -14
  54. package/dist/components/tree/Tree.js +9 -49
  55. package/dist/components/tree/Tree.styles.js +5 -5
  56. package/dist/components/tree-item/TreeItem.d.ts +10 -29
  57. package/dist/components/tree-item/TreeItem.js +63 -95
  58. package/dist/components/tree-item/TreeItem.styles.js +10 -41
  59. package/dist/index.js +1 -0
  60. package/dist/integrations/react/UDivider.d.ts +8 -0
  61. package/dist/integrations/react/UDivider.js +10 -0
  62. package/dist/integrations/react/index.d.ts +1 -0
  63. package/dist/integrations/react/index.js +1 -0
  64. package/dist/internals/icon-helpers.d.ts +32 -0
  65. package/dist/internals/{icons.js → icon-helpers.js} +10 -4
  66. package/dist/internals/index.d.ts +1 -1
  67. package/dist/utilities/theme.js +16 -13
  68. package/package.json +57 -57
  69. package/dist/components/split-panel/SplitPanel.types.d.ts +0 -2
  70. package/dist/components/split-panel/Splitter.d.ts +0 -17
  71. package/dist/components/split-panel/Splitter.js +0 -45
  72. package/dist/internals/icons.d.ts +0 -6
  73. /package/dist/components/{split-panel/Splitter.styles.d.ts → divider/Divider.styles.d.ts} +0 -0
@@ -7,46 +7,27 @@ import { BaseElement } from '../BaseElement.js';
7
7
  export declare class TreeItem extends BaseElement {
8
8
  static styles: import('lit').CSSResultGroup[];
9
9
  static dependencies: Record<string, typeof BaseElement>;
10
+ headerEl: HTMLElement;
11
+ childrenItems: TreeItem[];
12
+ /** 트리 항목이 리프 노드인지 여부입니다. */
13
+ leaf: boolean;
14
+ /** 트리 항목의 들여쓰기 레벨입니다. */
15
+ level: number;
10
16
  /** 트리 항목이 비활성화 상태인지 여부입니다. */
11
17
  disabled: boolean;
12
18
  /** 트리 항목이 선택된 상태인지 여부입니다. */
13
19
  selected: boolean;
14
20
  /** 트리 항목이 확장된 상태인지 여부입니다. */
15
21
  expanded: boolean;
16
- /** 트리 항목이 리프 노드인지 여부입니다. */
17
- leaf: boolean;
18
- /** 트리 항목의 들여쓰기 레벨입니다. */
19
- level: number;
20
22
  /** 트리 항목의 값입니다. */
21
23
  value: string;
22
- /** 트리 항목의 아이콘입니다. */
23
- icon: string;
24
- private hasChildren;
25
24
  connectedCallback(): void;
26
25
  protected updated(changedProperties: PropertyValues): void;
27
26
  render(): import('lit-html').TemplateResult<1>;
28
- /** 확장/축소 아이콘을 렌더링합니다. */
29
- private renderExpandIcon;
30
- /** 커스텀 아이콘을 렌더링합니다. */
31
- private renderIcon;
27
+ /** 슬롯 변경 헤더용 노드와 자식 노드 분리 */
28
+ private handleSlotChange;
29
+ /** 자식 슬롯 변경 시 자식 노드 재설정 */
30
+ private handleChildrenSlotChange;
32
31
  /** 헤더 클릭 이벤트를 처리합니다. */
33
32
  private handleHeaderClick;
34
- /** 확장/축소 아이콘 클릭 이벤트를 처리합니다. */
35
- private handleExpandClick;
36
- /** 슬롯 변경 시 자식 노드 확인 */
37
- private handleSlotChange;
38
- /** 자식 노드가 있는지 확인합니다. */
39
- private checkForChildren;
40
- /**
41
- * 트리 항목을 확장합니다.
42
- */
43
- expand(): void;
44
- /**
45
- * 트리 항목을 축소합니다.
46
- */
47
- collapse(): void;
48
- /**
49
- * 트리 항목의 확장 상태를 토글합니다.
50
- */
51
- toggle(): void;
52
33
  }
@@ -1,6 +1,7 @@
1
- import { html, nothing } from 'lit';
2
- import { property, state } from 'lit/decorators.js';
1
+ import { html } from 'lit';
2
+ import { query, queryAssignedElements, state, property } from 'lit/decorators.js';
3
3
  import { BaseElement } from '../BaseElement.js';
4
+ import { Icon } from '../icon/Icon.js';
4
5
  import { styles } from './TreeItem.styles.js';
5
6
 
6
7
  var __defProp = Object.defineProperty;
@@ -12,17 +13,32 @@ var __decorateClass = (decorators, target, key, kind) => {
12
13
  if (result) __defProp(target, key, result);
13
14
  return result;
14
15
  };
15
- class TreeItem extends BaseElement {
16
+ const _TreeItem = class _TreeItem extends BaseElement {
16
17
  constructor() {
17
18
  super(...arguments);
19
+ this.leaf = true;
20
+ this.level = 0;
18
21
  this.disabled = false;
19
22
  this.selected = false;
20
23
  this.expanded = false;
21
- this.leaf = false;
22
- this.level = 0;
23
24
  this.value = "";
24
- this.icon = "";
25
- this.hasChildren = false;
25
+ /** 슬롯 변경 시 헤더용 노드와 자식 노드 분리 */
26
+ this.handleSlotChange = (e) => {
27
+ const slot = e.target;
28
+ const nodes = slot.assignedNodes({ flatten: true });
29
+ nodes.forEach((node) => {
30
+ if (node instanceof _TreeItem) {
31
+ node.setAttribute("slot", "children");
32
+ }
33
+ });
34
+ };
35
+ /** 자식 슬롯 변경 시 자식 노드 재설정 */
36
+ this.handleChildrenSlotChange = () => {
37
+ this.leaf = this.childrenItems.length === 0;
38
+ this.childrenItems.forEach((child) => {
39
+ child.level = this.level + 1;
40
+ });
41
+ };
26
42
  /** 헤더 클릭 이벤트를 처리합니다. */
27
43
  this.handleHeaderClick = (e) => {
28
44
  if (this.disabled) {
@@ -30,34 +46,27 @@ class TreeItem extends BaseElement {
30
46
  e.stopPropagation();
31
47
  return;
32
48
  }
33
- this.selected = true;
34
- this.emit("u-select", { value: this.value, item: this });
35
- };
36
- /** 확장/축소 아이콘 클릭 이벤트를 처리합니다. */
37
- this.handleExpandClick = (e) => {
38
- e.stopPropagation();
39
- if (this.disabled || this.leaf || !this.hasChildren) {
40
- return;
49
+ if (this.leaf) {
50
+ this.selected = true;
51
+ this.emit("u-select", { value: this.value, item: this });
52
+ } else {
53
+ this.expanded = !this.expanded;
54
+ this.emit("u-toggle", { expanded: this.expanded, item: this });
41
55
  }
42
- this.expanded = !this.expanded;
43
- this.emit("u-toggle", { expanded: this.expanded, item: this });
44
- };
45
- /** 슬롯 변경 시 자식 노드 확인 */
46
- this.handleSlotChange = () => {
47
- this.checkForChildren();
48
56
  };
49
57
  }
50
58
  static {
51
59
  this.styles = [super.styles, styles];
52
60
  }
53
61
  static {
54
- this.dependencies = {};
62
+ this.dependencies = {
63
+ "u-icon": Icon
64
+ };
55
65
  }
56
66
  connectedCallback() {
57
67
  super.connectedCallback();
58
68
  this.setAttribute("role", "treeitem");
59
69
  this.setAttribute("tabindex", this.disabled ? "-1" : "0");
60
- this.checkForChildren();
61
70
  }
62
71
  updated(changedProperties) {
63
72
  super.updated(changedProperties);
@@ -66,98 +75,57 @@ class TreeItem extends BaseElement {
66
75
  this.setAttribute("aria-disabled", this.disabled ? "true" : "false");
67
76
  }
68
77
  if (changedProperties.has("expanded")) {
69
- this.setAttribute("aria-expanded", this.hasChildren ? String(this.expanded) : "false");
78
+ this.setAttribute("aria-expanded", this.expanded ? "true" : "false");
70
79
  }
71
80
  if (changedProperties.has("selected")) {
72
81
  this.setAttribute("aria-selected", this.selected ? "true" : "false");
73
82
  }
83
+ if (changedProperties.has("level")) {
84
+ this.setAttribute("aria-level", String(this.level + 1));
85
+ this.headerEl.style.paddingLeft = `calc(${this.level} * var(--indent-size, 20px))`;
86
+ }
74
87
  }
75
88
  render() {
76
89
  return html`
77
- <div class="header" @click=${this.handleHeaderClick} style="padding-left: calc(${this.level} * 20px)">
78
- ${this.renderExpandIcon()}
79
- ${this.renderIcon()}
80
- <span class="label">
81
- <slot name="label"></slot>
82
- <slot></slot>
83
- </span>
90
+ <div class="header" @click=${this.handleHeaderClick}>
91
+ <u-icon class="expand-icon"
92
+ ?hidden=${this.leaf}
93
+ name=${this.expanded ? "chevron-down" : "chevron-right"}
94
+ ></u-icon>
95
+ <slot name="prefix"></slot>
96
+ <slot @slotchange=${this.handleSlotChange}></slot>
97
+ <slot name="suffix"></slot>
84
98
  </div>
85
99
  <div class="children" ?hidden=${!this.expanded}>
86
- <slot name="children" @slotchange=${this.handleSlotChange}></slot>
100
+ <slot name="children" @slotchange=${this.handleChildrenSlotChange}></slot>
87
101
  </div>
88
102
  `;
89
103
  }
90
- /** 확장/축소 아이콘을 렌더링합니다. */
91
- renderExpandIcon() {
92
- if (this.leaf || !this.hasChildren) {
93
- return html`<span class="expand-icon placeholder"></span>`;
94
- }
95
- return html`
96
- <span class="expand-icon" @click=${this.handleExpandClick}>
97
- ${this.expanded ? "▼" : "▶"}
98
- </span>
99
- `;
100
- }
101
- /** 커스텀 아이콘을 렌더링합니다. */
102
- renderIcon() {
103
- if (!this.icon) {
104
- return nothing;
105
- }
106
- return html`<span class="icon">${this.icon}</span>`;
107
- }
108
- /** 자식 노드가 있는지 확인합니다. */
109
- checkForChildren() {
110
- const childrenSlot = this.shadowRoot?.querySelector('slot[name="children"]');
111
- const children = childrenSlot?.assignedElements() || [];
112
- this.hasChildren = children.length > 0;
113
- this.setAttribute("aria-expanded", this.hasChildren ? String(this.expanded) : "false");
114
- }
115
- /**
116
- * 트리 항목을 확장합니다.
117
- */
118
- expand() {
119
- if (!this.leaf && this.hasChildren) {
120
- this.expanded = true;
121
- }
122
- }
123
- /**
124
- * 트리 항목을 축소합니다.
125
- */
126
- collapse() {
127
- this.expanded = false;
128
- }
129
- /**
130
- * 트리 항목의 확장 상태를 토글합니다.
131
- */
132
- toggle() {
133
- if (!this.leaf && this.hasChildren) {
134
- this.expanded = !this.expanded;
135
- }
136
- }
137
- }
104
+ };
138
105
  __decorateClass([
139
- property({ type: Boolean, reflect: true })
140
- ], TreeItem.prototype, "disabled");
106
+ query(".header")
107
+ ], _TreeItem.prototype, "headerEl");
141
108
  __decorateClass([
142
- property({ type: Boolean, reflect: true })
143
- ], TreeItem.prototype, "selected");
109
+ queryAssignedElements({ slot: "children", selector: "u-tree-item", flatten: true })
110
+ ], _TreeItem.prototype, "childrenItems");
144
111
  __decorateClass([
145
- property({ type: Boolean, reflect: true })
146
- ], TreeItem.prototype, "expanded");
112
+ state()
113
+ ], _TreeItem.prototype, "leaf");
114
+ __decorateClass([
115
+ state()
116
+ ], _TreeItem.prototype, "level");
147
117
  __decorateClass([
148
118
  property({ type: Boolean, reflect: true })
149
- ], TreeItem.prototype, "leaf");
119
+ ], _TreeItem.prototype, "disabled");
150
120
  __decorateClass([
151
- property({ type: Number, reflect: true })
152
- ], TreeItem.prototype, "level");
121
+ property({ type: Boolean, reflect: true })
122
+ ], _TreeItem.prototype, "selected");
153
123
  __decorateClass([
154
- property({ type: String })
155
- ], TreeItem.prototype, "value");
124
+ property({ type: Boolean, reflect: true })
125
+ ], _TreeItem.prototype, "expanded");
156
126
  __decorateClass([
157
127
  property({ type: String })
158
- ], TreeItem.prototype, "icon");
159
- __decorateClass([
160
- state()
161
- ], TreeItem.prototype, "hasChildren");
128
+ ], _TreeItem.prototype, "value");
129
+ let TreeItem = _TreeItem;
162
130
 
163
131
  export { TreeItem };
@@ -3,15 +3,14 @@ import { css } from 'lit';
3
3
  const styles = css`
4
4
  :host {
5
5
  display: block;
6
- --tree-indent: 20px;
6
+
7
+ --indent-size: 20px;
7
8
  }
8
-
9
9
  :host([disabled]) {
10
10
  opacity: 0.5;
11
11
  pointer-events: none;
12
12
  cursor: not-allowed;
13
13
  }
14
-
15
14
  :host([disabled]) .header {
16
15
  cursor: not-allowed;
17
16
  pointer-events: none;
@@ -30,68 +29,38 @@ const styles = css`
30
29
  user-select: none;
31
30
  cursor: pointer;
32
31
  }
33
-
34
32
  :host(:not([disabled])) .header:hover {
35
33
  background-color: var(--u-bg-color-hover, #f5f5f5);
36
34
  }
37
-
38
35
  :host([selected]) .header {
39
36
  color: var(--u-blue-600, #0066cc);
40
37
  background-color: var(--u-blue-0, #e8f4f8);
41
38
  }
42
39
 
43
40
  .expand-icon {
44
- display: flex;
45
- align-items: center;
46
- justify-content: center;
47
- width: 16px;
48
- height: 16px;
49
- font-size: 10px;
50
- color: var(--u-icon-color, #757575);
51
41
  transition: transform 0.2s ease, color 0.2s ease;
52
42
  cursor: pointer;
53
43
  }
54
-
55
- .expand-icon:hover {
56
- color: var(--u-icon-color-hover, #0066cc);
57
- }
58
-
59
- .expand-icon.placeholder {
60
- cursor: default;
61
- opacity: 0;
62
- pointer-events: none;
63
- }
64
-
65
- .icon {
66
- display: flex;
44
+
45
+ slot[name="prefix"],
46
+ slot[name="suffix"] {
47
+ display: inline-flex;
67
48
  align-items: center;
68
49
  justify-content: center;
69
- width: 18px;
70
- height: 18px;
71
- font-size: 14px;
72
- color: var(--u-icon-color, #757575);
73
50
  }
74
-
75
- .label {
51
+ slot:not([name]) {
76
52
  flex: 1;
53
+ display: inline-flex;
54
+ align-items: center;
55
+ justify-content: flex-start;
77
56
  overflow: hidden;
78
57
  text-overflow: ellipsis;
79
58
  white-space: nowrap;
80
- font-size: 14px;
81
- color: var(--u-text-color, #212121);
82
- }
83
-
84
- :host([selected]) .label {
85
- color: var(--u-blue-700, #1976d2);
86
59
  }
87
60
 
88
61
  .children {
89
62
  display: block;
90
63
  }
91
-
92
- .children[hidden] {
93
- display: none;
94
- }
95
64
  `;
96
65
 
97
66
  export { styles };
package/dist/index.js CHANGED
@@ -2,6 +2,7 @@ export { Alert } from './components/alert/Alert.js';
2
2
  export { Button } from './components/button/Button.js';
3
3
  export { ContextMenu } from './components/context-menu/ContextMenu.js';
4
4
  export { Dialog } from './components/dialog/Dialog.js';
5
+ export { Divider } from './components/divider/Divider.js';
5
6
  export { Form } from './components/form/Form.js';
6
7
  export { Icon } from './components/icon/Icon.js';
7
8
  export { IconButton } from './components/icon-button/IconButton.js';
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ import { Divider } from '../../components/divider/index';
3
+
4
+ export declare const UDivider: React.ForwardRefExoticComponent<
5
+ Partial<Divider> & React.HTMLAttributes<Divider>
6
+ >;
7
+
8
+ export type UDividerProps = React.ComponentProps<typeof UDivider>;
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ import { createComponent } from '@lit/react';
3
+ import { Divider } from '../../components/divider/index';
4
+
5
+ export const UDivider = createComponent({
6
+ react: React,
7
+ tagName: 'u-divider',
8
+ elementClass: Divider,
9
+ events: {}
10
+ });
@@ -10,6 +10,7 @@ export { UButton, UButtonProps } from './UButton';
10
10
  export { UContextMenu, UContextMenuProps } from './UContextMenu';
11
11
  export { UCopyButton, UCopyButtonProps } from './UCopyButton';
12
12
  export { UDialog, UDialogProps } from './UDialog';
13
+ export { UDivider, UDividerProps } from './UDivider';
13
14
  export { UForm, UFormProps } from './UForm';
14
15
  export { UIcon, UIconProps } from './UIcon';
15
16
  export { UIconButton, UIconButtonProps } from './UIconButton';
@@ -3,6 +3,7 @@ export { UButton } from './UButton.js';
3
3
  export { UContextMenu } from './UContextMenu.js';
4
4
  export { UCopyButton } from './UCopyButton.js';
5
5
  export { UDialog } from './UDialog.js';
6
+ export { UDivider } from './UDivider.js';
6
7
  export { UForm } from './UForm.js';
7
8
  export { UIcon } from './UIcon.js';
8
9
  export { UIconButton } from './UIconButton.js';
@@ -0,0 +1,32 @@
1
+ /**
2
+ * 아이콘 이름과 SVG 소스를 매핑하는 레지스트리입니다.
3
+ *
4
+ * - 키: SVG 파일명에서 확장자를 제거한 문자열 (예: `close.svg` → `"close"`)
5
+ * - 값: SVG 파일의 raw 문자열 (`?raw` 옵션으로 로드됨)
6
+ *
7
+ * Vite의 `import.meta.glob`을 사용하여
8
+ * `../assets/icons/*.svg` 경로의 모든 SVG 파일을 빌드 시점에 한 번에 로드합니다.
9
+ * 이 레지스트리는 런타임 동안 불변이며, 아이콘 조회 시 재사용됩니다.
10
+ */
11
+ export declare const iconBundle: Map<string, string>;
12
+ /**
13
+ * 현재 설정된 아이콘 기본 URL을 반환합니다.
14
+ *
15
+ * 이 값은 아이콘을 정적 경로 또는 CDN 등에서 동적으로 로드할 때
16
+ * prefix로 사용됩니다.
17
+ *
18
+ * @returns 아이콘 로딩에 사용되는 기본 URL (예: `/assets/icons/`)
19
+ */
20
+ export declare function getBaseUrl(): string;
21
+ /**
22
+ * 아이콘을 외부에서 로드할 때 사용할 기본 URL을 설정합니다.
23
+ *
24
+ * 예:
25
+ * - `/assets/icons/`
26
+ * - `https://cdn.example.com/icons/`
27
+ *
28
+ * 일반적으로 마지막에 슬래시(`/`)가 포함된 형태를 권장합니다.
29
+ *
30
+ * @param url 아이콘이 배포된 기본 경로
31
+ */
32
+ export declare function setBaseUrl(url: string): void;
@@ -29,14 +29,20 @@ import * as search from '../assets/icons/search.svg.js';
29
29
  import * as speedometer from '../assets/icons/speedometer.svg.js';
30
30
  import * as xLg from '../assets/icons/x-lg.svg.js';
31
31
 
32
- const icons = new Map(
33
- 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
32
+ let iconBaseUrl = "/assets/icons/";
33
+ const iconBundle = new Map(
34
+ Object.entries(
35
+ /* #__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
34
36
 
35
37
 
36
- })).map(([path, module]) => {
38
+ })
39
+ ).map(([path, module]) => {
37
40
  const name = path.split("/").pop()?.replace(".svg", "") || "";
38
41
  return [name, module.default];
39
42
  }).filter(([name]) => name !== "")
40
43
  );
44
+ function getBaseUrl() {
45
+ return iconBaseUrl;
46
+ }
41
47
 
42
- export { icons };
48
+ export { getBaseUrl, iconBundle };
@@ -1,4 +1,4 @@
1
1
  export * from './attribute-converters.js';
2
- export * from './icons.js';
2
+ export * from './icon-helpers.js';
3
3
  export * from './node-helpers.js';
4
4
  export * from './react-wrapper.js';
@@ -2,6 +2,13 @@ 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 styleAssets = Object.entries(/* #__PURE__ */ Object.assign({"../assets/styles/dark.css": dark,"../assets/styles/light.css": light
6
+
7
+
8
+ })).map(([path, module]) => {
9
+ const name = path.split("/").pop()?.replace(".css", "") || "";
10
+ return [name, module.default];
11
+ }).filter(([name]) => name !== "");
5
12
  class Theme {
6
13
  /** private 생성자 — 외부에서 new Theme()를 할 수 없게 함 */
7
14
  constructor() {
@@ -43,30 +50,26 @@ class Theme {
43
50
  const useBuiltIn = options?.useBuiltIn ?? true;
44
51
  if (useBuiltIn) {
45
52
  this.log("Import enabled: loading styles via internal assets");
46
- const assets = Object.entries(/* #__PURE__ */ Object.assign({"../assets/styles/dark.css": dark,"../assets/styles/light.css": light
47
-
48
-
49
- }));
50
- this.log(`found ${assets.length} style assets`, assets.map((a) => a[0]));
51
- for (let [path, module] of assets) {
52
- const fileName = path.split("/").pop() || path;
53
+ for (let [name, module] of styleAssets) {
53
54
  const style = document.createElement("style");
54
- style.setAttribute("data-path", fileName);
55
- style.textContent = module.default;
56
- if (document.head.querySelector(`style[data-path="${fileName}"]`)) {
57
- this.log("style already present, skipping", fileName);
55
+ style.setAttribute("data-path", name);
56
+ style.textContent = module;
57
+ if (document.head.querySelector(`style[data-path="${name}"]`)) {
58
+ this.log("style already present, skipping", name);
58
59
  continue;
59
60
  }
60
61
  document.head.appendChild(style);
61
- this.log("appended style to head", fileName);
62
+ this.log("appended style to head", name);
62
63
  }
63
64
  }
64
- let theme2 = options?.default || "system";
65
+ let theme2 = options?.default ?? "system";
65
66
  if (this.storage !== null) {
66
67
  const savedTheme = await this.storage.get(this.STORAGE_KEY_DEFAULT);
67
68
  if (savedTheme) {
68
69
  theme2 = savedTheme;
69
70
  this.log("loaded theme from storage", theme2);
71
+ } else {
72
+ this.log("no saved theme in storage, using default", theme2);
70
73
  }
71
74
  }
72
75
  this.set(theme2);
package/package.json CHANGED
@@ -1,58 +1,58 @@
1
- {
2
- "name": "@iyulab/components",
3
- "description": "web-components library by iyulab based on lit-element",
4
- "version": "0.1.3",
5
- "keywords": [
6
- "iyulab",
7
- "web-components",
8
- "lit-element"
9
- ],
10
- "license": "MIT",
11
- "author": "iyulab",
12
- "repository": {
13
- "type": "git",
14
- "url": "https://github.com/iyulab/node-components.git"
15
- },
16
- "files": [
17
- "dist",
18
- "LICENSE",
19
- "README.md",
20
- "CHANGELOG.md",
21
- "package.json"
22
- ],
23
- "type": "module",
24
- "types": "./dist/index.d.ts",
25
- "exports": {
26
- ".": {
27
- "types": "./dist/index.d.ts",
28
- "import": "./dist/index.js"
29
- },
30
- "./dist/*": {
31
- "types": "./dist/*.d.ts",
32
- "import": "./dist/*"
33
- }
34
- },
35
- "scripts": {
36
- "start": "vite --force",
37
- "build": "eslint && vite build"
38
- },
39
- "dependencies": {
40
- "@floating-ui/dom": "^1.7.4",
41
- "lit": "^3.3.1",
42
- "react": "^19.2.0",
43
- "reflect-metadata": "^0.2.2"
44
- },
45
- "devDependencies": {
46
- "@lit/react": "^1.0.8",
47
- "@eslint/js": "^9.39.1",
48
- "@types/node": "^24.10.1",
49
- "eslint": "^9.39.1",
50
- "eslint-plugin-lit": "^2.1.1",
51
- "globals": "^16.5.0",
52
- "typescript": "^5.9.3",
53
- "typescript-eslint": "^8.46.4",
54
- "vite": "^7.2.2",
55
- "vite-plugin-dts": "^4.5.4",
56
- "vite-plugin-static-copy": "^3.1.4"
57
- }
1
+ {
2
+ "name": "@iyulab/components",
3
+ "description": "web-components library by iyulab based on lit-element",
4
+ "version": "0.1.4",
5
+ "keywords": [
6
+ "iyulab",
7
+ "web-components",
8
+ "lit-element"
9
+ ],
10
+ "license": "MIT",
11
+ "author": "iyulab",
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "https://github.com/iyulab/node-components.git"
15
+ },
16
+ "files": [
17
+ "dist",
18
+ "LICENSE",
19
+ "README.md",
20
+ "CHANGELOG.md",
21
+ "package.json"
22
+ ],
23
+ "type": "module",
24
+ "types": "./dist/index.d.ts",
25
+ "exports": {
26
+ ".": {
27
+ "types": "./dist/index.d.ts",
28
+ "import": "./dist/index.js"
29
+ },
30
+ "./dist/*": {
31
+ "types": "./dist/*.d.ts",
32
+ "import": "./dist/*"
33
+ }
34
+ },
35
+ "scripts": {
36
+ "start": "vite --force",
37
+ "build": "eslint && vite build"
38
+ },
39
+ "dependencies": {
40
+ "@floating-ui/dom": "^1.7.4",
41
+ "lit": "^3.3.1",
42
+ "react": "^19.2.1",
43
+ "reflect-metadata": "^0.2.2"
44
+ },
45
+ "devDependencies": {
46
+ "@lit/react": "^1.0.8",
47
+ "@eslint/js": "^9.39.1",
48
+ "@types/node": "^24.10.1",
49
+ "eslint": "^9.39.1",
50
+ "eslint-plugin-lit": "^2.1.1",
51
+ "globals": "^16.5.0",
52
+ "typescript": "^5.9.3",
53
+ "typescript-eslint": "^8.48.1",
54
+ "vite": "^7.2.6",
55
+ "vite-plugin-dts": "^4.5.4",
56
+ "vite-plugin-static-copy": "^3.1.4"
57
+ }
58
58
  }