@designbasekorea/ui 0.2.41 → 0.3.1

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
@@ -2416,23 +2416,18 @@ const Button = forwardRef(({ variant = 'primary', size = 'm', radius, fullWidth
2416
2416
  return `designbase-button--radius-${radius}`;
2417
2417
  }
2418
2418
  // 아이콘 전용 버튼도 일반 버튼과 동일한 radius 적용
2419
- return `designbase-button--radius-${size === 'xs' || size === 's' ? 's' : size === 'l' || size === 'xl' ? 'l' : 'm'}`;
2419
+ if (size === 's')
2420
+ return 'designbase-button--radius-s';
2421
+ if (size === 'l')
2422
+ return 'designbase-button--radius-l';
2423
+ return 'designbase-button--radius-m';
2420
2424
  };
2421
2425
  const classes = clsx('designbase-button', `designbase-button--${variant}`, `designbase-button--${size}`, getRadiusClass(), {
2422
2426
  'designbase-button--full-width': fullWidth,
2423
2427
  'designbase-button--loading': loading,
2424
2428
  'designbase-button--icon-only': iconOnly,
2425
2429
  }, className);
2426
- const iconSize = (() => {
2427
- switch (size) {
2428
- case 'xs': return 12;
2429
- case 's': return 14;
2430
- case 'm': return 16;
2431
- case 'l': return 18;
2432
- case 'xl': return 20;
2433
- default: return 16;
2434
- }
2435
- })();
2430
+ const iconSize = size === 's' ? 14 : size === 'l' ? 18 : 16;
2436
2431
  // 아이콘 색상 결정
2437
2432
  const getIconColor = () => {
2438
2433
  switch (variant) {
@@ -2452,7 +2447,7 @@ const Button = forwardRef(({ variant = 'primary', size = 'm', radius, fullWidth
2452
2447
  };
2453
2448
  const renderContent = () => {
2454
2449
  if (loading) {
2455
- return (jsxs(Fragment, { children: [jsx(Spinner, { type: "circular", size: size === 'xs' ? 'xs' : size === 's' ? 's' : 'm', color: getIconColor(), speed: 1, showLabel: false }), !iconOnly && jsx("span", { children: "\uB85C\uB529 \uC911..." })] }));
2450
+ return (jsxs(Fragment, { children: [jsx(Spinner, { type: "circular", size: size === 's' ? 's' : size === 'l' ? 'l' : 'm', color: getIconColor(), speed: 1, showLabel: false }), !iconOnly && jsx("span", { children: "\uB85C\uB529 \uC911..." })] }));
2456
2451
  }
2457
2452
  // iconOnly 버튼일 때는 children을 아이콘으로 처리
2458
2453
  if (iconOnly && children && React.isValidElement(children)) {
@@ -4011,7 +4006,7 @@ ModalHeader.displayName = 'ModalHeader';
4011
4006
  ModalBody.displayName = 'ModalBody';
4012
4007
  ModalFooter.displayName = 'ModalFooter';
4013
4008
 
4014
- const Label = ({ children, htmlFor, required = false, size = 's', disabled = false, error = false, className, onClick, }) => {
4009
+ const Label = ({ children, htmlFor, id, required = false, size = 's', disabled = false, error = false, className, onClick, }) => {
4015
4010
  const classes = [
4016
4011
  'designbase-label',
4017
4012
  `designbase-label--${size}`,
@@ -4021,7 +4016,7 @@ const Label = ({ children, htmlFor, required = false, size = 's', disabled = fal
4021
4016
  ]
4022
4017
  .filter(Boolean)
4023
4018
  .join(' ');
4024
- return (jsxs("label", { htmlFor: htmlFor, className: classes, onClick: onClick, children: [children, required && jsx("span", { className: "designbase-label__required", children: "*" })] }));
4019
+ return (jsxs("label", { htmlFor: htmlFor, id: id, className: classes, onClick: onClick, children: [children, required && jsx("span", { className: "designbase-label__required", children: "*" })] }));
4025
4020
  };
4026
4021
  Label.displayName = 'Label';
4027
4022
 
@@ -4052,12 +4047,17 @@ const Input = forwardRef(({ type = 'text', label, placeholder, defaultValue, val
4052
4047
  'designbase-input--with-end-icon': EndIcon || isPassword,
4053
4048
  }, className);
4054
4049
  const inputClasses = clsx('designbase-input__field', inputClassName);
4055
- const iconSizeMap = {
4056
- sm: 14,
4057
- md: 16,
4058
- lg: 18,
4059
- };
4060
- const iconSize = iconSizeMap[size];
4050
+ const iconSize = React.useMemo(() => {
4051
+ switch (size) {
4052
+ case 's':
4053
+ return 16;
4054
+ case 'l':
4055
+ return 24;
4056
+ case 'm':
4057
+ default:
4058
+ return 20;
4059
+ }
4060
+ }, [size]);
4061
4061
  return (jsxs("div", { className: classes, children: [label && (jsx(Label, { htmlFor: inputId, required: required, error: error, disabled: disabled, size: size === 's' ? 's' : size === 'm' ? 'm' : 'l', children: label })), jsxs("div", { className: "designbase-input__wrapper", children: [actualStartIcon && (jsx("div", { className: "designbase-input__start-icon", children: React.createElement(actualStartIcon, { size: iconSize }) })), jsx("input", { ...props, ref: forwardedRef, id: inputId, type: actualType, value: value, defaultValue: defaultValue, placeholder: placeholder, disabled: disabled, readOnly: readOnly, required: required, className: inputClasses, onChange: handleChange, onFocus: onFocus, onBlur: onBlur, "aria-describedby": clsx(helperText && helperTextId, error && errorMessage && errorMessageId), "aria-invalid": error }), isPassword && (jsx("button", { type: "button", className: "designbase-input__password-toggle", onClick: handlePasswordToggle, disabled: disabled, "aria-label": showPassword ? '비밀번호 숨기기' : '비밀번호 보기', children: React.createElement(PasswordIcon, { size: iconSize }) })), EndIcon && !isPassword && (jsx("div", { className: "designbase-input__end-icon", children: React.createElement(EndIcon, { size: iconSize }) }))] }), helperText && !error && (jsx("p", { id: helperTextId, className: "designbase-input__helper-text", children: helperText })), error && errorMessage && (jsx("p", { id: errorMessageId, className: "designbase-input__error-message", children: errorMessage }))] }));
4062
4062
  });
4063
4063
  Input.displayName = 'Input';
@@ -4098,6 +4098,157 @@ const Checkbox = forwardRef(({ isSelected, defaultSelected, isIndeterminate = fa
4098
4098
  });
4099
4099
  Checkbox.displayName = 'Checkbox';
4100
4100
 
4101
+ const SearchBar = ({ value, defaultValue = '', placeholder = '검색...', size = 'm', variant = 'default', disabled = false, readOnly = false, fullWidth = false, searchIcon: SearchIconComponent = SearchIcon, clearIcon: ClearIconComponent = CloseIcon, enableRecentSearches = false, recentSearchesKey = 'searchbar-recent-searches', suggestedSearches = [], suggestionRollingInterval = 5000, onChange, onSearch, onFocus, onBlur, onKeyDown, className, ...rest }) => {
4102
+ const [internalValue, setInternalValue] = useState(defaultValue);
4103
+ const [recentSearches, setRecentSearches] = useState([]);
4104
+ const [showRecentSearches, setShowRecentSearches] = useState(false);
4105
+ const [currentSuggestion, setCurrentSuggestion] = useState(0);
4106
+ const [isFocused, setIsFocused] = useState(false);
4107
+ const inputRef = useRef(null);
4108
+ const suggestionIntervalRef = useRef(null);
4109
+ const currentValue = value !== undefined ? value : internalValue;
4110
+ // 최근 검색어 로드
4111
+ useEffect(() => {
4112
+ if (enableRecentSearches) {
4113
+ try {
4114
+ const stored = localStorage.getItem(recentSearchesKey);
4115
+ if (stored) {
4116
+ setRecentSearches(JSON.parse(stored));
4117
+ }
4118
+ }
4119
+ catch (error) {
4120
+ console.warn('최근 검색어를 불러올 수 없습니다:', error);
4121
+ }
4122
+ }
4123
+ }, [enableRecentSearches, recentSearchesKey]);
4124
+ // 추천 검색어 롤링 (value가 없을 때만)
4125
+ useEffect(() => {
4126
+ if (suggestedSearches.length > 0 && !currentValue && currentValue === '') {
4127
+ suggestionIntervalRef.current = setInterval(() => {
4128
+ setCurrentSuggestion(prev => (prev + 1) % suggestedSearches.length);
4129
+ }, suggestionRollingInterval);
4130
+ }
4131
+ else {
4132
+ if (suggestionIntervalRef.current) {
4133
+ clearInterval(suggestionIntervalRef.current);
4134
+ suggestionIntervalRef.current = null;
4135
+ }
4136
+ }
4137
+ return () => {
4138
+ if (suggestionIntervalRef.current) {
4139
+ clearInterval(suggestionIntervalRef.current);
4140
+ }
4141
+ };
4142
+ }, [suggestedSearches.length, currentValue, suggestionRollingInterval]);
4143
+ useEffect(() => {
4144
+ if (value !== undefined) {
4145
+ setInternalValue(value);
4146
+ }
4147
+ }, [value]);
4148
+ const handleChange = (e) => {
4149
+ const newValue = e.target.value;
4150
+ setInternalValue(newValue);
4151
+ onChange?.(newValue);
4152
+ };
4153
+ const handleClear = () => {
4154
+ setInternalValue('');
4155
+ onChange?.('');
4156
+ inputRef.current?.focus();
4157
+ };
4158
+ const handleSearch = (searchValue) => {
4159
+ const searchTerm = searchValue || currentValue.trim();
4160
+ if (searchTerm) {
4161
+ onSearch?.(searchTerm);
4162
+ // 최근 검색어 저장
4163
+ if (enableRecentSearches) {
4164
+ const newRecentSearches = [
4165
+ searchTerm,
4166
+ ...recentSearches.filter(item => item !== searchTerm)
4167
+ ].slice(0, 10); // 최대 10개
4168
+ setRecentSearches(newRecentSearches);
4169
+ try {
4170
+ localStorage.setItem(recentSearchesKey, JSON.stringify(newRecentSearches));
4171
+ }
4172
+ catch (error) {
4173
+ console.warn('최근 검색어를 저장할 수 없습니다:', error);
4174
+ }
4175
+ }
4176
+ }
4177
+ };
4178
+ const handleKeyDown = (e) => {
4179
+ if (e.key === 'Enter') {
4180
+ handleSearch();
4181
+ }
4182
+ onKeyDown?.(e);
4183
+ };
4184
+ const handleFocus = (e) => {
4185
+ setIsFocused(true);
4186
+ setShowRecentSearches(enableRecentSearches && recentSearches.length > 0);
4187
+ onFocus?.(e);
4188
+ };
4189
+ const handleBlur = (e) => {
4190
+ setIsFocused(false);
4191
+ // 약간의 지연을 두어 클릭 이벤트가 처리되도록 함
4192
+ setTimeout(() => {
4193
+ setShowRecentSearches(false);
4194
+ }, 200);
4195
+ onBlur?.(e);
4196
+ };
4197
+ const handleRecentSearchClick = (searchTerm) => {
4198
+ setInternalValue(searchTerm);
4199
+ onChange?.(searchTerm);
4200
+ setShowRecentSearches(false);
4201
+ handleSearch(searchTerm);
4202
+ };
4203
+ const handleRemoveRecentSearch = (searchTerm) => {
4204
+ const newRecentSearches = recentSearches.filter(item => item !== searchTerm);
4205
+ setRecentSearches(newRecentSearches);
4206
+ try {
4207
+ localStorage.setItem(recentSearchesKey, JSON.stringify(newRecentSearches));
4208
+ }
4209
+ catch (error) {
4210
+ console.warn('최근 검색어를 삭제할 수 없습니다:', error);
4211
+ }
4212
+ };
4213
+ const handleClearAllRecentSearches = () => {
4214
+ setRecentSearches([]);
4215
+ try {
4216
+ localStorage.removeItem(recentSearchesKey);
4217
+ }
4218
+ catch (error) {
4219
+ console.warn('최근 검색어를 모두 삭제할 수 없습니다:', error);
4220
+ }
4221
+ };
4222
+ const handleSuggestionClick = (suggestion) => {
4223
+ setInternalValue(suggestion);
4224
+ onChange?.(suggestion);
4225
+ // 롤링 중단
4226
+ if (suggestionIntervalRef.current) {
4227
+ clearInterval(suggestionIntervalRef.current);
4228
+ suggestionIntervalRef.current = null;
4229
+ }
4230
+ handleSearch(suggestion);
4231
+ };
4232
+ const classes = clsx('designbase-search-bar', `designbase-search-bar--${size}`, `designbase-search-bar--${variant}`, {
4233
+ 'designbase-search-bar--disabled': disabled,
4234
+ 'designbase-search-bar--readonly': readOnly,
4235
+ 'designbase-search-bar--full-width': fullWidth,
4236
+ 'designbase-search-bar--has-value': currentValue && currentValue.length > 0,
4237
+ }, className);
4238
+ const inputClasses = clsx('designbase-search-bar__input', {
4239
+ 'designbase-search-bar__input--disabled': disabled,
4240
+ 'designbase-search-bar__input--readonly': readOnly,
4241
+ });
4242
+ // 현재 플레이스홀더 (value가 없을 때만 추천 검색어 롤링)
4243
+ const currentPlaceholder = suggestedSearches.length > 0 && !currentValue && currentValue === ''
4244
+ ? suggestedSearches[currentSuggestion]
4245
+ : placeholder;
4246
+ return (jsxs("div", { className: classes, role: "search", children: [jsxs("div", { className: "designbase-search-bar__container", children: [jsx("div", { className: "designbase-search-bar__search-icon", children: jsx(SearchIconComponent, { size: size === 's' ? 16 : size === 'l' ? 24 : 20 }) }), 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 && (jsx("button", { type: "button", className: "designbase-search-bar__clear-button", onClick: handleClear, "aria-label": "\uAC80\uC0C9\uC5B4 \uC9C0\uC6B0\uAE30", children: jsx(ClearIconComponent, { size: size === 's' ? 16 : size === 'l' ? 24 : 20 }) }))] }), showRecentSearches && recentSearches.length > 0 && (jsxs("div", { className: "designbase-search-bar__recent-searches", children: [jsxs("div", { className: "designbase-search-bar__recent-header", children: [jsx("span", { className: "designbase-search-bar__recent-title", children: "\uCD5C\uADFC \uAC80\uC0C9\uC5B4" }), 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" })] }), jsx("div", { className: "designbase-search-bar__recent-list", children: recentSearches.map((searchTerm, index) => (jsxs("div", { className: "designbase-search-bar__recent-item", children: [jsx("button", { type: "button", className: "designbase-search-bar__recent-search-button", onClick: () => handleRecentSearchClick(searchTerm), children: searchTerm }), jsx("button", { type: "button", className: "designbase-search-bar__recent-remove-button", onClick: () => handleRemoveRecentSearch(searchTerm), "aria-label": `${searchTerm} 삭제`, children: jsx(CloseIcon, { size: 16 }) })] }, index))) })] })), suggestedSearches.length > 0 && isFocused && !currentValue && (jsxs("div", { className: "designbase-search-bar__suggestions", children: [jsx("div", { className: "designbase-search-bar__suggestions-header", children: jsx("span", { className: "designbase-search-bar__suggestions-title", children: "\uCD94\uCC9C \uAC80\uC0C9\uC5B4" }) }), jsx("div", { className: "designbase-search-bar__suggestions-list", children: suggestedSearches.map((suggestion, index) => (jsx("button", { type: "button", className: clsx('designbase-search-bar__suggestion-item', {
4247
+ 'designbase-search-bar__suggestion-item--active': index === currentSuggestion
4248
+ }), onClick: () => handleSuggestionClick(suggestion), children: suggestion }, index))) })] }))] }));
4249
+ };
4250
+ SearchBar.displayName = 'SearchBar';
4251
+
4101
4252
  const Select = ({ value, defaultValue, options, label, placeholder = '선택하세요', multiple = false, searchable = false, disabled = false, readOnly = false, required = false, error = false, errorMessage, helperText, size = 'm', fullWidth = false, dropdownWidth = 'auto', position = 'bottom', maxHeight = 200, showClearButton = true, className, onChange, onFocus, onBlur, ...props }) => {
4102
4253
  const [isOpen, setIsOpen] = useState(false);
4103
4254
  const [selectedValue, setSelectedValue] = useState(value ?? defaultValue ?? (multiple ? [] : ''));
@@ -4242,9 +4393,6 @@ const Select = ({ value, defaultValue, options, label, placeholder = '선택하
4242
4393
  setSelectedValue(newValue);
4243
4394
  onChange?.(newValue);
4244
4395
  };
4245
- const handleSearchChange = (e) => {
4246
- setSearchTerm(e.target.value);
4247
- };
4248
4396
  const classes = clsx('designbase-select', `designbase-select--${size}`, {
4249
4397
  'designbase-select--open': isOpen,
4250
4398
  'designbase-select--error': error,
@@ -4252,9 +4400,11 @@ const Select = ({ value, defaultValue, options, label, placeholder = '선택하
4252
4400
  'designbase-select--readonly': readOnly,
4253
4401
  'designbase-select--full-width': fullWidth,
4254
4402
  'designbase-select--multiple': multiple,
4403
+ 'designbase-select--searchable': searchable,
4255
4404
  }, className);
4256
4405
  const triggerClasses = clsx('designbase-select__trigger', {
4257
4406
  'designbase-select__trigger--focused': isOpen,
4407
+ 'designbase-select__trigger--searchable': searchable,
4258
4408
  });
4259
4409
  const dropdownClasses = clsx('designbase-select__dropdown', `designbase-select__dropdown--${dropdownWidth}`, `designbase-select__dropdown--${position}`, {
4260
4410
  'designbase-select__dropdown--open': isOpen,
@@ -4262,23 +4412,23 @@ const Select = ({ value, defaultValue, options, label, placeholder = '선택하
4262
4412
  const filteredOptions = getFilteredOptions();
4263
4413
  const selectedLabels = getSelectedLabels();
4264
4414
  const hasValue = multiple ? selectedValue.length > 0 : selectedValue !== '';
4265
- return (jsxs("div", { className: classes, ref: containerRef, children: [label && (jsxs("label", { 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 ? 'select-label' : undefined, ...props, children: [jsx("div", { className: "designbase-select__value", children: multiple ? (jsxs("div", { className: "designbase-select__tags", ref: tagsContainerRef, children: [selectedValue.map((value) => {
4266
- const option = options.find(opt => opt.value === value);
4267
- 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) => {
4268
- e.stopPropagation();
4269
- handleRemoveValue(value);
4270
- }, children: jsx(CloseIcon, { size: 12 }) })] }, value));
4271
- }), searchable && isOpen && (jsx("input", { ref: inputRef, type: "text", className: "designbase-select__search-input", value: searchTerm, onChange: handleSearchChange, placeholder: "\uAC80\uC0C9...", onClick: (e) => e.stopPropagation() }))] })) : (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 }) })] })] }), jsx("div", { className: dropdownClasses, ref: dropdownRef, children: 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) => {
4272
- const isSelected = multiple
4273
- ? selectedValue.includes(option.value)
4274
- : selectedValue === option.value;
4275
- const isFocused = index === focusedIndex;
4276
- return (jsxs("div", { className: clsx('designbase-select__option', {
4277
- 'designbase-select__option--selected': isSelected,
4278
- 'designbase-select__option--focused': isFocused,
4279
- 'designbase-select__option--disabled': option.disabled,
4280
- }), 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));
4281
- })) }) }), helperText && !error && (jsx("p", { className: "designbase-select__helper-text", children: helperText })), error && errorMessage && (jsx("p", { className: "designbase-select__error-message", children: errorMessage }))] }));
4415
+ return (jsxs("div", { className: classes, ref: containerRef, children: [label && (jsxs("label", { 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 ? 'select-label' : undefined, ...props, children: [jsx("div", { className: "designbase-select__value", children: multiple ? (jsx("div", { className: "designbase-select__tags", ref: tagsContainerRef, children: selectedValue.map((value) => {
4416
+ const option = options.find(opt => opt.value === value);
4417
+ 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) => {
4418
+ e.stopPropagation();
4419
+ handleRemoveValue(value);
4420
+ }, children: jsx(CloseIcon, { size: 12 }) })] }, value));
4421
+ }) })) : (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) => {
4422
+ const isSelected = multiple
4423
+ ? selectedValue.includes(option.value)
4424
+ : selectedValue === option.value;
4425
+ const isFocused = index === focusedIndex;
4426
+ return (jsxs("div", { className: clsx('designbase-select__option', {
4427
+ 'designbase-select__option--selected': isSelected,
4428
+ 'designbase-select__option--focused': isFocused,
4429
+ 'designbase-select__option--disabled': option.disabled,
4430
+ }), 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));
4431
+ })) })] }), helperText && !error && (jsx("p", { className: "designbase-select__helper-text", children: helperText })), error && errorMessage && (jsx("p", { className: "designbase-select__error-message", children: errorMessage }))] }));
4282
4432
  };
