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