@jk-core/components 1.1.17 → 1.1.19

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 (91) hide show
  1. package/README.md +73 -73
  2. package/dist/index.js +1299 -997
  3. package/dist/index.js.map +1 -1
  4. package/dist/index.umd.cjs +8 -8
  5. package/dist/index.umd.cjs.map +1 -1
  6. package/dist/src/common/Carousel/index.d.ts +15 -0
  7. package/dist/src/common/RollingBanner/index.d.ts +11 -0
  8. package/dist/src/index.d.ts +3 -1
  9. package/dist/src/utils/ts/formatMoney.d.ts +1 -1
  10. package/package.json +99 -99
  11. package/src/Calendar/Calendar.module.scss +213 -213
  12. package/src/Calendar/RangeCalendar.tsx +125 -125
  13. package/src/Calendar/ScrollCalendar.module.scss +214 -214
  14. package/src/Calendar/ScrollCalendar.tsx +124 -124
  15. package/src/Calendar/SingleCalendar.tsx +121 -121
  16. package/src/Calendar/components/DateLabel/DateLabel.module.scss +89 -89
  17. package/src/Calendar/components/DateLabel/index.tsx +91 -91
  18. package/src/Calendar/components/DayTile/DayTile.module.scss +117 -117
  19. package/src/Calendar/components/DayTile/index.tsx +108 -108
  20. package/src/Calendar/components/MonthTile/MonthTile.module.scss +59 -59
  21. package/src/Calendar/components/MonthTile/index.tsx +50 -50
  22. package/src/Calendar/components/ViewSelector/ViewSelector.module.scss +48 -48
  23. package/src/Calendar/components/ViewSelector/index.tsx +49 -49
  24. package/src/Calendar/components/YearTile/YearTile.module.scss +85 -85
  25. package/src/Calendar/components/YearTile/index.tsx +65 -65
  26. package/src/Calendar/hooks/useCalendarNav.ts +83 -83
  27. package/src/Calendar/hooks/useDateSelect.ts +54 -54
  28. package/src/Calendar/index.scss +189 -189
  29. package/src/Calendar/index.tsx +66 -66
  30. package/src/Calendar/type.ts +3 -3
  31. package/src/Calendar/utils/getWeeksInMonth.ts +45 -45
  32. package/src/Calendar/utils/isInRange.ts +8 -8
  33. package/src/Calendar/utils/isSameDay.ts +21 -21
  34. package/src/assets/arrow.svg +11 -11
  35. package/src/assets/close.svg +15 -15
  36. package/src/assets/drop-arrow.svg +3 -3
  37. package/src/common/Accordion/Accordion.module.scss +53 -53
  38. package/src/common/Accordion/arrow-down.svg +3 -3
  39. package/src/common/Accordion/arrow-up.svg +3 -3
  40. package/src/common/Accordion/index.tsx +54 -54
  41. package/src/common/Breadcrumbs/Breadcrumbs.module.scss +46 -46
  42. package/src/common/Breadcrumbs/home.svg +5 -5
  43. package/src/common/Breadcrumbs/index.tsx +82 -82
  44. package/src/common/Button/Button.module.scss +127 -127
  45. package/src/common/Button/index.tsx +60 -60
  46. package/src/common/Card/Card.module.scss +28 -28
  47. package/src/common/Card/index.tsx +19 -19
  48. package/src/common/Carousel/Carousel.module.scss +222 -0
  49. package/src/common/Carousel/index.tsx +411 -0
  50. package/src/common/Divider/Divider.module.scss +101 -101
  51. package/src/common/Divider/index.tsx +24 -24
  52. package/src/common/DropDown/DropDown.module.scss +135 -135
  53. package/src/common/DropDown/List.tsx +156 -156
  54. package/src/common/DropDown/arrow-down.svg +3 -3
  55. package/src/common/DropDown/index.tsx +108 -108
  56. package/src/common/DropDown/search.svg +4 -4
  57. package/src/common/Pagination/Pagination.module.scss +210 -210
  58. package/src/common/Pagination/arrow-left.svg +11 -11
  59. package/src/common/Pagination/arrow-right.svg +11 -11
  60. package/src/common/Pagination/index.tsx +156 -156
  61. package/src/common/RollingBanner/RollingBanner.module.scss +126 -0
  62. package/src/common/RollingBanner/index.tsx +140 -0
  63. package/src/common/SegmentButton/SegmentButton.module.scss +46 -45
  64. package/src/common/SegmentButton/index.tsx +79 -79
  65. package/src/common/Skeleton/Skeleton.module.scss +80 -80
  66. package/src/common/Skeleton/index.tsx +47 -47
  67. package/src/common/SwitchButton/SwitchButton.module.scss +65 -65
  68. package/src/common/SwitchButton/index.tsx +57 -57
  69. package/src/common/Table/Table.module.scss +70 -70
  70. package/src/common/Table/index.tsx +128 -128
  71. package/src/index.scss +1 -1
  72. package/src/index.tsx +24 -22
  73. package/src/styles/color.scss +346 -346
  74. package/src/styles/font-face.scss +18 -18
  75. package/src/styles/font.scss +49 -49
  76. package/src/styles/mediaQuery.scss +22 -22
  77. package/src/styles/scrollbar.scss +71 -71
  78. package/src/svg.d.ts +6 -6
  79. package/src/utils/styles/mediaQuery.scss +22 -22
  80. package/src/utils/ts/allowDecimal.ts +4 -4
  81. package/src/utils/ts/autoHypen.ts +33 -33
  82. package/src/utils/ts/calculateMax.ts +24 -24
  83. package/src/utils/ts/checkIsMobilePlatform.ts +15 -15
  84. package/src/utils/ts/formatFileSize.ts +16 -16
  85. package/src/utils/ts/formatMoney.ts +16 -16
  86. package/src/utils/ts/gradientRatio.ts +61 -61
  87. package/src/utils/ts/kiloToMega.ts +30 -30
  88. package/src/utils/ts/maskingPhone.ts +8 -8
  89. package/src/utils/ts/toQueryString.ts +7 -7
  90. package/src/utils/ts/valueAsNumber.ts +15 -15
  91. package/src/vite-env.d.ts +2 -2
