@designbasekorea/ui 0.5.4 → 0.5.6

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
@@ -4451,7 +4451,7 @@
4451
4451
  });
4452
4452
  Checkbox.displayName = 'Checkbox';
4453
4453
 
4454
- const SearchBar = ({ value, defaultValue = '', placeholder = '검색...', size = 'm', variant = 'default', disabled = false, readOnly = false, fullWidth = false, searchIcon: SearchIconComponent = icons.SearchIcon, clearIcon: ClearIconComponent = icons.CloseIcon, enableRecentSearches = false, recentSearchesKey = 'searchbar-recent-searches', suggestedSearches = [], suggestionRollingInterval = 5000, onChange, onSearch, onFocus, onBlur, onKeyDown, className, ...rest }) => {
4454
+ const SearchBar = ({ value, defaultValue = '', placeholder = '검색...', size = 'm', variant = 'default', disabled = false, readOnly = false, fullWidth = false, searchIcon: SearchIconComponent = icons.SearchIcon, clearIcon: ClearIconComponent = icons.CloseIcon, enableRecentSearches = false, recentSearchesKey = 'searchbar-recent-searches', suggestedSearches = [], suggestionRollingInterval = 5000, onChange, onSearch, onFocus, onBlur, onKeyDown, showShortcut = false, shortcutLabel = '⌘K', className, ...rest }) => {
4455
4455
  const [internalValue, setInternalValue] = React.useState(defaultValue);
4456
4456
  const [recentSearches, setRecentSearches] = React.useState([]);
4457
4457
  const [showRecentSearches, setShowRecentSearches] = React.useState(false);
@@ -4596,7 +4596,8 @@
4596
4596
  const currentPlaceholder = suggestedSearches.length > 0 && !currentValue && currentValue === ''
4597
4597
  ? suggestedSearches[currentSuggestion]
4598
4598
  : placeholder;
4599
- return (jsxRuntime.jsxs("div", { className: classes, role: "search", children: [jsxRuntime.jsxs("div", { className: "designbase-search-bar__container", children: [jsxRuntime.jsx("div", { className: "designbase-search-bar__search-icon", children: jsxRuntime.jsx(SearchIconComponent, { size: size === 's' ? 16 : size === 'l' ? 24 : 20 }) }), jsxRuntime.jsx("input", { ref: inputRef, type: "text", className: inputClasses, value: currentValue, placeholder: currentPlaceholder, disabled: disabled, readOnly: readOnly, onChange: handleChange, onFocus: handleFocus, onBlur: handleBlur, onKeyDown: handleKeyDown, "aria-label": "\uAC80\uC0C9\uC5B4 \uC785\uB825", ...rest }), currentValue && currentValue.length > 0 && !disabled && !readOnly && (jsxRuntime.jsx("button", { type: "button", className: "designbase-search-bar__clear-button", onClick: handleClear, "aria-label": "\uAC80\uC0C9\uC5B4 \uC9C0\uC6B0\uAE30", children: jsxRuntime.jsx(ClearIconComponent, { size: size === 's' ? 16 : size === 'l' ? 24 : 20 }) }))] }), showRecentSearches && recentSearches.length > 0 && (jsxRuntime.jsxs("div", { className: "designbase-search-bar__recent-searches", children: [jsxRuntime.jsxs("div", { className: "designbase-search-bar__recent-header", children: [jsxRuntime.jsx("span", { className: "designbase-search-bar__recent-title", children: "\uCD5C\uADFC \uAC80\uC0C9\uC5B4" }), jsxRuntime.jsx("button", { type: "button", className: "designbase-search-bar__clear-all-button", onClick: handleClearAllRecentSearches, "aria-label": "\uBAA8\uB4E0 \uCD5C\uADFC \uAC80\uC0C9\uC5B4 \uC0AD\uC81C", children: "\uC804\uCCB4 \uC0AD\uC81C" })] }), jsxRuntime.jsx("div", { className: "designbase-search-bar__recent-list", children: recentSearches.map((searchTerm, index) => (jsxRuntime.jsxs("div", { className: "designbase-search-bar__recent-item", children: [jsxRuntime.jsx("button", { type: "button", className: "designbase-search-bar__recent-search-button", onClick: () => handleRecentSearchClick(searchTerm), children: searchTerm }), jsxRuntime.jsx("button", { type: "button", className: "designbase-search-bar__recent-remove-button", onClick: () => handleRemoveRecentSearch(searchTerm), "aria-label": `${searchTerm} 삭제`, children: jsxRuntime.jsx(icons.CloseIcon, { size: 16 }) })] }, index))) })] })), suggestedSearches.length > 0 && isFocused && !currentValue && (jsxRuntime.jsxs("div", { className: "designbase-search-bar__suggestions", children: [jsxRuntime.jsx("div", { className: "designbase-search-bar__suggestions-header", children: jsxRuntime.jsx("span", { className: "designbase-search-bar__suggestions-title", children: "\uCD94\uCC9C \uAC80\uC0C9\uC5B4" }) }), jsxRuntime.jsx("div", { className: "designbase-search-bar__suggestions-list", children: suggestedSearches.map((suggestion, index) => (jsxRuntime.jsx("button", { type: "button", className: clsx('designbase-search-bar__suggestion-item', {
4599
+ const shortcutBadgeSize = size === 'l' ? 'm' : 's';
4600
+ return (jsxRuntime.jsxs("div", { className: classes, role: "search", children: [jsxRuntime.jsxs("div", { className: "designbase-search-bar__container", children: [jsxRuntime.jsx("div", { className: "designbase-search-bar__search-icon", children: jsxRuntime.jsx(SearchIconComponent, { size: size === 's' ? 16 : size === 'l' ? 24 : 20 }) }), jsxRuntime.jsx("input", { ref: inputRef, type: "text", className: inputClasses, value: currentValue, placeholder: currentPlaceholder, disabled: disabled, readOnly: readOnly, onChange: handleChange, onFocus: handleFocus, onBlur: handleBlur, onKeyDown: handleKeyDown, "aria-label": "\uAC80\uC0C9\uC5B4 \uC785\uB825", ...rest }), showShortcut && !currentValue && !disabled && !readOnly && (jsxRuntime.jsx(Badge, { className: "designbase-search-bar__shortcut-badge", size: shortcutBadgeSize, variant: "secondary", style: "text", "aria-hidden": "true", children: shortcutLabel })), currentValue && currentValue.length > 0 && !disabled && !readOnly && (jsxRuntime.jsx("button", { type: "button", className: "designbase-search-bar__clear-button", onClick: handleClear, "aria-label": "\uAC80\uC0C9\uC5B4 \uC9C0\uC6B0\uAE30", children: jsxRuntime.jsx(ClearIconComponent, { size: size === 's' ? 16 : size === 'l' ? 24 : 20 }) }))] }), showRecentSearches && recentSearches.length > 0 && (jsxRuntime.jsxs("div", { className: "designbase-search-bar__recent-searches", children: [jsxRuntime.jsxs("div", { className: "designbase-search-bar__recent-header", children: [jsxRuntime.jsx("span", { className: "designbase-search-bar__recent-title", children: "\uCD5C\uADFC \uAC80\uC0C9\uC5B4" }), jsxRuntime.jsx("button", { type: "button", className: "designbase-search-bar__clear-all-button", onClick: handleClearAllRecentSearches, "aria-label": "\uBAA8\uB4E0 \uCD5C\uADFC \uAC80\uC0C9\uC5B4 \uC0AD\uC81C", children: "\uC804\uCCB4 \uC0AD\uC81C" })] }), jsxRuntime.jsx("div", { className: "designbase-search-bar__recent-list", children: recentSearches.map((searchTerm, index) => (jsxRuntime.jsxs("div", { className: "designbase-search-bar__recent-item", children: [jsxRuntime.jsx("button", { type: "button", className: "designbase-search-bar__recent-search-button", onClick: () => handleRecentSearchClick(searchTerm), children: searchTerm }), jsxRuntime.jsx("button", { type: "button", className: "designbase-search-bar__recent-remove-button", onClick: () => handleRemoveRecentSearch(searchTerm), "aria-label": `${searchTerm} 삭제`, children: jsxRuntime.jsx(icons.CloseIcon, { size: 16 }) })] }, index))) })] })), suggestedSearches.length > 0 && isFocused && !currentValue && (jsxRuntime.jsxs("div", { className: "designbase-search-bar__suggestions", children: [jsxRuntime.jsx("div", { className: "designbase-search-bar__suggestions-header", children: jsxRuntime.jsx("span", { className: "designbase-search-bar__suggestions-title", children: "\uCD94\uCC9C \uAC80\uC0C9\uC5B4" }) }), jsxRuntime.jsx("div", { className: "designbase-search-bar__suggestions-list", children: suggestedSearches.map((suggestion, index) => (jsxRuntime.jsx("button", { type: "button", className: clsx('designbase-search-bar__suggestion-item', {
4600
4601
  'designbase-search-bar__suggestion-item--active': index === currentSuggestion
4601
4602
  }), onClick: () => handleSuggestionClick(suggestion), children: suggestion }, index))) })] }))] }));
4602
4603
  };
@@ -8205,7 +8206,7 @@
8205
8206
  const renderButtons = () => {
8206
8207
  if (buttons.length === 0)
8207
8208
  return null;
8208
- return (jsxRuntime.jsx("div", { className: "designbase-hero-feature__buttons", children: buttons.map((button, index) => (jsxRuntime.jsx(Button, { href: button.href, variant: button.variant || 'primary', size: button.size || 'md', onClick: button.onClick, target: button.external ? '_blank' : undefined, rel: button.external ? 'noopener noreferrer' : undefined, icon: button.icon, children: button.text }, index))) }));
8209
+ return (jsxRuntime.jsx("div", { className: "designbase-hero-feature__buttons", children: buttons.map((button, index) => (jsxRuntime.jsx(Button, { href: button.href, variant: button.variant || 'primary', size: button.size || 'm', onClick: button.onClick, target: button.external ? '_blank' : undefined, rel: button.external ? 'noopener noreferrer' : undefined, icon: button.icon, children: button.text }, index))) }));
8209
8210
  };
8210
8211
  const renderStats = () => {
8211
8212
  if (stats.length === 0)
@@ -8596,12 +8597,11 @@
8596
8597
  })), currentIndex: selectedImageIndex, isOpen: true, onOpenChange: handleLightboxClose, onImageChange: handleLightboxNavigate }))] }));
8597
8598
  };
8598
8599
 
8599
- const List = ({ items, size = 'm', variant = 'default', itemType = 'default', layout = 'vertical', selectable = false, multiple = false, selectedItems = [], draggable = false, spacing = 'm', alignment = 'start', onItemClick, onItemSelect, onItemDrag, emptyState, loading = false, loadingCount = 3, className, }) => {
8600
+ const List = ({ items, size = 'm', variant = 'navigation', itemType = 'default', layout = 'vertical', selectable = false, multiple = false, selectedItems = [], draggable = false, spacing = 's', alignment = 'start', showLeadingIcon = true, showDescription = false, showMeta = false, showBadge = true, showArrow = true, clickableArea = 'item', onItemClick, onItemSelect, onItemDrag, emptyState, loading = false, loadingCount = 3, className, }) => {
8600
8601
  const [internalSelectedItems, setInternalSelectedItems] = React.useState(selectedItems);
8601
8602
  const [draggedItem, setDraggedItem] = React.useState(null);
8602
- // 아이콘 크기 계산 (m이 기본값)
8603
8603
  const iconSize = size === 's' ? 16 : size === 'l' ? 24 : 20;
8604
- // 외부에서 선택된 아이템이 변경되면 내부 상태 업데이트
8604
+ const shouldShowArrow = showArrow;
8605
8605
  React.useEffect(() => {
8606
8606
  setInternalSelectedItems(selectedItems);
8607
8607
  }, [selectedItems]);
@@ -8612,7 +8612,7 @@
8612
8612
  let newSelectedItems;
8613
8613
  if (multiple) {
8614
8614
  if (internalSelectedItems.includes(item.id)) {
8615
- newSelectedItems = internalSelectedItems.filter(id => id !== item.id);
8615
+ newSelectedItems = internalSelectedItems.filter((id) => id !== item.id);
8616
8616
  }
8617
8617
  else {
8618
8618
  newSelectedItems = [...internalSelectedItems, item.id];
@@ -8626,6 +8626,12 @@
8626
8626
  }
8627
8627
  onItemClick?.(item, index);
8628
8628
  };
8629
+ const handleItemKeyDown = (e, item, index) => {
8630
+ if (e.key === 'Enter' || e.key === ' ') {
8631
+ e.preventDefault();
8632
+ handleItemClick(item, index);
8633
+ }
8634
+ };
8629
8635
  const handleItemDragStart = (e, itemId) => {
8630
8636
  if (!draggable)
8631
8637
  return;
@@ -8648,9 +8654,7 @@
8648
8654
  const handleItemDragEnd = () => {
8649
8655
  setDraggedItem(null);
8650
8656
  };
8651
- const isItemSelected = (itemId) => {
8652
- return internalSelectedItems.includes(itemId);
8653
- };
8657
+ const isItemSelected = (itemId) => internalSelectedItems.includes(itemId);
8654
8658
  const renderBadge = (badge) => {
8655
8659
  if (!badge)
8656
8660
  return null;
@@ -8669,17 +8673,38 @@
8669
8673
  const renderItem = (item, index) => {
8670
8674
  const isSelected = isItemSelected(item.id);
8671
8675
  const isDragging = draggedItem === item.id;
8676
+ const isClickable = Boolean(onItemClick || selectable);
8677
+ const hasDescription = showDescription && Boolean(item.description);
8678
+ const hasMeta = showMeta && Boolean(item.meta?.length);
8679
+ const hasSecondaryInfo = hasDescription || hasMeta;
8680
+ const hasLeadingVisual = Boolean(item.image || (showLeadingIcon && item.icon));
8681
+ const hasTrailing = Boolean((showBadge && item.badge) ||
8682
+ item.actions?.length ||
8683
+ shouldShowArrow ||
8684
+ draggable);
8672
8685
  const itemClasses = clsx('designbase-list__item', `designbase-list__item--size-${size}`, `designbase-list__item--variant-${variant}`, `designbase-list__item--type-${itemType}`, `designbase-list__item--layout-${layout}`, `designbase-list__item--spacing-${spacing}`, `designbase-list__item--alignment-${alignment}`, {
8673
8686
  'designbase-list__item--selected': isSelected,
8674
8687
  'designbase-list__item--disabled': item.disabled,
8675
8688
  'designbase-list__item--dragging': isDragging,
8676
- 'designbase-list__item--clickable': onItemClick || selectable,
8689
+ 'designbase-list__item--clickable': isClickable,
8677
8690
  'designbase-list__item--draggable': draggable,
8691
+ 'designbase-list__item--with-leading': hasLeadingVisual,
8692
+ 'designbase-list__item--with-secondary': hasSecondaryInfo,
8693
+ 'designbase-list__item--with-trailing': hasTrailing,
8678
8694
  });
8679
- return (jsxRuntime.jsxs("div", { className: itemClasses, onClick: () => handleItemClick(item, index), draggable: draggable, onDragStart: (e) => handleItemDragStart(e, item.id), onDragOver: handleItemDragOver, onDrop: (e) => handleItemDrop(e, item.id), onDragEnd: handleItemDragEnd, role: selectable ? 'button' : undefined, tabIndex: selectable ? 0 : undefined, "aria-selected": selectable ? isSelected : undefined, children: [selectable && (jsxRuntime.jsx("div", { className: "designbase-list__item-checkbox", children: jsxRuntime.jsx("input", { type: multiple ? 'checkbox' : 'radio', checked: isSelected, onChange: () => handleItemClick(item, index), disabled: item.disabled }) })), item.icon && (jsxRuntime.jsx("div", { className: "designbase-list__item-icon", children: React.isValidElement(item.icon) ? (React.cloneElement(item.icon, {
8680
- size: iconSize,
8681
- color: 'currentColor'
8682
- })) : item.icon })), item.image && (jsxRuntime.jsx("div", { className: "designbase-list__item-image", children: jsxRuntime.jsx("img", { src: item.image, alt: item.title }) })), jsxRuntime.jsxs("div", { className: "designbase-list__item-content", children: [jsxRuntime.jsxs("div", { className: "designbase-list__item-header", children: [jsxRuntime.jsx("h4", { className: "designbase-list__item-title", children: item.title }), item.badge && renderBadge(item.badge)] }), item.description && (jsxRuntime.jsx("p", { className: "designbase-list__item-description", children: item.description })), item.meta && renderMeta(item.meta)] }), item.actions && renderActions(item.actions), draggable && (jsxRuntime.jsx("div", { className: "designbase-list__item-drag-handle", children: "\u22EE\u22EE" }))] }, item.id));
8695
+ const itemIsInteractive = clickableArea === 'item' && isClickable && !item.disabled;
8696
+ const contentIsInteractive = clickableArea === 'content' && isClickable && !item.disabled;
8697
+ return (jsxRuntime.jsxs("div", { className: itemClasses, onClick: itemIsInteractive ? () => handleItemClick(item, index) : undefined, onKeyDown: itemIsInteractive ? (e) => handleItemKeyDown(e, item, index) : undefined, draggable: draggable, onDragStart: (e) => handleItemDragStart(e, item.id), onDragOver: handleItemDragOver, onDrop: (e) => handleItemDrop(e, item.id), onDragEnd: handleItemDragEnd, role: itemIsInteractive ? 'button' : undefined, tabIndex: itemIsInteractive ? 0 : undefined, "aria-selected": selectable ? isSelected : undefined, children: [selectable && (jsxRuntime.jsx("div", { className: "designbase-list__item-checkbox", onClick: (e) => e.stopPropagation(), children: jsxRuntime.jsx("input", { type: multiple ? 'checkbox' : 'radio', checked: isSelected, onChange: (e) => {
8698
+ e.stopPropagation();
8699
+ handleItemClick(item, index);
8700
+ }, disabled: item.disabled }) })), showLeadingIcon && item.icon && !item.image && (jsxRuntime.jsx("div", { className: "designbase-list__item-icon", children: React.isValidElement(item.icon)
8701
+ ? React.cloneElement(item.icon, {
8702
+ size: iconSize,
8703
+ color: 'currentColor',
8704
+ })
8705
+ : item.icon })), item.image && (jsxRuntime.jsx("div", { className: "designbase-list__item-image", children: jsxRuntime.jsx("img", { src: item.image, alt: item.title }) })), jsxRuntime.jsxs("div", { className: clsx('designbase-list__item-content', {
8706
+ 'designbase-list__item-content--clickable': contentIsInteractive,
8707
+ }), onClick: contentIsInteractive ? () => handleItemClick(item, index) : undefined, onKeyDown: contentIsInteractive ? (e) => handleItemKeyDown(e, item, index) : undefined, role: contentIsInteractive ? 'button' : undefined, tabIndex: contentIsInteractive ? 0 : undefined, children: [jsxRuntime.jsx("div", { className: "designbase-list__item-header", children: jsxRuntime.jsx("h4", { className: "designbase-list__item-title", children: item.title }) }), hasDescription && jsxRuntime.jsx("p", { className: "designbase-list__item-description", children: item.description }), hasMeta && renderMeta(item.meta)] }), (showBadge && item.badge) || item.actions || shouldShowArrow || draggable ? (jsxRuntime.jsxs("div", { className: "designbase-list__item-trailing", children: [showBadge && item.badge && renderBadge(item.badge), item.actions && renderActions(item.actions), shouldShowArrow && (jsxRuntime.jsx("div", { className: "designbase-list__item-arrow", "aria-hidden": "true", children: jsxRuntime.jsx(icons.ChevronRightIcon, { size: 16 }) })), draggable && jsxRuntime.jsx("div", { className: "designbase-list__item-drag-handle", children: "\u22EE\u22EE" })] })) : null] }, item.id));
8683
8708
  };
8684
8709
  const renderLoadingSkeleton = () => {
8685
8710
  return Array.from({ length: loadingCount }, (_, index) => (jsxRuntime.jsx("div", { className: "designbase-list__item designbase-list__item--loading", children: jsxRuntime.jsxs("div", { className: "designbase-list__item-skeleton", children: [jsxRuntime.jsx("div", { className: "designbase-list__item-skeleton-icon" }), jsxRuntime.jsxs("div", { className: "designbase-list__item-skeleton-content", children: [jsxRuntime.jsx("div", { className: "designbase-list__item-skeleton-title" }), jsxRuntime.jsx("div", { className: "designbase-list__item-skeleton-description" })] })] }) }, index)));
@@ -8691,12 +8716,12 @@
8691
8716
  'designbase-list--loading': loading,
8692
8717
  }, className);
8693
8718
  if (loading) {
8694
- return (jsxRuntime.jsx("div", { className: classes, children: renderLoadingSkeleton() }));
8719
+ return jsxRuntime.jsx("div", { className: classes, children: renderLoadingSkeleton() });
8695
8720
  }
8696
8721
  if (items.length === 0 && emptyState) {
8697
8722
  return (jsxRuntime.jsx("div", { className: classes, children: jsxRuntime.jsx("div", { className: "designbase-list__empty", children: emptyState }) }));
8698
8723
  }
8699
- return (jsxRuntime.jsx("div", { className: classes, children: items.map((item, index) => renderItem(item, index)) }));
8724
+ return jsxRuntime.jsx("div", { className: classes, children: items.map((item, index) => renderItem(item, index)) });
8700
8725
  };
8701
8726
 
8702
8727
  const DesignBaseLogo = ({ width = 193, height = 40, color, className, }) => {
@@ -8784,6 +8809,77 @@
8784
8809
  };
8785
8810
  Logo.displayName = 'Logo';
8786
8811
 
8812
+ const Marquee = ({ children, items, direction = 'left', duration = 20, speed = 1, size = 'm', variant = 'default', bordered, pauseOnHover = true, fadeEdges = false, fadeWidth = 48, edgePadding, gap = 24, alignY = 'center', className, ariaLabel = 'Scrolling content', }) => {
8813
+ const containerRef = React.useRef(null);
8814
+ const baseGroupRef = React.useRef(null);
8815
+ const [containerWidth, setContainerWidth] = React.useState(0);
8816
+ const [baseGroupWidth, setBaseGroupWidth] = React.useState(0);
8817
+ const resolvedItems = React.useMemo(() => ((items && items.length > 0) ? items : (children ? [children] : [])), [items, children]);
8818
+ if (resolvedItems.length === 0) {
8819
+ return null;
8820
+ }
8821
+ const resolvedSpeed = Number.isFinite(speed) && speed > 0 ? speed : 1;
8822
+ const resolvedDuration = Math.max(duration, 1) / resolvedSpeed;
8823
+ const resolvedFadeWidth = Math.max(fadeWidth, 0);
8824
+ const resolvedEdgePadding = edgePadding !== undefined
8825
+ ? Math.max(edgePadding, 0)
8826
+ : (fadeEdges ? resolvedFadeWidth : 0);
8827
+ const resolvedGap = Math.max(gap, 0);
8828
+ React.useEffect(() => {
8829
+ const updateSize = () => {
8830
+ const nextContainerWidth = Math.ceil(containerRef.current?.clientWidth ?? 0);
8831
+ const nextBaseGroupWidth = Math.ceil(baseGroupRef.current?.scrollWidth ?? 0);
8832
+ setContainerWidth((prev) => (prev !== nextContainerWidth ? nextContainerWidth : prev));
8833
+ setBaseGroupWidth((prev) => (prev !== nextBaseGroupWidth ? nextBaseGroupWidth : prev));
8834
+ };
8835
+ updateSize();
8836
+ const observer = new ResizeObserver(updateSize);
8837
+ if (containerRef.current)
8838
+ observer.observe(containerRef.current);
8839
+ if (baseGroupRef.current)
8840
+ observer.observe(baseGroupRef.current);
8841
+ const images = baseGroupRef.current?.querySelectorAll('img') ?? [];
8842
+ images.forEach((img) => {
8843
+ img.addEventListener('load', updateSize);
8844
+ img.addEventListener('error', updateSize);
8845
+ });
8846
+ return () => {
8847
+ observer.disconnect();
8848
+ images.forEach((img) => {
8849
+ img.removeEventListener('load', updateSize);
8850
+ img.removeEventListener('error', updateSize);
8851
+ });
8852
+ };
8853
+ }, [resolvedItems, resolvedGap, size, fadeEdges, resolvedEdgePadding]);
8854
+ const duplicateCount = React.useMemo(() => {
8855
+ if (baseGroupWidth <= 0)
8856
+ return 1;
8857
+ return Math.max(1, Math.ceil(containerWidth / baseGroupWidth));
8858
+ }, [containerWidth, baseGroupWidth]);
8859
+ const isReady = baseGroupWidth > 0;
8860
+ const classes = clsx('designbase-marquee', `designbase-marquee--size-${size}`, `designbase-marquee--variant-${variant}`, `designbase-marquee--align-${alignY}`, {
8861
+ 'designbase-marquee--pause-on-hover': pauseOnHover,
8862
+ 'designbase-marquee--fade-edges': fadeEdges,
8863
+ 'designbase-marquee--right': direction === 'right',
8864
+ 'designbase-marquee--bordered': bordered ?? variant === 'outlined',
8865
+ 'designbase-marquee--ready': isReady,
8866
+ }, className);
8867
+ const style = {
8868
+ '--db-marquee-duration': `${resolvedDuration}s`,
8869
+ // 그룹간 간격까지 포함해 이동 거리를 맞춰야 루프 경계 점프가 사라짐
8870
+ '--db-marquee-shift': `${baseGroupWidth + resolvedGap}px`,
8871
+ '--db-marquee-gap': `${resolvedGap}px`,
8872
+ '--db-marquee-fade-width': `${resolvedFadeWidth}px`,
8873
+ '--db-marquee-edge-padding': `${resolvedEdgePadding}px`,
8874
+ };
8875
+ const screenReaderText = (items && items.length > 0)
8876
+ ? items.filter((item) => typeof item === 'string').join(' • ') || ariaLabel
8877
+ : (typeof children === 'string' ? children : ariaLabel);
8878
+ const renderGroup = (key, ref) => (jsxRuntime.jsx("div", { className: "designbase-marquee__group", "aria-hidden": "true", ref: ref, children: resolvedItems.map((item, index) => (jsxRuntime.jsx("div", { className: "designbase-marquee__item", children: item }, `${key}-${index}`))) }, key));
8879
+ return (jsxRuntime.jsxs("div", { className: classes, style: style, role: "region", "aria-label": ariaLabel, ref: containerRef, children: [jsxRuntime.jsx("span", { className: "designbase-marquee__sr-only", children: screenReaderText }), jsxRuntime.jsxs("div", { className: "designbase-marquee__track", children: [renderGroup('base', baseGroupRef), Array.from({ length: duplicateCount }).map((_, index) => renderGroup(`dup-${index}`))] })] }));
8880
+ };
8881
+ Marquee.displayName = 'Marquee';
8882
+
8787
8883
  const MarkdownEditor = ({ size = 'm', variant = 'default', mode = 'preview', // 기본값을 preview로 변경
8788
8884
  theme = 'light', value = '', placeholder = '마크다운을 입력하세요...', minHeight = 200, maxHeight = 600, autoHeight = false, readonly = false, disabled = false, showToolbar = true, toolbarItems = [], showStatus = true, showWordCount = true, showLineCount = true, autoSave = false, autoSaveInterval = 30000, // 30초
8789
8885
  onFileUpload, onChange, onSave, onFocus, onBlur, className, }) => {
@@ -10833,14 +10929,34 @@
10833
10929
  return (jsxRuntime.jsx("div", { className: classes, style: style, children: jsxRuntime.jsx("div", { ref: scrollRef, className: "designbase-scroll-area__content", children: children }) }));
10834
10930
  };
10835
10931
 
10836
- const Section = ({ title, subtitle, description, size = 'm', variant = 'default', header, footer, actions, noPadding = false, fullWidth = false, fullHeight = false, className, children, }) => {
10932
+ const Section = ({ title, subtitle, description = '', size = 'm', variant = 'default', header, footer, actions, noPadding = false, fullWidth = false, fullHeight = false, className, children, }) => {
10933
+ const normalizeActionButtonSize = (node) => {
10934
+ if (!React.isValidElement(node))
10935
+ return node;
10936
+ const element = node;
10937
+ const elementType = element.type;
10938
+ const isButtonComponent = elementType?.displayName === 'Button' || elementType?.name === 'Button';
10939
+ // Button이고 size가 지정되지 않았으면 기본값 m 적용
10940
+ if (isButtonComponent && element.props?.size === undefined) {
10941
+ return React.cloneElement(element, { size: 'm' });
10942
+ }
10943
+ if (element.props?.children) {
10944
+ return React.cloneElement(element, {
10945
+ children: React.Children.map(element.props.children, normalizeActionButtonSize),
10946
+ });
10947
+ }
10948
+ return element;
10949
+ };
10950
+ const normalizedActions = actions
10951
+ ? React.Children.map(actions, normalizeActionButtonSize)
10952
+ : actions;
10837
10953
  const classes = clsx('designbase-section', `designbase-section--size-${size}`, `designbase-section--variant-${variant}`, {
10838
10954
  'designbase-section--no-padding': noPadding,
10839
10955
  'designbase-section--full-width': fullWidth,
10840
10956
  'designbase-section--full-height': fullHeight,
10841
10957
  }, className);
10842
- const hasHeader = title || subtitle || description || header || actions;
10843
- return (jsxRuntime.jsxs("section", { className: classes, children: [hasHeader && (jsxRuntime.jsx("div", { className: "designbase-section__header", children: header || (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [(title || subtitle) && (jsxRuntime.jsxs("div", { className: "designbase-section__title-area", children: [title && (jsxRuntime.jsx("h2", { className: "designbase-section__title", children: title })), subtitle && (jsxRuntime.jsx("h3", { className: "designbase-section__subtitle", children: subtitle })), description && (jsxRuntime.jsx("p", { className: "designbase-section__description", children: description }))] })), actions && (jsxRuntime.jsx("div", { className: "designbase-section__actions", children: actions }))] })) })), jsxRuntime.jsx("div", { className: "designbase-section__content", children: children }), footer && (jsxRuntime.jsx("div", { className: "designbase-section__footer", children: footer }))] }));
10958
+ const hasHeader = title || subtitle || description || header || normalizedActions;
10959
+ return (jsxRuntime.jsxs("section", { className: classes, children: [hasHeader && (jsxRuntime.jsx("div", { className: "designbase-section__header", children: header || (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [(title || subtitle) && (jsxRuntime.jsxs("div", { className: "designbase-section__title-area", children: [title && (jsxRuntime.jsx("h2", { className: "designbase-section__title", children: title })), subtitle && (jsxRuntime.jsx("h3", { className: "designbase-section__subtitle", children: subtitle })), description && (jsxRuntime.jsx("p", { className: "designbase-section__description", children: description }))] })), normalizedActions && (jsxRuntime.jsx("div", { className: "designbase-section__actions", children: normalizedActions }))] })) })), jsxRuntime.jsx("div", { className: "designbase-section__content", children: children }), footer && (jsxRuntime.jsx("div", { className: "designbase-section__footer", children: footer }))] }));
10844
10960
  };
10845
10961
 
10846
10962
  const Share = ({ url, title, description = '', imageUrl, hashtags = [], variant = 'button', size = 'm', position = 'bottom', platforms = ['facebook', 'x', 'linkedin', 'whatsapp', 'email', 'link'], customPlatforms = {}, buttonText = '공유', buttonIcon = icons.ShareAltIcon, modalTitle = '공유하기', copySuccessMessage = '링크가 클립보드에 복사되었습니다!', showQrCode = true, qrCodeSize = 200, className, style, onShare, onShareError, onCopySuccess, onCopyError, }) => {
@@ -11093,11 +11209,11 @@
11093
11209
  switch (size) {
11094
11210
  case 'xs':
11095
11211
  return variant === 'circular' ? '16px' : '12px';
11096
- case 'sm':
11212
+ case 's':
11097
11213
  return variant === 'circular' ? '24px' : '16px';
11098
- case 'md':
11214
+ case 'm':
11099
11215
  return variant === 'circular' ? '32px' : '20px';
11100
- case 'lg':
11216
+ case 'l':
11101
11217
  return variant === 'circular' ? '48px' : '24px';
11102
11218
  case 'xl':
11103
11219
  return variant === 'circular' ? '64px' : '32px';
@@ -11109,9 +11225,9 @@
11109
11225
  const getTextLineHeight = () => {
11110
11226
  switch (size) {
11111
11227
  case 'xs': return '12px';
11112
- case 'sm': return '16px';
11113
- case 'md': return '20px';
11114
- case 'lg': return '24px';
11228
+ case 's': return '16px';
11229
+ case 'm': return '20px';
11230
+ case 'l': return '24px';
11115
11231
  case 'xl': return '32px';
11116
11232
  default: return '20px';
11117
11233
  }
@@ -12575,6 +12691,7 @@
12575
12691
  exports.List = List;
12576
12692
  exports.Logo = Logo;
12577
12693
  exports.MarkdownEditor = MarkdownEditor;
12694
+ exports.Marquee = Marquee;
12578
12695
  exports.Masonry = Masonry;
12579
12696
  exports.MenuItem = MenuItem;
12580
12697
  exports.Modal = Modal;