@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.js CHANGED
@@ -4344,8 +4344,9 @@ const Modal = ({ isOpen, onClose, title, size = 'm', closeOnOutsideClick = true,
4344
4344
  return (jsxRuntime.jsx("div", { className: overlayClasses, onClick: closeOnOutsideClick ? onClose : undefined, children: jsxRuntime.jsxs("div", { ref: modalRef, className: modalClasses, onClick: (e) => e.stopPropagation(), role: "dialog", "aria-modal": "true", "aria-labelledby": title ? titleId : undefined, children: [title && (jsxRuntime.jsx(ModalHeader, { title: title, titleId: titleId, showCloseButton: true, onClose: onClose, iconSize: iconSize })), jsxRuntime.jsx("div", { className: "designbase-modal__content", children: children })] }) }));
4345
4345
  };
4346
4346
  const ModalHeader = ({ title, titleId, showCloseButton = true, onClose, iconSize = 20, className, children, }) => {
4347
+ const fallbackTitleId = React.useId();
4347
4348
  const classes = clsx('designbase-modal__header', className);
4348
- return (jsxRuntime.jsxs("div", { className: classes, children: [jsxRuntime.jsxs("div", { className: "designbase-modal__header-content", children: [title && (jsxRuntime.jsx("h2", { id: titleId || 'modal-title', className: "designbase-modal__title", children: title })), children] }), showCloseButton && onClose && (jsxRuntime.jsx("button", { type: "button", onClick: onClose, "aria-label": "\uBAA8\uB2EC \uB2EB\uAE30", className: "designbase-modal__close-button", children: jsxRuntime.jsx(icons.CloseIcon, { size: iconSize, color: "currentColor" }) }))] }));
4349
+ return (jsxRuntime.jsxs("div", { className: classes, children: [jsxRuntime.jsxs("div", { className: "designbase-modal__header-content", children: [title && (jsxRuntime.jsx("h2", { id: titleId || fallbackTitleId, className: "designbase-modal__title", children: title })), children] }), showCloseButton && onClose && (jsxRuntime.jsx("button", { type: "button", onClick: onClose, "aria-label": "\uBAA8\uB2EC \uB2EB\uAE30", className: "designbase-modal__close-button", children: jsxRuntime.jsx(icons.CloseIcon, { size: iconSize, color: "currentColor" }) }))] }));
4349
4350
  };
4350
4351
  const ModalBody = ({ className, children, }) => {
4351
4352
  const classes = clsx('designbase-modal__body', className);
@@ -4608,7 +4609,11 @@ const Select = ({ value, defaultValue, options, label, placeholder = '선택하
4608
4609
  const [selectedValue, setSelectedValue] = React.useState(value ?? defaultValue ?? (multiple ? [] : ''));
4609
4610
  const [searchTerm, setSearchTerm] = React.useState('');
4610
4611
  const [focusedIndex, setFocusedIndex] = React.useState(-1);
4611
- const labelId = React.useId();
4612
+ const selectId = React.useId();
4613
+ const labelId = `${selectId}-label`;
4614
+ const listboxId = `${selectId}-listbox`;
4615
+ const helperTextId = `${selectId}-helper-text`;
4616
+ const errorTextId = `${selectId}-error-text`;
4612
4617
  const containerRef = React.useRef(null);
4613
4618
  const inputRef = React.useRef(null);
4614
4619
  const dropdownRef = React.useRef(null);
@@ -4768,23 +4773,29 @@ const Select = ({ value, defaultValue, options, label, placeholder = '선택하
4768
4773
  const filteredOptions = getFilteredOptions();
4769
4774
  const selectedLabels = getSelectedLabels();
4770
4775
  const hasValue = multiple ? selectedValue.length > 0 : selectedValue !== '';
4771
- return (jsxRuntime.jsxs("div", { className: classes, ref: containerRef, children: [label && (jsxRuntime.jsxs("label", { id: labelId, className: "designbase-select__label", children: [label, required && jsxRuntime.jsx("span", { className: "designbase-select__required", children: "*" })] })), jsxRuntime.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: [jsxRuntime.jsx("div", { className: "designbase-select__value", children: multiple ? (jsxRuntime.jsx("div", { className: "designbase-select__tags", ref: tagsContainerRef, children: selectedValue.map((value) => {
4776
+ const activeDescendantId = focusedIndex >= 0 ? `${selectId}-option-${focusedIndex}` : undefined;
4777
+ const describedBy = error && errorMessage
4778
+ ? errorTextId
4779
+ : helperText
4780
+ ? helperTextId
4781
+ : undefined;
4782
+ return (jsxRuntime.jsxs("div", { className: classes, ref: containerRef, children: [label && (jsxRuntime.jsxs("label", { id: labelId, className: "designbase-select__label", children: [label, required && jsxRuntime.jsx("span", { className: "designbase-select__required", children: "*" })] })), jsxRuntime.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: [jsxRuntime.jsx("div", { className: "designbase-select__value", children: multiple ? (jsxRuntime.jsx("div", { className: "designbase-select__tags", ref: tagsContainerRef, children: selectedValue.map((value) => {
4772
4783
  const option = options.find(opt => opt.value === value);
4773
4784
  return (jsxRuntime.jsxs("span", { className: "designbase-select__tag", children: [jsxRuntime.jsx("span", { className: "designbase-select__tag-label", children: option?.label || value }), jsxRuntime.jsx("button", { type: "button", className: "designbase-select__tag-remove", onClick: (e) => {
4774
4785
  e.stopPropagation();
4775
4786
  handleRemoveValue(value);
4776
4787
  }, children: jsxRuntime.jsx(icons.CloseIcon, { size: 12 }) })] }, value));
4777
- }) })) : (jsxRuntime.jsx("span", { className: "designbase-select__single-value", children: selectedLabels || placeholder })) }), jsxRuntime.jsxs("div", { className: "designbase-select__indicators", children: [showClearButton && hasValue && !disabled && !readOnly && (jsxRuntime.jsx("button", { type: "button", className: "designbase-select__clear-button", onClick: handleClearAll, "aria-label": "\uBAA8\uB4E0 \uAC12 \uC9C0\uC6B0\uAE30", children: jsxRuntime.jsx(icons.CloseIcon, { size: 16 }) })), jsxRuntime.jsx("div", { className: "designbase-select__chevron", children: isOpen ? jsxRuntime.jsx(icons.ChevronUpIcon, { size: 16 }) : jsxRuntime.jsx(icons.ChevronDownIcon, { size: 16 }) })] })] }), jsxRuntime.jsxs("div", { className: dropdownClasses, ref: dropdownRef, children: [searchable && (jsxRuntime.jsx("div", { className: "designbase-select__search", onMouseDown: (e) => e.stopPropagation(), onClick: (e) => e.stopPropagation(), children: jsxRuntime.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() }) })), jsxRuntime.jsx("div", { className: "designbase-select__options", style: { maxHeight: `${maxHeight}px` }, role: "listbox", children: filteredOptions.length === 0 ? (jsxRuntime.jsx("div", { className: "designbase-select__no-options", children: searchTerm ? '검색 결과가 없습니다.' : '옵션이 없습니다.' })) : (filteredOptions.map((option, index) => {
4788
+ }) })) : (jsxRuntime.jsx("span", { className: "designbase-select__single-value", children: selectedLabels || placeholder })) }), jsxRuntime.jsxs("div", { className: "designbase-select__indicators", children: [showClearButton && hasValue && !disabled && !readOnly && (jsxRuntime.jsx("button", { type: "button", className: "designbase-select__clear-button", onClick: handleClearAll, "aria-label": "\uBAA8\uB4E0 \uAC12 \uC9C0\uC6B0\uAE30", children: jsxRuntime.jsx(icons.CloseIcon, { size: 16 }) })), jsxRuntime.jsx("div", { className: "designbase-select__chevron", children: isOpen ? jsxRuntime.jsx(icons.ChevronUpIcon, { size: 16 }) : jsxRuntime.jsx(icons.ChevronDownIcon, { size: 16 }) })] })] }), jsxRuntime.jsxs("div", { className: dropdownClasses, ref: dropdownRef, children: [searchable && (jsxRuntime.jsx("div", { className: "designbase-select__search", onMouseDown: (e) => e.stopPropagation(), onClick: (e) => e.stopPropagation(), children: jsxRuntime.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() }) })), jsxRuntime.jsx("div", { className: "designbase-select__options", style: { maxHeight: `${maxHeight}px` }, id: listboxId, role: "listbox", children: filteredOptions.length === 0 ? (jsxRuntime.jsx("div", { className: "designbase-select__no-options", children: searchTerm ? '검색 결과가 없습니다.' : '옵션이 없습니다.' })) : (filteredOptions.map((option, index) => {
4778
4789
  const isSelected = multiple
4779
4790
  ? selectedValue.includes(option.value)
4780
4791
  : selectedValue === option.value;
4781
4792
  const isFocused = index === focusedIndex;
4782
- return (jsxRuntime.jsxs("div", { className: clsx('designbase-select__option', {
4793
+ return (jsxRuntime.jsxs("div", { id: `${selectId}-option-${index}`, className: clsx('designbase-select__option', {
4783
4794
  'designbase-select__option--selected': isSelected,
4784
4795
  'designbase-select__option--focused': isFocused,
4785
4796
  'designbase-select__option--disabled': option.disabled,
4786
4797
  }), onClick: () => handleOptionSelect(option), role: "option", "aria-selected": isSelected, children: [multiple && (jsxRuntime.jsx("div", { className: "designbase-select__checkbox", children: jsxRuntime.jsx(Checkbox, { isSelected: isSelected, isDisabled: option.disabled, size: "s", hasLabel: false, onChange: () => handleOptionSelect(option) }) })), jsxRuntime.jsx("span", { className: "designbase-select__option-label", children: option.label })] }, option.value));
4787
- })) })] }), helperText && !error && (jsxRuntime.jsx("p", { className: "designbase-select__helper-text", children: helperText })), error && errorMessage && (jsxRuntime.jsx("p", { className: "designbase-select__error-message", children: errorMessage }))] }));
4798
+ })) })] }), helperText && !error && (jsxRuntime.jsx("p", { id: helperTextId, className: "designbase-select__helper-text", children: helperText })), error && errorMessage && (jsxRuntime.jsx("p", { id: errorTextId, className: "designbase-select__error-message", children: errorMessage }))] }));
4788
4799
  };
4789
4800
  Select.displayName = 'Select';
4790
4801
 
@@ -8196,7 +8207,7 @@ const HeroFeature = ({ title, subtitle, description, image, imageAlt, background
8196
8207
  const renderButtons = () => {
8197
8208
  if (buttons.length === 0)
8198
8209
  return null;
8199
- 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))) }));
8210
+ 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))) }));
8200
8211
  };