@@ -0,0 +1,411 @@
1
+ import { ReactNode, useCallback, useEffect, useRef, useState } from 'react';
2
+ import styles from './Carousel.module.scss';
3
+
4
+ interface CarouselProps {
5
+ /**
6
+ * 캐러셀에 표시할 슬라이드 요소들입니다.
7
+ * 일반적으로 이미지나 기타 콘텐츠 요소들을 자식으로 전달합니다.
8
+ */
9
+ children: ReactNode[];
10
+ autoPlay?: boolean;
11
+ autoPlayInterval?: number;
12
+ showIndicators?: boolean;
13
+ showNavigation?: boolean;
14
+ className?: string;
15
+ }
16
+
17
+ export default function Carousel({
18
+ children,
19
+ autoPlay = false,
20
+ autoPlayInterval = 3000,
21
+ showIndicators = true,
22
+ showNavigation = true,
23
+ className = '',
24
+ }: CarouselProps) {
25
+ // 무한 루프를 위해 1부터 시작 (복제된 마지막 슬라이드 다음)
26
+ const [currentIndex, setCurrentIndex] = useState(1);
27
+ const [isTransitioning, setIsTransitioning] = useState(false);
28
+ const [isDragging, setIsDragging] = useState(false);
29
+ const [startPos, setStartPos] = useState(0);
30
+ const [currentTranslate, setCurrentTranslate] = useState(0);
31
+ const [prevTranslate, setPrevTranslate] = useState(0);
32
+
33
+ const carouselRef = useRef<HTMLDivElement>(null);
34
+ const containerRef = useRef<HTMLDivElement>(null);
35
+ const autoPlayRef = useRef<NodeJS.Timeout | null>(null);
36
+
37
+ // 총 슬라이드 개수 (원본)
38
+ const totalSlides = children.length;
39
+
40
+ // 복제 슬라이드 포함 (앞뒤로 하나씩 추가)
41
+ const extendedSlides = [
42
+ children[totalSlides - 1], // 마지막 슬라이드 복제 (앞에)
43
+ ...children, // 원본 슬라이드들
44
+ children[0], // 첫 번째 슬라이드 복제 (뒤에)
45
+ ];
46
+
47
+ // 실제 표시되는 슬라이드 인덱스 (인디케이터용)
48
+ const displayIndex = currentIndex - 1;
49
+
50
+ // 다음 슬라이드로 이동
51
+ const goToNext = useCallback(() => {
52
+ if (isTransitioning) return;
53
+ setIsTransitioning(true);
54
+ setCurrentIndex((prev) => prev + 1);
55
+ }, [isTransitioning]);
56
+
57
+ // 이전 슬라이드로 이동
58
+ const goToPrev = useCallback(() => {
59
+ if (isTransitioning) return;
60
+ setIsTransitioning(true);
61
+ setCurrentIndex((prev) => prev - 1);
62
+ }, [isTransitioning]);
63
+
64
+ // 특정 슬라이드로 이동
65
+ const goToSlide = useCallback((index: number) => {
66
+ if (isTransitioning) return;
67
+ if (index === displayIndex) return; // 이미 같은 슬라이드에 있으면 리턴
68
+
69
+ setIsTransitioning(true);
70
+ const targetIndex = index + 1; // 복제 슬라이드 오프셋 적용
71
+ setCurrentIndex(targetIndex);
72
+ }, [isTransitioning, displayIndex]);
73
+
74
+ // 자동재생 시작
75
+ const startAutoPlay = useCallback(() => {
76
+ // 이미 실행 중이면 중복 실행 방지
77
+ if (autoPlayRef.current) {
78
+ clearInterval(autoPlayRef.current);
79
+ autoPlayRef.current = null;
80
+ }
81
+
82
+ if (autoPlay) {
83
+ autoPlayRef.current = setInterval(() => {
84
+ goToNext();
85
+ }, autoPlayInterval);
86
+ }
87
+ }, [autoPlay, autoPlayInterval, goToNext]);
88
+
89
+ // 자동재생 중지
90
+ const stopAutoPlay = useCallback(() => {
91
+ if (autoPlayRef.current) {
92
+ clearInterval(autoPlayRef.current);
93
+ autoPlayRef.current = null;
94
+ }
95
+ }, []);
96
+
97
+ // 드래그 시작
98
+ const handleDragStart = (clientX: number) => {
99
+ setIsDragging(true);
100
+ setStartPos(clientX);
101
+ setCurrentTranslate(prevTranslate);
102
+ stopAutoPlay();
103
+ };
104
+
105
+ // 드래그 중
106
+ const handleDragMove = (clientX: number) => {
107
+ if (!isDragging) return;
108
+
109
+ const diff = clientX - startPos;
110
+ setCurrentTranslate(prevTranslate + diff);
111
+ };
112
+
113
+ // 드래그 종료
114
+ const handleDragEnd = () => {
115
+ if (!isDragging) return;
116
+
117
+ setIsDragging(false);
118
+
119
+ const containerWidth = containerRef.current?.offsetWidth || 0;
120
+ const threshold = containerWidth * 0.2; // 20% 이상 드래그시 슬라이드 변경
121
+ const diff = currentTranslate - prevTranslate;
122
+
123
+ if (Math.abs(diff) > threshold) {
124
+ if (diff > 0) {
125
+ goToPrev();
126
+ } else {
127
+ goToNext();
128
+ }
129
+ } else {
130
+ // 원래 위치로 복귀
131
+ setCurrentTranslate(prevTranslate);
132
+ }
133
+
134
+ // 드래그 종료 후 autoplay 재시작 (지연 실행으로 안정성 확보)
135
+ if (autoPlay) {
136
+ setTimeout(() => {
137
+ startAutoPlay();
138
+ }, 100);
139
+ }
140
+ };
141
+
142
+ // 마우스 이벤트 핸들러
143
+ const handleMouseDown = (e: React.MouseEvent) => {
144
+ e.preventDefault();
145
+ handleDragStart(e.clientX);
146
+ };
147
+
148
+ const handleMouseMove = (e: React.MouseEvent) => {
149
+ handleDragMove(e.clientX);
150
+ };
151
+
152
+ const handleMouseUp = () => {
153
+ handleDragEnd();
154
+ };
155
+
156
+ const handleMouseLeave = () => {
157
+ handleDragEnd();
158
+ // 마우스가 carousel을 벗어나면 autoplay 재시작
159
+ if (autoPlay && !isDragging) {
160
+ setTimeout(() => {
161
+ startAutoPlay();
162
+ }, 100);
163
+ }
164
+ };
165
+
166
+ // 터치 이벤트 핸들러
167
+ const handleTouchStart = (e: React.TouchEvent) => {
168
+ handleDragStart(e.touches[0].clientX);
169
+ };
170
+
171
+ const handleTouchMove = (e: React.TouchEvent) => {
172
+ handleDragMove(e.touches[0].clientX);
173
+ };
174
+
175
+ const handleTouchEnd = () => {
176
+ handleDragEnd();
177
+ };
178
+
179
+ // 키보드 이벤트 핸들러
180
+ const handleKeyDown = (e: React.KeyboardEvent) => {
181
+ if (e.key === 'ArrowLeft') {
182
+ goToPrev();
183
+ } else if (e.key === 'ArrowRight') {
184
+ goToNext();
185
+ }
186
+ };
187
+
188
+ // 트랜지션 완료 처리
189
+ const handleTransitionEnd = () => {
190
+ setIsTransitioning(false);
191
+
192
+ // 무한 루프 처리: 복제된 슬라이드에서 실제 슬라이드로 순간이동
193
+ if (carouselRef.current) {
194
+ if (currentIndex === 0) {
195
+ // 맨 앞의 복제된 슬라이드(마지막 아이템)에 있을 때 실제 마지막 슬라이드로 이동
196
+ carouselRef.current.style.transition = 'none';
197
+ setCurrentIndex(totalSlides);
198
+ const containerWidth = containerRef.current?.offsetWidth || 0;
199
+ const newTranslate = -totalSlides * containerWidth;
200
+ setPrevTranslate(newTranslate);
201
+ setCurrentTranslate(newTranslate);
202
+ setTimeout(() => {
203
+ if (carouselRef.current) {
204
+ carouselRef.current.style.transition = 'transform 0.3s ease-in-out';
205
+ }
206
+ }, 10);
207
+ } else if (currentIndex === totalSlides + 1) {
208
+ // 맨 뒤의 복제된 슬라이드(첫 번째 아이템)에 있을 때 실제 첫 번째 슬라이드로 이동
209
+ carouselRef.current.style.transition = 'none';
210
+ setCurrentIndex(1);
211
+ const containerWidth = containerRef.current?.offsetWidth || 0;
212
+ const newTranslate = -1 * containerWidth;
213
+ setPrevTranslate(newTranslate);
214
+ setCurrentTranslate(newTranslate);
215
+ setTimeout(() => {
216
+ if (carouselRef.current) {
217
+ carouselRef.current.style.transition = 'transform 0.3s ease-in-out';
218
+ }
219
+ }, 10);
220
+ } else {
221
+ // 일반적인 경우
222
+ const containerWidth = containerRef.current?.offsetWidth || 0;
223
+ const newTranslate = -currentIndex * containerWidth;
224
+ setPrevTranslate(newTranslate);
225
+ setCurrentTranslate(newTranslate);
226
+ }
227
+ }
228
+
229
+ // 트랜지션 완료 후 autoplay 재시작 확인
230
+ if (autoPlay && !isDragging && !autoPlayRef.current) {
231
+ setTimeout(() => {
232
+ startAutoPlay();
233
+ }, 100);
234
+ }
235
+ };
236
+
237
+ // 자동재생 효과
238
+ useEffect(() => {
239
+ if (autoPlay) {
240
+ startAutoPlay();
241
+ }
242
+
243
+ return () => {
244
+ stopAutoPlay();
245
+ };
246
+ }, [autoPlay, startAutoPlay, stopAutoPlay]);
247
+
248
+ // 초기 로드 시 올바른 위치 설정
249
+ useEffect(() => {
250
+ if (containerRef.current) {
251
+ const containerWidth = containerRef.current.offsetWidth;
252
+ const newTranslate = -currentIndex * containerWidth;
253
+ setPrevTranslate(newTranslate);
254
+ setCurrentTranslate(newTranslate);
255
+ }
256
+ }, [currentIndex]);
257
+
258
+ // 슬라이드 위치 업데이트
259
+ useEffect(() => {
260
+ if (!isDragging && containerRef.current) {
261
+ const containerWidth = containerRef.current.offsetWidth;
262
+ const newTranslate = -currentIndex * containerWidth;
263
+ setPrevTranslate(newTranslate);
264
+ setCurrentTranslate(newTranslate);
265
+ }
266
+ }, [currentIndex, isDragging]);
267
+
268
+ // 윈도우 리사이즈 처리
269
+ useEffect(() => {
270
+ const handleResize = () => {
271
+ if (containerRef.current) {
272
+ const containerWidth = containerRef.current.offsetWidth;
273
+ const newTranslate = -currentIndex * containerWidth;
274
+ setPrevTranslate(newTranslate);
275
+ setCurrentTranslate(newTranslate);
276
+ }
277
+ };
278
+
279
+ window.addEventListener('resize', handleResize);
280
+ return () => window.removeEventListener('resize', handleResize);
281
+ }, [currentIndex]);
282
+
283
+ return (
284
+ <div
285
+ className={`${styles.carousel} ${className}`}
286
+ onKeyDown={handleKeyDown}
287
+ tabIndex={0}
288
+ >
289
+ <div
290
+ ref={containerRef}
291
+ className={styles.carouselContainer}
292
+ onMouseDown={handleMouseDown}
293
+ onMouseMove={handleMouseMove}
294
+ onMouseUp={handleMouseUp}
295
+ onMouseLeave={handleMouseLeave}
296
+ onTouchStart={handleTouchStart}
297
+ onTouchMove={handleTouchMove}
298
+ onTouchEnd={handleTouchEnd}
299
+ onMouseEnter={() => {
300
+ // 마우스 호버 시 autoplay 일시정지 (드래그 중이 아닐 때만)
301
+ if (autoPlay && !isDragging) {
302
+ stopAutoPlay();
303
+ }
304
+ }}
305
+ >
306
+ <div
307
+ ref={carouselRef}
308
+ className={styles.carouselSlides}
309
+ style={{
310
+ transform: `translateX(${currentTranslate}px)`,
311
+ transition: isDragging ? 'none' : 'transform 0.3s ease-in-out',
312
+ }}
313
+ onTransitionEnd={handleTransitionEnd}
314
+ >
315
+ {extendedSlides.map((child, index) => (
316
+ <div key={`slide-${index}`} className={styles.carouselSlide}>
317
+ {child}
318
+ </div>
319
+ ))}
320
+ </div>
321
+ </div>
322
+
323
+ {/* Navigation Buttons */}
324
+ {showNavigation && (
325
+ <>
326
+ <button
327
+ type="button"
328
+ className={`${styles.carouselButton} ${styles.carouselButtonPrev}`}
329
+ onClick={() => {
330
+ goToPrev();
331
+ // 버튼 클릭 후 autoplay 재시작
332
+ if (autoPlay) {
333
+ setTimeout(() => {
334
+ startAutoPlay();
335
+ }, 100);
336
+ }
337
+ }}
338
+ onMouseEnter={() => autoPlay && stopAutoPlay()}
339
+ onMouseLeave={() => {
340
+ if (autoPlay) {
341
+ setTimeout(() => {
342
+ startAutoPlay();
343
+ }, 100);
344
+ }
345
+ }}
346
+ aria-label="이전 슬라이드"
347
+ >
348
+
349
+ </button>
350
+ <button
351
+ type="button"
352
+ className={`${styles.carouselButton} ${styles.carouselButtonNext}`}
353
+ onClick={() => {
354
+ goToNext();
355
+ // 버튼 클릭 후 autoplay 재시작
356
+ if (autoPlay) {
357
+ setTimeout(() => {
358
+ startAutoPlay();
359
+ }, 100);
360
+ }
361
+ }}
362
+ onMouseEnter={() => autoPlay && stopAutoPlay()}
363
+ onMouseLeave={() => {
364
+ if (autoPlay) {
365
+ setTimeout(() => {
366
+ startAutoPlay();
367
+ }, 100);
368
+ }
369
+ }}
370
+ aria-label="다음 슬라이드"
371
+ >
372
+
373
+ </button>
374
+ </>
375
+ )}
376
+
377
+ {/* Indicators */}
378
+ {showIndicators && (
379
+ <div className={styles.carouselIndicators}>
380
+ {children.map((_, index) => (
381
+ <button
382
+ key={index}
383
+ type="button"
384
+ className={`${styles.carouselIndicator} ${
385
+ index === displayIndex ? styles.active : ''
386
+ }`}
387
+ onClick={() => {
388
+ goToSlide(index);
389
+ // 인디케이터 클릭 후 autoplay 재시작
390
+ if (autoPlay) {
391
+ setTimeout(() => {
392
+ startAutoPlay();
393
+ }, 100);
394
+ }
395
+ }}
396
+ onMouseEnter={() => autoPlay && stopAutoPlay()}
397
+ onMouseLeave={() => {
398
+ if (autoPlay) {
399
+ setTimeout(() => {
400
+ startAutoPlay();
401
+ }, 100);
402
+ }
403
+ }}
404
+ aria-label={`슬라이드 ${index + 1}로 이동`}
405
+ />
406
+ ))}
407
+ </div>
408
+ )}
409
+ </div>
410
+ );
411
+ }
@@ -1,101 +1,101 @@
1
- .divider {
2
- display: flex;
3
- align-items: center;
4
- margin: 16px 0;
5
- align-self: center;
6
- justify-self: center;
7
-
8
- &.vertical {
9
- flex-direction: column;
10
- height: 100px;
11
- width: auto;
12
- margin: 0 16px;
13
- }
14
- }
15
-
16
- .content {
17
- display: flex;
18
- align-items: center;
19
- width: 100%;
20
-
21
- &::before,
22
- &::after {
23
- content: "";
24
- flex: 1;
25
- height: 1px;
26
- background-color: var(--G-30);
27
- }
28
-
29
- .vertical & {
30
- flex-direction: column;
31
- height: 100%;
32
- width: auto;
33
-
34
- &::before,
35
- &::after {
36
- width: 1px;
37
- height: auto;
38
- flex: 1;
39
- }
40
- }
41
- }
42
-
43
- .text {
44
- padding: 0 16px;
45
- color: var(--G-70);
46
- font-size: 14px;
47
- white-space: nowrap;
48
-
49
- .vertical & {
50
- padding: 16px 0;
51
- writing-mode: vertical-rl;
52
- }
53
- }
54
-
55
- // 텍스트가 없을 때는 전체 라인만 표시
56
- .noText .content {
57
- &::before {
58
- flex: 1;
59
- }
60
-
61
- &::after {
62
- display: none;
63
- }
64
- }
65
-
66
- // 정렬 옵션
67
- .left .content::before {
68
- flex: 0.2;
69
- }
70
-
71
- .right .content::after {
72
- flex: 0.2;
73
- }
74
-
75
- .center .content::before,
76
- .center .content::after {
77
- flex: 1;
78
- }
79
-
80
- .full {
81
- width: 100%;
82
- height: 100%;
83
- }
84
-
85
- .middle {
86
- width: 80%;
87
- height: 80%;
88
- }
89
-
90
- .short {
91
- width: 50%;
92
- height: 50%;
93
- }
94
-
95
- .horizontal {
96
- height: 1px !important;
97
- }
98
-
99
- .vertical {
100
- width: 1px !important;
101
- }
1
+ .divider {
2
+ display: flex;
3
+ align-items: center;
4
+ margin: 16px 0;
5
+ align-self: center;
6
+ justify-self: center;
7
+
8
+ &.vertical {
9
+ flex-direction: column;
10
+ height: 100px;
11
+ width: auto;
12
+ margin: 0 16px;
13
+ }
14
+ }
15
+
16
+ .content {
17
+ display: flex;
18
+ align-items: center;
19
+ width: 100%;
20
+
21
+ &::before,
22
+ &::after {
23
+ content: "";
24
+ flex: 1;
25
+ height: 1px;
26
+ background-color: var(--G-30);
27
+ }
28
+
29
+ .vertical & {
30
+ flex-direction: column;
31
+ height: 100%;
32
+ width: auto;
33
+
34
+ &::before,
35
+ &::after {
36
+ width: 1px;
37
+ height: auto;
38
+ flex: 1;
39
+ }
40
+ }
41
+ }
42
+
43
+ .text {
44
+ padding: 0 16px;
45
+ color: var(--G-70);
46
+ font-size: 14px;
47
+ white-space: nowrap;
48
+
49
+ .vertical & {
50
+ padding: 16px 0;
51
+ writing-mode: vertical-rl;
52
+ }
53
+ }
54
+
55
+ // 텍스트가 없을 때는 전체 라인만 표시
56
+ .noText .content {
57
+ &::before {
58
+ flex: 1;
59
+ }
60
+
61
+ &::after {
62
+ display: none;
63
+ }
64
+ }
65
+
66
+ // 정렬 옵션
67
+ .left .content::before {
68
+ flex: 0.2;
69
+ }
70
+
71
+ .right .content::after {
72
+ flex: 0.2;
73
+ }
74
+
75
+ .center .content::before,
76
+ .center .content::after {
77
+ flex: 1;
78
+ }
79
+
80
+ .full {
81
+ width: 100%;
82
+ height: 100%;
83
+ }
84
+
85
+ .middle {
86
+ width: 80%;
87
+ height: 80%;
88
+ }
89
+
90
+ .short {
91
+ width: 50%;
92
+ height: 50%;
93
+ }
94
+
95
+ .horizontal {
96
+ height: 1px !important;
97
+ }
98
+
99
+ .vertical {
100
+ width: 1px !important;
101
+ }
@@ -1,25 +1,25 @@
1
- import styles from './Divider.module.scss';
2
-
3
- interface DividerProps {
4
- children?: React.ReactNode;
5
- textAlign?: 'left' | 'center' | 'right';
6
- variant?: 'full' | 'middle' | 'short';
7
- orientation?: 'horizontal' | 'vertical';
8
- }
9
-
10
- export default function Divider({
11
- children,
12
- textAlign = 'center',
13
- variant = 'full',
14
- orientation = 'horizontal',
15
- }: DividerProps) {
16
- const hasText = Boolean(children);
17
-
18
- return (
19
- <div className={`${styles.divider} ${styles[variant]} ${styles[textAlign]} ${styles[orientation]} ${!hasText ? styles.noText : ''}`}>
20
- <div className={styles.content}>
21
- {children && <span className={styles.text}>{children}</span>}
22
- </div>
23
- </div>
24
- );
1
+ import styles from './Divider.module.scss';
2
+
3
+ interface DividerProps {
4
+ children?: React.ReactNode;
5
+ textAlign?: 'left' | 'center' | 'right';
6
+ variant?: 'full' | 'middle' | 'short';
7
+ orientation?: 'horizontal' | 'vertical';
8
+ }
9
+
10
+ export default function Divider({
11
+ children,
12
+ textAlign = 'center',
13
+ variant = 'full',
14
+ orientation = 'horizontal',
15
+ }: DividerProps) {
16
+ const hasText = Boolean(children);
17
+
18
+ return (
19
+ <div className={`${styles.divider} ${styles[variant]} ${styles[textAlign]} ${styles[orientation]} ${!hasText ? styles.noText : ''}`}>
20
+ <div className={styles.content}>
21
+ {children && <span className={styles.text}>{children}</span>}
22
+ </div>
23
+ </div>
24
+ );
25
25
  }