@designbasekorea/ui 0.3.2 → 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 +5 -6
- package/dist/index.esm.css +1 -1
- package/dist/index.esm.css.map +1 -1
- package/dist/index.esm.js +80 -102
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +80 -102
- 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 +80 -102
- package/dist/index.umd.js.map +1 -1
- package/package.json +5 -5
package/dist/index.umd.js
CHANGED
|
@@ -2195,9 +2195,13 @@
|
|
|
2195
2195
|
};
|
|
2196
2196
|
Spinner.displayName = 'Spinner';
|
|
2197
2197
|
|
|
2198
|
-
const GAP$1 = 8; // 트리거와의 간격
|
|
2199
|
-
const ARW = 6; //
|
|
2200
|
-
const PAD = 8; //
|
|
2198
|
+
const GAP$1 = 8; // 트리거와의 간격(박스)
|
|
2199
|
+
const ARW = 6; // border 삼각형 사이즈(너 SCSS에서 6px)
|
|
2200
|
+
const PAD = 8; // start/end 여백
|
|
2201
|
+
// ✅ 네가 말한 “-10이 되어야 제대로”를 상수로 고정
|
|
2202
|
+
const OUT = -10; // bottom일 때 top, right일 때 left
|
|
2203
|
+
// ✅ top/left는 대칭적으로 “박스에 살짝 겹치게” 만들어 seam 제거
|
|
2204
|
+
const INSET = 2; // (pRect.height - 2), (pRect.width - 2)
|
|
2201
2205
|
const Tooltip = ({ content, children, position = 'top', size = 'm', variant = 'default', delay = 200, hideDelay = 80, alwaysShow = false, disabled = false, maxWidth = 240, showArrow = true, className, ...props }) => {
|
|
2202
2206
|
const [visible, setVisible] = React.useState(false);
|
|
2203
2207
|
const [style, setStyle] = React.useState({});
|
|
@@ -2216,115 +2220,110 @@
|
|
|
2216
2220
|
const groupOf = (p) => p.startsWith('top') ? 'top' :
|
|
2217
2221
|
p.startsWith('bottom') ? 'bottom' :
|
|
2218
2222
|
p.startsWith('left') ? 'left' : 'right';
|
|
2219
|
-
// 위치 계산 (⚠️ 뷰포트 클램핑 후 화살표도 보정)
|
|
2220
2223
|
const calculatePosition = React.useCallback(() => {
|
|
2221
2224
|
if (!triggerRef.current || !tooltipRef.current)
|
|
2222
2225
|
return;
|
|
2223
2226
|
const tRect = triggerRef.current.getBoundingClientRect();
|
|
2224
2227
|
const pRect = tooltipRef.current.getBoundingClientRect();
|
|
2225
2228
|
let top = 0, left = 0;
|
|
2226
|
-
// 1차: 이상적(미보정) 화살표 좌표
|
|
2227
2229
|
let aTop = 0, aLeft = 0;
|
|
2228
2230
|
switch (position) {
|
|
2229
2231
|
case 'top':
|
|
2230
2232
|
top = tRect.top - pRect.height - GAP$1;
|
|
2231
2233
|
left = tRect.left + tRect.width / 2 - pRect.width / 2;
|
|
2232
|
-
aTop = pRect.height;
|
|
2234
|
+
aTop = pRect.height - INSET; // ✅ top은 박스 아래쪽에 살짝 겹침
|
|
2233
2235
|
aLeft = pRect.width / 2 - ARW;
|
|
2234
2236
|
break;
|
|
2235
2237
|
case 'top-start':
|
|
2236
2238
|
top = tRect.top - pRect.height - GAP$1;
|
|
2237
2239
|
left = tRect.left;
|
|
2238
|
-
aTop = pRect.height;
|
|
2240
|
+
aTop = pRect.height - INSET;
|
|
2239
2241
|
aLeft = PAD;
|
|
2240
2242
|
break;
|
|
2241
2243
|
case 'top-end':
|
|
2242
2244
|
top = tRect.top - pRect.height - GAP$1;
|
|
2243
2245
|
left = tRect.right - pRect.width;
|
|
2244
|
-
aTop = pRect.height;
|
|
2245
|
-
aLeft = pRect.width - PAD;
|
|
2246
|
+
aTop = pRect.height - INSET;
|
|
2247
|
+
aLeft = pRect.width - PAD - ARW;
|
|
2246
2248
|
break;
|
|
2247
2249
|
case 'bottom':
|
|
2248
2250
|
top = tRect.bottom + GAP$1;
|
|
2249
2251
|
left = tRect.left + tRect.width / 2 - pRect.width / 2;
|
|
2250
|
-
aTop = -
|
|
2252
|
+
aTop = OUT; // ✅ 네 요구: -10
|
|
2251
2253
|
aLeft = pRect.width / 2 - ARW;
|
|
2252
2254
|
break;
|
|
2253
2255
|
case 'bottom-start':
|
|
2254
2256
|
top = tRect.bottom + GAP$1;
|
|
2255
2257
|
left = tRect.left;
|
|
2256
|
-
aTop = -
|
|
2258
|
+
aTop = OUT; // ✅ -10
|
|
2257
2259
|
aLeft = PAD;
|
|
2258
2260
|
break;
|
|
2259
2261
|
case 'bottom-end':
|
|
2260
2262
|
top = tRect.bottom + GAP$1;
|
|
2261
2263
|
left = tRect.right - pRect.width;
|
|
2262
|
-
aTop = -
|
|
2263
|
-
aLeft = pRect.width - PAD;
|
|
2264
|
+
aTop = OUT; // ✅ -10
|
|
2265
|
+
aLeft = pRect.width - PAD - ARW;
|
|
2264
2266
|
break;
|
|
2265
2267
|
case 'left':
|
|
2266
2268
|
top = tRect.top + tRect.height / 2 - pRect.height / 2;
|
|
2267
2269
|
left = tRect.left - pRect.width - GAP$1;
|
|
2268
2270
|
aTop = pRect.height / 2 - ARW;
|
|
2269
|
-
aLeft = pRect.width;
|
|
2271
|
+
aLeft = pRect.width - INSET; // ✅ left는 박스 오른쪽에 살짝 겹침
|
|
2270
2272
|
break;
|
|
2271
2273
|
case 'left-start':
|
|
2272
2274
|
top = tRect.top;
|
|
2273
2275
|
left = tRect.left - pRect.width - GAP$1;
|
|
2274
2276
|
aTop = PAD;
|
|
2275
|
-
aLeft = pRect.width;
|
|
2277
|
+
aLeft = pRect.width - INSET;
|
|
2276
2278
|
break;
|
|
2277
2279
|
case 'left-end':
|
|
2278
2280
|
top = tRect.bottom - pRect.height;
|
|
2279
2281
|
left = tRect.left - pRect.width - GAP$1;
|
|
2280
|
-
aTop = pRect.height - PAD;
|
|
2281
|
-
aLeft = pRect.width;
|
|
2282
|
+
aTop = pRect.height - PAD - ARW;
|
|
2283
|
+
aLeft = pRect.width - INSET;
|
|
2282
2284
|
break;
|
|
2283
2285
|
case 'right':
|
|
2284
2286
|
top = tRect.top + tRect.height / 2 - pRect.height / 2;
|
|
2285
2287
|
left = tRect.right + GAP$1;
|
|
2286
2288
|
aTop = pRect.height / 2 - ARW;
|
|
2287
|
-
aLeft =
|
|
2289
|
+
aLeft = OUT; // ✅ 네 요구: left:-10
|
|
2288
2290
|
break;
|
|
2289
2291
|
case 'right-start':
|
|
2290
2292
|
top = tRect.top;
|
|
2291
2293
|
left = tRect.right + GAP$1;
|
|
2292
2294
|
aTop = PAD;
|
|
2293
|
-
aLeft = -
|
|
2295
|
+
aLeft = OUT; // ✅ -10
|
|
2294
2296
|
break;
|
|
2295
2297
|
case 'right-end':
|
|
2296
2298
|
top = tRect.bottom - pRect.height;
|
|
2297
2299
|
left = tRect.right + GAP$1;
|
|
2298
|
-
aTop = pRect.height - PAD;
|
|
2299
|
-
aLeft = -
|
|
2300
|
+
aTop = pRect.height - PAD - ARW;
|
|
2301
|
+
aLeft = OUT; // ✅ -10
|
|
2300
2302
|
break;
|
|
2301
2303
|
}
|
|
2302
|
-
// 뷰포트 클램핑
|
|
2304
|
+
// 뷰포트 클램핑(툴팁 박스)
|
|
2303
2305
|
const vw = window.innerWidth;
|
|
2304
2306
|
const vh = window.innerHeight;
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2307
|
+
const EDGE = 8;
|
|
2308
|
+
if (left < EDGE)
|
|
2309
|
+
left = EDGE;
|
|
2310
|
+
if (left + pRect.width > vw - EDGE)
|
|
2311
|
+
left = vw - pRect.width - EDGE;
|
|
2312
|
+
if (top < EDGE)
|
|
2313
|
+
top = EDGE;
|
|
2314
|
+
if (top + pRect.height > vh - EDGE)
|
|
2315
|
+
top = vh - pRect.height - EDGE;
|
|
2316
|
+
// 클램핑으로 박스가 이동했을 때, 화살표가 트리거를 향하도록 보정
|
|
2314
2317
|
const g = groupOf(position);
|
|
2315
2318
|
if (g === 'top' || g === 'bottom') {
|
|
2316
|
-
// 트리거 중앙 X 를 툴팁 좌표계로 변환
|
|
2317
2319
|
const triggerCenterX = tRect.left + tRect.width / 2;
|
|
2318
|
-
const localX = triggerCenterX - left - ARW;
|
|
2319
|
-
|
|
2320
|
-
aLeft = Math.min(pRect.width - PAD, Math.max(PAD, localX));
|
|
2321
|
-
// aTop은 이미 위/아래에 고정(-ARW 또는 높이)
|
|
2320
|
+
const localX = triggerCenterX - left - ARW;
|
|
2321
|
+
aLeft = Math.min(pRect.width - PAD - ARW, Math.max(PAD, localX));
|
|
2322
2322
|
}
|
|
2323
2323
|
else {
|
|
2324
2324
|
const triggerCenterY = tRect.top + tRect.height / 2;
|
|
2325
2325
|
const localY = triggerCenterY - top - ARW;
|
|
2326
|
-
aTop = Math.min(pRect.height - PAD, Math.max(PAD, localY));
|
|
2327
|
-
// aLeft는 이미 좌/우에 고정(-ARW 또는 너비)
|
|
2326
|
+
aTop = Math.min(pRect.height - PAD - ARW, Math.max(PAD, localY));
|
|
2328
2327
|
}
|
|
2329
2328
|
setStyle({
|
|
2330
2329
|
position: 'fixed',
|
|
@@ -2332,17 +2331,15 @@
|
|
|
2332
2331
|
left,
|
|
2333
2332
|
maxWidth,
|
|
2334
2333
|
zIndex: 9999,
|
|
2335
|
-
pointerEvents: 'none',
|
|
2334
|
+
pointerEvents: 'none',
|
|
2336
2335
|
});
|
|
2337
2336
|
setArrowStyle({ position: 'absolute', top: aTop, left: aLeft });
|
|
2338
2337
|
setPlacementGroup(g);
|
|
2339
2338
|
}, [position, maxWidth]);
|
|
2340
|
-
// 초기 페인트 전에 위치 확정
|
|
2341
2339
|
React.useLayoutEffect(() => {
|
|
2342
2340
|
if (visible || alwaysShow)
|
|
2343
2341
|
calculatePosition();
|
|
2344
2342
|
}, [visible, alwaysShow, calculatePosition]);
|
|
2345
|
-
// 스크롤/리사이즈/크기변화 추적 (rAF 스로틀)
|
|
2346
2343
|
React.useEffect(() => {
|
|
2347
2344
|
if (!(visible || alwaysShow))
|
|
2348
2345
|
return;
|
|
@@ -2373,7 +2370,6 @@
|
|
|
2373
2370
|
cancelAnimationFrame(rafId.current);
|
|
2374
2371
|
};
|
|
2375
2372
|
}, [visible, alwaysShow, calculatePosition]);
|
|
2376
|
-
// show/hide
|
|
2377
2373
|
const show = React.useCallback(() => {
|
|
2378
2374
|
if (disabled)
|
|
2379
2375
|
return;
|
|
@@ -2387,10 +2383,12 @@
|
|
|
2387
2383
|
timers.current.t = setTimeout(() => setVisible(false), Math.max(0, hideDelay));
|
|
2388
2384
|
}, [disabled, hideDelay]);
|
|
2389
2385
|
React.useEffect(() => () => clearTimer(), []);
|
|
2390
|
-
React.useEffect(() => {
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2386
|
+
React.useEffect(() => {
|
|
2387
|
+
if (!disabled && alwaysShow)
|
|
2388
|
+
setVisible(true);
|
|
2389
|
+
else if (!alwaysShow)
|
|
2390
|
+
setVisible(false);
|
|
2391
|
+
}, [alwaysShow, disabled]);
|
|
2394
2392
|
const onKeyDown = React.useCallback((e) => {
|
|
2395
2393
|
if (e.key === 'Escape') {
|
|
2396
2394
|
clearTimer();
|
|
@@ -4918,23 +4916,7 @@
|
|
|
4918
4916
|
onError?.();
|
|
4919
4917
|
}
|
|
4920
4918
|
};
|
|
4921
|
-
// aspect ratio
|
|
4922
|
-
const getAspectRatioStyle = () => {
|
|
4923
|
-
if (ratio === 'auto')
|
|
4924
|
-
return {};
|
|
4925
|
-
const ratios = {
|
|
4926
|
-
'1:1': '100%',
|
|
4927
|
-
'16:9': '56.25%',
|
|
4928
|
-
'4:3': '75%',
|
|
4929
|
-
'3:2': '66.67%',
|
|
4930
|
-
'3:4': '133.33%',
|
|
4931
|
-
'2:1': '50%',
|
|
4932
|
-
'auto': 'auto',
|
|
4933
|
-
};
|
|
4934
|
-
return {
|
|
4935
|
-
paddingBottom: ratios[ratio],
|
|
4936
|
-
};
|
|
4937
|
-
};
|
|
4919
|
+
// aspect ratio는 CSS 클래스로 처리되므로 인라인 스타일 불필요
|
|
4938
4920
|
// 둥근 모서리 클래스 계산
|
|
4939
4921
|
const getRoundedClass = () => {
|
|
4940
4922
|
if (rounded === true)
|
|
@@ -4961,7 +4943,6 @@
|
|
|
4961
4943
|
height: fullHeight ? '100%' : height,
|
|
4962
4944
|
maxWidth,
|
|
4963
4945
|
maxHeight,
|
|
4964
|
-
...getAspectRatioStyle(),
|
|
4965
4946
|
};
|
|
4966
4947
|
const getRatioClass = () => {
|
|
4967
4948
|
if (ratio === 'auto')
|
|
@@ -6318,7 +6299,7 @@
|
|
|
6318
6299
|
}
|
|
6319
6300
|
const hasSubMenu = item.subItems && item.subItems.length > 0;
|
|
6320
6301
|
const isSubMenuOpen = activeSubMenu === item.id;
|
|
6321
|
-
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) =>
|
|
6302
|
+
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', {
|
|
6322
6303
|
'designbase-context-menu__submenu--open': isSubMenuOpen,
|
|
6323
6304
|
}), onMouseEnter: () => setActiveSubMenu(item.id), onMouseLeave: handleSubMenuClose, children: item.subItems.map((subItem, subIndex) => renderMenuItem(subItem, subIndex)) }))] }, item.id));
|
|
6324
6305
|
}, [activeSubMenu, handleItemClick, handleSubMenuOpen, handleSubMenuClose]);
|
|
@@ -8843,7 +8824,7 @@
|
|
|
8843
8824
|
'designbase-masonry--infinite-scroll': infiniteScroll,
|
|
8844
8825
|
}, className);
|
|
8845
8826
|
const distributedImages = distributeImages();
|
|
8846
|
-
const renderImage = (image, index, columnIndex) => (jsxRuntime.jsxs("div", { ref: (el) =>
|
|
8827
|
+
const renderImage = (image, index, columnIndex) => (jsxRuntime.jsxs("div", { ref: (el) => { imageRefs.current[index] = el; }, className: clsx('designbase-masonry__item', {
|
|
8847
8828
|
'designbase-masonry__item--visible': visibleImages.includes(index),
|
|
8848
8829
|
}), style: {
|
|
8849
8830
|
animationDelay: `${index * animationDelay}ms`,
|
|
@@ -9556,15 +9537,16 @@
|
|
|
9556
9537
|
const classes = clsx('designbase-popover', `designbase-popover--${size}`, `designbase-popover--${variant}`, `designbase-popover--${position}`, { 'designbase-popover--visible': isOpen, 'designbase-popover--disabled': disabled }, className);
|
|
9557
9538
|
const arrowClasses = clsx('designbase-popover__arrow', `designbase-popover__arrow--${position}`);
|
|
9558
9539
|
// 자식에 트리거 이벤트 주입
|
|
9540
|
+
const childProps = children.props;
|
|
9559
9541
|
const enhancedChildren = React.cloneElement(children, {
|
|
9560
9542
|
ref: triggerRef,
|
|
9561
|
-
onClick: (e) => {
|
|
9562
|
-
onMouseEnter: (e) => {
|
|
9563
|
-
onMouseLeave: (e) => {
|
|
9564
|
-
onFocus: (e) => {
|
|
9565
|
-
onBlur: (e) => {
|
|
9566
|
-
onKeyDown: (e) => {
|
|
9567
|
-
tabIndex:
|
|
9543
|
+
onClick: (e) => { childProps.onClick?.(e); handleClick(e); },
|
|
9544
|
+
onMouseEnter: (e) => { childProps.onMouseEnter?.(e); handleMouseEnter(); },
|
|
9545
|
+
onMouseLeave: (e) => { childProps.onMouseLeave?.(e); handleMouseLeave(); },
|
|
9546
|
+
onFocus: (e) => { childProps.onFocus?.(e); handleFocus(); },
|
|
9547
|
+
onBlur: (e) => { childProps.onBlur?.(e); handleBlur(); },
|
|
9548
|
+
onKeyDown: (e) => { childProps.onKeyDown?.(e); handleKeyDown(e); },
|
|
9549
|
+
tabIndex: childProps.tabIndex ?? 0,
|
|
9568
9550
|
'aria-expanded': isOpen,
|
|
9569
9551
|
'aria-haspopup': 'dialog',
|
|
9570
9552
|
});
|
|
@@ -9615,16 +9597,20 @@
|
|
|
9615
9597
|
const status = getStepStatus(index, item.status);
|
|
9616
9598
|
const isLast = index === items.length - 1;
|
|
9617
9599
|
const isClickable = clickable && !disabled && !item.disabled;
|
|
9600
|
+
// 연결선의 상태 결정: 현재 단계가 완료되었으면 completed로 표시
|
|
9601
|
+
const prevStatus = index > 0 ? getStepStatus(index - 1, items[index - 1].status) : 'pending';
|
|
9602
|
+
const connectorStatus = prevStatus === 'completed' ? 'completed' : status;
|
|
9618
9603
|
const stepClasses = clsx('designbase-progress-step__item', `designbase-progress-step__item--${status}`, {
|
|
9619
9604
|
'designbase-progress-step__item--clickable': isClickable,
|
|
9620
9605
|
'designbase-progress-step__item--disabled': item.disabled,
|
|
9621
9606
|
});
|
|
9622
|
-
|
|
9607
|
+
const connectorClasses = clsx('designbase-progress-step__connector', `designbase-progress-step__connector--${connectorStatus}`);
|
|
9608
|
+
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) => {
|
|
9623
9609
|
if (e.key === 'Enter' || e.key === ' ') {
|
|
9624
9610
|
e.preventDefault();
|
|
9625
9611
|
handleStepClick(item, index);
|
|
9626
9612
|
}
|
|
9627
|
-
}, 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:
|
|
9613
|
+
}, 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));
|
|
9628
9614
|
}) }));
|
|
9629
9615
|
};
|
|
9630
9616
|
|
|
@@ -11384,7 +11370,7 @@
|
|
|
11384
11370
|
};
|
|
11385
11371
|
Tabs.displayName = 'Tabs';
|
|
11386
11372
|
|
|
11387
|
-
const Timeline = ({ items,
|
|
11373
|
+
const Timeline = ({ items, type = 'alternate', variant = 'default', size = 'm', color = 'primary', clickable = false, fullWidth = false, disabled = false, className, style, onItemClick, }) => {
|
|
11388
11374
|
const handleItemClick = (item, index) => {
|
|
11389
11375
|
if (disabled || item.disabled || !clickable)
|
|
11390
11376
|
return;
|
|
@@ -11392,20 +11378,13 @@
|
|
|
11392
11378
|
onItemClick?.(item, index);
|
|
11393
11379
|
};
|
|
11394
11380
|
const getItemPosition = (index) => {
|
|
11395
|
-
|
|
11396
|
-
|
|
11397
|
-
return 'left';
|
|
11398
|
-
case 'right':
|
|
11399
|
-
return 'right';
|
|
11400
|
-
case 'alternate':
|
|
11401
|
-
return index % 2 === 0 ? 'left' : 'right';
|
|
11402
|
-
case 'reverse-alternate':
|
|
11403
|
-
return index % 2 === 0 ? 'right' : 'left';
|
|
11404
|
-
default:
|
|
11405
|
-
return 'left';
|
|
11381
|
+
if (type === 'left') {
|
|
11382
|
+
return 'left';
|
|
11406
11383
|
}
|
|
11384
|
+
// alternate 타입: 짝수는 왼쪽, 홀수는 오른쪽
|
|
11385
|
+
return index % 2 === 0 ? 'left' : 'right';
|
|
11407
11386
|
};
|
|
11408
|
-
const classes = clsx('designbase-timeline', `designbase-timeline--${
|
|
11387
|
+
const classes = clsx('designbase-timeline', `designbase-timeline--${type}`, `designbase-timeline--${variant}`, `designbase-timeline--${size}`, {
|
|
11409
11388
|
'designbase-timeline--clickable': clickable,
|
|
11410
11389
|
'designbase-timeline--full-width': fullWidth,
|
|
11411
11390
|
'designbase-timeline--disabled': disabled,
|
|
@@ -11420,30 +11399,29 @@
|
|
|
11420
11399
|
'designbase-timeline__item--disabled': item.disabled,
|
|
11421
11400
|
});
|
|
11422
11401
|
const contentClasses = clsx('designbase-timeline__content', `designbase-timeline__content--${itemPosition}`);
|
|
11423
|
-
const separatorClasses = clsx('designbase-timeline__separator', `designbase-timeline__separator--${itemPosition}`);
|
|
11424
11402
|
const dotClasses = clsx('designbase-timeline__dot', `designbase-timeline__dot--${itemColor}`, `designbase-timeline__dot--${variant}`, {
|
|
11425
11403
|
'designbase-timeline__dot--clickable': isClickable,
|
|
11426
11404
|
});
|
|
11427
|
-
return (jsxRuntime.jsxs("div", { className: itemClasses, children: [jsxRuntime.
|
|
11428
|
-
if (e.key === 'Enter' || e.key === ' ') {
|
|
11429
|
-
e.preventDefault();
|
|
11430
|
-
handleItemClick(item, index);
|
|
11431
|
-
}
|
|
11432
|
-
}, 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) => {
|
|
11405
|
+
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) => {
|
|
11433
11406
|
if (e.key === 'Enter' || e.key === ' ') {
|
|
11434
11407
|
e.preventDefault();
|
|
11435
11408
|
handleItemClick(item, index);
|
|
11436
11409
|
}
|
|
11437
|
-
}, children: item.icon ? (jsxRuntime.jsx("div", { className: "designbase-timeline__icon", children: item.icon })) : (jsxRuntime.jsx("
|
|
11410
|
+
}, 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) => {
|
|
11411
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
11412
|
+
e.preventDefault();
|
|
11413
|
+
handleItemClick(item, index);
|
|
11414
|
+
}
|
|
11415
|
+
}, 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));
|
|
11438
11416
|
}) }) }));
|
|
11439
11417
|
};
|
|
11440
11418
|
|
|
11441
|
-
const Toast = ({ id, status = 'info', title, description, icon: Icon, duration = 5000, showProgress = false, showCloseButton = true,
|
|
11419
|
+
const Toast = ({ id, status = 'info', title, description, icon: Icon, duration = 5000, showProgress = false, showCloseButton = true, onClose, className, }) => {
|
|
11442
11420
|
const [isVisible, setIsVisible] = React.useState(false);
|
|
11443
11421
|
const [progress, setProgress] = React.useState(100);
|
|
11444
11422
|
const progressRef = React.useRef(null);
|
|
11445
|
-
const timeoutRef = React.useRef();
|
|
11446
|
-
const progressIntervalRef = React.useRef();
|
|
11423
|
+
const timeoutRef = React.useRef(undefined);
|
|
11424
|
+
const progressIntervalRef = React.useRef(undefined);
|
|
11447
11425
|
// 토스트 표시 애니메이션
|
|
11448
11426
|
React.useEffect(() => {
|
|
11449
11427
|
const timer = setTimeout(() => setIsVisible(true), 50);
|
|
@@ -11489,7 +11467,7 @@
|
|
|
11489
11467
|
clearInterval(progressIntervalRef.current);
|
|
11490
11468
|
handleClose();
|
|
11491
11469
|
};
|
|
11492
|
-
const classes = clsx('designbase-toast', `designbase-toast--${status}`,
|
|
11470
|
+
const classes = clsx('designbase-toast', `designbase-toast--${status}`, {
|
|
11493
11471
|
'designbase-toast--visible': isVisible,
|
|
11494
11472
|
'designbase-toast--with-icon': Icon,
|
|
11495
11473
|
'designbase-toast--with-description': description,
|
|
@@ -11551,7 +11529,7 @@
|
|
|
11551
11529
|
}
|
|
11552
11530
|
return context;
|
|
11553
11531
|
};
|
|
11554
|
-
const ToastProvider = ({ children }) => {
|
|
11532
|
+
const ToastProvider = ({ children, position = 'top-right' }) => {
|
|
11555
11533
|
const [toasts, setToasts] = React.useState([]);
|
|
11556
11534
|
const addToast = React.useCallback((toast) => {
|
|
11557
11535
|
const id = `toast-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
@@ -11568,7 +11546,7 @@
|
|
|
11568
11546
|
const removeToast = React.useCallback((id) => {
|
|
11569
11547
|
setToasts(prev => prev.filter(toast => toast.id !== id));
|
|
11570
11548
|
}, []);
|
|
11571
|
-
return (jsxRuntime.jsxs(ToastContext.Provider, { value: { addToast, removeToast }, children: [children, jsxRuntime.jsx(ToastContainer, { toasts: toasts, onRemoveToast: removeToast })] }));
|
|
11549
|
+
return (jsxRuntime.jsxs(ToastContext.Provider, { value: { addToast, removeToast }, children: [children, jsxRuntime.jsx(ToastContainer, { toasts: toasts, position: position, onRemoveToast: removeToast })] }));
|
|
11572
11550
|
};
|
|
11573
11551
|
|
|
11574
11552
|
const Toggle = React.forwardRef(({ isSelected, defaultSelected, isDisabled = false, isReadOnly = false, size = 'm', children, className, onChange, ...props }, forwardedRef) => {
|