@iyulab/components 0.2.3 → 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.
- package/CHANGELOG.md +33 -0
- package/dist/assets/icons/arrow-down-up.svg.js +3 -0
- package/dist/assets/icons/code-slash.svg.js +3 -0
- package/dist/assets/icons/download.svg.js +3 -0
- package/dist/assets/icons/sort-alpha-down.svg.js +3 -0
- package/dist/assets/icons/sort-alpha-up.svg.js +3 -0
- package/dist/components/UElement.d.ts +59 -0
- package/dist/components/UElement.js +96 -0
- package/dist/components/{FloatingElement.d.ts → UFloatingElement.d.ts} +4 -4
- package/dist/components/{FloatingElement.js → UFloatingElement.js} +13 -13
- package/dist/components/UJsonElement.d.ts +46 -0
- package/dist/components/UJsonElement.js +93 -0
- package/dist/components/UJsonElement.styles.js +95 -0
- package/dist/components/{ModalElement.d.ts → UModalElement.d.ts} +4 -4
- package/dist/components/{ModalElement.js → UModalElement.js} +8 -8
- package/dist/components/UModalElement.styles.d.ts +1 -0
- package/dist/components/alert/UAlert.component.d.ts +3 -3
- package/dist/components/alert/UAlert.component.js +2 -2
- package/dist/components/button/UButton.component.d.ts +3 -3
- package/dist/components/button/UButton.component.js +2 -2
- package/dist/components/card/UCard.component.d.ts +21 -0
- package/dist/components/card/UCard.component.js +66 -0
- package/dist/components/card/UCard.d.ts +7 -0
- package/dist/components/card/UCard.js +5 -0
- package/dist/components/card/UCard.styles.d.ts +1 -0
- package/dist/components/card/UCard.styles.js +76 -0
- package/dist/components/carousel/UCarousel.component.d.ts +78 -0
- package/dist/components/carousel/UCarousel.component.js +264 -0
- package/dist/components/carousel/UCarousel.d.ts +7 -0
- package/dist/components/carousel/UCarousel.js +5 -0
- package/dist/components/carousel/UCarousel.styles.d.ts +1 -0
- package/dist/components/carousel/UCarousel.styles.js +112 -0
- package/dist/components/dialog/UDialog.component.d.ts +4 -4
- package/dist/components/dialog/UDialog.component.js +2 -2
- package/dist/components/divider/UDivider.component.d.ts +3 -3
- package/dist/components/divider/UDivider.component.js +2 -2
- package/dist/components/drawer/UDrawer.component.d.ts +4 -4
- package/dist/components/drawer/UDrawer.component.js +2 -2
- package/dist/components/form/UForm.component.d.ts +3 -3
- package/dist/components/form/UForm.component.js +2 -2
- package/dist/components/icon/UIcon.component.d.ts +3 -3
- package/dist/components/icon/UIcon.component.js +2 -2
- package/dist/components/input/UInput.component.d.ts +3 -3
- package/dist/components/input/UInput.component.js +2 -2
- package/dist/components/menu/UMenu.component.d.ts +4 -4
- package/dist/components/menu/UMenu.component.js +2 -2
- package/dist/components/menu-item/UMenuItem.component.d.ts +3 -3
- package/dist/components/menu-item/UMenuItem.component.js +2 -2
- package/dist/components/progress-bar/UProgressBar.component.d.ts +3 -3
- package/dist/components/progress-bar/UProgressBar.component.js +2 -2
- package/dist/components/progress-ring/UProgressRing.component.d.ts +3 -3
- package/dist/components/progress-ring/UProgressRing.component.js +2 -2
- package/dist/components/skeleton/USkeleton.component.d.ts +3 -3
- package/dist/components/skeleton/USkeleton.component.js +2 -2
- package/dist/components/spinner/USpinner.component.d.ts +3 -3
- package/dist/components/spinner/USpinner.component.js +2 -2
- package/dist/components/split-panel/USplitPanel.component.d.ts +3 -3
- package/dist/components/split-panel/USplitPanel.component.js +2 -2
- package/dist/components/tag/UTag.component.d.ts +3 -3
- package/dist/components/tag/UTag.component.js +2 -2
- package/dist/components/tooltip/UTooltip.component.d.ts +4 -4
- package/dist/components/tooltip/UTooltip.component.js +2 -2
- package/dist/components/tree/UTree.component.d.ts +3 -3
- package/dist/components/tree/UTree.component.js +2 -2
- package/dist/components/tree-item/UTreeItem.component.d.ts +3 -3
- package/dist/components/tree-item/UTreeItem.component.js +2 -2
- package/dist/index.d.ts +8 -0
- package/dist/index.js +10 -0
- package/dist/react-components/UCard.d.ts +8 -0
- package/dist/react-components/UCard.js +10 -0
- package/dist/react-components/UCarousel.d.ts +8 -0
- package/dist/react-components/UCarousel.js +10 -0
- package/dist/react-components/index.d.ts +2 -0
- package/dist/react-components/index.js +2 -0
- package/dist/utilities/IconRegistry.js +16 -1
- package/dist/utilities/elements.d.ts +23 -0
- package/dist/utilities/elements.js +23 -1
- package/dist/utilities/sanitizers.d.ts +35 -0
- package/dist/utilities/sanitizers.js +43 -0
- package/package.json +21 -11
- package/dist/components/BaseElement.d.ts +0 -33
- package/dist/components/BaseElement.js +0 -59
- /package/dist/components/{BaseElement.styles.d.ts → UElement.styles.d.ts} +0 -0
- /package/dist/components/{BaseElement.styles.js → UElement.styles.js} +0 -0
- /package/dist/components/{FloatingElement.styles.d.ts → UFloatingElement.styles.d.ts} +0 -0
- /package/dist/components/{FloatingElement.styles.js → UFloatingElement.styles.js} +0 -0
- /package/dist/components/{ModalElement.styles.d.ts → UJsonElement.styles.d.ts} +0 -0
- /package/dist/components/{ModalElement.styles.js → UModalElement.styles.js} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,38 @@
|
|
|
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
|
+
|
|
26
|
+
## 0.3.0 (2026-02-26)
|
|
27
|
+
|
|
28
|
+
### Features
|
|
29
|
+
- **UCard**: Added card layout component with `header`, `footer`, `media` slots
|
|
30
|
+
- **UCarousel**: Added carousel component with autoplay, drag, navigation, multi-slide view
|
|
31
|
+
|
|
32
|
+
### Improvements
|
|
33
|
+
- Moved `@lit/react`, `react` to optional peerDependencies
|
|
34
|
+
- Updated devDependencies
|
|
35
|
+
|
|
3
36
|
## 0.2.3 (2026-02-09)
|
|
4
37
|
|
|
5
38
|
### 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 {
|
|
3
|
+
import { UElement } from './UElement.js';
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
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
|
|
13
|
+
export declare class UFloatingElement extends UElement {
|
|
14
14
|
/** 기본 스타일을 정의합니다. */
|
|
15
15
|
static styles: CSSResultGroup;
|
|
16
16
|
/** 종속된 컴포넌트를 정의합니다. */
|
|
17
|
-
static dependencies: Record<string, typeof
|
|
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 {
|
|
5
|
-
import { styles } from './
|
|
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
|
|
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
|
-
],
|
|
169
|
+
], UFloatingElement.prototype, "target");
|
|
170
170
|
__decorateClass([
|
|
171
171
|
state()
|
|
172
|
-
],
|
|
172
|
+
], UFloatingElement.prototype, "anchors");
|
|
173
173
|
__decorateClass([
|
|
174
174
|
property({ type: String, reflect: true })
|
|
175
|
-
],
|
|
175
|
+
], UFloatingElement.prototype, "for");
|
|
176
176
|
__decorateClass([
|
|
177
177
|
property({ type: Boolean, reflect: true })
|
|
178
|
-
],
|
|
178
|
+
], UFloatingElement.prototype, "visible");
|
|
179
179
|
__decorateClass([
|
|
180
180
|
property({ type: String, reflect: true })
|
|
181
|
-
],
|
|
181
|
+
], UFloatingElement.prototype, "strategy");
|
|
182
182
|
__decorateClass([
|
|
183
183
|
property({ type: String })
|
|
184
|
-
],
|
|
184
|
+
], UFloatingElement.prototype, "placement");
|
|
185
185
|
__decorateClass([
|
|
186
186
|
property({ type: Number })
|
|
187
|
-
],
|
|
187
|
+
], UFloatingElement.prototype, "distance");
|
|
188
188
|
__decorateClass([
|
|
189
189
|
property({ type: Number })
|
|
190
|
-
],
|
|
190
|
+
], UFloatingElement.prototype, "offset");
|
|
191
191
|
__decorateClass([
|
|
192
192
|
property({ type: Boolean })
|
|
193
|
-
],
|
|
193
|
+
], UFloatingElement.prototype, "shift");
|
|
194
194
|
|
|
195
|
-
export {
|
|
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"><${tag}></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 {
|
|
2
|
+
import { UElement } from './UElement.js';
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
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
|
|
12
|
+
export declare abstract class UModalElement extends UElement {
|
|
13
13
|
/** 기본 스타일을 정의합니다. */
|
|
14
14
|
static styles: CSSResultGroup;
|
|
15
15
|
/** 종속된 컴포넌트를 정의합니다. */
|
|
16
|
-
static dependencies: Record<string, typeof
|
|
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 {
|
|
3
|
-
import { styles } from './
|
|
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
|
|
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
|
-
],
|
|
133
|
+
], UModalElement.prototype, "open");
|
|
134
134
|
__decorateClass([
|
|
135
135
|
property({ type: String, reflect: true })
|
|
136
|
-
],
|
|
136
|
+
], UModalElement.prototype, "strategy");
|
|
137
137
|
__decorateClass([
|
|
138
138
|
property({ type: Boolean, reflect: true })
|
|
139
|
-
],
|
|
139
|
+
], UModalElement.prototype, "modal");
|
|
140
140
|
__decorateClass([
|
|
141
141
|
property({ type: Boolean, reflect: true })
|
|
142
|
-
],
|
|
142
|
+
], UModalElement.prototype, "closable");
|
|
143
143
|
|
|
144
|
-
export {
|
|
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 {
|
|
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
|
|
8
|
+
export declare class UAlert extends UElement {
|
|
9
9
|
static styles: import('lit').CSSResultGroup[];
|
|
10
|
-
static dependencies: Record<string, typeof
|
|
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 {
|
|
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
|
|
17
|
+
class UAlert extends UElement {
|
|
18
18
|
constructor() {
|
|
19
19
|
super(...arguments);
|
|
20
20
|
this.open = false;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
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
|
|
9
|
+
export declare class UButton extends UElement {
|
|
10
10
|
static styles: import('lit').CSSResultGroup[];
|
|
11
|
-
static dependencies: Record<string, typeof
|
|
11
|
+
static dependencies: Record<string, typeof UElement>;
|
|
12
12
|
/** 버튼의 스타일 변형을 설정합니다. */
|
|
13
13
|
variant: ButtonVariant;
|
|
14
14
|
/** 버튼이 비활성화 상태인지 여부를 설정합니다. 비활성화된 버튼은 클릭할 수 없습니다. */
|