@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.
Files changed (88) hide show
  1. package/CHANGELOG.md +33 -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 +21 -0
  22. package/dist/components/card/UCard.component.js +66 -0
  23. package/dist/components/card/UCard.d.ts +7 -0
  24. package/dist/components/card/UCard.js +5 -0
  25. package/dist/components/card/UCard.styles.d.ts +1 -0
  26. package/dist/components/card/UCard.styles.js +76 -0
  27. package/dist/components/carousel/UCarousel.component.d.ts +78 -0
  28. package/dist/components/carousel/UCarousel.component.js +264 -0
  29. package/dist/components/carousel/UCarousel.d.ts +7 -0
  30. package/dist/components/carousel/UCarousel.js +5 -0
  31. package/dist/components/carousel/UCarousel.styles.d.ts +1 -0
  32. package/dist/components/carousel/UCarousel.styles.js +112 -0
  33. package/dist/components/dialog/UDialog.component.d.ts +4 -4
  34. package/dist/components/dialog/UDialog.component.js +2 -2
  35. package/dist/components/divider/UDivider.component.d.ts +3 -3
  36. package/dist/components/divider/UDivider.component.js +2 -2
  37. package/dist/components/drawer/UDrawer.component.d.ts +4 -4
  38. package/dist/components/drawer/UDrawer.component.js +2 -2
  39. package/dist/components/form/UForm.component.d.ts +3 -3
  40. package/dist/components/form/UForm.component.js +2 -2
  41. package/dist/components/icon/UIcon.component.d.ts +3 -3
  42. package/dist/components/icon/UIcon.component.js +2 -2
  43. package/dist/components/input/UInput.component.d.ts +3 -3
  44. package/dist/components/input/UInput.component.js +2 -2
  45. package/dist/components/menu/UMenu.component.d.ts +4 -4
  46. package/dist/components/menu/UMenu.component.js +2 -2
  47. package/dist/components/menu-item/UMenuItem.component.d.ts +3 -3
  48. package/dist/components/menu-item/UMenuItem.component.js +2 -2
  49. package/dist/components/progress-bar/UProgressBar.component.d.ts +3 -3
  50. package/dist/components/progress-bar/UProgressBar.component.js +2 -2
  51. package/dist/components/progress-ring/UProgressRing.component.d.ts +3 -3
  52. package/dist/components/progress-ring/UProgressRing.component.js +2 -2
  53. package/dist/components/skeleton/USkeleton.component.d.ts +3 -3
  54. package/dist/components/skeleton/USkeleton.component.js +2 -2
  55. package/dist/components/spinner/USpinner.component.d.ts +3 -3
  56. package/dist/components/spinner/USpinner.component.js +2 -2
  57. package/dist/components/split-panel/USplitPanel.component.d.ts +3 -3
  58. package/dist/components/split-panel/USplitPanel.component.js +2 -2
  59. package/dist/components/tag/UTag.component.d.ts +3 -3
  60. package/dist/components/tag/UTag.component.js +2 -2
  61. package/dist/components/tooltip/UTooltip.component.d.ts +4 -4
  62. package/dist/components/tooltip/UTooltip.component.js +2 -2
  63. package/dist/components/tree/UTree.component.d.ts +3 -3
  64. package/dist/components/tree/UTree.component.js +2 -2
  65. package/dist/components/tree-item/UTreeItem.component.d.ts +3 -3
  66. package/dist/components/tree-item/UTreeItem.component.js +2 -2
  67. package/dist/index.d.ts +8 -0
  68. package/dist/index.js +10 -0
  69. package/dist/react-components/UCard.d.ts +8 -0
  70. package/dist/react-components/UCard.js +10 -0
  71. package/dist/react-components/UCarousel.d.ts +8 -0
  72. package/dist/react-components/UCarousel.js +10 -0
  73. package/dist/react-components/index.d.ts +2 -0
  74. package/dist/react-components/index.js +2 -0
  75. package/dist/utilities/IconRegistry.js +16 -1
  76. package/dist/utilities/elements.d.ts +23 -0
  77. package/dist/utilities/elements.js +23 -1
  78. package/dist/utilities/sanitizers.d.ts +35 -0
  79. package/dist/utilities/sanitizers.js +43 -0
  80. package/package.json +21 -11
  81. package/dist/components/BaseElement.d.ts +0 -33
  82. package/dist/components/BaseElement.js +0 -59
  83. /package/dist/components/{BaseElement.styles.d.ts → UElement.styles.d.ts} +0 -0
  84. /package/dist/components/{BaseElement.styles.js → UElement.styles.js} +0 -0
  85. /package/dist/components/{FloatingElement.styles.d.ts → UFloatingElement.styles.d.ts} +0 -0
  86. /package/dist/components/{FloatingElement.styles.js → UFloatingElement.styles.js} +0 -0
  87. /package/dist/components/{ModalElement.styles.d.ts → UJsonElement.styles.d.ts} +0 -0
  88. /package/dist/components/{ModalElement.styles.js → UModalElement.styles.js} +0 -0
