@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.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 = -ARW;
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 = -ARW;
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 = -ARW;
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 = -ARW;
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 = -ARW;
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 = -ARW;
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
- if (left < 8)
2305
- left = 8;
2306
- if (left + pRect.width > vw - 8)
2307
- left = vw - pRect.width - 8;
2308
- if (top < 8)
2309
- top = 8;
2310
- if (top + pRect.height > vh - 8)
2311
- top = vh - pRect.height - 8;
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
- // 8px ~ (width-8px) 범위로 제한
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', // hover 유지
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(() => { if (!disabled && alwaysShow)
2390
- setVisible(true);
2391
- else if (!alwaysShow)
2392
- setVisible(false); }, [alwaysShow, disabled]);
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();
@@ -4917,23 +4915,7 @@ const Image$1 = ({ src, alt = '', ratio = 'auto', fit = 'cover', loading = 'lazy
4917
4915
  onError?.();
4918
4916
  }
4919
4917
  };
4920
- // aspect ratio 계산
4921
- const getAspectRatioStyle = () => {
4922
- if (ratio === 'auto')
4923
- return {};
4924
- const ratios = {
4925
- '1:1': '100%',
4926
- '16:9': '56.25%',
4927
- '4:3': '75%',
4928
- '3:2': '66.67%',
4929
- '3:4': '133.33%',
4930
- '2:1': '50%',
4931
- 'auto': 'auto',
4932
- };
4933
- return {
4934
- paddingBottom: ratios[ratio],
4935
- };
4936
- };
4918
+ // aspect ratio CSS 클래스로 처리되므로 인라인 스타일 불필요
4937
4919
  // 둥근 모서리 클래스 계산
4938
4920
  const getRoundedClass = () => {
4939
4921
  if (rounded === true)
@@ -4960,7 +4942,6 @@ const Image$1 = ({ src, alt = '', ratio = 'auto', fit = 'cover', loading = 'lazy
4960
4942
  height: fullHeight ? '100%' : height,
4961
4943
  maxWidth,
4962
4944
  maxHeight,
4963
- ...getAspectRatioStyle(),
4964
4945
  };
4965
4946
  const getRatioClass = () => {
4966
4947
  if (ratio === 'auto')
@@ -6317,7 +6298,7 @@ const ContextMenu = ({ items, open, x, y, onClose, className, }) => {
6317
6298
  }
6318
6299
  const hasSubMenu = item.subItems && item.subItems.length > 0;
6319
6300
  const isSubMenuOpen = activeSubMenu === item.id;
6320
- 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', {
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', {
6321
6302
  'designbase-context-menu__submenu--open': isSubMenuOpen,
6322
6303
  }), onMouseEnter: () => setActiveSubMenu(item.id), onMouseLeave: handleSubMenuClose, children: item.subItems.map((subItem, subIndex) => renderMenuItem(subItem, subIndex)) }))] }, item.id));
6323
6304
  }, [activeSubMenu, handleItemClick, handleSubMenuOpen, handleSubMenuClose]);
@@ -8842,7 +8823,7 @@ const Masonry = ({ images, columns = 3, spacing = 'm', ratio = 'auto', fit = 'co
8842
8823
  'designbase-masonry--infinite-scroll': infiniteScroll,
8843
8824
  }, className);
8844
8825
  const distributedImages = distributeImages();
