@iyulab/components 0.3.0 → 0.4.0

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 (75) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/dist/assets/icons/arrow-down-up.svg.js +3 -0
  3. package/dist/assets/icons/code-slash.svg.js +3 -0
  4. package/dist/assets/icons/download.svg.js +3 -0
  5. package/dist/assets/icons/sort-alpha-down.svg.js +3 -0
  6. package/dist/assets/icons/sort-alpha-up.svg.js +3 -0
  7. package/dist/components/UElement.d.ts +59 -0
  8. package/dist/components/UElement.js +96 -0
  9. package/dist/components/{FloatingElement.d.ts → UFloatingElement.d.ts} +4 -4
  10. package/dist/components/{FloatingElement.js → UFloatingElement.js} +13 -13
  11. package/dist/components/UJsonElement.d.ts +46 -0
  12. package/dist/components/UJsonElement.js +93 -0
  13. package/dist/components/UJsonElement.styles.js +95 -0
  14. package/dist/components/{ModalElement.d.ts → UModalElement.d.ts} +4 -4
  15. package/dist/components/{ModalElement.js → UModalElement.js} +8 -8
  16. package/dist/components/UModalElement.styles.d.ts +1 -0
  17. package/dist/components/alert/UAlert.component.d.ts +3 -3
  18. package/dist/components/alert/UAlert.component.js +2 -2
  19. package/dist/components/button/UButton.component.d.ts +3 -3
  20. package/dist/components/button/UButton.component.js +2 -2
  21. package/dist/components/card/UCard.component.d.ts +2 -2
  22. package/dist/components/card/UCard.component.js +2 -2
  23. package/dist/components/carousel/UCarousel.component.d.ts +34 -23
  24. package/dist/components/carousel/UCarousel.component.js +124 -103
  25. package/dist/components/carousel/UCarousel.styles.js +22 -23
  26. package/dist/components/dialog/UDialog.component.d.ts +4 -4
  27. package/dist/components/dialog/UDialog.component.js +2 -2
  28. package/dist/components/divider/UDivider.component.d.ts +3 -3
  29. package/dist/components/divider/UDivider.component.js +2 -2
  30. package/dist/components/drawer/UDrawer.component.d.ts +4 -4
  31. package/dist/components/drawer/UDrawer.component.js +2 -2
  32. package/dist/components/form/UForm.component.d.ts +3 -3
  33. package/dist/components/form/UForm.component.js +2 -2
  34. package/dist/components/icon/UIcon.component.d.ts +3 -3
  35. package/dist/components/icon/UIcon.component.js +2 -2
  36. package/dist/components/input/UInput.component.d.ts +3 -3
  37. package/dist/components/input/UInput.component.js +2 -2
  38. package/dist/components/menu/UMenu.component.d.ts +4 -4
  39. package/dist/components/menu/UMenu.component.js +2 -2
  40. package/dist/components/menu-item/UMenuItem.component.d.ts +3 -3
  41. package/dist/components/menu-item/UMenuItem.component.js +2 -2
  42. package/dist/components/progress-bar/UProgressBar.component.d.ts +3 -3
  43. package/dist/components/progress-bar/UProgressBar.component.js +2 -2
  44. package/dist/components/progress-ring/UProgressRing.component.d.ts +3 -3
  45. package/dist/components/progress-ring/UProgressRing.component.js +2 -2
  46. package/dist/components/skeleton/USkeleton.component.d.ts +3 -3
  47. package/dist/components/skeleton/USkeleton.component.js +2 -2
  48. package/dist/components/spinner/USpinner.component.d.ts +3 -3
  49. package/dist/components/spinner/USpinner.component.js +2 -2
  50. package/dist/components/split-panel/USplitPanel.component.d.ts +3 -3
  51. package/dist/components/split-panel/USplitPanel.component.js +2 -2
  52. package/dist/components/tag/UTag.component.d.ts +3 -3
  53. package/dist/components/tag/UTag.component.js +2 -2
  54. package/dist/components/tooltip/UTooltip.component.d.ts +4 -4
  55. package/dist/components/tooltip/UTooltip.component.js +2 -2
  56. package/dist/components/tree/UTree.component.d.ts +3 -3
  57. package/dist/components/tree/UTree.component.js +2 -2
  58. package/dist/components/tree-item/UTreeItem.component.d.ts +3 -3
  59. package/dist/components/tree-item/UTreeItem.component.js +2 -2
  60. package/dist/index.d.ts +6 -0
  61. package/dist/index.js +6 -0
  62. package/dist/utilities/IconRegistry.js +16 -1
  63. package/dist/utilities/elements.d.ts +23 -0
  64. package/dist/utilities/elements.js +23 -1
  65. package/dist/utilities/sanitizers.d.ts +35 -0
  66. package/dist/utilities/sanitizers.js +43 -0
  67. package/package.json +4 -5
  68. package/dist/components/BaseElement.d.ts +0 -33
  69. package/dist/components/BaseElement.js +0 -59
  70. /package/dist/components/{BaseElement.styles.d.ts → UElement.styles.d.ts} +0 -0
  71. /package/dist/components/{BaseElement.styles.js → UElement.styles.js} +0 -0
  72. /package/dist/components/{FloatingElement.styles.d.ts → UFloatingElement.styles.d.ts} +0 -0
  73. /package/dist/components/{FloatingElement.styles.js → UFloatingElement.styles.js} +0 -0
  74. /package/dist/components/{ModalElement.styles.d.ts → UJsonElement.styles.d.ts} +0 -0
  75. /package/dist/components/{ModalElement.styles.js → UModalElement.styles.js} +0 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,28 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.4.0 (2026-03-02)