@@ -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 { USpinner } from '../spinner/USpinner.component.js';
5
5
  import { styles } from './UButton.styles.js';
6
6
 
@@ -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 UButton extends BaseElement {
16
+ class UButton extends UElement {
17
17
  constructor() {
18
18
  super(...arguments);
19
19
  this.variant = "default";
@@ -0,0 +1,21 @@
1
+ import { UElement } from '../UElement.js';
2
+ /**
3
+ * Card 컴포넌트는 콘텐츠를 카드 형태로 표시합니다.
4
+ * @slot - 카드의 메인 콘텐츠를 삽입합니다.
5
+ * @slot header - 카드 상단의 헤더 영역에 표시할 콘텐츠를 삽입합니다.
6
+ * @slot footer - 카드 하단의 푸터 영역에 표시할 콘텐츠를 삽입합니다.
7
+ * @slot media - 카드의 미디어 영역에 표시할 이미지, 비디오 등을 삽입합니다.
8
+ */
9
+ export declare class UCard extends UElement {
10
+ static styles: import('lit').CSSResultGroup[];
11
+ /** 카드의 그림자 효과를 제거할지 여부를 설정합니다. */
12
+ shadowless: boolean;
13
+ /** 카드의 경계선을 제거할지 여부를 설정합니다. */
14
+ borderless: boolean;
15
+ /** 카드에 호버 효과를 적용할지 여부를 설정합니다. */
16
+ hoverable: boolean;
17
+ /** 카드의 레이아웃 방향을 설정합니다. 'vertical'(세로) 또는 'horizontal'(가로) */
18
+ orientation: 'vertical' | 'horizontal';
19
+ render(): import('lit-html').TemplateResult<1>;
20
+ private handleSlotChange;
21
+ }
@@ -0,0 +1,66 @@
1
+ import { html } from 'lit';
2
+ import { property } from 'lit/decorators.js';
3
+ import { UElement } from '../UElement.js';
4
+ import { styles } from './UCard.styles.js';
5
+
6
+ var __defProp = Object.defineProperty;
7
+ var __decorateClass = (decorators, target, key, kind) => {
8
+ var result = void 0 ;
9
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
10
+ if (decorator = decorators[i])
11
+ result = (decorator(target, key, result) ) || result;
12
+ if (result) __defProp(target, key, result);
13
+ return result;
14
+ };
15
+ class UCard extends UElement {
16
+ constructor() {
17
+ super(...arguments);
18
+ this.shadowless = false;
19
+ this.borderless = false;
20
+ this.hoverable = false;
21
+ this.orientation = "vertical";
22
+ }
23
+ static {
24
+ this.styles = [super.styles, styles];
25
+ }
26
+ render() {
27
+ return html`
28
+ <div part="media" class="media">
29
+ <slot name="media" @slotchange=${this.handleSlotChange}></slot>
30
+ </div>
31
+ <div class="content">
32
+ <header part="header" class="header">
33
+ <slot name="header" @slotchange=${this.handleSlotChange}></slot>
34
+ </header>
35
+ <div part="body" class="body">
36
+ <slot @slotchange=${this.handleSlotChange}></slot>
37
+ </div>
38
+ <footer part="footer" class="footer">
39
+ <slot name="footer" @slotchange=${this.handleSlotChange}></slot>
40
+ </footer>
41
+ </div>
42
+ `;
43
+ }
44
+ handleSlotChange(e) {
45
+ const slot = e.target;
46
+ const container = slot.parentElement;
47
+ const hasContent = slot.assignedNodes({ flatten: true }).length > 0;
48
+ if (container) {
49
+ container.classList.toggle("has-content", hasContent);
50
+ }
51
+ }
52
+ }
53
+ __decorateClass([
54
+ property({ type: Boolean, reflect: true })
55
+ ], UCard.prototype, "shadowless");
56
+ __decorateClass([
57
+ property({ type: Boolean, reflect: true })
58
+ ], UCard.prototype, "borderless");
59
+ __decorateClass([
60
+ property({ type: Boolean, reflect: true })
61
+ ], UCard.prototype, "hoverable");
62
+ __decorateClass([
63
+ property({ type: String, reflect: true })
64
+ ], UCard.prototype, "orientation");
65
+
66
+ export { UCard };
@@ -0,0 +1,7 @@
1
+ import { UCard } from './UCard.component.js';
2
+ declare global {
3
+ interface HTMLElementTagNameMap {
4
+ "u-card": UCard;
5
+ }
6
+ }
7
+ export { UCard };
@@ -0,0 +1,5 @@
1
+ import { UCard } from './UCard.component.js';
2
+
3
+ UCard.define("u-card");
4
+
5
+ export { UCard };
@@ -0,0 +1 @@
1
+ export declare const styles: import('lit').CSSResult;
@@ -0,0 +1,76 @@
1
+ import { css } from 'lit';
2
+
3
+ const styles = css`
4
+ :host {
5
+ display: flex;
6
+ flex-direction: column;
7
+ background-color: var(--u-panel-bg-color);
8
+ border-radius: 8px;
9
+ overflow: hidden;
10
+ border: 1px solid var(--u-border-color);
11
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
12
+ }
13
+ :host([borderless]) {
14
+ border: none;
15
+ }
16
+ :host([shadowless]) {
17
+ box-shadow: none;
18
+ }
19
+ :host([hoverable]) {
20
+ cursor: pointer;
21
+ transition: all 0.2s ease;
22
+ }
23
+ :host([hoverable]:hover) {
24
+ transform: translateY(-2px);
25
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
26
+ }
27
+ :host([orientation="horizontal"]) {
28
+ flex-direction: row;
29
+ }
30
+
31
+ .media {
32
+ display: none;
33
+ flex-shrink: 0;
34
+ overflow: hidden;
35
+ }
36
+ .media.has-content {
37
+ display: block;
38
+ }
39
+
40
+ .content {
41
+ display: flex;
42
+ flex-direction: column;
43
+ flex: 1;
44
+ min-width: 0;
45
+ }
46
+
47
+ .header {
48
+ display: none;
49
+ padding: 16px;
50
+ border-bottom: 1px solid var(--u-border-color);
51
+ }
52
+ .header.has-content {
53
+ display: block;
54
+ }
55
+
56
+ .body {
57
+ display: none;
58
+ flex: 1;
59
+ padding: 16px;
60
+ }
61
+ .body.has-content {
62
+ display: block;
63
+ }
64
+
65
+ .footer {
66
+ display: none;
67
+ padding: 16px;
68
+ border-top: 1px solid var(--u-border-color);
69
+ }
70
+ .footer.has-content {
71
+ display: block;
72
+ }
73
+
74
+ `;
75
+
76
+ export { styles };
@@ -0,0 +1,78 @@
1
+ import { PropertyValues } from 'lit';
2
+ import { UElement } from '../UElement.js';
3
+ /**
4
+ * Carousel 컴포넌트는 여러 슬라이드를 회전하며 표시합니다.
5
+ *
6
+ * @slot - 슬라이드로 표시할 콘텐츠. 각 자식 요소가 하나의 슬라이드.
7
+ * @event u-change - 슬라이드 변경 시. detail: { index: number }
8
+ *
9
+ * @csspart slides - 슬라이드 컨테이너 (aspect-ratio 등 외부 스타일링)
10
+ * @csspart prev-button - 이전 버튼
11
+ * @csspart next-button - 다음 버튼
12
+ * @csspart indicator - 인디케이터 컨테이너
13
+ * @csspart dot - 인디케이터 도트
14
+ */
15
+ export declare class UCarousel extends UElement {
16
+ static styles: import('lit').CSSResultGroup[];
17
+ static dependencies: Record<string, typeof UElement>;
18
+ /** 자동 재생 활성화 */
19
+ autoplay: boolean;
20
+ /** 자동 재생 간격 (ms) */
21
+ autoplayInterval: number;
22
+ /** 처음/끝에서 순환 이동 */
23
+ loop: boolean;
24
+ /** 이전/다음 네비게이션 버튼 표시 */
25
+ navigation: boolean;
26
+ /** 페이지 인디케이터 표시 */
27
+ pagination: boolean;
28
+ /** 드래그로 슬라이드 전환 */
29
+ draggable: boolean;
30
+ /** 한 화면에 표시할 슬라이드 수 */
31
+ slidesPerView: number;
32
+ /** 한 번에 이동할 슬라이드 수 */
33
+ slidesPerMove: number;
34
+ /** 슬라이드 간 간격 (px) */
35
+ gap: number;
36
+ /** 현재 활성 슬라이드 인덱스 */
37
+ index: number;
38
+ /** 전체 슬라이드 수 */
39
+ private slideCount;
40
+ /** 드래그 중인지 여부 */
41
+ private isDragging;
42
+ /** 드래그 중 이동 보정값 (단위: %) */
43
+ private dragOffset;
44
+ /** 타이머 및 드래그 상태 추적 필드 */
45
+ private autoplayTimer?;
46
+ private dragStartX;
47
+ private dragStartTime;
48
+ private pointerDown;
49
+ /** 한 화면에 표시할 슬라이드 수 (최소 1) */
50
+ private get perView();
51
+ /** 한 번에 이동할 슬라이드 수 (최소 1) */
52
+ private get perMove();
53
+ /** 슬라이드가 이동할 수 있는 최대 index */
54
+ private get maxIndex();
55
+ /** 총 페이지 수 (인디케이터 도트 수) */
56
+ private get pageCount();
57
+ /** 현재 페이지 (인디케이터 도트 활성화에 사용) */
58
+ private get currentPage();
59
+ connectedCallback(): void;
60
+ disconnectedCallback(): void;
61
+ protected willUpdate(changedProperties: PropertyValues): void;
62
+ protected updated(changedProperties: PropertyValues): void;
63
+ render(): import('lit-html').TemplateResult<1>;
64
+ /** 이전 슬라이드로 이동 */
65
+ prev: () => void;
66
+ /** 다음 슬라이드로 이동 */
67
+ next: () => void;
68
+ /** 지정한 인덱스로 이동 */
69
+ goTo: (index: number) => void;
70
+ private startAutoplay;
71
+ private stopAutoplay;
72
+ private handleSlotChange;
73
+ private handleDragStart;
74
+ private handlePointerDown;
75
+ private handlePointerMove;
76
+ private handlePointerUp;
77
+ private handleClickCancel;
78
+ }
@@ -0,0 +1,264 @@
1
+ import { html } from 'lit';
2
+ import { property, state } from 'lit/decorators.js';
3
+ import { UElement } from '../UElement.js';
4
+ import { UButton } from '../button/UButton.component.js';
5
+ import { UIcon } from '../icon/UIcon.component.js';
6
+ import { styles } from './UCarousel.styles.js';
7
+
8
+ var __defProp = Object.defineProperty;
9
+ var __decorateClass = (decorators, target, key, kind) => {
10
+ var result = void 0 ;
11
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
12
+ if (decorator = decorators[i])
13
+ result = (decorator(target, key, result) ) || result;
14
+ if (result) __defProp(target, key, result);
15
+ return result;
16
+ };
17
+ class UCarousel extends UElement {
18
+ constructor() {
19
+ super(...arguments);
20
+ this.autoplay = false;
21
+ this.autoplayInterval = 3e3;
22
+ this.loop = false;
23
+ this.navigation = false;
24
+ this.pagination = false;
25
+ this.draggable = false;
26
+ this.slidesPerView = 1;
27
+ this.slidesPerMove = 1;
28
+ this.gap = 0;
29
+ this.index = 0;
30
+ this.slideCount = 0;
31
+ this.isDragging = false;
32
+ this.dragOffset = 0;
33
+ this.dragStartX = 0;
34
+ this.dragStartTime = 0;
35
+ this.pointerDown = false;
36
+ /** 이전 슬라이드로 이동 */
37
+ this.prev = () => {
38
+ const target = Math.max(0, this.index - this.perMove);
39
+ if (target !== this.index) {
40
+ this.goTo(target);
41
+ } else if (this.loop) {
42
+ this.goTo(Math.min((this.pageCount - 1) * this.perMove, this.maxIndex));
43
+ }
44
+ };
45
+ /** 다음 슬라이드로 이동 */
46
+ this.next = () => {
47
+ const target = Math.min(this.maxIndex, this.index + this.perMove);
48
+ if (target !== this.index) {
49
+ this.goTo(target);
50
+ } else if (this.loop) {
51
+ this.goTo(0);
52
+ }
53
+ };
54
+ /** 지정한 인덱스로 이동 */
55
+ this.goTo = (index) => {
56
+ if (index < 0 || index > this.maxIndex || index === this.index) return;
57
+ this.index = index;
58
+ this.emit("u-change", {
59
+ index: this.index
60
+ });
61
+ if (this.autoplay) this.startAutoplay();
62
+ };
63
+ this.handleDragStart = (e) => {
64
+ e.preventDefault();
65
+ };
66
+ this.handlePointerDown = (e) => {
67
+ if (e.button !== 0) return;
68
+ this.pointerDown = true;
69
+ this.dragStartX = e.clientX;
70
+ this.dragOffset = 0;
71
+ this.dragStartTime = Date.now();
72
+ if (this.autoplay) this.stopAutoplay();
73
+ };
74
+ this.handlePointerMove = (e) => {
75
+ if (!this.pointerDown) return;
76
+ const wrapper = e.currentTarget;
77
+ const offset = (e.clientX - this.dragStartX) / wrapper.offsetWidth * 100;
78
+ if (!this.isDragging && Math.abs(e.clientX - this.dragStartX) > 5) {
79
+ this.isDragging = true;
80
+ wrapper.setPointerCapture(e.pointerId);
81
+ }
82
+ if (this.isDragging) {
83
+ this.dragOffset = offset;
84
+ }
85
+ };
86
+ this.handlePointerUp = (e) => {
87
+ if (!this.pointerDown) return;
88
+ const elapsed = Date.now() - this.dragStartTime;
89
+ const absDrag = Math.abs(this.dragOffset);
90
+ if (this.isDragging && (absDrag > 20 || absDrag > 5 && elapsed < 300)) {
91
+ if (this.dragOffset < 0) this.next();
92
+ else this.prev();
93
+ this.addEventListener("click", this.handleClickCancel, {
94
+ capture: true,
95
+ once: true
96
+ });
97
+ }
98
+ if (this.isDragging) {
99
+ const wrapper = e.currentTarget;
100
+ wrapper.releasePointerCapture(e.pointerId);
101
+ }
102
+ this.pointerDown = false;
103
+ this.isDragging = false;
104
+ this.dragOffset = 0;
105
+ if (this.autoplay) this.startAutoplay();
106
+ };
107
+ this.handleClickCancel = (e) => {
108
+ e.preventDefault();
109
+ e.stopPropagation();
110
+ };
111
+ }
112
+ static {
113
+ this.styles = [super.styles, styles];
114
+ }
115
+ static {
116
+ this.dependencies = {
117
+ "u-button": UButton,
118
+ "u-icon": UIcon
119
+ };
120
+ }
121
+ /** 한 화면에 표시할 슬라이드 수 (최소 1) */
122
+ get perView() {
123
+ return Math.max(1, this.slidesPerView);
124
+ }
125
+ /** 한 번에 이동할 슬라이드 수 (최소 1) */
126
+ get perMove() {
127
+ return Math.max(1, this.slidesPerMove);
128
+ }
129
+ /** 슬라이드가 이동할 수 있는 최대 index */
130
+ get maxIndex() {
131
+ return Math.max(0, this.slideCount - this.perView);
132
+ }
133
+ /** 총 페이지 수 (인디케이터 도트 수) */
134
+ get pageCount() {
135
+ return this.maxIndex <= 0 ? 1 : Math.ceil(this.maxIndex / this.perMove) + 1;
136
+ }
137
+ /** 현재 페이지 (인디케이터 도트 활성화에 사용) */
138
+ get currentPage() {
139
+ return this.index >= this.maxIndex ? this.pageCount - 1 : Math.floor(this.index / this.perMove);
140
+ }
141
+ connectedCallback() {
142
+ super.connectedCallback();
143
+ if (this.autoplay) this.startAutoplay();
144
+ }
145
+ disconnectedCallback() {
146
+ this.stopAutoplay();
147
+ super.disconnectedCallback();
148
+ }
149
+ willUpdate(changedProperties) {
150
+ super.willUpdate(changedProperties);
151
+ if (changedProperties.has("slidesPerView")) {
152
+ this.style.setProperty("--slides-per-view", String(this.perView));
153
+ }
154
+ if (changedProperties.has("gap")) {
155
+ this.style.setProperty("--slide-gap", `${this.gap}px`);
156
+ }
157
+ }
158
+ updated(changedProperties) {
159
+ super.updated(changedProperties);
160
+ if (changedProperties.has("autoplay") || changedProperties.has("autoplayInterval")) {
161
+ if (this.autoplay) this.startAutoplay();
162
+ else this.stopAutoplay();
163
+ }
164
+ }
165
+ render() {
166
+ const pct = -(this.index * (100 / this.perView)) + this.dragOffset;
167
+ const gapPx = this.gap > 0 ? -(this.index * this.gap / this.perView) : 0;
168
+ const transform = gapPx ? `translateX(calc(${pct}% + ${gapPx}px))` : `translateX(${pct}%)`;
169
+ const style = `transform: ${transform}${this.isDragging ? "; transition: none" : ""}`;
170
+ return html`
171
+ <div class="slides-wrapper"
172
+ @dragstart=${this.handleDragStart}
173
+ @pointerdown=${this.draggable ? this.handlePointerDown : null}
174
+ @pointermove=${this.draggable ? this.handlePointerMove : null}
175
+ @pointerup=${this.draggable ? this.handlePointerUp : null}
176
+ @pointerleave=${this.draggable ? this.handlePointerUp : null}>
177
+ <div part="slides" class="slides" style="${style}">
178
+ <slot @slotchange=${this.handleSlotChange}></slot>
179
+ </div>
180
+ </div>
181
+
182
+ <u-button part="prev-button" class="nav-button prev"
183
+ ?hidden=${!this.navigation || !this.loop && this.index <= 0}
184
+ @click=${this.prev}>
185
+ <u-icon lib="internal" name="chevron-left"></u-icon>
186
+ </u-button>
187
+ <u-button part="next-button" class="nav-button next"
188
+ ?hidden=${!this.navigation || !this.loop && this.index >= this.maxIndex}
189
+ @click=${this.next}>
190
+ <u-icon lib="internal" name="chevron-right"></u-icon>
191
+ </u-button>
192
+
193
+ <div part="indicator" class="indicator"
194
+ ?hidden=${!this.pagination || !this.slideCount}>
195
+ ${Array.from({ length: this.pageCount }, (_, i) => html`
196
+ <button part="dot" class="dot"
197
+ ?active=${i === this.currentPage}
198
+ @click=${() => this.goTo(Math.min(i * this.perMove, this.maxIndex))}>
199
+ </button>
200
+ `)}
201
+ </div>
202
+ `;
203
+ }
204
+ startAutoplay() {
205
+ this.stopAutoplay();
206
+ this.autoplayTimer = window.setInterval(() => {
207
+ this.next();
208
+ }, this.autoplayInterval);
209
+ }
210
+ stopAutoplay() {
211
+ if (this.autoplayTimer) {
212
+ clearInterval(this.autoplayTimer);
213
+ this.autoplayTimer = void 0;
214
+ }
215
+ }
216
+ handleSlotChange(e) {
217
+ const slot = e.target;
218
+ this.slideCount = slot.assignedElements().length;
219
+ if (this.index >= this.slideCount) {
220
+ this.index = Math.max(0, this.slideCount - 1);
221
+ }
222
+ }
223
+ }
224
+ __decorateClass([
225
+ property({ type: Boolean })
226
+ ], UCarousel.prototype, "autoplay");
227
+ __decorateClass([
228
+ property({ type: Number, attribute: "autoplay-interval" })
229
+ ], UCarousel.prototype, "autoplayInterval");
230
+ __decorateClass([
231
+ property({ type: Boolean })
232
+ ], UCarousel.prototype, "loop");
233
+ __decorateClass([
234
+ property({ type: Boolean })
235
+ ], UCarousel.prototype, "navigation");
236
+ __decorateClass([
237
+ property({ type: Boolean })
238
+ ], UCarousel.prototype, "pagination");
239
+ __decorateClass([
240
+ property({ type: Boolean, reflect: true })
241
+ ], UCarousel.prototype, "draggable");
242
+ __decorateClass([
243
+ property({ type: Number, attribute: "slides-per-view" })
244
+ ], UCarousel.prototype, "slidesPerView");
245
+ __decorateClass([
246
+ property({ type: Number, attribute: "slides-per-move" })
247
+ ], UCarousel.prototype, "slidesPerMove");
248
+ __decorateClass([
249
+ property({ type: Number })
250
+ ], UCarousel.prototype, "gap");
251
+ __decorateClass([
252
+ property({ type: Number })
253
+ ], UCarousel.prototype, "index");
254
+ __decorateClass([
255
+ state()
256
+ ], UCarousel.prototype, "slideCount");
257
+ __decorateClass([
258
+ state()
259
+ ], UCarousel.prototype, "isDragging");
260
+ __decorateClass([
261
+ state()
262
+ ], UCarousel.prototype, "dragOffset");
263
+
264
+ export { UCarousel };
@@ -0,0 +1,7 @@
1
+ import { UCarousel } from './UCarousel.component.js';
2
+ declare global {
3
+ interface HTMLElementTagNameMap {
4
+ "u-carousel": UCarousel;
5
+ }
6
+ }
7
+ export { UCarousel };
@@ -0,0 +1,5 @@
1
+ import { UCarousel } from './UCarousel.component.js';
2
+
3
+ UCarousel.define("u-carousel");
4
+
5
+ export { UCarousel };
@@ -0,0 +1 @@
1
+ export declare const styles: import('lit').CSSResult;
@@ -0,0 +1,112 @@
1
+ import { css } from 'lit';
2
+
3
+ const styles = css`
4
+ :host {
5
+ --slide-gap: 0px;
6
+ --slides-per-view: 1;
7
+ }
8
+ :host {
9
+ position: relative;
10
+ display: block;
11
+ width: 100%;
12
+ overflow: hidden;
13
+ }
14
+ :host([draggable]) .slides-wrapper {
15
+ cursor: grab;
16
+ user-select: none;
17
+ }
18
+ :host([draggable]) .slides-wrapper:active {
19
+ cursor: grabbing;
20
+ }
21
+ :host([draggable]) ::slotted(*) {
22
+ -webkit-user-drag: none;
23
+ user-select: none;
24
+ }
25
+
26
+ /* ── Slides ── */
27
+ .slides-wrapper {
28
+ position: relative;
29
+ width: 100%;
30
+ height: 100%;
31
+ overflow: hidden;
32
+ touch-action: pan-y;
33
+ }
34
+
35
+ .slides {
36
+ display: flex;
37
+ flex-direction: row;
38
+ width: 100%;
39
+ height: 100%;
40
+ gap: var(--slide-gap, 0px);
41
+ transition: transform 0.3s ease-in-out;
42
+ }
43
+
44
+ ::slotted(*) {
45
+ flex: 0 0 calc(
46
+ (100% - (var(--slides-per-view) - 1) * var(--slide-gap, 0px)) / var(--slides-per-view)
47
+ );
48
+ min-width: 0;
49
+ height: 100%;
50
+ }
51
+
52
+ /* ── Navigation ── */
53
+ .nav-button {
54
+ position: absolute;
55
+ z-index: 10;
56
+ top: 50%;
57
+ transform: translateY(-50%);
58
+ display: flex;
59
+ align-items: center;
60
+ justify-content: center;
61
+ font-size: 24px;
62
+ color: var(--u-neutral-900);
63
+ border: none;
64
+ background-color: transparent;
65
+ }
66
+ .nav-button:hover {
67
+ opacity: 0.5;
68
+ transform: scale(1.2) translateY(-40%);
69
+ }
70
+ .nav-button:active {
71
+ opacity: 0.8;
72
+ transform: scale(1.1) translateY(-45%);
73
+ }
74
+
75
+ .nav-button.prev { left: 16px; }
76
+ .nav-button.next { right: 16px; }
77
+
78
+ /* ── Pagination ── */
79
+ .indicator {
80
+ position: absolute;
81
+ z-index: 10;
82
+ bottom: 16px;
83
+ left: 50%;
84
+ display: flex;
85
+ flex-direction: row;
86
+ align-items: center;
87
+ justify-content: center;
88
+ gap: 8px;
89
+ transform: translateX(-50%);
90
+ }
91
+
92
+ .dot {
93
+ width: 10px;
94
+ height: 10px;
95
+ padding: 0;
96
+ border: none;
97
+ border-radius: 50%;
98
+ background-color: var(--u-neutral-400);
99
+ cursor: pointer;
100
+ transition: all 0.2s ease;
101
+ }
102
+ .dot:hover {
103
+ background-color: var(--u-neutral-200);
104
+ }
105
+ .dot[active] {
106
+ width: 24px;
107
+ border-radius: 5px;
108
+ background-color: var(--u-neutral-100);
109
+ }
110
+ `;
111
+
112
+ export { styles };
@@ -1,12 +1,12 @@
1
- import { BaseElement } from '../BaseElement.js';
2
- import { ModalElement } from '../ModalElement.js';
1
+ import { UElement } from '../UElement.js';
2
+ import { UModalElement } from '../UModalElement.js';
3
3
  /**
4
4
  * Dialog 컴포넌트는 모달 대화상자를 제공합니다.
5
5
  * 오버레이와 함께 화면 중앙에 표시되며, 헤더, 본문, 푸터 영역을 슬롯으로 제공합니다.
6
6
  */
7
- export declare class UDialog extends ModalElement {
7
+ export declare class UDialog extends UModalElement {
8
8
  static styles: import('lit').CSSResultGroup[];
9
- static dependencies: Record<string, typeof BaseElement>;
9
+ static dependencies: Record<string, typeof UElement>;
10
10
  /** 헤드리스 모드 여부 */
11
11
  headless: boolean;
12
12
  /** 타이틀 텍스트 */