8201
8212
  const renderStats = () => {
8202
8213
  if (stats.length === 0)
@@ -10824,14 +10835,34 @@ const ScrollArea = ({ direction = 'vertical', scrollbarStyle = 'auto', maxHeight
10824
10835
  return (jsxRuntime.jsx("div", { className: classes, style: style, children: jsxRuntime.jsx("div", { ref: scrollRef, className: "designbase-scroll-area__content", children: children }) }));
10825
10836
  };
10826
10837
 
10827
- const Section = ({ title, subtitle, description, size = 'm', variant = 'default', header, footer, actions, noPadding = false, fullWidth = false, fullHeight = false, className, children, }) => {
10838
+ const Section = ({ title, subtitle, description = '', size = 'm', variant = 'default', header, footer, actions, noPadding = false, fullWidth = false, fullHeight = false, className, children, }) => {
10839
+ const normalizeActionButtonSize = (node) => {
10840
+ if (!React.isValidElement(node))
10841
+ return node;
10842
+ const element = node;
10843
+ const elementType = element.type;
10844
+ const isButtonComponent = elementType?.displayName === 'Button' || elementType?.name === 'Button';
10845
+ // Button이고 size가 지정되지 않았으면 기본값 m 적용
10846
+ if (isButtonComponent && element.props?.size === undefined) {
10847
+ return React.cloneElement(element, { size: 'm' });
10848
+ }
10849
+ if (element.props?.children) {
10850
+ return React.cloneElement(element, {
10851
+ children: React.Children.map(element.props.children, normalizeActionButtonSize),
10852
+ });
10853
+ }
10854
+ return element;
10855
+ };
10856
+ const normalizedActions = actions
10857
+ ? React.Children.map(actions, normalizeActionButtonSize)
10858
+ : actions;
10828
10859
  const classes = clsx('designbase-section', `designbase-section--size-${size}`, `designbase-section--variant-${variant}`, {
10829
10860
  'designbase-section--no-padding': noPadding,
10830
10861
  'designbase-section--full-width': fullWidth,
10831
10862
  'designbase-section--full-height': fullHeight,
10832
10863
  }, className);
10833
- const hasHeader = title || subtitle || description || header || actions;
10834
- 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 }))] }));
10864
+ const hasHeader = title || subtitle || description || header || normalizedActions;
10865
+ 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 }))] }));
10835
10866
  };