4
+
5
+ ### Breaking Changes
6
+ - **BaseElement / FloatingElement / ModalElement**: Renamed to `UElement`, `UFloatingElement`, `UModalElement` to align with the `U` prefix naming convention
7
+ - All components updated to use the renamed base classes
8
+
9
+ ### Features
10
+ - **UJsonElement**: Added new base class that reads JSON from a `<script type="application/json">` tag in light DOM and maps properties to the component automatically
11
+ - Includes built-in error UI rendering via `error()` method
12
+ - Provides static `buildHTML()` helper to generate safe component HTML from JSON data
13
+ - **Icons**: Added new icon assets
14
+ - `arrow-down-up`, `code-slash`, `download`, `sort-alpha-down`, `sort-alpha-up`
15
+
16
+ ### New Utilities
17
+ - **sanitizers.ts**: Added HTML/XSS protection utilities
18
+ - `stripZeroWidth()`: Removes zero-width characters (ZWSP, BOM, etc.)
19
+ - `escapeHtmlText()`: Escapes special characters for HTML text context
20
+ - `escapeHtmlAttr()`: Escapes special characters for HTML attribute context
21
+ - `escapeHtmlHref()`: Sanitizes and validates `href`/`src` values (blocks `javascript:`, `data:`, `vbscript:` protocols)
22
+
23
+ ### Bug Fixes
24
+ - **UCarousel**: Fixed tap vs drag detection — pointer target is now tracked to dispatch a `click` event on tap when drag distance is below threshold
25
+
3
26
  ## 0.3.0 (2026-02-26)
4
27
 
5
28
  ### Features