4283
4433
  Select.displayName = 'Select';
4284
4434
 
@@ -5219,8 +5369,6 @@ const Carousel = ({ items, size = 'm', variant = 'default', theme = 'light', tra
5219
5369
  const handleTouchEndEvent = useCallback(() => {
5220
5370
  handleTouchEnd();
5221
5371
  }, [handleTouchEnd]);
5222
- // 현재 아이템
5223
- const currentItem = items[currentIndex];
5224
5372
  // 슬라이드 스타일 계산
5225
5373
  const getSlideStyle = () => {
5226
5374
  const containerWidth = containerRef.current?.offsetWidth || 1;
@@ -5235,9 +5383,6 @@ const Carousel = ({ items, size = 'm', variant = 'default', theme = 'light', tra
5235
5383
  // 네비게이션 버튼 비활성화 상태
5236
5384
  const isPrevDisabled = !infinite && currentIndex === 0;
5237
5385
  const isNextDisabled = !infinite && currentIndex === items.length - 1;
5238
- // 좋아요/북마크 상태
5239
- const isLiked = currentItem ? likedItems.has(currentItem.id) : false;
5240
- const isBookmarked = currentItem ? bookmarkedItems.has(currentItem.id) : false;
5241
5386
  if (items.length === 0)
5242
5387
  return null;
5243
5388
  return (jsxs("div", { className: clsx('designbase-carousel', `designbase-carousel--size-${size}`, `designbase-carousel--variant-${variant}`, `designbase-carousel--theme-${theme}`, `designbase-carousel--transition-${transition}`, `designbase-carousel--indicator-${indicatorStyle}`, {
@@ -5258,13 +5403,17 @@ const Carousel = ({ items, size = 'm', variant = 'default', theme = 'light', tra
5258
5403
  color: item.textColor || (item.image ? '#ffffff' : undefined),
5259
5404
  }, children: item.title })), showDescription && item.description && (jsx("p", { className: "designbase-carousel__slide-description", style: {
5260
5405
  color: item.textColor || (item.image ? '#ffffff' : undefined),
5261
- }, children: item.description })), item.meta && (jsxs("div", { className: "designbase-carousel__slide-meta", children: [item.meta.author && (jsx("span", { className: "designbase-carousel__slide-author", children: item.meta.author })), item.meta.date && (jsx("span", { className: "designbase-carousel__slide-date", children: item.meta.date })), item.meta.rating && (jsxs("span", { className: "designbase-carousel__slide-rating", children: ["\u2B50 ", item.meta.rating] }))] }))] })) : null] })), jsxs("div", { className: "designbase-carousel__slide-actions", children: [enableLike && (jsx("button", { className: clsx('designbase-carousel__action-button', 'designbase-carousel__action-button--like', { 'designbase-carousel__action-button--active': isLiked }), onClick: (e) => {
5406
+ }, children: item.description })), item.meta && (jsxs("div", { className: "designbase-carousel__slide-meta", children: [item.meta.author && (jsx("span", { className: "designbase-carousel__slide-author", children: item.meta.author })), item.meta.date && (jsx("span", { className: "designbase-carousel__slide-date", children: item.meta.date })), item.meta.rating && (jsxs("span", { className: "designbase-carousel__slide-rating", children: ["\u2B50 ", item.meta.rating] }))] }))] })) : null] })), jsxs("div", { className: "designbase-carousel__slide-actions", children: [enableLike && (jsx("button", { className: clsx('designbase-carousel__action-button', 'designbase-carousel__action-button--like', {
5407
+ 'designbase-carousel__action-button--active': likedItems.has(item.id),
5408
+ }), onClick: (e) => {
5262
5409
  e.stopPropagation();
5263
5410
  handleLike(item, index);
5264
- }, title: isLiked ? "좋아요 취소" : "좋아요", children: jsx(HeartIcon, { size: iconSize, color: "currentColor" }) })), enableBookmark && (jsx("button", { className: clsx('designbase-carousel__action-button', 'designbase-carousel__action-button--bookmark', { 'designbase-carousel__action-button--active': isBookmarked }), onClick: (e) => {
5411
+ }, title: likedItems.has(item.id) ? "좋아요 취소" : "좋아요", children: jsx(HeartIcon, { size: iconSize, color: "currentColor" }) })), enableBookmark && (jsx("button", { className: clsx('designbase-carousel__action-button', 'designbase-carousel__action-button--bookmark', {
5412
+ 'designbase-carousel__action-button--active': bookmarkedItems.has(item.id),
5413
+ }), onClick: (e) => {
5265
5414
  e.stopPropagation();
5266
5415
  handleBookmark(item, index);
5267
- }, title: isBookmarked ? "북마크 해제" : "북마크", children: jsx(BookmarkIcon, { size: iconSize, color: "currentColor" }) })), enableShare && (jsx("button", { className: "designbase-carousel__action-button designbase-carousel__action-button--share", onClick: (e) => {
5416
+ }, title: bookmarkedItems.has(item.id) ? "북마크 해제" : "북마크", children: jsx(BookmarkIcon, { size: iconSize, color: "currentColor" }) })), enableShare && (jsx("button", { className: "designbase-carousel__action-button designbase-carousel__action-button--share", onClick: (e) => {
5268
5417
  e.stopPropagation();
5269
5418
  handleShare(item, index);
5270
5419
  }, title: "\uACF5\uC720", children: jsx(ShareAltIcon, { size: iconSize, color: "currentColor" }) })), enableDownload && item.image && (jsx("button", { className: "designbase-carousel__action-button designbase-carousel__action-button--download", onClick: (e) => {
@@ -8927,157 +9076,6 @@ const Tutorial = ({ steps, currentStep = 0, isActive, onStart, onEnd, onStepChan
8927
9076
  };
8928
9077
  Tutorial.displayName = 'Tutorial';
8929
9078
 
8930
- const SearchBar = ({ value, defaultValue = '', placeholder = '검색...', size = 'm', variant = 'default', disabled = false, readOnly = false, fullWidth = false, searchIcon: SearchIconComponent = SearchIcon, clearIcon: ClearIconComponent = CloseIcon, enableRecentSearches = false, recentSearchesKey = 'searchbar-recent-searches', suggestedSearches = [], suggestionRollingInterval = 5000, onChange, onSearch, onFocus, onBlur, onKeyDown, className, ...props }) => {
8931
- const [internalValue, setInternalValue] = useState(defaultValue);
8932
- const [recentSearches, setRecentSearches] = useState([]);
8933
- const [showRecentSearches, setShowRecentSearches] = useState(false);
8934
- const [currentSuggestion, setCurrentSuggestion] = useState(0);
8935
- const [isFocused, setIsFocused] = useState(false);
8936
- const inputRef = useRef(null);
8937
- const suggestionIntervalRef = useRef(null);
8938
- const currentValue = value !== undefined ? value : internalValue;
8939
- // 최근 검색어 로드
8940
- useEffect(() => {
8941
- if (enableRecentSearches) {
8942
- try {
8943
- const stored = localStorage.getItem(recentSearchesKey);
8944
- if (stored) {
8945
- setRecentSearches(JSON.parse(stored));
8946
- }
8947
- }
8948
- catch (error) {
8949
- console.warn('최근 검색어를 불러올 수 없습니다:', error);
8950
- }
8951
- }
8952
- }, [enableRecentSearches, recentSearchesKey]);
8953
- // 추천 검색어 롤링 (value가 없을 때만)
8954
- useEffect(() => {
8955
- if (suggestedSearches.length > 0 && !currentValue && currentValue === '') {
8956
- suggestionIntervalRef.current = setInterval(() => {
8957
- setCurrentSuggestion(prev => (prev + 1) % suggestedSearches.length);
8958
- }, suggestionRollingInterval);
8959
- }
8960
- else {
8961
- if (suggestionIntervalRef.current) {
8962
- clearInterval(suggestionIntervalRef.current);
8963
- suggestionIntervalRef.current = null;
8964
- }
8965
- }
8966
- return () => {
8967
- if (suggestionIntervalRef.current) {
8968
- clearInterval(suggestionIntervalRef.current);
8969
- }
8970
- };
8971
- }, [suggestedSearches.length, currentValue, suggestionRollingInterval]);
8972
- useEffect(() => {
8973
- if (value !== undefined) {
8974
- setInternalValue(value);
8975
- }
8976
- }, [value]);
8977
- const handleChange = (e) => {
8978
- const newValue = e.target.value;
8979
- setInternalValue(newValue);
8980
- onChange?.(newValue);
8981
- };
8982
- const handleClear = () => {
8983
- setInternalValue('');
8984
- onChange?.('');
8985
- inputRef.current?.focus();
8986
- };
8987
- const handleSearch = (searchValue) => {
8988
- const searchTerm = searchValue || currentValue.trim();
8989
- if (searchTerm) {
8990
- onSearch?.(searchTerm);
8991
- // 최근 검색어 저장
8992
- if (enableRecentSearches) {
8993
- const newRecentSearches = [
8994
- searchTerm,
8995
- ...recentSearches.filter(item => item !== searchTerm)
8996
- ].slice(0, 10); // 최대 10개
8997
- setRecentSearches(newRecentSearches);
8998
- try {
8999
- localStorage.setItem(recentSearchesKey, JSON.stringify(newRecentSearches));
9000
- }
9001
- catch (error) {
9002
- console.warn('최근 검색어를 저장할 수 없습니다:', error);
9003
- }
9004
- }
9005
- }
9006
- };
9007
- const handleKeyDown = (e) => {
9008
- if (e.key === 'Enter') {
9009
- handleSearch();
9010
- }
9011
- onKeyDown?.(e);
9012
- };
9013
- const handleFocus = (e) => {
9014
- setIsFocused(true);
9015
- setShowRecentSearches(enableRecentSearches && recentSearches.length > 0);
9016
- onFocus?.(e);
9017
- };
9018
- const handleBlur = (e) => {
9019
- setIsFocused(false);
9020
- // 약간의 지연을 두어 클릭 이벤트가 처리되도록 함
9021
- setTimeout(() => {
9022
- setShowRecentSearches(false);
9023
- }, 200);
9024
- onBlur?.(e);
9025
- };
9026
- const handleRecentSearchClick = (searchTerm) => {
9027
- setInternalValue(searchTerm);
9028
- onChange?.(searchTerm);
9029
- setShowRecentSearches(false);
9030
- handleSearch(searchTerm);
9031
- };
9032
- const handleRemoveRecentSearch = (searchTerm) => {
9033
- const newRecentSearches = recentSearches.filter(item => item !== searchTerm);
9034
- setRecentSearches(newRecentSearches);
9035
- try {
9036
- localStorage.setItem(recentSearchesKey, JSON.stringify(newRecentSearches));
9037
- }
9038
- catch (error) {
9039
- console.warn('최근 검색어를 삭제할 수 없습니다:', error);
9040
- }
9041
- };
9042
- const handleClearAllRecentSearches = () => {
9043
- setRecentSearches([]);
9044
- try {
9045
- localStorage.removeItem(recentSearchesKey);
9046
- }
9047
- catch (error) {
9048
- console.warn('최근 검색어를 모두 삭제할 수 없습니다:', error);
9049
- }
9050
- };
9051
- const handleSuggestionClick = (suggestion) => {
9052
- setInternalValue(suggestion);
9053
- onChange?.(suggestion);
9054
- // 롤링 중단
9055
- if (suggestionIntervalRef.current) {
9056
- clearInterval(suggestionIntervalRef.current);
9057
- suggestionIntervalRef.current = null;
9058
- }
9059
- handleSearch(suggestion);
9060
- };
9061
- const classes = clsx('designbase-search-bar', `designbase-search-bar--${size}`, `designbase-search-bar--${variant}`, {
9062
- 'designbase-search-bar--disabled': disabled,
9063
- 'designbase-search-bar--readonly': readOnly,
9064
- 'designbase-search-bar--full-width': fullWidth,
9065
- 'designbase-search-bar--has-value': currentValue && currentValue.length > 0,
9066
- }, className);
9067
- const inputClasses = clsx('designbase-search-bar__input', {
9068
- 'designbase-search-bar__input--disabled': disabled,
9069
- 'designbase-search-bar__input--readonly': readOnly,
9070
- });
9071
- // 현재 플레이스홀더 (value가 없을 때만 추천 검색어 롤링)
9072
- const currentPlaceholder = suggestedSearches.length > 0 && !currentValue && currentValue === ''
9073
- ? suggestedSearches[currentSuggestion]
9074
- : placeholder;
9075
- return (jsxs("div", { className: classes, role: "search", children: [jsxs("div", { className: "designbase-search-bar__container", children: [jsx("div", { className: "designbase-search-bar__search-icon", children: jsx(SearchIconComponent, { size: size === 's' ? 16 : size === 'l' ? 24 : 20 }) }), 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", ...props }), currentValue && currentValue.length > 0 && !disabled && !readOnly && (jsx("button", { type: "button", className: "designbase-search-bar__clear-button", onClick: handleClear, "aria-label": "\uAC80\uC0C9\uC5B4 \uC9C0\uC6B0\uAE30", children: jsx(ClearIconComponent, { size: size === 's' ? 16 : size === 'l' ? 24 : 20 }) }))] }), showRecentSearches && recentSearches.length > 0 && (jsxs("div", { className: "designbase-search-bar__recent-searches", children: [jsxs("div", { className: "designbase-search-bar__recent-header", children: [jsx("span", { className: "designbase-search-bar__recent-title", children: "\uCD5C\uADFC \uAC80\uC0C9\uC5B4" }), 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" })] }), jsx("div", { className: "designbase-search-bar__recent-list", children: recentSearches.map((searchTerm, index) => (jsxs("div", { className: "designbase-search-bar__recent-item", children: [jsx("button", { type: "button", className: "designbase-search-bar__recent-search-button", onClick: () => handleRecentSearchClick(searchTerm), children: searchTerm }), jsx("button", { type: "button", className: "designbase-search-bar__recent-remove-button", onClick: () => handleRemoveRecentSearch(searchTerm), "aria-label": `${searchTerm} 삭제`, children: jsx(CloseIcon, { size: 16 }) })] }, index))) })] })), suggestedSearches.length > 0 && isFocused && !currentValue && (jsxs("div", { className: "designbase-search-bar__suggestions", children: [jsx("div", { className: "designbase-search-bar__suggestions-header", children: jsx("span", { className: "designbase-search-bar__suggestions-title", children: "\uCD94\uCC9C \uAC80\uC0C9\uC5B4" }) }), jsx("div", { className: "designbase-search-bar__suggestions-list", children: suggestedSearches.map((suggestion, index) => (jsx("button", { type: "button", className: clsx('designbase-search-bar__suggestion-item', {
9076
- 'designbase-search-bar__suggestion-item--active': index === currentSuggestion
9077
- }), onClick: () => handleSuggestionClick(suggestion), children: suggestion }, index))) })] }))] }));
9078
- };
9079
- SearchBar.displayName = 'SearchBar';
9080
-
9081
9079
  const Navbar = ({ size = 'm', variant = 'default', position = 'static', logo, onLogoClick, items = [], onItemClick, userMenuItems = [], onUserMenuItemClick, userProfile, onLoginClick, onLogoutClick, isAuthenticated = false, showSearch = false, onSearch, searchPlaceholder = '검색...', fullWidth = false, shadow = false, className, ...props }) => {
9082
9080
  const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
9083
9081
  const [isUserMenuOpen, setIsUserMenuOpen] = useState(false);
@@ -11590,6 +11588,47 @@ const Toggle = forwardRef(({ isSelected, defaultSelected, isDisabled = false, is
11590
11588
  });
11591
11589
  Toggle.displayName = 'Toggle';
11592
11590
 
11591
+ const clampRating = (rating, maxRating) => {
11592
+ if (typeof rating !== 'number' || Number.isNaN(rating))
11593
+ return undefined;
11594
+ if (rating < 0)
11595
+ return 0;
11596
+ if (rating > maxRating)
11597
+ return maxRating;
11598
+ return Math.round(rating * 10) / 10;
11599
+ };
11600
+ const Testimonial = ({ quote, author, role, company, avatar, rating, maxRating = 5, size = 'm', align = 'left', badge, children, className, badgeProps, avatarProps, ratingProps, }) => {
11601
+ const clampedRating = clampRating(rating, maxRating);
11602
+ const avatarSizeMap = {
11603
+ s: 's',
11604
+ m: 'm',
11605
+ l: 'l',
11606
+ };
11607
+ const ratingSizeMap = {
11608
+ s: 's',
11609
+ m: 'm',
11610
+ l: 'l',
11611
+ };
11612
+ const { className: badgeCustomClassName, size: badgeSize, variant: badgeVariant, style: badgeStyle, ...restBadgeProps } = badgeProps ?? {};
11613
+ const { className: avatarCustomClassName, size: avatarSize, alt: avatarAlt, src: avatarSrc, ...restAvatarProps } = avatarProps ?? {};
11614
+ const { className: ratingCustomClassName, maxValue: ratingMaxValueOverride, size: ratingSize, display: ratingDisplay, allowHalf: ratingAllowHalf, readonly: ratingReadonly, color: ratingColor, customColor: ratingCustomColor, ...restRatingProps } = ratingProps ?? {};
11615
+ const computedBadgeSize = badgeSize ?? 's';
11616
+ const computedBadgeVariant = badgeVariant ?? 'primary';
11617
+ const computedBadgeStyle = badgeStyle ?? 'text';
11618
+ const computedAvatarSrc = avatarSrc ?? avatar;
11619
+ const computedAvatarAlt = avatarAlt ?? `${author} 프로필 이미지`;
11620
+ const computedAvatarSize = avatarSize ?? avatarSizeMap[size];
11621
+ const computedRatingMaxValue = ratingMaxValueOverride ?? maxRating;
11622
+ const computedRatingSize = ratingSize ?? ratingSizeMap[size];
11623
+ const computedRatingDisplay = ratingDisplay ?? 'both';
11624
+ const computedRatingAllowHalf = ratingAllowHalf ?? true;
11625
+ const computedRatingReadonly = ratingReadonly ?? true;
11626
+ const computedRatingColor = ratingColor ?? 'primary';
11627
+ const computedRatingCustomColor = computedRatingColor === 'custom' ? ratingCustomColor : undefined;
11628
+ const shouldRenderAvatar = Boolean(computedAvatarSrc || restAvatarProps.initials || restAvatarProps.icon);
11629
+ return (jsxs("figure", { className: clsx('designbase-testimonial', `designbase-testimonial--size-${size}`, `designbase-testimonial--align-${align}`, className), children: [badge && (jsx(Badge, { size: computedBadgeSize, variant: computedBadgeVariant, style: computedBadgeStyle, className: clsx('designbase-testimonial__badge', badgeCustomClassName), ...restBadgeProps, children: badge })), jsxs("blockquote", { className: "designbase-testimonial__quote", children: ["\u201C", quote, "\u201D"] }), jsxs("figcaption", { className: "designbase-testimonial__footer", children: [shouldRenderAvatar && (jsx("div", { className: "designbase-testimonial__avatar", children: jsx(Avatar, { src: computedAvatarSrc, alt: computedAvatarAlt, size: computedAvatarSize, className: clsx('designbase-testimonial__avatar-image', avatarCustomClassName), ...restAvatarProps }) })), jsxs("div", { className: "designbase-testimonial__meta", children: [jsx("span", { className: "designbase-testimonial__author", children: author }), (role || company) && (jsx("span", { className: "designbase-testimonial__role", children: [role, company].filter(Boolean).join(' · ') }))] }), typeof clampedRating === 'number' && (jsx(Rating, { value: clampedRating, maxValue: computedRatingMaxValue, size: computedRatingSize, display: computedRatingDisplay, allowHalf: computedRatingAllowHalf, readonly: computedRatingReadonly, color: computedRatingColor, customColor: computedRatingCustomColor, className: clsx('designbase-testimonial__rating', ratingCustomClassName), ...restRatingProps }))] }), children && jsx("div", { className: "designbase-testimonial__extra", children: children })] }));
11630
+ };
11631
+
11593
11632
  const Toolbar = ({ items, size = 'm', variant = 'default', position = 'top', fullWidth = false, fixed = false, shadow = true, rounded = true, className, children, }) => {
11594
11633
  const [openDropdown, setOpenDropdown] = React.useState(null);
11595
11634
  const mapSizeToButtonSize = (size) => {
@@ -12140,5 +12179,5 @@ const toggleTheme = () => {
12140
12179
  console.log('toggleTheme called');
12141
12180
  };
12142
12181
 
12143
- export { Accordion, AdBanner, Alert, AnimationBackground, AnimationText, AudioPlayer, Avatar, Backdrop, Badge, Banner, BottomNavigation, BottomSheet, Breadcrumbs, Button, Calendar, Card, Carousel, Checkbox, Chip, ColorPicker, Confirm, Container, ContextMenu, Countdown, DatePicker, Divider, Drawer, Dropdown, Dropzone, EmptyState, FileUploader, FloatingActionButton, Form, Gradient, Grid, HeroFeature, Image$1 as Image, ImageList, Indicator, Input, Label, Lightbox, List, Logo, MarkdownEditor, Masonry, MenuItem, Modal, ModalBody, ModalFooter, ModalHeader, Navbar, OnboardingModal, Pagination, Popover, Progress, ProgressStep, Progressbar, Radio, RandomGradient, RangeSlider, Rating, Reorder, ResizablePanels, ScrollArea, SearchBar, Section, SegmentControl, Select, Share, Sidebar, Skeleton, Spinner, SplitView, Stack, Stat, Stepper, Table, Tabs, Textarea, TimePicker, Timeline, Toast, ToastContainer, ToastProvider, Toggle, Toolbar, Tooltip, Tutorial, VideoPlayer, YouTubePlayer, getTheme, setTheme, toggleTheme, useToast };
12182
+ export { Accordion, AdBanner, Alert, AnimationBackground, AnimationText, AudioPlayer, Avatar, Backdrop, Badge, Banner, BottomNavigation, BottomSheet, Breadcrumbs, Button, Calendar, Card, Carousel, Checkbox, Chip, ColorPicker, Confirm, Container, ContextMenu, Countdown, DatePicker, Divider, Drawer, Dropdown, Dropzone, EmptyState, FileUploader, FloatingActionButton, Form, Gradient, Grid, HeroFeature, Image$1 as Image, ImageList, Indicator, Input, Label, Lightbox, List, Logo, MarkdownEditor, Masonry, MenuItem, Modal, ModalBody, ModalFooter, ModalHeader, Navbar, OnboardingModal, Pagination, Popover, Progress, ProgressStep, Progressbar, Radio, RandomGradient, RangeSlider, Rating, Reorder, ResizablePanels, ScrollArea, SearchBar, Section, SegmentControl, Select, Share, Sidebar, Skeleton, Spinner, SplitView, Stack, Stat, Stepper, Table, Tabs, Testimonial, Textarea, TimePicker, Timeline, Toast, ToastContainer, ToastProvider, Toggle, Toolbar, Tooltip, Tutorial, VideoPlayer, YouTubePlayer, getTheme, setTheme, toggleTheme, useToast };
12144
12183
  //# sourceMappingURL=index.esm.js.map