@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.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 = -ARW;
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 = -ARW;
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 = -ARW;
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 = -ARW;
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 = -ARW;
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 = -ARW;
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
- if (left < 8)
2306
- left = 8;
2307
- if (left + pRect.width > vw - 8)
2308
- left = vw - pRect.width - 8;
2309
- if (top < 8)
2310
- top = 8;
2311
- if (top + pRect.height > vh - 8)
2312
- top = vh - pRect.height - 8;
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
- // 8px ~ (width-8px) 범위로 제한
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', // hover 유지
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(() => { if (!disabled && alwaysShow)
2391
- setVisible(true);
2392
- else if (!alwaysShow)
2393
- setVisible(false); }, [alwaysShow, disabled]);
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) => (subMenuRefs.current[item.id] = el), className: clsx('designbase-context-menu__submenu', {
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) => (imageRefs.current[index] = el), className: clsx('designbase-masonry__item', {
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) => { children.props.onClick?.(e); handleClick(e); },
9562
- onMouseEnter: (e) => { children.props.onMouseEnter?.(e); handleMouseEnter(); },
9563
- onMouseLeave: (e) => { children.props.onMouseLeave?.(e); handleMouseLeave(); },
9564
- onFocus: (e) => { children.props.onFocus?.(e); handleFocus(); },
9565
- onBlur: (e) => { children.props.onBlur?.(e); handleBlur(); },
9566
- onKeyDown: (e) => { children.props.onKeyDown?.(e); handleKeyDown(e); },
9567
- tabIndex: children.props.tabIndex ?? 0,
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
- return (jsxRuntime.jsxs("div", { className: stepClasses, children: [jsxRuntime.jsxs("div", { className: "designbase-progress-step__indicator-container", children: [jsxRuntime.jsx("div", { className: "designbase-progress-step__indicator", onClick: () => handleStepClick(item, index), tabIndex: isClickable ? 0 : -1, role: isClickable ? 'button' : undefined, "aria-label": `${item.title} 단계로 이동`, onKeyDown: (e) => {
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: "designbase-progress-step__connector" }))] }), 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));
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, position = 'alternate', variant = 'default', size = 'm', color = 'primary', clickable = false, fullWidth = false, disabled = false, className, style, onItemClick, }) => {
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
- switch (position) {
11396
- case 'left':
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--${position}`, `designbase-timeline--${variant}`, `designbase-timeline--${size}`, {
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.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) => {
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("div", { className: "designbase-timeline__dot-inner" })) }), !isLast && (jsxRuntime.jsx("div", { className: "designbase-timeline__connector" }))] })] }, item.id));
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, position = 'top-right', onClose, className, }) => {
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}`, `designbase-toast--${position}`, {
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) => {