@@ -0,0 +1,3 @@
1
+ const arrowDownUp = "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16 16\">\n <path fill-rule=\"evenodd\" d=\"M11.5 15a.5.5 0 0 0 .5-.5V2.707l3.146 3.147a.5.5 0 0 0 .708-.708l-4-4a.5.5 0 0 0-.708 0l-4 4a.5.5 0 1 0 .708.708L11 2.707V14.5a.5.5 0 0 0 .5.5m-7-14a.5.5 0 0 1 .5.5v11.793l3.146-3.147a.5.5 0 0 1 .708.708l-4 4a.5.5 0 0 1-.708 0l-4-4a.5.5 0 0 1 .708-.708L4 13.293V1.5a.5.5 0 0 1 .5-.5\"/>\n</svg>";
2
+
3
+ export { arrowDownUp as default };
@@ -0,0 +1,3 @@
1
+ const codeSlash = "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16 16\">\n <path d=\"M10.478 1.647a.5.5 0 1 0-.956-.294l-4 13a.5.5 0 0 0 .956.294zM4.854 4.146a.5.5 0 0 1 0 .708L1.707 8l3.147 3.146a.5.5 0 0 1-.708.708l-3.5-3.5a.5.5 0 0 1 0-.708l3.5-3.5a.5.5 0 0 1 .708 0m6.292 0a.5.5 0 0 0 0 .708L14.293 8l-3.147 3.146a.5.5 0 0 0 .708.708l3.5-3.5a.5.5 0 0 0 0-.708l-3.5-3.5a.5.5 0 0 0-.708 0\"/>\n</svg>";
2
+
3
+ export { codeSlash as default };
@@ -0,0 +1,3 @@
1
+ const download = "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16 16\">\n <path d=\"M.5 9.9a.5.5 0 0 1 .5.5v2.5a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-2.5a.5.5 0 0 1 1 0v2.5a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2v-2.5a.5.5 0 0 1 .5-.5\"/>\n <path d=\"M7.646 11.854a.5.5 0 0 0 .708 0l3-3a.5.5 0 0 0-.708-.708L8.5 10.293V1.5a.5.5 0 0 0-1 0v8.793L5.354 8.146a.5.5 0 1 0-.708.708z\"/>\n</svg>";
2
+
3
+ export { download as default };
@@ -0,0 +1,3 @@
1
+ const sortAlphaDown = "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16 16\">\n <path d=\"M12.96 7H9.028v-.691l2.579-3.72v-.054H9.098v-.867h3.785v.691l-2.567 3.72v.054h2.645z\"/>\n <path fill-rule=\"evenodd\" d=\"M10.082 12.629 9.664 14H8.598l1.789-5.332h1.234L13.402 14h-1.12l-.419-1.371zm1.57-.785L11 9.688h-.047l-.652 2.156z\"/>\n <path d=\"M4.5 2.5a.5.5 0 0 0-1 0v9.793l-1.146-1.147a.5.5 0 0 0-.708.708l2 1.999.007.007a.497.497 0 0 0 .7-.006l2-2a.5.5 0 0 0-.707-.708L4.5 12.293z\"/>\n</svg>";
2
+
3
+ export { sortAlphaDown as default };
@@ -0,0 +1,3 @@
1
+ const sortAlphaUp = "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16 16\">\n <path xmlns=\"http://www.w3.org/2000/svg\" fill-rule=\"evenodd\" d=\"M10.082 5.629 9.664 7H8.598l1.789-5.332h1.234L13.402 7h-1.12l-.419-1.371zm1.57-.785L11 2.687h-.047l-.652 2.157z\"/>\n <path xmlns=\"http://www.w3.org/2000/svg\" d=\"M12.96 14H9.028v-.691l2.579-3.72v-.054H9.098v-.867h3.785v.691l-2.567 3.72v.054h2.645zm-8.46-.5a.5.5 0 0 1-1 0V3.707L2.354 4.854a.5.5 0 1 1-.708-.708l2-1.999.007-.007a.5.5 0 0 1 .7.006l2 2a.5.5 0 1 1-.707.708L4.5 3.707z\"/>\n</svg>";
2
+
3
+ export { sortAlphaUp as default };
@@ -0,0 +1,59 @@
1
+ import { LitElement, CSSResultGroup, RenderOptions } from 'lit';
2
+ /**
3
+ * UElement는 LitElement를 확장한 기본 Web Component 클래스입니다.
4
+ * 이 클래스는 자동으로 종속된 컴포넌트를 정의하며, 유용한 헬퍼 메서드들을 제공합니다.
5
+ */
6
+ export declare class UElement extends LitElement {
7
+ /**
8
+ * 기본 스타일을 정의합니다.
9
+ */
10
+ static styles: CSSResultGroup;
11
+ /**
12
+ * 현재 컴포넌트에 종속된 컴포넌트들을 정의하는 정적 속성입니다.
13
+ * 이 속성은 컴포넌트가 정의될 때 자동으로 호출되어
14
+ * 종속된 컴포넌트를 등록합니다.
15
+ */
16
+ static dependencies: Record<string, typeof UElement>;
17
+ constructor();
18
+ /**
19
+ * 커스텀 엘리먼트를 정의합니다.
20
+ * 이미 정의된 엘리먼트는 다시 정의하지 않습니다.
21
+ * @param name - 커스텀 엘리먼트의 이름
22
+ * @param options - 엘리먼트 정의 옵션
23
+ */
24
+ static define(name: string, options?: ElementDefinitionOptions): void;
25
+ /**
26
+ * 커스텀 이벤트를 디스패치합니다.
27
+ * @param name - 이벤트 이름
28
+ * @param value - 이벤트의 detail에 포함될 데이터
29
+ * @param options - 추가 이벤트 옵션 (예: bubbles, composed 등)
30
+ * @returns 이벤트가 성공적으로 디스패치되었는지 여부
31
+ */
32
+ protected emit(name: string, value?: any, options?: CustomEventInit): boolean;
33
+ /**
34
+ * 현재 shadow DOM의 렌더 결과를 지정한 템플릿으로 완전히 교체합니다.
35
+ *
36
+ * @param value - Lit 템플릿 결과 또는 기타 렌더링 가능한 값
37
+ * @param options - Lit의 RenderOptions (예: renderBefore 등)
38
+ *
39
+ * @remarks
40
+ * Lit은 브라우저 환경에 따라 스타일을 두 가지 방식으로 주입합니다.
41
+ *
42
+ * - **모던 브라우저**: `shadowRoot.adoptedStyleSheets`에 `CSSStyleSheet` 객체로 주입.
43
+ * 이 경우 `<style>` 태그 노드는 존재하지 않으므로 전체 `shadowRoot`를 교체해도 스타일이 유지됩니다.
44
+ *
45
+ * - **구형 브라우저 (폴리필 환경)**: `<style>` 태그를 shadow DOM 안에 직접 주입.
46
+ * 이 경우 `<style>` 태그 노드를 제거하면 스타일이 사라지므로, 에러 UI로 교체할 때는 `<style>` 태그 노드를 보존해야 합니다.
47
+ *
48
+ * 따라서 `<style>` 태그 노드는 보존하고 나머지 노드를 제거한 뒤
49
+ * 에러 div를 append하는 방식으로 양쪽 환경 모두에서 안전하게 동작합니다.
50
+ *
51
+ * @example
52
+ * ```ts
53
+ * this.replace(html`
54
+ * <span class="error">Something went wrong</span>
55
+ * `);
56
+ * ```
57
+ */
58
+ protected replace(value: unknown, options?: RenderOptions): void;
59
+ }
@@ -0,0 +1,96 @@
1
+ import { LitElement, render } from 'lit';
2
+ import { styles } from './UElement.styles.js';
3
+
4
+ class UElement extends LitElement {
5
+ static {
6
+ /**
7
+ * 기본 스타일을 정의합니다.
8
+ */
9
+ this.styles = styles;
10
+ }
11
+ static {
12
+ /**
13
+ * 현재 컴포넌트에 종속된 컴포넌트들을 정의하는 정적 속성입니다.
14
+ * 이 속성은 컴포넌트가 정의될 때 자동으로 호출되어
15
+ * 종속된 컴포넌트를 등록합니다.
16
+ */
17
+ this.dependencies = {};
18
+ }
19
+ constructor() {
20
+ super();
21
+ Object.entries(this.constructor.dependencies).forEach(([name, component]) => {
22
+ component.define(name);
23
+ });
24
+ }
25
+ /**
26
+ * 커스텀 엘리먼트를 정의합니다.
27
+ * 이미 정의된 엘리먼트는 다시 정의하지 않습니다.
28
+ * @param name - 커스텀 엘리먼트의 이름
29
+ * @param options - 엘리먼트 정의 옵션
30
+ */
31
+ static define(name, options = {}) {
32
+ if (!customElements.get(name)) {
33
+ try {
34
+ customElements.define(name, this, options);
35
+ } catch (error) {
36
+ console.warn(`Failed to register component "${name}":`, error);
37
+ }
38
+ }
39
+ }
40
+ /**
41
+ * 커스텀 이벤트를 디스패치합니다.
42
+ * @param name - 이벤트 이름
43
+ * @param value - 이벤트의 detail에 포함될 데이터
44
+ * @param options - 추가 이벤트 옵션 (예: bubbles, composed 등)
45
+ * @returns 이벤트가 성공적으로 디스패치되었는지 여부
46
+ */
47
+ emit(name, value, options) {
48
+ const event = new CustomEvent(name, {
49
+ bubbles: true,
50
+ composed: true,
51
+ cancelable: false,
52
+ detail: value,
53
+ ...options
54
+ });
55
+ return this.dispatchEvent(event);
56
+ }
57
+ /**
58
+ * 현재 shadow DOM의 렌더 결과를 지정한 템플릿으로 완전히 교체합니다.
59
+ *
60
+ * @param value - Lit 템플릿 결과 또는 기타 렌더링 가능한 값
61
+ * @param options - Lit의 RenderOptions (예: renderBefore 등)
62
+ *
63
+ * @remarks
64
+ * Lit은 브라우저 환경에 따라 스타일을 두 가지 방식으로 주입합니다.
65
+ *
66
+ * - **모던 브라우저**: `shadowRoot.adoptedStyleSheets`에 `CSSStyleSheet` 객체로 주입.
67
+ * 이 경우 `<style>` 태그 노드는 존재하지 않으므로 전체 `shadowRoot`를 교체해도 스타일이 유지됩니다.
68
+ *
69
+ * - **구형 브라우저 (폴리필 환경)**: `<style>` 태그를 shadow DOM 안에 직접 주입.
70
+ * 이 경우 `<style>` 태그 노드를 제거하면 스타일이 사라지므로, 에러 UI로 교체할 때는 `<style>` 태그 노드를 보존해야 합니다.
71
+ *
72
+ * 따라서 `<style>` 태그 노드는 보존하고 나머지 노드를 제거한 뒤
73
+ * 에러 div를 append하는 방식으로 양쪽 환경 모두에서 안전하게 동작합니다.
74
+ *
75
+ * @example
76
+ * ```ts
77
+ * this.replace(html`
78
+ * <span class="error">Something went wrong</span>
79
+ * `);
80
+ * ```
81
+ */
82
+ replace(value, options) {
83
+ if (!this.shadowRoot) return;
84
+ Array.from(this.shadowRoot.childNodes).forEach((node) => {
85
+ if (!(node instanceof HTMLStyleElement)) {
86
+ node.parentNode?.removeChild(node);
87
+ }
88
+ });
89
+ const container = document.createElement("div");
90
+ container.style.display = "contents";
91
+ this.shadowRoot.appendChild(container);
92
+ render(value, container, options);
93
+ }
94
+ }
95
+
96
+ export { UElement };
@@ -1,8 +1,8 @@
1
1
  import { CSSResultGroup, PropertyValues } from 'lit';
