@designbasekorea/ui 0.5.2 → 0.5.5

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
@@ -4342,8 +4342,9 @@ const Modal = ({ isOpen, onClose, title, size = 'm', closeOnOutsideClick = true,
4342
4342
  return (jsx("div", { className: overlayClasses, onClick: closeOnOutsideClick ? onClose : undefined, children: jsxs("div", { ref: modalRef, className: modalClasses, onClick: (e) => e.stopPropagation(), role: "dialog", "aria-modal": "true", "aria-labelledby": title ? titleId : undefined, children: [title && (jsx(ModalHeader, { title: title, titleId: titleId, showCloseButton: true, onClose: onClose, iconSize: iconSize })), jsx("div", { className: "designbase-modal__content", children: children })] }) }));
4343
4343
  };
4344
4344
  const ModalHeader = ({ title, titleId, showCloseButton = true, onClose, iconSize = 20, className, children, }) => {
4345
+ const fallbackTitleId = useId();
4345
4346
  const classes = clsx('designbase-modal__header', className);
4346
- return (jsxs("div", { className: classes, children: [jsxs("div", { className: "designbase-modal__header-content", children: [title && (jsx("h2", { id: titleId || 'modal-title', className: "designbase-modal__title", children: title })), children] }), showCloseButton && onClose && (jsx("button", { type: "button", onClick: onClose, "aria-label": "\uBAA8\uB2EC \uB2EB\uAE30", className: "designbase-modal__close-button", children: jsx(CloseIcon, { size: iconSize, color: "currentColor" }) }))] }));
4347
+ return (jsxs("div", { className: classes, children: [jsxs("div", { className: "designbase-modal__header-content", children: [title && (jsx("h2", { id: titleId || fallbackTitleId, className: "designbase-modal__title", children: title })), children] }), showCloseButton && onClose && (jsx("button", { type: "button", onClick: onClose, "aria-label": "\uBAA8\uB2EC \uB2EB\uAE30", className: "designbase-modal__close-button", children: jsx(CloseIcon, { size: iconSize, color: "currentColor" }) }))] }));
4347
4348
  };
4348
4349
  const ModalBody = ({ className, children, }) => {
4349
4350
  const classes = clsx('designbase-modal__body', className);
@@ -4606,7 +4607,11 @@ const Select = ({ value, defaultValue, options, label, placeholder = '선택하
4606
4607
  const [selectedValue, setSelectedValue] = useState(value ?? defaultValue ?? (multiple ? [] : ''));
4607
4608
  const [searchTerm, setSearchTerm] = useState('');
4608
4609
  const [focusedIndex, setFocusedIndex] = useState(-1);
4609
- const labelId = useId();
4610
+ const selectId = useId();
4611
+ const labelId = `${selectId}-label`;
4612
+ const listboxId = `${selectId}-listbox`;
4613
+ const helperTextId = `${selectId}-helper-text`;
4614
+ const errorTextId = `${selectId}-error-text`;
4610
4615
  const containerRef = useRef(null);
4611
4616
  const inputRef = useRef(null);
4612
4617
  const dropdownRef = useRef(null);
@@ -4766,23 +4771,29 @@ const Select = ({ value, defaultValue, options, label, placeholder = '선택하
4766
4771
  const filteredOptions = getFilteredOptions();
4767
4772
  const selectedLabels = getSelectedLabels();
4768
4773
  const hasValue = multiple ? selectedValue.length > 0 : selectedValue !== '';
4769
- return (jsxs("div", { className: classes, ref: containerRef, children: [label && (jsxs("label", { id: labelId, className: "designbase-select__label", children: [label, required && jsx("span", { className: "designbase-select__required", children: "*" })] })), jsxs("div", { className: triggerClasses, onClick: handleToggle, onFocus: onFocus, onBlur: onBlur, tabIndex: disabled || readOnly ? -1 : 0, role: "combobox", "aria-expanded": isOpen, "aria-haspopup": "listbox", "aria-labelledby": label ? labelId : undefined, ...props, children: [jsx("div", { className: "designbase-select__value", children: multiple ? (jsx("div", { className: "designbase-select__tags", ref: tagsContainerRef, children: selectedValue.map((value) => {
4774
+ const activeDescendantId = focusedIndex >= 0 ? `${selectId}-option-${focusedIndex}` : undefined;
4775
+ const describedBy = error && errorMessage
4776
+ ? errorTextId
4777
+ : helperText
4778
+ ? helperTextId
4779
+ : undefined;
4780
+ return (jsxs("div", { className: classes, ref: containerRef, children: [label && (jsxs("label", { id: labelId, className: "designbase-select__label", children: [label, required && jsx("span", { className: "designbase-select__required", children: "*" })] })), jsxs("div", { className: triggerClasses, onClick: handleToggle, onFocus: onFocus, onBlur: onBlur, tabIndex: disabled || readOnly ? -1 : 0, role: "combobox", "aria-expanded": isOpen, "aria-haspopup": "listbox", "aria-controls": listboxId, "aria-activedescendant": activeDescendantId, "aria-labelledby": label ? labelId : undefined, "aria-describedby": describedBy, "aria-invalid": error, ...props, children: [jsx("div", { className: "designbase-select__value", children: multiple ? (jsx("div", { className: "designbase-select__tags", ref: tagsContainerRef, children: selectedValue.map((value) => {
4770
4781
  const option = options.find(opt => opt.value === value);
4771
4782
  return (jsxs("span", { className: "designbase-select__tag", children: [jsx("span", { className: "designbase-select__tag-label", children: option?.label || value }), jsx("button", { type: "button", className: "designbase-select__tag-remove", onClick: (e) => {
4772
4783
  e.stopPropagation();
4773
4784
  handleRemoveValue(value);
4774
4785
  }, children: jsx(CloseIcon, { size: 12 }) })] }, value));
4775
- }) })) : (jsx("span", { className: "designbase-select__single-value", children: selectedLabels || placeholder })) }), jsxs("div", { className: "designbase-select__indicators", children: [showClearButton && hasValue && !disabled && !readOnly && (jsx("button", { type: "button", className: "designbase-select__clear-button", onClick: handleClearAll, "aria-label": "\uBAA8\uB4E0 \uAC12 \uC9C0\uC6B0\uAE30", children: jsx(CloseIcon, { size: 16 }) })), jsx("div", { className: "designbase-select__chevron", children: isOpen ? jsx(ChevronUpIcon, { size: 16 }) : jsx(ChevronDownIcon, { size: 16 }) })] })] }), jsxs("div", { className: dropdownClasses, ref: dropdownRef, children: [searchable && (jsx("div", { className: "designbase-select__search", onMouseDown: (e) => e.stopPropagation(), onClick: (e) => e.stopPropagation(), children: jsx(SearchBar, { value: searchTerm, onChange: (value) => setSearchTerm(value), onSearch: (val) => setSearchTerm(val), placeholder: "\uC635\uC158 \uAC80\uC0C9", size: size, variant: "outlined", fullWidth: true, onFocus: (e) => e.stopPropagation(), onBlur: (e) => e.stopPropagation() }) })), jsx("div", { className: "designbase-select__options", style: { maxHeight: `${maxHeight}px` }, role: "listbox", children: filteredOptions.length === 0 ? (jsx("div", { className: "designbase-select__no-options", children: searchTerm ? '검색 결과가 없습니다.' : '옵션이 없습니다.' })) : (filteredOptions.map((option, index) => {
4786
+ }) })) : (jsx("span", { className: "designbase-select__single-value", children: selectedLabels || placeholder })) }), jsxs("div", { className: "designbase-select__indicators", children: [showClearButton && hasValue && !disabled && !readOnly && (jsx("button", { type: "button", className: "designbase-select__clear-button", onClick: handleClearAll, "aria-label": "\uBAA8\uB4E0 \uAC12 \uC9C0\uC6B0\uAE30", children: jsx(CloseIcon, { size: 16 }) })), jsx("div", { className: "designbase-select__chevron", children: isOpen ? jsx(ChevronUpIcon, { size: 16 }) : jsx(ChevronDownIcon, { size: 16 }) })] })] }), jsxs("div", { className: dropdownClasses, ref: dropdownRef, children: [searchable && (jsx("div", { className: "designbase-select__search", onMouseDown: (e) => e.stopPropagation(), onClick: (e) => e.stopPropagation(), children: jsx(SearchBar, { value: searchTerm, onChange: (value) => setSearchTerm(value), onSearch: (val) => setSearchTerm(val), placeholder: "\uC635\uC158 \uAC80\uC0C9", size: size, variant: "outlined", fullWidth: true, onFocus: (e) => e.stopPropagation(), onBlur: (e) => e.stopPropagation() }) })), jsx("div", { className: "designbase-select__options", style: { maxHeight: `${maxHeight}px` }, id: listboxId, role: "listbox", children: filteredOptions.length === 0 ? (jsx("div", { className: "designbase-select__no-options", children: searchTerm ? '검색 결과가 없습니다.' : '옵션이 없습니다.' })) : (filteredOptions.map((option, index) => {
4776
4787
  const isSelected = multiple
4777
4788
  ? selectedValue.includes(option.value)
4778
4789
  : selectedValue === option.value;
4779
4790
  const isFocused = index === focusedIndex;
4780
- return (jsxs("div", { className: clsx('designbase-select__option', {
4791
+ return (jsxs("div", { id: `${selectId}-option-${index}`, className: clsx('designbase-select__option', {
4781
4792
  'designbase-select__option--selected': isSelected,
4782
4793
  'designbase-select__option--focused': isFocused,
4783
4794
  'designbase-select__option--disabled': option.disabled,
4784
4795
  }), onClick: () => handleOptionSelect(option), role: "option", "aria-selected": isSelected, children: [multiple && (jsx("div", { className: "designbase-select__checkbox", children: jsx(Checkbox, { isSelected: isSelected, isDisabled: option.disabled, size: "s", hasLabel: false, onChange: () => handleOptionSelect(option) }) })), jsx("span", { className: "designbase-select__option-label", children: option.label })] }, option.value));
4785
- })) })] }), helperText && !error && (jsx("p", { className: "designbase-select__helper-text", children: helperText })), error && errorMessage && (jsx("p", { className: "designbase-select__error-message", children: errorMessage }))] }));
4796
+ })) })] }), helperText && !error && (jsx("p", { id: helperTextId, className: "designbase-select__helper-text", children: helperText })), error && errorMessage && (jsx("p", { id: errorTextId, className: "designbase-select__error-message", children: errorMessage }))] }));
4786
4797
  };
4787
4798
  Select.displayName = 'Select';
4788
4799
 
@@ -8194,7 +8205,7 @@ const HeroFeature = ({ title, subtitle, description, image, imageAlt, background
8194
8205
  const renderButtons = () => {
8195
8206
  if (buttons.length === 0)
8196
8207
  return null;
8197
- return (jsx("div", { className: "designbase-hero-feature__buttons", children: buttons.map((button, index) => (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))) }));
8208
+ return (jsx("div", { className: "designbase-hero-feature__buttons", children: buttons.map((button, index) => (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))) }));
8198
8209
  };
8199
8210
  const renderStats = () => {
8200
8211
  if (stats.length === 0)
@@ -10822,14 +10833,34 @@ const ScrollArea = ({ direction = 'vertical', scrollbarStyle = 'auto', maxHeight
10822
10833
  return (jsx("div", { className: classes, style: style, children: jsx("div", { ref: scrollRef, className: "designbase-scroll-area__content", children: children }) }));
10823
10834
  };
10824
10835
 
10825
- const Section = ({ title, subtitle, description, size = 'm', variant = 'default', header, footer, actions, noPadding = false, fullWidth = false, fullHeight = false, className, children, }) => {
10836
+ const Section = ({ title, subtitle, description = '', size = 'm', variant = 'default', header, footer, actions, noPadding = false, fullWidth = false, fullHeight = false, className, children, }) => {
10837
+ const normalizeActionButtonSize = (node) => {
10838
+ if (!React.isValidElement(node))
10839
+ return node;
10840
+ const element = node;
10841
+ const elementType = element.type;
10842
+ const isButtonComponent = elementType?.displayName === 'Button' || elementType?.name === 'Button';
10843
+ // Button이고 size가 지정되지 않았으면 기본값 m 적용
10844
+ if (isButtonComponent && element.props?.size === undefined) {
10845
+ return React.cloneElement(element, { size: 'm' });
10846
+ }
10847
+ if (element.props?.children) {
10848
+ return React.cloneElement(element, {
10849
+ children: React.Children.map(element.props.children, normalizeActionButtonSize),
10850
+ });
10851
+ }
10852
+ return element;
10853
+ };
10854
+ const normalizedActions = actions
10855
+ ? React.Children.map(actions, normalizeActionButtonSize)
10856
+ : actions;
10826
10857
  const classes = clsx('designbase-section', `designbase-section--size-${size}`, `designbase-section--variant-${variant}`, {
10827
10858
  'designbase-section--no-padding': noPadding,
10828
10859
  'designbase-section--full-width': fullWidth,
10829
10860
  'designbase-section--full-height': fullHeight,
10830
10861
  }, className);
10831
- const hasHeader = title || subtitle || description || header || actions;
10832
- return (jsxs("section", { className: classes, children: [hasHeader && (jsx("div", { className: "designbase-section__header", children: header || (jsxs(Fragment, { children: [(title || subtitle) && (jsxs("div", { className: "designbase-section__title-area", children: [title && (jsx("h2", { className: "designbase-section__title", children: title })), subtitle && (jsx("h3", { className: "designbase-section__subtitle", children: subtitle })), description && (jsx("p", { className: "designbase-section__description", children: description }))] })), actions && (jsx("div", { className: "designbase-section__actions", children: actions }))] })) })), jsx("div", { className: "designbase-section__content", children: children }), footer && (jsx("div", { className: "designbase-section__footer", children: footer }))] }));
10862
+ const hasHeader = title || subtitle || description || header || normalizedActions;
10863
+ return (jsxs("section", { className: classes, children: [hasHeader && (jsx("div", { className: "designbase-section__header", children: header || (jsxs(Fragment, { children: [(title || subtitle) && (jsxs("div", { className: "designbase-section__title-area", children: [title && (jsx("h2", { className: "designbase-section__title", children: title })), subtitle && (jsx("h3", { className: "designbase-section__subtitle", children: subtitle })), description && (jsx("p", { className: "designbase-section__description", children: description }))] })), normalizedActions && (jsx("div", { className: "designbase-section__actions", children: normalizedActions }))] })) })), jsx("div", { className: "designbase-section__content", children: children }), footer && (jsx("div", { className: "designbase-section__footer", children: footer }))] }));
10833
10864
  };
10834
10865
 
10835
10866
  const Share = ({ url, title, description = '', imageUrl, hashtags = [], variant = 'button', size = 'm', position = 'bottom', platforms = ['facebook', 'x', 'linkedin', 'whatsapp', 'email', 'link'], customPlatforms = {}, buttonText = '공유', buttonIcon = ShareAltIcon, modalTitle = '공유하기', copySuccessMessage = '링크가 클립보드에 복사되었습니다!', showQrCode = true, qrCodeSize = 200, className, style, onShare, onShareError, onCopySuccess, onCopyError, }) => {
@@ -11082,11 +11113,11 @@ const Skeleton = forwardRef(({ variant = 'text', size = 'm', width, height, anim
11082
11113
  switch (size) {
11083
11114
  case 'xs':
11084
11115
  return variant === 'circular' ? '16px' : '12px';
11085
- case 'sm':
11116
+ case 's':
11086
11117
  return variant === 'circular' ? '24px' : '16px';
11087
- case 'md':
11118
+ case 'm':
11088
11119
  return variant === 'circular' ? '32px' : '20px';
11089
- case 'lg':
11120
+ case 'l':
11090
11121
  return variant === 'circular' ? '48px' : '24px';
11091
11122
  case 'xl':
11092
11123
  return variant === 'circular' ? '64px' : '32px';
@@ -11098,9 +11129,9 @@ const Skeleton = forwardRef(({ variant = 'text', size = 'm', width, height, anim
11098
11129
  const getTextLineHeight = () => {
11099
11130
  switch (size) {
11100
11131
  case 'xs': return '12px';
11101
- case 'sm': return '16px';
11102
- case 'md': return '20px';
11103
- case 'lg': return '24px';
11132
+ case 's': return '16px';
11133
+ case 'm': return '20px';
11134
+ case 'l': return '24px';
11104
11135
  case 'xl': return '32px';
11105
11136
  default: return '20px';
11106
11137
  }