@designbasekorea/ui 0.3.1 → 0.3.3
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/dist/index.css +1 -1
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +7 -6
- package/dist/index.esm.css +1 -1
- package/dist/index.esm.css.map +1 -1
- package/dist/index.esm.js +88 -104
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +88 -104
- package/dist/index.js.map +1 -1
- package/dist/index.umd.css +1 -1
- package/dist/index.umd.css.map +1 -1
- package/dist/index.umd.js +88 -104
- package/dist/index.umd.js.map +1 -1
- package/package.json +7 -7
package/dist/index.esm.js
CHANGED
|
@@ -2194,9 +2194,13 @@ const Spinner = ({ type = 'circular', size = 'm', color, speed = 1, label = '로
|
|
|
2194
2194
|
};
|
|
2195
2195
|
Spinner.displayName = 'Spinner';
|
|
2196
2196
|
|
|
2197
|
-
const GAP$1 = 8; // 트리거와의 간격
|
|
2198
|
-
const ARW = 6; //
|
|
2199
|
-
const PAD = 8; //
|
|
2197
|
+
const GAP$1 = 8; // 트리거와의 간격(박스)
|
|
2198
|
+
const ARW = 6; // border 삼각형 사이즈(너 SCSS에서 6px)
|
|
2199
|
+
const PAD = 8; // start/end 여백
|
|
2200
|
+
// ✅ 네가 말한 “-10이 되어야 제대로”를 상수로 고정
|
|
2201
|
+
const OUT = -10; // bottom일 때 top, right일 때 left
|
|
2202
|
+
// ✅ top/left는 대칭적으로 “박스에 살짝 겹치게” 만들어 seam 제거
|
|
2203
|
+
const INSET = 2; // (pRect.height - 2), (pRect.width - 2)
|
|
2200
2204
|
const Tooltip = ({ content, children, position = 'top', size = 'm', variant = 'default', delay = 200, hideDelay = 80, alwaysShow = false, disabled = false, maxWidth = 240, showArrow = true, className, ...props }) => {
|
|
2201
2205
|
const [visible, setVisible] = useState(false);
|
|
2202
2206
|
const [style, setStyle] = useState({});
|
|
@@ -2215,115 +2219,110 @@ const Tooltip = ({ content, children, position = 'top', size = 'm', variant = 'd
|
|
|
2215
2219
|
const groupOf = (p) => p.startsWith('top') ? 'top' :
|
|
2216
2220
|
p.startsWith('bottom') ? 'bottom' :
|
|
2217
2221
|
p.startsWith('left') ? 'left' : 'right';
|
|
2218
|
-
// 위치 계산 (⚠️ 뷰포트 클램핑 후 화살표도 보정)
|
|
2219
2222
|
const calculatePosition = useCallback(() => {
|
|
2220
2223
|
if (!triggerRef.current || !tooltipRef.current)
|
|
2221
2224
|
return;
|
|
2222
2225
|
const tRect = triggerRef.current.getBoundingClientRect();
|
|
2223
2226
|
const pRect = tooltipRef.current.getBoundingClientRect();
|
|
2224
2227
|
let top = 0, left = 0;
|
|
2225
|
-
// 1차: 이상적(미보정) 화살표 좌표
|
|
2226
2228
|
let aTop = 0, aLeft = 0;
|
|
2227
2229
|
switch (position) {
|
|
2228
2230
|
case 'top':
|
|
2229
2231
|
top = tRect.top - pRect.height - GAP$1;
|
|
2230
2232
|
left = tRect.left + tRect.width / 2 - pRect.width / 2;
|
|
2231
|
-
aTop = pRect.height;
|
|
2233
|
+
aTop = pRect.height - INSET; // ✅ top은 박스 아래쪽에 살짝 겹침
|
|
2232
2234
|
aLeft = pRect.width / 2 - ARW;
|
|
2233
2235
|
break;
|
|
2234
2236
|
case 'top-start':
|
|
2235
2237
|
top = tRect.top - pRect.height - GAP$1;
|
|
2236
2238
|
left = tRect.left;
|
|
2237
|
-
aTop = pRect.height;
|
|
2239
|
+
aTop = pRect.height - INSET;
|
|
2238
2240
|
aLeft = PAD;
|
|
2239
2241
|
break;
|
|
2240
2242
|
case 'top-end':
|
|
2241
2243
|
top = tRect.top - pRect.height - GAP$1;
|
|
2242
2244
|
left = tRect.right - pRect.width;
|
|
2243
|
-
aTop = pRect.height;
|
|
2244
|
-
aLeft = pRect.width - PAD;
|
|
2245
|
+
aTop = pRect.height - INSET;
|
|
2246
|
+
aLeft = pRect.width - PAD - ARW;
|
|
2245
2247
|
break;
|
|
2246
2248
|
case 'bottom':
|
|
2247
2249
|
top = tRect.bottom + GAP$1;
|
|
2248
2250
|
left = tRect.left + tRect.width / 2 - pRect.width / 2;
|
|
2249
|
-
aTop = -
|
|
2251
|
+
aTop = OUT; // ✅ 네 요구: -10
|
|
2250
2252
|
aLeft = pRect.width / 2 - ARW;
|
|
2251
2253
|
break;
|
|
2252
2254
|
case 'bottom-start':
|
|
2253
2255
|
top = tRect.bottom + GAP$1;
|
|
2254
2256
|
left = tRect.left;
|
|
2255
|
-
aTop = -
|
|
2257
|
+
aTop = OUT; // ✅ -10
|
|
2256
2258
|
aLeft = PAD;
|
|
2257
2259
|
break;
|
|
2258
2260
|
case 'bottom-end':
|
|
2259
2261
|
top = tRect.bottom + GAP$1;
|
|
2260
2262
|
left = tRect.right - pRect.width;
|
|
2261
|
-
aTop = -
|
|
2262
|
-
aLeft = pRect.width - PAD;
|
|
2263
|
+
aTop = OUT; // ✅ -10
|
|
2264
|
+
aLeft = pRect.width - PAD - ARW;
|
|
2263
2265
|
break;
|
|
2264
2266
|
case 'left':
|
|
2265
2267
|
top = tRect.top + tRect.height / 2 - pRect.height / 2;
|
|
2266
2268
|
left = tRect.left - pRect.width - GAP$1;
|
|
2267
2269
|
aTop = pRect.height / 2 - ARW;
|
|
2268
|
-
aLeft = pRect.width;
|
|
2270
|
+
aLeft = pRect.width - INSET; // ✅ left는 박스 오른쪽에 살짝 겹침
|
|
2269
2271
|
break;
|
|
2270
2272
|
case 'left-start':
|
|
2271
2273
|
top = tRect.top;
|
|
2272
2274
|
left = tRect.left - pRect.width - GAP$1;
|
|
2273
2275
|
aTop = PAD;
|
|
2274
|
-
aLeft = pRect.width;
|
|
2276
|
+
aLeft = pRect.width - INSET;
|
|
2275
2277
|
break;
|
|
2276
2278
|
case 'left-end':
|
|
2277
2279
|
top = tRect.bottom - pRect.height;
|
|
2278
2280
|
left = tRect.left - pRect.width - GAP$1;
|
|
2279
|
-
aTop = pRect.height - PAD;
|
|
2280
|
-
aLeft = pRect.width;
|
|
2281
|
+
aTop = pRect.height - PAD - ARW;
|
|
2282
|
+
aLeft = pRect.width - INSET;
|
|
2281
2283
|
break;
|
|
2282
2284
|
case 'right':
|
|
2283
2285
|
top = tRect.top + tRect.height / 2 - pRect.height / 2;
|
|
2284
2286
|
left = tRect.right + GAP$1;
|
|
2285
2287
|
aTop = pRect.height / 2 - ARW;
|
|
2286
|
-
aLeft =
|
|
2288
|
+
aLeft = OUT; // ✅ 네 요구: left:-10
|
|
2287
2289
|
break;
|
|
2288
2290
|
case 'right-start':
|
|
2289
2291
|
top = tRect.top;
|
|
2290
2292
|
left = tRect.right + GAP$1;
|
|
2291
2293
|
aTop = PAD;
|
|
2292
|
-
aLeft = -
|
|
2294
|
+
aLeft = OUT; // ✅ -10
|
|
2293
2295
|
break;
|
|
2294
2296
|
case 'right-end':
|
|
2295
2297
|
top = tRect.bottom - pRect.height;
|
|
2296
2298
|
left = tRect.right + GAP$1;
|
|
2297
|
-
aTop = pRect.height - PAD;
|
|
2298
|
-
aLeft = -
|
|
2299
|
+
aTop = pRect.height - PAD - ARW;
|
|
2300
|
+
aLeft = OUT; // ✅ -10
|
|
2299
2301
|
break;
|
|
2300
2302
|
}
|
|
2301
|
-
// 뷰포트 클램핑
|
|
2303
|
+
// 뷰포트 클램핑(툴팁 박스)
|
|
2302
2304
|
const vw = window.innerWidth;
|
|
2303
2305
|
const vh = window.innerHeight;
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2306
|
+
const EDGE = 8;
|
|
2307
|
+
if (left < EDGE)
|
|
2308
|
+
left = EDGE;
|
|
2309
|
+
if (left + pRect.width > vw - EDGE)
|
|
2310
|
+
left = vw - pRect.width - EDGE;
|
|
2311
|
+
if (top < EDGE)
|
|
2312
|
+
top = EDGE;
|
|
2313
|
+
if (top + pRect.height > vh - EDGE)
|
|
2314
|
+
top = vh - pRect.height - EDGE;
|
|
2315
|
+
// 클램핑으로 박스가 이동했을 때, 화살표가 트리거를 향하도록 보정
|
|
2313
2316
|
const g = groupOf(position);
|
|
2314
2317
|
if (g === 'top' || g === 'bottom') {
|
|
2315
|
-
// 트리거 중앙 X 를 툴팁 좌표계로 변환
|
|
2316
2318
|
const triggerCenterX = tRect.left + tRect.width / 2;
|
|
2317
|
-
const localX = triggerCenterX - left - ARW;
|
|
2318
|
-
|
|
2319
|
-
aLeft = Math.min(pRect.width - PAD, Math.max(PAD, localX));
|
|
2320
|
-
// aTop은 이미 위/아래에 고정(-ARW 또는 높이)
|
|
2319
|
+
const localX = triggerCenterX - left - ARW;
|
|
2320
|
+
aLeft = Math.min(pRect.width - PAD - ARW, Math.max(PAD, localX));
|
|
2321
2321
|
}
|
|
2322
2322
|
else {
|
|
2323
2323
|
const triggerCenterY = tRect.top + tRect.height / 2;
|
|
2324
2324
|
const localY = triggerCenterY - top - ARW;
|
|
2325
|
-
aTop = Math.min(pRect.height - PAD, Math.max(PAD, localY));
|
|
2326
|
-
// aLeft는 이미 좌/우에 고정(-ARW 또는 너비)
|
|
2325
|
+
aTop = Math.min(pRect.height - PAD - ARW, Math.max(PAD, localY));
|
|
2327
2326
|
}
|
|
2328
2327
|
setStyle({
|
|
2329
2328
|
position: 'fixed',
|
|
@@ -2331,17 +2330,15 @@ const Tooltip = ({ content, children, position = 'top', size = 'm', variant = 'd
|
|
|
2331
2330
|
left,
|
|
2332
2331
|
maxWidth,
|
|
2333
2332
|
zIndex: 9999,
|
|
2334
|
-
pointerEvents: 'none',
|
|
2333
|
+
pointerEvents: 'none',
|
|
2335
2334
|
});
|
|
2336
2335
|
setArrowStyle({ position: 'absolute', top: aTop, left: aLeft });
|
|
2337
2336
|
setPlacementGroup(g);
|
|
2338
2337
|
}, [position, maxWidth]);
|
|
2339
|
-
// 초기 페인트 전에 위치 확정
|
|
2340
2338
|
useLayoutEffect(() => {
|
|
2341
2339
|
if (visible || alwaysShow)
|
|
2342
2340
|
calculatePosition();
|
|
2343
2341
|
}, [visible, alwaysShow, calculatePosition]);
|
|
2344
|
-
// 스크롤/리사이즈/크기변화 추적 (rAF 스로틀)
|
|
2345
2342
|
useEffect(() => {
|
|
2346
2343
|
if (!(visible || alwaysShow))
|
|
2347
2344
|
return;
|
|
@@ -2372,7 +2369,6 @@ const Tooltip = ({ content, children, position = 'top', size = 'm', variant = 'd
|
|
|
2372
2369
|
cancelAnimationFrame(rafId.current);
|
|
2373
2370
|
};
|
|
2374
2371
|
}, [visible, alwaysShow, calculatePosition]);
|
|
2375
|
-
// show/hide
|
|
2376
2372
|
const show = useCallback(() => {
|
|
2377
2373
|
if (disabled)
|
|
2378
2374
|
return;
|
|
@@ -2386,10 +2382,12 @@ const Tooltip = ({ content, children, position = 'top', size = 'm', variant = 'd
|
|
|
2386
2382
|
timers.current.t = setTimeout(() => setVisible(false), Math.max(0, hideDelay));
|
|
2387
2383
|
}, [disabled, hideDelay]);
|
|
2388
2384
|
useEffect(() => () => clearTimer(), []);
|
|
2389
|
-
useEffect(() => {
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2385
|
+
useEffect(() => {
|
|
2386
|
+
if (!disabled && alwaysShow)
|
|
2387
|
+
setVisible(true);
|
|
2388
|
+
else if (!alwaysShow)
|
|
2389
|
+
setVisible(false);
|
|
2390
|
+
}, [alwaysShow, disabled]);
|
|
2393
2391
|
const onKeyDown = useCallback((e) => {
|
|
2394
2392
|
if (e.key === 'Escape') {
|
|
2395
2393
|
clearTimer();
|
|
@@ -2402,7 +2400,7 @@ const Tooltip = ({ content, children, position = 'top', size = 'm', variant = 'd
|
|
|
2402
2400
|
};
|
|
2403
2401
|
Tooltip.displayName = 'Tooltip';
|
|
2404
2402
|
|
|
2405
|
-
const Button = forwardRef(({ variant = 'primary', size = 'm', radius, fullWidth = false, disabled = false, loading = false, iconOnly = false, startIcon: StartIcon, endIcon: EndIcon, tooltip, tooltipProps, className, children, onPress, type = 'button', ...props }, forwardedRef) => {
|
|
2403
|
+
const Button = forwardRef(({ variant = 'primary', size = 'm', radius, fullWidth = false, disabled = false, loading = false, loadingText, iconOnly = false, startIcon: StartIcon, endIcon: EndIcon, tooltip, tooltipProps, className, children, onPress, type = 'button', ...props }, forwardedRef) => {
|
|
2406
2404
|
const ref = $df56164dff5785e2$export$4338b53315abf666(forwardedRef);
|
|
2407
2405
|
const { buttonProps } = $701a24aa0da5b062$export$ea18c227d4417cc3({
|
|
2408
2406
|
...props,
|
|
@@ -2447,7 +2445,13 @@ const Button = forwardRef(({ variant = 'primary', size = 'm', radius, fullWidth
|
|
|
2447
2445
|
};
|
|
2448
2446
|
const renderContent = () => {
|
|
2449
2447
|
if (loading) {
|
|
2450
|
-
|
|
2448
|
+
// 로딩 중 표시할 텍스트 결정: loadingText > children > 기본값
|
|
2449
|
+
const displayText = loadingText !== undefined
|
|
2450
|
+
? loadingText
|
|
2451
|
+
: (!iconOnly && children)
|
|
2452
|
+
? children
|
|
2453
|
+
: null;
|
|
2454
|
+
return (jsxs(Fragment, { children: [jsx(Spinner, { type: "circular", size: size === 's' ? 's' : size === 'l' ? 'l' : 'm', color: getIconColor(), speed: 1, showLabel: false }), displayText && jsx("span", { children: displayText })] }));
|
|
2451
2455
|
}
|
|
2452
2456
|
// iconOnly 버튼일 때는 children을 아이콘으로 처리
|
|
2453
2457
|
if (iconOnly && children && React.isValidElement(children)) {
|
|
@@ -4911,23 +4915,7 @@ const Image$1 = ({ src, alt = '', ratio = 'auto', fit = 'cover', loading = 'lazy
|
|
|
4911
4915
|
onError?.();
|
|
4912
4916
|
}
|
|
4913
4917
|
};
|
|
4914
|
-
// aspect ratio
|
|
4915
|
-
const getAspectRatioStyle = () => {
|
|
4916
|
-
if (ratio === 'auto')
|
|
4917
|
-
return {};
|
|
4918
|
-
const ratios = {
|
|
4919
|
-
'1:1': '100%',
|
|
4920
|
-
'16:9': '56.25%',
|
|
4921
|
-
'4:3': '75%',
|
|
4922
|
-
'3:2': '66.67%',
|
|
4923
|
-
'3:4': '133.33%',
|
|
4924
|
-
'2:1': '50%',
|
|
4925
|
-
'auto': 'auto',
|
|
4926
|
-
};
|
|
4927
|
-
return {
|
|
4928
|
-
paddingBottom: ratios[ratio],
|
|
4929
|
-
};
|
|
4930
|
-
};
|
|
4918
|
+
// aspect ratio는 CSS 클래스로 처리되므로 인라인 스타일 불필요
|
|
4931
4919
|
// 둥근 모서리 클래스 계산
|
|
4932
4920
|
const getRoundedClass = () => {
|
|
4933
4921
|
if (rounded === true)
|
|
@@ -4954,7 +4942,6 @@ const Image$1 = ({ src, alt = '', ratio = 'auto', fit = 'cover', loading = 'lazy
|
|
|
4954
4942
|
height: fullHeight ? '100%' : height,
|
|
4955
4943
|
maxWidth,
|
|
4956
4944
|
maxHeight,
|
|
4957
|
-
...getAspectRatioStyle(),
|
|
4958
4945
|
};
|
|
4959
4946
|
const getRatioClass = () => {
|
|
4960
4947
|
if (ratio === 'auto')
|
|
@@ -6311,7 +6298,7 @@ const ContextMenu = ({ items, open, x, y, onClose, className, }) => {
|
|
|
6311
6298
|
}
|
|
6312
6299
|
const hasSubMenu = item.subItems && item.subItems.length > 0;
|
|
6313
6300
|
const isSubMenuOpen = activeSubMenu === item.id;
|
|
6314
|
-
return (jsxs("div", { className: "designbase-context-menu__item-wrapper", children: [jsx(MenuItem, { id: item.id, label: item.label || '', icon: item.icon, onClick: () => handleItemClick(item), disabled: item.disabled, variant: item.variant, className: item.className }), hasSubMenu && (jsx("div", { ref: (el) =>
|
|
6301
|
+
return (jsxs("div", { className: "designbase-context-menu__item-wrapper", children: [jsx(MenuItem, { id: item.id, label: item.label || '', icon: item.icon, onClick: () => handleItemClick(item), disabled: item.disabled, variant: item.variant, className: item.className }), hasSubMenu && (jsx("div", { ref: (el) => { subMenuRefs.current[item.id] = el; }, className: clsx('designbase-context-menu__submenu', {
|
|
6315
6302
|
'designbase-context-menu__submenu--open': isSubMenuOpen,
|
|
6316
6303
|
}), onMouseEnter: () => setActiveSubMenu(item.id), onMouseLeave: handleSubMenuClose, children: item.subItems.map((subItem, subIndex) => renderMenuItem(subItem, subIndex)) }))] }, item.id));
|
|
6317
6304
|
}, [activeSubMenu, handleItemClick, handleSubMenuOpen, handleSubMenuClose]);
|
|
@@ -8836,7 +8823,7 @@ const Masonry = ({ images, columns = 3, spacing = 'm', ratio = 'auto', fit = 'co
|
|
|
8836
8823
|
'designbase-masonry--infinite-scroll': infiniteScroll,
|
|
8837
8824
|
}, className);
|
|
8838
8825
|
const distributedImages = distributeImages();
|
|
8839
|
-
const renderImage = (image, index, columnIndex) => (jsxs("div", { ref: (el) =>
|
|
8826
|
+
const renderImage = (image, index, columnIndex) => (jsxs("div", { ref: (el) => { imageRefs.current[index] = el; }, className: clsx('designbase-masonry__item', {
|
|
8840
8827
|
'designbase-masonry__item--visible': visibleImages.includes(index),
|
|
8841
8828
|
}), style: {
|
|
8842
8829
|
animationDelay: `${index * animationDelay}ms`,
|
|
@@ -9549,15 +9536,16 @@ hideDelay = 80, alwaysShow = false, disabled = false, maxWidth = 300, showArrow
|
|
|
9549
9536
|
const classes = clsx('designbase-popover', `designbase-popover--${size}`, `designbase-popover--${variant}`, `designbase-popover--${position}`, { 'designbase-popover--visible': isOpen, 'designbase-popover--disabled': disabled }, className);
|
|
9550
9537
|
const arrowClasses = clsx('designbase-popover__arrow', `designbase-popover__arrow--${position}`);
|
|
9551
9538
|
// 자식에 트리거 이벤트 주입
|
|
9539
|
+
const childProps = children.props;
|
|
9552
9540
|
const enhancedChildren = React.cloneElement(children, {
|
|
9553
9541
|
ref: triggerRef,
|
|
9554
|
-
onClick: (e) => {
|
|
9555
|
-
onMouseEnter: (e) => {
|
|
9556
|
-
onMouseLeave: (e) => {
|
|
9557
|
-
onFocus: (e) => {
|
|
9558
|
-
onBlur: (e) => {
|
|
9559
|
-
onKeyDown: (e) => {
|
|
9560
|
-
tabIndex:
|
|
9542
|
+
onClick: (e) => { childProps.onClick?.(e); handleClick(e); },
|
|
9543
|
+
onMouseEnter: (e) => { childProps.onMouseEnter?.(e); handleMouseEnter(); },
|
|
9544
|
+
onMouseLeave: (e) => { childProps.onMouseLeave?.(e); handleMouseLeave(); },
|
|
9545
|
+
onFocus: (e) => { childProps.onFocus?.(e); handleFocus(); },
|
|
9546
|
+
onBlur: (e) => { childProps.onBlur?.(e); handleBlur(); },
|
|
9547
|
+
onKeyDown: (e) => { childProps.onKeyDown?.(e); handleKeyDown(e); },
|
|
9548
|
+
tabIndex: childProps.tabIndex ?? 0,
|
|
9561
9549
|
'aria-expanded': isOpen,
|
|
9562
9550
|
'aria-haspopup': 'dialog',
|
|
9563
9551
|
});
|
|
@@ -9608,16 +9596,20 @@ const ProgressStep = ({ items, size = 'm', layout = 'vertical', currentStep = 0,
|
|
|
9608
9596
|
const status = getStepStatus(index, item.status);
|
|
9609
9597
|
const isLast = index === items.length - 1;
|
|
9610
9598
|
const isClickable = clickable && !disabled && !item.disabled;
|
|
9599
|
+
// 연결선의 상태 결정: 현재 단계가 완료되었으면 completed로 표시
|
|
9600
|
+
const prevStatus = index > 0 ? getStepStatus(index - 1, items[index - 1].status) : 'pending';
|
|
9601
|
+
const connectorStatus = prevStatus === 'completed' ? 'completed' : status;
|
|
9611
9602
|
const stepClasses = clsx('designbase-progress-step__item', `designbase-progress-step__item--${status}`, {
|
|
9612
9603
|
'designbase-progress-step__item--clickable': isClickable,
|
|
9613
9604
|
'designbase-progress-step__item--disabled': item.disabled,
|
|
9614
9605
|
});
|
|
9615
|
-
|
|
9606
|
+
const connectorClasses = clsx('designbase-progress-step__connector', `designbase-progress-step__connector--${connectorStatus}`);
|
|
9607
|
+
return (jsxs("div", { className: stepClasses, children: [jsxs("div", { className: "designbase-progress-step__indicator-container", children: [jsxs("div", { className: "designbase-progress-step__indicator", onClick: () => handleStepClick(item, index), tabIndex: isClickable ? 0 : -1, role: isClickable ? 'button' : undefined, "aria-label": `${item.title} 단계로 이동`, onKeyDown: (e) => {
|
|
9616
9608
|
if (e.key === 'Enter' || e.key === ' ') {
|
|
9617
9609
|
e.preventDefault();
|
|
9618
9610
|
handleStepClick(item, index);
|
|
9619
9611
|
}
|
|
9620
|
-
}, children: item.icon ? (jsx("div", { className: "designbase-progress-step__icon", children: item.icon })) : (jsx("span", { className: "designbase-progress-step__number", children: index + 1 })) }), !isLast && (jsx("div", { className:
|
|
9612
|
+
}, children: [status === 'active' && (jsx("div", { className: "designbase-progress-step__pulse" })), item.icon ? (jsx("div", { className: "designbase-progress-step__icon", children: item.icon })) : (jsx("span", { className: "designbase-progress-step__number", children: index + 1 }))] }), !isLast && (jsx("div", { className: connectorClasses }))] }), jsxs("div", { className: "designbase-progress-step__content", children: [jsxs("div", { className: "designbase-progress-step__header", children: [jsx("h3", { className: "designbase-progress-step__title", children: item.title }), item.timestamp && (jsx("span", { className: "designbase-progress-step__timestamp", children: item.timestamp }))] }), item.description && (jsx("p", { className: "designbase-progress-step__description", children: item.description }))] })] }, item.id));
|
|
9621
9613
|
}) }));
|
|
9622
9614
|
};
|
|
9623
9615
|
|
|
@@ -11377,7 +11369,7 @@ const Tabs = ({ items, defaultSelectedId, selectedId, orientation = 'horizontal'
|
|
|
11377
11369
|
};
|
|
11378
11370
|
Tabs.displayName = 'Tabs';
|
|
11379
11371
|
|
|
11380
|
-
const Timeline = ({ items,
|
|
11372
|
+
const Timeline = ({ items, type = 'alternate', variant = 'default', size = 'm', color = 'primary', clickable = false, fullWidth = false, disabled = false, className, style, onItemClick, }) => {
|
|
11381
11373
|
const handleItemClick = (item, index) => {
|
|
11382
11374
|
if (disabled || item.disabled || !clickable)
|
|
11383
11375
|
return;
|
|
@@ -11385,20 +11377,13 @@ const Timeline = ({ items, position = 'alternate', variant = 'default', size = '
|
|
|
11385
11377
|
onItemClick?.(item, index);
|
|
11386
11378
|
};
|
|
11387
11379
|
const getItemPosition = (index) => {
|
|
11388
|
-
|
|
11389
|
-
|
|
11390
|
-
return 'left';
|
|
11391
|
-
case 'right':
|
|
11392
|
-
return 'right';
|
|
11393
|
-
case 'alternate':
|
|
11394
|
-
return index % 2 === 0 ? 'left' : 'right';
|
|
11395
|
-
case 'reverse-alternate':
|
|
11396
|
-
return index % 2 === 0 ? 'right' : 'left';
|
|
11397
|
-
default:
|
|
11398
|
-
return 'left';
|
|
11380
|
+
if (type === 'left') {
|
|
11381
|
+
return 'left';
|
|
11399
11382
|
}
|
|
11383
|
+
// alternate 타입: 짝수는 왼쪽, 홀수는 오른쪽
|
|
11384
|
+
return index % 2 === 0 ? 'left' : 'right';
|
|
11400
11385
|
};
|
|
11401
|
-
const classes = clsx('designbase-timeline', `designbase-timeline--${
|
|
11386
|
+
const classes = clsx('designbase-timeline', `designbase-timeline--${type}`, `designbase-timeline--${variant}`, `designbase-timeline--${size}`, {
|
|
11402
11387
|
'designbase-timeline--clickable': clickable,
|
|
11403
11388
|
'designbase-timeline--full-width': fullWidth,
|
|
11404
11389
|
'designbase-timeline--disabled': disabled,
|
|
@@ -11413,30 +11398,29 @@ const Timeline = ({ items, position = 'alternate', variant = 'default', size = '
|
|
|
11413
11398
|
'designbase-timeline__item--disabled': item.disabled,
|
|
11414
11399
|
});
|
|
11415
11400
|
const contentClasses = clsx('designbase-timeline__content', `designbase-timeline__content--${itemPosition}`);
|
|
11416
|
-
const separatorClasses = clsx('designbase-timeline__separator', `designbase-timeline__separator--${itemPosition}`);
|
|
11417
11401
|
const dotClasses = clsx('designbase-timeline__dot', `designbase-timeline__dot--${itemColor}`, `designbase-timeline__dot--${variant}`, {
|
|
11418
11402
|
'designbase-timeline__dot--clickable': isClickable,
|
|
11419
11403
|
});
|
|
11420
|
-
return (jsxs("div", { className: itemClasses, children: [
|
|
11421
|
-
if (e.key === 'Enter' || e.key === ' ') {
|
|
11422
|
-
e.preventDefault();
|
|
11423
|
-
handleItemClick(item, index);
|
|
11424
|
-
}
|
|
11425
|
-
}, children: [item.timestamp && (jsx("div", { className: "designbase-timeline__timestamp", children: item.timestamp })), jsx("h3", { className: "designbase-timeline__title", children: item.title }), item.description && (jsx("p", { className: "designbase-timeline__description", children: item.description }))] }) }), jsxs("div", { className: separatorClasses, children: [jsx("div", { className: dotClasses, onClick: () => handleItemClick(item, index), tabIndex: isClickable ? 0 : -1, role: isClickable ? 'button' : undefined, "aria-label": `${item.title} 타임라인 점`, onKeyDown: (e) => {
|
|
11404
|
+
return (jsxs("div", { className: itemClasses, children: [jsxs("div", { className: "designbase-timeline__indicator-container", children: [jsx("div", { className: dotClasses, onClick: () => handleItemClick(item, index), tabIndex: isClickable ? 0 : -1, role: isClickable ? 'button' : undefined, "aria-label": `${item.title} 타임라인 점`, onKeyDown: (e) => {
|
|
11426
11405
|
if (e.key === 'Enter' || e.key === ' ') {
|
|
11427
11406
|
e.preventDefault();
|
|
11428
11407
|
handleItemClick(item, index);
|
|
11429
11408
|
}
|
|
11430
|
-
}, children: item.icon ? (jsx("div", { className: "designbase-timeline__icon", children: item.icon })) : (jsx("
|
|
11409
|
+
}, children: item.icon ? (jsx("div", { className: "designbase-timeline__icon", children: item.icon })) : (jsx("span", { className: "designbase-timeline__number", children: index + 1 })) }), !isLast && (jsx("div", { className: "designbase-timeline__connector" }))] }), jsx("div", { className: contentClasses, children: jsxs("div", { className: "designbase-timeline__content-inner", onClick: () => handleItemClick(item, index), tabIndex: isClickable ? 0 : -1, role: isClickable ? 'button' : undefined, "aria-label": `${item.title} 타임라인 아이템`, onKeyDown: (e) => {
|
|
11410
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
11411
|
+
e.preventDefault();
|
|
11412
|
+
handleItemClick(item, index);
|
|
11413
|
+
}
|
|
11414
|
+
}, children: [item.timestamp && (jsx("div", { className: "designbase-timeline__timestamp", children: item.timestamp })), jsx("h3", { className: "designbase-timeline__title", children: item.title }), item.description && (jsx("p", { className: "designbase-timeline__description", children: item.description }))] }) })] }, item.id));
|
|
11431
11415
|
}) }) }));
|
|
11432
11416
|
};
|
|
11433
11417
|
|
|
11434
|
-
const Toast = ({ id, status = 'info', title, description, icon: Icon, duration = 5000, showProgress = false, showCloseButton = true,
|
|
11418
|
+
const Toast = ({ id, status = 'info', title, description, icon: Icon, duration = 5000, showProgress = false, showCloseButton = true, onClose, className, }) => {
|
|
11435
11419
|
const [isVisible, setIsVisible] = useState(false);
|
|
11436
11420
|
const [progress, setProgress] = useState(100);
|
|
11437
11421
|
const progressRef = useRef(null);
|
|
11438
|
-
const timeoutRef = useRef();
|
|
11439
|
-
const progressIntervalRef = useRef();
|
|
11422
|
+
const timeoutRef = useRef(undefined);
|
|
11423
|
+
const progressIntervalRef = useRef(undefined);
|
|
11440
11424
|
// 토스트 표시 애니메이션
|
|
11441
11425
|
useEffect(() => {
|
|
11442
11426
|
const timer = setTimeout(() => setIsVisible(true), 50);
|
|
@@ -11482,7 +11466,7 @@ const Toast = ({ id, status = 'info', title, description, icon: Icon, duration =
|
|
|
11482
11466
|
clearInterval(progressIntervalRef.current);
|
|
11483
11467
|
handleClose();
|
|
11484
11468
|
};
|
|
11485
|
-
const classes = clsx('designbase-toast', `designbase-toast--${status}`,
|
|
11469
|
+
const classes = clsx('designbase-toast', `designbase-toast--${status}`, {
|
|
11486
11470
|
'designbase-toast--visible': isVisible,
|
|
11487
11471
|
'designbase-toast--with-icon': Icon,
|
|
11488
11472
|
'designbase-toast--with-description': description,
|
|
@@ -11544,7 +11528,7 @@ const useToast = () => {
|
|
|
11544
11528
|
}
|
|
11545
11529
|
return context;
|
|
11546
11530
|
};
|
|
11547
|
-
const ToastProvider = ({ children }) => {
|
|
11531
|
+
const ToastProvider = ({ children, position = 'top-right' }) => {
|
|
11548
11532
|
const [toasts, setToasts] = useState([]);
|
|
11549
11533
|
const addToast = useCallback((toast) => {
|
|
11550
11534
|
const id = `toast-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
@@ -11561,7 +11545,7 @@ const ToastProvider = ({ children }) => {
|
|
|
11561
11545
|
const removeToast = useCallback((id) => {
|
|
11562
11546
|
setToasts(prev => prev.filter(toast => toast.id !== id));
|
|
11563
11547
|
}, []);
|
|
11564
|
-
return (jsxs(ToastContext.Provider, { value: { addToast, removeToast }, children: [children, jsx(ToastContainer, { toasts: toasts, onRemoveToast: removeToast })] }));
|
|
11548
|
+
return (jsxs(ToastContext.Provider, { value: { addToast, removeToast }, children: [children, jsx(ToastContainer, { toasts: toasts, position: position, onRemoveToast: removeToast })] }));
|
|
11565
11549
|
};
|
|
11566
11550
|
|
|
11567
11551
|
const Toggle = forwardRef(({ isSelected, defaultSelected, isDisabled = false, isReadOnly = false, size = 'm', children, className, onChange, ...props }, forwardedRef) => {
|