2
2
  import { Placement, VirtualElement } from '@floating-ui/dom';
3
- import { BaseElement } from './BaseElement.js';
3
+ import { UElement } from './UElement.js';
4
4
  /**
5
- * FloatingElement는 팝오버, 툴팁 등 화면에 떠 있는 엘리먼트를 구현하기 위한 기본 클래스입니다.
5
+ * UFloatingElement는 팝오버, 툴팁 등 화면에 떠 있는 엘리먼트를 구현하기 위한 기본 클래스입니다.
6
6
  * 이 클래스를 상속하여 커스텀 팝오버 컴포넌트를 만들 수 있습니다.
7
7
  *
8
8
  * 1. for, anchor 속성을 통해 연결될 대상 엘리먼트를 지정할 수 있습니다.
@@ -10,11 +10,11 @@ import { BaseElement } from './BaseElement.js';
10
10
  * 3. show() 및 hide() 메서드를 통해 프로그래밍적으로 표시하거나 숨길 수 있습니다.
11
11
  * 4. strategy, placement, distance, shift 속성을 통해 표시 위치 결정 방식을 설정할 수 있습니다.
12
12
  */
13
- export declare class FloatingElement extends BaseElement {
13
+ export declare class UFloatingElement extends UElement {
14
14
  /** 기본 스타일을 정의합니다. */
15
15
  static styles: CSSResultGroup;
16
16
  /** 종속된 컴포넌트를 정의합니다. */
17
- static dependencies: Record<string, typeof BaseElement>;
17
+ static dependencies: Record<string, typeof UElement>;
18
18
  private rafId;
19
19
  private cleanup;
20
20
  /**
@@ -1,8 +1,8 @@
1
1
  import { state, property } from 'lit/decorators.js';
2
2
  import { autoUpdate, computePosition, offset, shift, flip, autoPlacement } from '@floating-ui/dom';
3
3
  import { getParentElement, querySelectorAllWithin } from '../utilities/elements.js';
4
- import { BaseElement } from './BaseElement.js';
5
- import { styles } from './FloatingElement.styles.js';
4
+ import { UElement } from './UElement.js';
5
+ import { styles } from './UFloatingElement.styles.js';
6
6
 
7
7
  var __defProp = Object.defineProperty;
8
8
  var __decorateClass = (decorators, target, key, kind) => {
@@ -13,7 +13,7 @@ var __decorateClass = (decorators, target, key, kind) => {
13
13
  if (result) __defProp(target, key, result);
14
14
  return result;
15
15
  };
16
- class FloatingElement extends BaseElement {
16
+ class UFloatingElement extends UElement {
17
17
  constructor() {
18
18
  super(...arguments);
19
19
  // 애니메이션 프레임 아이디
@@ -166,30 +166,30 @@ class FloatingElement extends BaseElement {
166
166
  }
167
167
  __decorateClass([
168
168
  state()
169
- ], FloatingElement.prototype, "target");
169
+ ], UFloatingElement.prototype, "target");
170
170
  __decorateClass([
171
171
  state()
172
- ], FloatingElement.prototype, "anchors");
172
+ ], UFloatingElement.prototype, "anchors");
173
173
  __decorateClass([
174
174
  property({ type: String, reflect: true })
175
- ], FloatingElement.prototype, "for");
175
+ ], UFloatingElement.prototype, "for");
176
176
  __decorateClass([
177
177
  property({ type: Boolean, reflect: true })
178
- ], FloatingElement.prototype, "visible");
178
+ ], UFloatingElement.prototype, "visible");
179
179
  __decorateClass([
180
180
  property({ type: String, reflect: true })
181
- ], FloatingElement.prototype, "strategy");
181
+ ], UFloatingElement.prototype, "strategy");
182
182
  __decorateClass([
183
183
  property({ type: String })
184
- ], FloatingElement.prototype, "placement");
184
+ ], UFloatingElement.prototype, "placement");
185
185
  __decorateClass([
186
186
  property({ type: Number })
187
- ], FloatingElement.prototype, "distance");
187
+ ], UFloatingElement.prototype, "distance");
188
188
  __decorateClass([
189
189
  property({ type: Number })
190
- ], FloatingElement.prototype, "offset");
190
+ ], UFloatingElement.prototype, "offset");
191
191
  __decorateClass([
192
192
  property({ type: Boolean })
193
- ], FloatingElement.prototype, "shift");
193
+ ], UFloatingElement.prototype, "shift");
194
194
 
195
- export { FloatingElement };
195
+ export { UFloatingElement };
@@ -0,0 +1,46 @@
1
+ import { UElement } from './UElement.js';
2
+ /**
3
+ * `UJsonElement`는 light DOM 내 `<script type="application/json">` 태그에서
4
+ * JSON 데이터를 읽어 컴포넌트 프로퍼티에 자동으로 매핑하는 기반 클래스입니다.
5
+ *
6
+ * 사용 예시:
7
+ * ```html
8
+ * <my-component>
9
+ * <script type="application/json">{ "items": [1, 2, 3] }</script>
10
+ * </my-component>
11
+ * ```
12
+ *
13
+ * JSON 최상위 키가 컴포넌트의 프로퍼티 이름과 일치하면 자동으로 할당됩니다.
14
+ */
15
+ export declare class UJsonElement extends UElement {
16
+ static styles: import('lit').CSSResultGroup[];
17
+ static dependencies: Record<string, typeof UElement>;
18
+ connectedCallback(): void;
19
+ /**
20
+ * 지정한 태그와 데이터로 커스텀 엘리먼트 HTML 문자열을 생성합니다.
21
+ * 데이터는 `<script type="application/json">` 태그로 주입됩니다.
22
+ * 태그이름이 등록되지 않은 경우 빈 문자열을 반환합니다.
23
+ *
24
+ * @param tag - 커스텀 엘리먼트 태그 이름 (예: `"u-table-block"`)
25
+ * @param json - JSON 데이터 객체 또는 문자열
26
+ * @param attrs - 추가 속성 객체 (선택적, `buildElementHTML` 규칙 적용)
27
+ * @returns 생성된 HTML 문자열
28
+ */
29
+ static buildHTML(tag: string, json: any, attrs?: Record<string, string | boolean | object | null | undefined>): string;
30
+ /**
31
+ * `data` 객체를 컴포넌트 프로퍼티에 할당합니다.
32
+ * `data`가 제공되지 않은 경우 light DOM 내 `<script type="application/json">` 태그에서 JSON 데이터를 읽어 프로퍼티에 자동으로 할당합니다.
33
+ * 오류가 발생할 경우 `error()`를 호출하여 에러 UI로 대체합니다.
34
+ *
35
+ * @param data - JSON 데이터 객체 (선택적)
36
+ */
37
+ protected load(data?: object): Promise<void>;
38
+ /**
39
+ * 오류 발생 시 Lit이 주입한 스타일시트를 보존하고 나머지 렌더링 결과를 에러 UI로 교체합니다.
40
+ * 일반적으로 JSON 파싱 오류의 경우 `data`가 객체가 아닌 문자열이거나 JSON 형식이 잘못된 경우입니다.
41
+ * 이 함수는 Lit 렌더링이 완료된 후에 호출됩니다.
42
+ *
43
+ * @param error - 발생한 오류 객체
44
+ */
45
+ protected error(error: unknown): Promise<void>;
46
+ }
@@ -0,0 +1,93 @@
1
+ import { html } from 'lit';
2
+ import { buildElementHTML } from '../utilities/elements.js';
3
+ import { UElement } from './UElement.js';
4
+ import { UIcon } from './icon/UIcon.component.js';
5
+ import { styles } from './UJsonElement.styles.js';
6
+
7
+ class UJsonElement extends UElement {
8
+ static {
9
+ this.styles = [super.styles, styles];
10
+ }
11
+ static {
12
+ this.dependencies = {
13
+ "u-icon": UIcon
14
+ };
15
+ }
16
+ connectedCallback() {
17
+ super.connectedCallback();
18
+ this.load();
19
+ }
20
+ /**
21
+ * 지정한 태그와 데이터로 커스텀 엘리먼트 HTML 문자열을 생성합니다.
22
+ * 데이터는 `<script type="application/json">` 태그로 주입됩니다.
23
+ * 태그이름이 등록되지 않은 경우 빈 문자열을 반환합니다.
24
+ *
25
+ * @param tag - 커스텀 엘리먼트 태그 이름 (예: `"u-table-block"`)
26
+ * @param json - JSON 데이터 객체 또는 문자열
27
+ * @param attrs - 추가 속성 객체 (선택적, `buildElementHTML` 규칙 적용)
28
+ * @returns 생성된 HTML 문자열
29
+ */
30
+ static buildHTML(tag, json, attrs = {}) {
31
+ if (!customElements.get(tag)) return "";
32
+ const jsonStr = typeof json === "string" ? json : JSON.stringify(json);
33
+ const safe = jsonStr.replace(/&/g, "\\u0026").replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
34
+ const content = `<script type="application/json">${safe}<\/script>`;
35
+ return buildElementHTML(tag, attrs, content);
36
+ }
37
+ /**
38
+ * `data` 객체를 컴포넌트 프로퍼티에 할당합니다.
39
+ * `data`가 제공되지 않은 경우 light DOM 내 `<script type="application/json">` 태그에서 JSON 데이터를 읽어 프로퍼티에 자동으로 할당합니다.
40
+ * 오류가 발생할 경우 `error()`를 호출하여 에러 UI로 대체합니다.
41
+ *
42
+ * @param data - JSON 데이터 객체 (선택적)
43
+ */
44
+ async load(data) {
45
+ try {
46
+ if (!data) {
47
+ const script = this.querySelector('script[type="application/json"]');
48
+ data = JSON.parse(script?.textContent || "{}");
49
+ }
50
+ if (typeof data !== "object" || data === null || Array.isArray(data)) {
51
+ throw new Error("Invalid JSON data: expected an object at the top level");
52
+ }
53
+ Object.assign(this, data);
54
+ } catch (error) {
55
+ await this.error(error);
56
+ }
57
+ }
58
+ /**
59
+ * 오류 발생 시 Lit이 주입한 스타일시트를 보존하고 나머지 렌더링 결과를 에러 UI로 교체합니다.
60
+ * 일반적으로 JSON 파싱 오류의 경우 `data`가 객체가 아닌 문자열이거나 JSON 형식이 잘못된 경우입니다.
61
+ * 이 함수는 Lit 렌더링이 완료된 후에 호출됩니다.
62
+ *
63
+ * @param error - 발생한 오류 객체
64
+ */
65
+ async error(error) {
66
+ await this.updateComplete;
67
+ if (!this.shadowRoot) return;
68
+ const tag = this.tagName.toLowerCase();
69
+ const type = error instanceof Error ? error.constructor.name : "UnknownError";
70
+ const message = error instanceof Error ? error.message : String(error);
71
+ this.replace(html`
72
+ <div class="error-container">
73
+ <div class="error-header">
74
+ <u-icon class="error-icon" lib="internal" name="exclamation-triangle-fill"></u-icon>
75
+ <span class="error-title">Render Error</span>
76
+ <code class="error-tag">&lt;${tag}&gt;</code>
77
+ </div>
78
+ <div class="error-body">
79
+ <div class="error-row">
80
+ <span class="error-label">Type</span>
81
+ <code class="error-type">${type}</code>
82
+ </div>
83
+ <div class="error-row">
84
+ <span class="error-label">Message</span>
85
+ <pre class="error-message">${message}</pre>
86
+ </div>
87
+ </div>
88
+ </div>
89
+ `);
90
+ }
91
+ }
92
+
93
+ export { UJsonElement };
@@ -0,0 +1,95 @@
1
+ import { css } from 'lit';
2
+
3
+ const styles = css`
4
+ .error-container {
5
+ display: flex;
6
+ flex-direction: column;
7
+ border: 1px solid var(--u-red-200);
8
+ border-radius: 10px;
9
+ background: var(--u-red-0);
10
+ color: var(--u-red-700);
11
+ overflow: hidden;
12
+ font-size: 0.875em;
13
+ line-height: 1.5;
14
+ }
15
+
16
+ .error-header {
17
+ display: flex;
18
+ flex-direction: row;
19
+ align-items: center;
20
+ gap: 0.5em;
21
+ padding: 0.55em 0.9em;
22
+ background: var(--u-red-50);
23
+ border-bottom: 1px solid var(--u-red-200);
24
+ }
25
+
26
+ .error-icon {
27
+ font-size: 0.95em;
28
+ color: var(--u-red-500);
29
+ flex-shrink: 0;
30
+ }
31
+
32
+ .error-title {
33
+ font-weight: 700;
34
+ letter-spacing: 0.01em;
35
+ flex: 1;
36
+ }
37
+
38
+ .error-tag {
39
+ font-family: var(--u-font-mono);
40
+ font-size: 0.85em;
41
+ padding: 0.1em 0.45em;
42
+ color: var(--u-red-600);
43
+ border: 1px solid var(--u-red-200);
44
+ border-radius: 4px;
45
+ background: var(--u-red-100);
46
+ }
47
+
48
+ .error-body {
49
+ display: flex;
50
+ flex-direction: column;
51
+ padding: 0.6em 0.9em;
52
+ gap: 0.45em;
53
+ }
54
+
55
+ .error-row {
56
+ display: flex;
57
+ flex-direction: row;
58
+ align-items: baseline;
59
+ gap: 0.6em;
60
+ min-height: 1.6em;
61
+ }
62
+
63
+ .error-label {
64
+ flex-shrink: 0;
65
+ width: 5em;
66
+ font-size: 0.78em;
67
+ font-weight: 700;
68
+ text-transform: uppercase;
69
+ letter-spacing: 0.06em;
70
+ opacity: 0.55;
71
+ padding-top: 0.15em;
72
+ }
73
+
74
+ .error-type {
75
+ font-family: var(--u-font-mono);
76
+ font-size: 0.85em;
77
+ padding: 0.1em 0.4em;
78
+ color: var(--u-red-700);
79
+ background: var(--u-red-100);
80
+ border-radius: 4px;
81
+ }
82
+
83
+ .error-message {
84
+ margin: 0;
85
+ flex: 1;
86
+ white-space: pre-wrap;
87
+ word-break: break-all;
88
+ font-family: var(--u-font-mono);
89
+ font-size: 0.9em;
90
+ opacity: 0.85;
91
+ line-height: 1.55;
92
+ }
93
+ `;
94
+
95
+ export { styles };
@@ -1,7 +1,7 @@
1
1
  import { CSSResultGroup, PropertyValues } from 'lit';
2
- import { BaseElement } from './BaseElement.js';
2
+ import { UElement } from './UElement.js';
3
3
  /**
4
- * ModalElement는 다이얼로그, 드로어 등 화면에 오버레이로 표시되는 엘리먼트를 구현하기 위한 기본 클래스입니다.
4
+ * UModalElement는 다이얼로그, 드로어 등 화면에 오버레이로 표시되는 엘리먼트를 구현하기 위한 기본 클래스입니다.
5
5
  * 이 클래스를 상속하여 커스텀 모달 컴포넌트를 만들 수 있습니다.
6
6
  *
7
7
  * 1. open 속성을 통해 엘리먼트의 표시 여부를 제어할 수 있습니다.
@@ -9,11 +9,11 @@ import { BaseElement } from './BaseElement.js';
9
9
  * 3. closable 속성을 통해 이벤트에 의한 닫기 허용 여부를 설정할 수 있습니다.
10
10
  * 4. show() 및 hide() 메서드를 통해 프로그래밍적으로 표시하거나 숨길 수 있습니다.
11
11
  */
12
- export declare abstract class ModalElement extends BaseElement {
12
+ export declare abstract class UModalElement extends UElement {
13
13
  /** 기본 스타일을 정의합니다. */
14
14
  static styles: CSSResultGroup;
15
15
  /** 종속된 컴포넌트를 정의합니다. */
16
- static dependencies: Record<string, typeof BaseElement>;
16
+ static dependencies: Record<string, typeof UElement>;
17
17
  /**
18
18
  * 현재 엘리먼트의 열림/닫힘 상태입니다.
19
19
  *
@@ -1,6 +1,6 @@
1
1
  import { property } from 'lit/decorators.js';
2
- import { BaseElement } from './BaseElement.js';
3
- import { styles } from './ModalElement.styles.js';
2
+ import { UElement } from './UElement.js';
3
+ import { styles } from './UModalElement.styles.js';
4
4
 
5
5
  var __defProp = Object.defineProperty;
6
6
  var __decorateClass = (decorators, target, key, kind) => {
@@ -11,7 +11,7 @@ var __decorateClass = (decorators, target, key, kind) => {
11
11
  if (result) __defProp(target, key, result);
12
12
  return result;
13
13
  };
14
- class ModalElement extends BaseElement {
14
+ class UModalElement extends UElement {
15
15
  constructor() {
16
16
  super(...arguments);
17
17
  this.open = false;
@@ -130,15 +130,15 @@ class ModalElement extends BaseElement {
130
130
  }
131
131
  __decorateClass([
132
132
  property({ type: Boolean, reflect: true })
133
- ], ModalElement.prototype, "open");
133
+ ], UModalElement.prototype, "open");
134
134
  __decorateClass([
135
135
  property({ type: String, reflect: true })
136
- ], ModalElement.prototype, "strategy");
136
+ ], UModalElement.prototype, "strategy");
137
137
  __decorateClass([
138
138
  property({ type: Boolean, reflect: true })
139
- ], ModalElement.prototype, "modal");
139
+ ], UModalElement.prototype, "modal");
140
140
  __decorateClass([
141
141
  property({ type: Boolean, reflect: true })
142
- ], ModalElement.prototype, "closable");
142
+ ], UModalElement.prototype, "closable");
143
143
 
144
- export { ModalElement };
144
+ export { UModalElement };
@@ -0,0 +1 @@
1
+ export declare const styles: import('lit').CSSResult;
@@ -1,13 +1,13 @@
1
1
  import { PropertyValues } from 'lit';
2
- import { BaseElement } from '../BaseElement.js';
2
+ import { UElement } from '../UElement.js';
3
3
  export type AlertType = "error" | "warning" | "info" | "success" | "notice";
4
4
  /**
5
5
  * 사용자에게 메시지를 표시하는 Alert 컴포넌트입니다.
6
6
  * 자동 닫힘 타이머, 접기/펼치기 기능 등을 제공합니다.
7
7
  */
8
- export declare class UAlert extends BaseElement {
8
+ export declare class UAlert extends UElement {
9
9
  static styles: import('lit').CSSResultGroup[];
10
- static dependencies: Record<string, typeof BaseElement>;
10
+ static dependencies: Record<string, typeof UElement>;
11
11
  private timeoutId?;
12
12
  /** 표시 여부 */
13
13
  open: boolean;
@@ -1,6 +1,6 @@
1
1
  import { html } from 'lit';
2
2
  import { property } from 'lit/decorators.js';
3
- import { BaseElement } from '../BaseElement.js';
3
+ import { UElement } from '../UElement.js';
4
4
  import { UIcon } from '../icon/UIcon.component.js';
5
5
  import { styles } from './UAlert.styles.js';
6
6
  import { unsafeHTML } from 'lit/directives/unsafe-html.js';
@@ -14,7 +14,7 @@ var __decorateClass = (decorators, target, key, kind) => {
14
14
  if (result) __defProp(target, key, result);
15
15
  return result;
16
16
  };
17
- class UAlert extends BaseElement {
17
+ class UAlert extends UElement {
18
18
  constructor() {
19
19
  super(...arguments);
20
20
  this.open = false;
@@ -1,4 +1,4 @@
1
- import { BaseElement } from '../BaseElement.js';
1
+ import { UElement } from '../UElement.js';
2
2
  export type ButtonVariant = "default" | "borderless" | "link";
3
3
  /**
4
4
  * Button 컴포넌트는 클릭 가능한 버튼을 나타내며, 로딩 상태와 툴팁 기능을 지원합니다.
@@ -6,9 +6,9 @@ export type ButtonVariant = "default" | "borderless" | "link";
6
6
  * @slot prefix - 버튼의 접두사로 표시할 콘텐츠를 삽입합니다.
7
7
  * @slot suffix - 버튼의 접미사로 표시할 콘텐츠를 삽입합니다.
8
8
  */
9
- export declare class UButton extends BaseElement {
9
+ export declare class UButton extends UElement {
10
10
  static styles: import('lit').CSSResultGroup[];
11
- static dependencies: Record<string, typeof BaseElement>;
11
+ static dependencies: Record<string, typeof UElement>;
12
12
  /** 버튼의 스타일 변형을 설정합니다. */
13
13
  variant: ButtonVariant;
14
14
  /** 버튼이 비활성화 상태인지 여부를 설정합니다. 비활성화된 버튼은 클릭할 수 없습니다. */