10836
10867
 
10837
10868
  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, }) => {
@@ -11084,11 +11115,11 @@ const Skeleton = React.forwardRef(({ variant = 'text', size = 'm', width, height
11084
11115
  switch (size) {
11085
11116
  case 'xs':
11086
11117
  return variant === 'circular' ? '16px' : '12px';
11087
- case 'sm':
11118
+ case 's':
11088
11119
  return variant === 'circular' ? '24px' : '16px';
11089
- case 'md':
11120
+ case 'm':
11090
11121
  return variant === 'circular' ? '32px' : '20px';
11091
- case 'lg':
11122
+ case 'l':
11092
11123
  return variant === 'circular' ? '48px' : '24px';
11093
11124
  case 'xl':
11094
11125
  return variant === 'circular' ? '64px' : '32px';
@@ -11100,9 +11131,9 @@ const Skeleton = React.forwardRef(({ variant = 'text', size = 'm', width, height
11100
11131
  const getTextLineHeight = () => {
11101
11132
  switch (size) {
11102
11133
  case 'xs': return '12px';
11103
- case 'sm': return '16px';
11104
- case 'md': return '20px';
11105
- case 'lg': return '24px';
11134
+ case 's': return '16px';
11135
+ case 'm': return '20px';
11136
+ case 'l': return '24px';
11106
11137
  case 'xl': return '32px';
11107
11138
  default: return '20px';
11108
11139
  }