8845
- const renderImage = (image, index, columnIndex) => (jsxs("div", { ref: (el) => (imageRefs.current[index] = el), className: clsx('designbase-masonry__item', {
8826
+ const renderImage = (image, index, columnIndex) => (jsxs("div", { ref: (el) => { imageRefs.current[index] = el; }, className: clsx('designbase-masonry__item', {
8846
8827
  'designbase-masonry__item--visible': visibleImages.includes(index),
8847
8828
  }), style: {
8848
8829
  animationDelay: `${index * animationDelay}ms`,
@@ -9555,15 +9536,16 @@ hideDelay = 80, alwaysShow = false, disabled = false, maxWidth = 300, showArrow
9555
9536
  const classes = clsx('designbase-popover', `designbase-popover--${size}`, `designbase-popover--${variant}`, `designbase-popover--${position}`, { 'designbase-popover--visible': isOpen, 'designbase-popover--disabled': disabled }, className);
9556
9537
  const arrowClasses = clsx('designbase-popover__arrow', `designbase-popover__arrow--${position}`);
9557
9538
  // 자식에 트리거 이벤트 주입
9539
+ const childProps = children.props;
9558
9540
  const enhancedChildren = React.cloneElement(children, {
9559
9541
  ref: triggerRef,
9560
- onClick: (e) => { children.props.onClick?.(e); handleClick(e); },
9561
- onMouseEnter: (e) => { children.props.onMouseEnter?.(e); handleMouseEnter(); },
9562
- onMouseLeave: (e) => { children.props.onMouseLeave?.(e); handleMouseLeave(); },
9563
- onFocus: (e) => { children.props.onFocus?.(e); handleFocus(); },
9564
- onBlur: (e) => { children.props.onBlur?.(e); handleBlur(); },
9565
- onKeyDown: (e) => { children.props.onKeyDown?.(e); handleKeyDown(e); },
9566
- tabIndex: children.props.tabIndex ?? 0,
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,
9567
9549
  'aria-expanded': isOpen,
9568
9550
  'aria-haspopup': 'dialog',
9569
9551
  });
@@ -9614,16 +9596,20 @@ const ProgressStep = ({ items, size = 'm', layout = 'vertical', currentStep = 0,
9614
9596
  const status = getStepStatus(index, item.status);
9615
9597
  const isLast = index === items.length - 1;
9616
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;
9617
9602
  const stepClasses = clsx('designbase-progress-step__item', `designbase-progress-step__item--${status}`, {
9618
9603
  'designbase-progress-step__item--clickable': isClickable,
9619
9604
  'designbase-progress-step__item--disabled': item.disabled,
9620
9605
  });
9621
- return (jsxs("div", { className: stepClasses, children: [jsxs("div", { className: "designbase-progress-step__indicator-container", children: [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) => {
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) => {
9622
9608
  if (e.key === 'Enter' || e.key === ' ') {
9623
9609
  e.preventDefault();
9624
9610
  handleStepClick(item, index);
9625
9611
  }
9626
- }, 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: "designbase-progress-step__connector" }))] }), 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));
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));
9627
9613
  }) }));
9628
9614
  };
9629
9615
 
@@ -11383,7 +11369,7 @@ const Tabs = ({ items, defaultSelectedId, selectedId, orientation = 'horizontal'
11383
11369
  };
11384
11370
  Tabs.displayName = 'Tabs';
11385
11371
 
11386
- const Timeline = ({ items, position = 'alternate', variant = 'default', size = 'm', color = 'primary', clickable = false, fullWidth = false, disabled = false, className, style, onItemClick, }) => {
11372
+ const Timeline = ({ items, type = 'alternate', variant = 'default', size = 'm', color = 'primary', clickable = false, fullWidth = false, disabled = false, className, style, onItemClick, }) => {
11387
11373
  const handleItemClick = (item, index) => {
11388
11374
  if (disabled || item.disabled || !clickable)
11389
11375
  return;
@@ -11391,20 +11377,13 @@ const Timeline = ({ items, position = 'alternate', variant = 'default', size = '
11391
11377
  onItemClick?.(item, index);
11392
11378
  };
11393
11379
  const getItemPosition = (index) => {
11394
- switch (position) {
11395
- case 'left':
11396
- return 'left';
11397
- case 'right':
11398
- return 'right';
11399
- case 'alternate':
11400
- return index % 2 === 0 ? 'left' : 'right';
11401
- case 'reverse-alternate':
11402
- return index % 2 === 0 ? 'right' : 'left';
11403
- default:
11404
- return 'left';
11380
+ if (type === 'left') {
11381
+ return 'left';
11405
11382
  }
11383
+ // alternate 타입: 짝수는 왼쪽, 홀수는 오른쪽
11384
+ return index % 2 === 0 ? 'left' : 'right';
11406
11385
  };
11407
- const classes = clsx('designbase-timeline', `designbase-timeline--${position}`, `designbase-timeline--${variant}`, `designbase-timeline--${size}`, {
11386
+ const classes = clsx('designbase-timeline', `designbase-timeline--${type}`, `designbase-timeline--${variant}`, `designbase-timeline--${size}`, {
11408
11387
  'designbase-timeline--clickable': clickable,
11409
11388
  'designbase-timeline--full-width': fullWidth,
11410
11389
  'designbase-timeline--disabled': disabled,
@@ -11419,30 +11398,29 @@ const Timeline = ({ items, position = 'alternate', variant = 'default', size = '
11419
11398
  'designbase-timeline__item--disabled': item.disabled,
11420
11399
  });
11421
11400
  const contentClasses = clsx('designbase-timeline__content', `designbase-timeline__content--${itemPosition}`);
11422
- const separatorClasses = clsx('designbase-timeline__separator', `designbase-timeline__separator--${itemPosition}`);
11423
11401
  const dotClasses = clsx('designbase-timeline__dot', `designbase-timeline__dot--${itemColor}`, `designbase-timeline__dot--${variant}`, {
11424
11402
  'designbase-timeline__dot--clickable': isClickable,
11425
11403
  });
11426
- return (jsxs("div", { className: itemClasses, children: [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) => {
11427
- if (e.key === 'Enter' || e.key === ' ') {
11428
- e.preventDefault();
11429
- handleItemClick(item, index);
11430
- }
11431
- }, 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) => {
11432
11405
  if (e.key === 'Enter' || e.key === ' ') {
11433
11406
  e.preventDefault();
11434
11407
  handleItemClick(item, index);
11435
11408
  }
11436
- }, children: item.icon ? (jsx("div", { className: "designbase-timeline__icon", children: item.icon })) : (jsx("div", { className: "designbase-timeline__dot-inner" })) }), !isLast && (jsx("div", { className: "designbase-timeline__connector" }))] })] }, item.id));
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));
11437
11415
  }) }) }));
11438
11416
  };
11439
11417
 
11440
- const Toast = ({ id, status = 'info', title, description, icon: Icon, duration = 5000, showProgress = false, showCloseButton = true, position = 'top-right', onClose, className, }) => {
11418
+ const Toast = ({ id, status = 'info', title, description, icon: Icon, duration = 5000, showProgress = false, showCloseButton = true, onClose, className, }) => {
11441
11419
  const [isVisible, setIsVisible] = useState(false);
11442
11420
  const [progress, setProgress] = useState(100);
11443
11421
  const progressRef = useRef(null);
11444
- const timeoutRef = useRef();
11445
- const progressIntervalRef = useRef();
11422
+ const timeoutRef = useRef(undefined);
11423
+ const progressIntervalRef = useRef(undefined);
11446
11424
  // 토스트 표시 애니메이션
11447
11425
  useEffect(() => {
11448
11426
  const timer = setTimeout(() => setIsVisible(true), 50);
@@ -11488,7 +11466,7 @@ const Toast = ({ id, status = 'info', title, description, icon: Icon, duration =
11488
11466
  clearInterval(progressIntervalRef.current);
11489
11467
  handleClose();
11490
11468
  };
11491
- const classes = clsx('designbase-toast', `designbase-toast--${status}`, `designbase-toast--${position}`, {
11469
+ const classes = clsx('designbase-toast', `designbase-toast--${status}`, {
11492
11470
  'designbase-toast--visible': isVisible,
11493
11471
  'designbase-toast--with-icon': Icon,
11494
11472
  'designbase-toast--with-description': description,
@@ -11550,7 +11528,7 @@ const useToast = () => {
11550
11528
  }
11551
11529
  return context;
11552
11530
  };
11553
- const ToastProvider = ({ children }) => {
11531
+ const ToastProvider = ({ children, position = 'top-right' }) => {
11554
11532
  const [toasts, setToasts] = useState([]);
11555
11533
  const addToast = useCallback((toast) => {
11556
11534
  const id = `toast-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
@@ -11567,7 +11545,7 @@ const ToastProvider = ({ children }) => {
11567
11545
  const removeToast = useCallback((id) => {
11568
11546
  setToasts(prev => prev.filter(toast => toast.id !== id));
11569
11547
  }, []);
11570
- 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 })] }));
11571
11549
  };
11572
11550
 
11573
11551
  const Toggle = forwardRef(({ isSelected, defaultSelected, isDisabled = false, isReadOnly = false, size = 'm', children, className, onChange, ...props }, forwardedRef) => {