@designbasekorea/ui 0.2.41 → 0.3.2
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/README.md +4 -4
- package/dist/index.css +1 -1
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +43 -3
- package/dist/index.esm.css +1 -1
- package/dist/index.esm.css.map +1 -1
- package/dist/index.esm.js +246 -201
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +246 -200
- package/dist/index.js.map +1 -1
- package/dist/index.umd.css +1 -1
- package/dist/index.umd.css.map +1 -1
- package/dist/index.umd.js +246 -200
- package/dist/index.umd.js.map +1 -1
- package/package.json +3 -3
package/dist/index.esm.js
CHANGED
|
@@ -2402,7 +2402,7 @@ const Tooltip = ({ content, children, position = 'top', size = 'm', variant = 'd
|
|
|
2402
2402
|
};
|
|
2403
2403
|
Tooltip.displayName = 'Tooltip';
|
|
2404
2404
|
|
|
2405
|
-
const Button = forwardRef(({ variant = 'primary', size = 'm', radius, fullWidth = false, disabled = false, loading = false, iconOnly = false, startIcon: StartIcon, endIcon: EndIcon, tooltip, tooltipProps, className, children, onPress, type = 'button', ...props }, forwardedRef) => {
|
|
2405
|
+
const Button = forwardRef(({ variant = 'primary', size = 'm', radius, fullWidth = false, disabled = false, loading = false, loadingText, iconOnly = false, startIcon: StartIcon, endIcon: EndIcon, tooltip, tooltipProps, className, children, onPress, type = 'button', ...props }, forwardedRef) => {
|
|
2406
2406
|
const ref = $df56164dff5785e2$export$4338b53315abf666(forwardedRef);
|
|
2407
2407
|
const { buttonProps } = $701a24aa0da5b062$export$ea18c227d4417cc3({
|
|
2408
2408
|
...props,
|
|
@@ -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
|
-
|
|
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,13 @@ const Button = forwardRef(({ variant = 'primary', size = 'm', radius, fullWidth
|
|
|
2452
2447
|
};
|
|
2453
2448
|
const renderContent = () => {
|
|
2454
2449
|
if (loading) {
|
|
2455
|
-
|
|
2450
|
+
// 로딩 중 표시할 텍스트 결정: loadingText > children > 기본값
|
|
2451
|
+
const displayText = loadingText !== undefined
|
|
2452
|
+
? loadingText
|
|
2453
|
+
: (!iconOnly && children)
|
|
2454
|
+
? children
|
|
2455
|
+
: null;
|
|
2456
|
+
return (jsxs(Fragment, { children: [jsx(Spinner, { type: "circular", size: size === 's' ? 's' : size === 'l' ? 'l' : 'm', color: getIconColor(), speed: 1, showLabel: false }), displayText && jsx("span", { children: displayText })] }));
|
|
2456
2457
|
}
|
|
2457
2458
|
// iconOnly 버튼일 때는 children을 아이콘으로 처리
|
|
2458
2459
|
if (iconOnly && children && React.isValidElement(children)) {
|
|
@@ -4011,7 +4012,7 @@ ModalHeader.displayName = 'ModalHeader';
|
|
|
4011
4012
|
ModalBody.displayName = 'ModalBody';
|
|
4012
4013
|
ModalFooter.displayName = 'ModalFooter';
|
|
4013
4014
|
|
|
4014
|
-
const Label = ({ children, htmlFor, required = false, size = 's', disabled = false, error = false, className, onClick, }) => {
|
|
4015
|
+
const Label = ({ children, htmlFor, id, required = false, size = 's', disabled = false, error = false, className, onClick, }) => {
|
|
4015
4016
|
const classes = [
|
|
4016
4017
|
'designbase-label',
|
|
4017
4018
|
`designbase-label--${size}`,
|
|
@@ -4021,7 +4022,7 @@ const Label = ({ children, htmlFor, required = false, size = 's', disabled = fal
|
|
|
4021
4022
|
]
|
|
4022
4023
|
.filter(Boolean)
|
|
4023
4024
|
.join(' ');
|
|
4024
|
-
return (jsxs("label", { htmlFor: htmlFor, className: classes, onClick: onClick, children: [children, required && jsx("span", { className: "designbase-label__required", children: "*" })] }));
|
|
4025
|
+
return (jsxs("label", { htmlFor: htmlFor, id: id, className: classes, onClick: onClick, children: [children, required && jsx("span", { className: "designbase-label__required", children: "*" })] }));
|
|
4025
4026
|
};
|
|
4026
4027
|
Label.displayName = 'Label';
|
|
4027
4028
|
|
|
@@ -4052,12 +4053,17 @@ const Input = forwardRef(({ type = 'text', label, placeholder, defaultValue, val
|
|
|
4052
4053
|
'designbase-input--with-end-icon': EndIcon || isPassword,
|
|
4053
4054
|
}, className);
|
|
4054
4055
|
const inputClasses = clsx('designbase-input__field', inputClassName);
|
|
4055
|
-
const
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
|
|
4056
|
+
const iconSize = React.useMemo(() => {
|
|
4057
|
+
switch (size) {
|
|
4058
|
+
case 's':
|
|
4059
|
+
return 16;
|
|
4060
|
+
case 'l':
|
|
4061
|
+
return 24;
|
|
4062
|
+
case 'm':
|
|
4063
|
+
default:
|
|
4064
|
+
return 20;
|
|
4065
|
+
}
|
|
4066
|
+
}, [size]);
|
|
4061
4067
|
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
4068
|
});
|
|
4063
4069
|
Input.displayName = 'Input';
|
|
@@ -4098,6 +4104,157 @@ const Checkbox = forwardRef(({ isSelected, defaultSelected, isIndeterminate = fa
|
|
|
4098
4104
|
});
|
|
4099
4105
|
Checkbox.displayName = 'Checkbox';
|
|
4100
4106
|
|
|
4107
|
+
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 }) => {
|
|
4108
|
+
const [internalValue, setInternalValue] = useState(defaultValue);
|
|
4109
|
+
const [recentSearches, setRecentSearches] = useState([]);
|
|
4110
|
+
const [showRecentSearches, setShowRecentSearches] = useState(false);
|
|
4111
|
+
const [currentSuggestion, setCurrentSuggestion] = useState(0);
|
|
4112
|
+
const [isFocused, setIsFocused] = useState(false);
|
|
4113
|
+
const inputRef = useRef(null);
|
|
4114
|
+
const suggestionIntervalRef = useRef(null);
|
|
4115
|
+
const currentValue = value !== undefined ? value : internalValue;
|
|
4116
|
+
// 최근 검색어 로드
|
|
4117
|
+
useEffect(() => {
|
|
4118
|
+
if (enableRecentSearches) {
|
|
4119
|
+
try {
|
|
4120
|
+
const stored = localStorage.getItem(recentSearchesKey);
|
|
4121
|
+
if (stored) {
|
|
4122
|
+
setRecentSearches(JSON.parse(stored));
|
|
4123
|
+
}
|
|
4124
|
+
}
|
|
4125
|
+
catch (error) {
|
|
4126
|
+
console.warn('최근 검색어를 불러올 수 없습니다:', error);
|
|
4127
|
+
}
|
|
4128
|
+
}
|
|
4129
|
+
}, [enableRecentSearches, recentSearchesKey]);
|
|
4130
|
+
// 추천 검색어 롤링 (value가 없을 때만)
|
|
4131
|
+
useEffect(() => {
|
|
4132
|
+
if (suggestedSearches.length > 0 && !currentValue && currentValue === '') {
|
|
4133
|
+
suggestionIntervalRef.current = setInterval(() => {
|
|
4134
|
+
setCurrentSuggestion(prev => (prev + 1) % suggestedSearches.length);
|
|
4135
|
+
}, suggestionRollingInterval);
|
|
4136
|
+
}
|
|
4137
|
+
else {
|
|
4138
|
+
if (suggestionIntervalRef.current) {
|
|
4139
|
+
clearInterval(suggestionIntervalRef.current);
|
|
4140
|
+
suggestionIntervalRef.current = null;
|
|
4141
|
+
}
|
|
4142
|
+
}
|
|
4143
|
+
return () => {
|
|
4144
|
+
if (suggestionIntervalRef.current) {
|
|
4145
|
+
clearInterval(suggestionIntervalRef.current);
|
|
4146
|
+
}
|
|
4147
|
+
};
|
|
4148
|
+
}, [suggestedSearches.length, currentValue, suggestionRollingInterval]);
|
|
4149
|
+
useEffect(() => {
|
|
4150
|
+
if (value !== undefined) {
|
|
4151
|
+
setInternalValue(value);
|
|
4152
|
+
}
|
|
4153
|
+
}, [value]);
|
|
4154
|
+
const handleChange = (e) => {
|
|
4155
|
+
const newValue = e.target.value;
|
|
4156
|
+
setInternalValue(newValue);
|
|
4157
|
+
onChange?.(newValue);
|
|
4158
|
+
};
|
|
4159
|
+
const handleClear = () => {
|
|
4160
|
+
setInternalValue('');
|
|
4161
|
+
onChange?.('');
|
|
4162
|
+
inputRef.current?.focus();
|
|
4163
|
+
};
|
|
4164
|
+
const handleSearch = (searchValue) => {
|
|
4165
|
+
const searchTerm = searchValue || currentValue.trim();
|
|
4166
|
+
if (searchTerm) {
|
|
4167
|
+
onSearch?.(searchTerm);
|
|
4168
|
+
// 최근 검색어 저장
|
|
4169
|
+
if (enableRecentSearches) {
|
|
4170
|
+
const newRecentSearches = [
|
|
4171
|
+
searchTerm,
|
|
4172
|
+
...recentSearches.filter(item => item !== searchTerm)
|
|
4173
|
+
].slice(0, 10); // 최대 10개
|
|
4174
|
+
setRecentSearches(newRecentSearches);
|
|
4175
|
+
try {
|
|
4176
|
+
localStorage.setItem(recentSearchesKey, JSON.stringify(newRecentSearches));
|
|
4177
|
+
}
|
|
4178
|
+
catch (error) {
|
|
4179
|
+
console.warn('최근 검색어를 저장할 수 없습니다:', error);
|
|
4180
|
+
}
|
|
4181
|
+
}
|
|
4182
|
+
}
|
|
4183
|
+
};
|
|
4184
|
+
const handleKeyDown = (e) => {
|
|
4185
|
+
if (e.key === 'Enter') {
|
|
4186
|
+
handleSearch();
|
|
4187
|
+
}
|
|
4188
|
+
onKeyDown?.(e);
|
|
4189
|
+
};
|
|
4190
|
+
const handleFocus = (e) => {
|
|
4191
|
+
setIsFocused(true);
|
|
4192
|
+
setShowRecentSearches(enableRecentSearches && recentSearches.length > 0);
|
|
4193
|
+
onFocus?.(e);
|
|
4194
|
+
};
|
|
4195
|
+
const handleBlur = (e) => {
|
|
4196
|
+
setIsFocused(false);
|
|
4197
|
+
// 약간의 지연을 두어 클릭 이벤트가 처리되도록 함
|
|
4198
|
+
setTimeout(() => {
|
|
4199
|
+
setShowRecentSearches(false);
|
|
4200
|
+
}, 200);
|
|
4201
|
+
onBlur?.(e);
|
|
4202
|
+
};
|
|
4203
|
+
const handleRecentSearchClick = (searchTerm) => {
|
|
4204
|
+
setInternalValue(searchTerm);
|
|
4205
|
+
onChange?.(searchTerm);
|
|
4206
|
+
setShowRecentSearches(false);
|
|
4207
|
+
handleSearch(searchTerm);
|
|
4208
|
+
};
|
|
4209
|
+
const handleRemoveRecentSearch = (searchTerm) => {
|
|
4210
|
+
const newRecentSearches = recentSearches.filter(item => item !== searchTerm);
|
|
4211
|
+
setRecentSearches(newRecentSearches);
|
|
4212
|
+
try {
|
|
4213
|
+
localStorage.setItem(recentSearchesKey, JSON.stringify(newRecentSearches));
|
|
4214
|
+
}
|
|
4215
|
+
catch (error) {
|
|
4216
|
+
console.warn('최근 검색어를 삭제할 수 없습니다:', error);
|
|
4217
|
+
}
|
|
4218
|
+
};
|
|
4219
|
+
const handleClearAllRecentSearches = () => {
|
|
4220
|
+
setRecentSearches([]);
|
|
4221
|
+
try {
|
|
4222
|
+
localStorage.removeItem(recentSearchesKey);
|
|
4223
|
+
}
|
|
4224
|
+
catch (error) {
|
|
4225
|
+
console.warn('최근 검색어를 모두 삭제할 수 없습니다:', error);
|
|
4226
|
+
}
|
|
4227
|
+
};
|
|
4228
|
+
const handleSuggestionClick = (suggestion) => {
|
|
4229
|
+
setInternalValue(suggestion);
|
|
4230
|
+
onChange?.(suggestion);
|
|
4231
|
+
// 롤링 중단
|
|
4232
|
+
if (suggestionIntervalRef.current) {
|
|
4233
|
+
clearInterval(suggestionIntervalRef.current);
|
|
4234
|
+
suggestionIntervalRef.current = null;
|
|
4235
|
+
}
|
|
4236
|
+
handleSearch(suggestion);
|
|
4237
|
+
};
|
|
4238
|
+
const classes = clsx('designbase-search-bar', `designbase-search-bar--${size}`, `designbase-search-bar--${variant}`, {
|
|
4239
|
+
'designbase-search-bar--disabled': disabled,
|
|
4240
|
+
'designbase-search-bar--readonly': readOnly,
|
|
4241
|
+
'designbase-search-bar--full-width': fullWidth,
|
|
4242
|
+
'designbase-search-bar--has-value': currentValue && currentValue.length > 0,
|
|
4243
|
+
}, className);
|
|
4244
|
+
const inputClasses = clsx('designbase-search-bar__input', {
|
|
4245
|
+
'designbase-search-bar__input--disabled': disabled,
|
|
4246
|
+
'designbase-search-bar__input--readonly': readOnly,
|
|
4247
|
+
});
|
|
4248
|
+
// 현재 플레이스홀더 (value가 없을 때만 추천 검색어 롤링)
|
|
4249
|
+
const currentPlaceholder = suggestedSearches.length > 0 && !currentValue && currentValue === ''
|
|
4250
|
+
? suggestedSearches[currentSuggestion]
|
|
4251
|
+
: placeholder;
|
|
4252
|
+
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', {
|
|
4253
|
+
'designbase-search-bar__suggestion-item--active': index === currentSuggestion
|
|
4254
|
+
}), onClick: () => handleSuggestionClick(suggestion), children: suggestion }, index))) })] }))] }));
|
|
4255
|
+
};
|
|
4256
|
+
SearchBar.displayName = 'SearchBar';
|
|
4257
|
+
|
|
4101
4258
|
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
4259
|
const [isOpen, setIsOpen] = useState(false);
|
|
4103
4260
|
const [selectedValue, setSelectedValue] = useState(value ?? defaultValue ?? (multiple ? [] : ''));
|
|
@@ -4242,9 +4399,6 @@ const Select = ({ value, defaultValue, options, label, placeholder = '선택하
|
|
|
4242
4399
|
setSelectedValue(newValue);
|
|
4243
4400
|
onChange?.(newValue);
|
|
4244
4401
|
};
|
|
4245
|
-
const handleSearchChange = (e) => {
|
|
4246
|
-
setSearchTerm(e.target.value);
|
|
4247
|
-
};
|
|
4248
4402
|
const classes = clsx('designbase-select', `designbase-select--${size}`, {
|
|
4249
4403
|
'designbase-select--open': isOpen,
|
|
4250
4404
|
'designbase-select--error': error,
|
|
@@ -4252,9 +4406,11 @@ const Select = ({ value, defaultValue, options, label, placeholder = '선택하
|
|
|
4252
4406
|
'designbase-select--readonly': readOnly,
|
|
4253
4407
|
'designbase-select--full-width': fullWidth,
|
|
4254
4408
|
'designbase-select--multiple': multiple,
|
|
4409
|
+
'designbase-select--searchable': searchable,
|
|
4255
4410
|
}, className);
|
|
4256
4411
|
const triggerClasses = clsx('designbase-select__trigger', {
|
|
4257
4412
|
'designbase-select__trigger--focused': isOpen,
|
|
4413
|
+
'designbase-select__trigger--searchable': searchable,
|
|
4258
4414
|
});
|
|
4259
4415
|
const dropdownClasses = clsx('designbase-select__dropdown', `designbase-select__dropdown--${dropdownWidth}`, `designbase-select__dropdown--${position}`, {
|
|
4260
4416
|
'designbase-select__dropdown--open': isOpen,
|
|
@@ -4262,23 +4418,23 @@ const Select = ({ value, defaultValue, options, label, placeholder = '선택하
|
|
|
4262
4418
|
const filteredOptions = getFilteredOptions();
|
|
4263
4419
|
const selectedLabels = getSelectedLabels();
|
|
4264
4420
|
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 ? (
|
|
4266
|
-
|
|
4267
|
-
|
|
4268
|
-
|
|
4269
|
-
|
|
4270
|
-
|
|
4271
|
-
|
|
4272
|
-
|
|
4273
|
-
|
|
4274
|
-
|
|
4275
|
-
|
|
4276
|
-
|
|
4277
|
-
|
|
4278
|
-
|
|
4279
|
-
|
|
4280
|
-
|
|
4281
|
-
|
|
4421
|
+
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) => {
|
|
4422
|
+
const option = options.find(opt => opt.value === value);
|
|
4423
|
+
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) => {
|
|
4424
|
+
e.stopPropagation();
|
|
4425
|
+
handleRemoveValue(value);
|
|
4426
|
+
}, children: jsx(CloseIcon, { size: 12 }) })] }, value));
|
|
4427
|
+
}) })) : (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) => {
|
|
4428
|
+
const isSelected = multiple
|
|
4429
|
+
? selectedValue.includes(option.value)
|
|
4430
|
+
: selectedValue === option.value;
|
|
4431
|
+
const isFocused = index === focusedIndex;
|
|
4432
|
+
return (jsxs("div", { className: clsx('designbase-select__option', {
|
|
4433
|
+
'designbase-select__option--selected': isSelected,
|
|
4434
|
+
'designbase-select__option--focused': isFocused,
|
|
4435
|
+
'designbase-select__option--disabled': option.disabled,
|
|
4436
|
+
}), 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));
|
|
4437
|
+
})) })] }), helperText && !error && (jsx("p", { className: "designbase-select__helper-text", children: helperText })), error && errorMessage && (jsx("p", { className: "designbase-select__error-message", children: errorMessage }))] }));
|
|
4282
4438
|
};
|
|
4283
4439
|
Select.displayName = 'Select';
|
|
4284
4440
|
|
|
@@ -5219,8 +5375,6 @@ const Carousel = ({ items, size = 'm', variant = 'default', theme = 'light', tra
|
|
|
5219
5375
|
const handleTouchEndEvent = useCallback(() => {
|
|
5220
5376
|
handleTouchEnd();
|
|
5221
5377
|
}, [handleTouchEnd]);
|
|
5222
|
-
// 현재 아이템
|
|
5223
|
-
const currentItem = items[currentIndex];
|
|
5224
5378
|
// 슬라이드 스타일 계산
|
|
5225
5379
|
const getSlideStyle = () => {
|
|
5226
5380
|
const containerWidth = containerRef.current?.offsetWidth || 1;
|
|
@@ -5235,9 +5389,6 @@ const Carousel = ({ items, size = 'm', variant = 'default', theme = 'light', tra
|
|
|
5235
5389
|
// 네비게이션 버튼 비활성화 상태
|
|
5236
5390
|
const isPrevDisabled = !infinite && currentIndex === 0;
|
|
5237
5391
|
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
5392
|
if (items.length === 0)
|
|
5242
5393
|
return null;
|
|
5243
5394
|
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 +5409,17 @@ const Carousel = ({ items, size = 'm', variant = 'default', theme = 'light', tra
|
|
|
5258
5409
|
color: item.textColor || (item.image ? '#ffffff' : undefined),
|
|
5259
5410
|
}, children: item.title })), showDescription && item.description && (jsx("p", { className: "designbase-carousel__slide-description", style: {
|
|
5260
5411
|
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', {
|
|
5412
|
+
}, 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', {
|
|
5413
|
+
'designbase-carousel__action-button--active': likedItems.has(item.id),
|
|
5414
|
+
}), onClick: (e) => {
|
|
5262
5415
|
e.stopPropagation();
|
|
5263
5416
|
handleLike(item, index);
|
|
5264
|
-
}, title:
|
|
5417
|
+
}, 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', {
|
|
5418
|
+
'designbase-carousel__action-button--active': bookmarkedItems.has(item.id),
|
|
5419
|
+
}), onClick: (e) => {
|
|
5265
5420
|
e.stopPropagation();
|
|
5266
5421
|
handleBookmark(item, index);
|
|
5267
|
-
}, title:
|
|
5422
|
+
}, 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
5423
|
e.stopPropagation();
|
|
5269
5424
|
handleShare(item, index);
|
|
5270
5425
|
}, 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 +9082,6 @@ const Tutorial = ({ steps, currentStep = 0, isActive, onStart, onEnd, onStepChan
|
|
|
8927
9082
|
};
|
|
8928
9083
|
Tutorial.displayName = 'Tutorial';
|
|
8929
9084
|
|
|
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
9085
|
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
9086
|
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
|
|
9083
9087
|
const [isUserMenuOpen, setIsUserMenuOpen] = useState(false);
|
|
@@ -11590,6 +11594,47 @@ const Toggle = forwardRef(({ isSelected, defaultSelected, isDisabled = false, is
|
|
|
11590
11594
|
});
|
|
11591
11595
|
Toggle.displayName = 'Toggle';
|
|
11592
11596
|
|
|
11597
|
+
const clampRating = (rating, maxRating) => {
|
|
11598
|
+
if (typeof rating !== 'number' || Number.isNaN(rating))
|
|
11599
|
+
return undefined;
|
|
11600
|
+
if (rating < 0)
|
|
11601
|
+
return 0;
|
|
11602
|
+
if (rating > maxRating)
|
|
11603
|
+
return maxRating;
|
|
11604
|
+
return Math.round(rating * 10) / 10;
|
|
11605
|
+
};
|
|
11606
|
+
const Testimonial = ({ quote, author, role, company, avatar, rating, maxRating = 5, size = 'm', align = 'left', badge, children, className, badgeProps, avatarProps, ratingProps, }) => {
|
|
11607
|
+
const clampedRating = clampRating(rating, maxRating);
|
|
11608
|
+
const avatarSizeMap = {
|
|
11609
|
+
s: 's',
|
|
11610
|
+
m: 'm',
|
|
11611
|
+
l: 'l',
|
|
11612
|
+
};
|
|
11613
|
+
const ratingSizeMap = {
|
|
11614
|
+
s: 's',
|
|
11615
|
+
m: 'm',
|
|
11616
|
+
l: 'l',
|
|
11617
|
+
};
|
|
11618
|
+
const { className: badgeCustomClassName, size: badgeSize, variant: badgeVariant, style: badgeStyle, ...restBadgeProps } = badgeProps ?? {};
|
|
11619
|
+
const { className: avatarCustomClassName, size: avatarSize, alt: avatarAlt, src: avatarSrc, ...restAvatarProps } = avatarProps ?? {};
|
|
11620
|
+
const { className: ratingCustomClassName, maxValue: ratingMaxValueOverride, size: ratingSize, display: ratingDisplay, allowHalf: ratingAllowHalf, readonly: ratingReadonly, color: ratingColor, customColor: ratingCustomColor, ...restRatingProps } = ratingProps ?? {};
|
|
11621
|
+
const computedBadgeSize = badgeSize ?? 's';
|
|
11622
|
+
const computedBadgeVariant = badgeVariant ?? 'primary';
|
|
11623
|
+
const computedBadgeStyle = badgeStyle ?? 'text';
|
|
11624
|
+
const computedAvatarSrc = avatarSrc ?? avatar;
|
|
11625
|
+
const computedAvatarAlt = avatarAlt ?? `${author} 프로필 이미지`;
|
|
11626
|
+
const computedAvatarSize = avatarSize ?? avatarSizeMap[size];
|
|
11627
|
+
const computedRatingMaxValue = ratingMaxValueOverride ?? maxRating;
|
|
11628
|
+
const computedRatingSize = ratingSize ?? ratingSizeMap[size];
|
|
11629
|
+
const computedRatingDisplay = ratingDisplay ?? 'both';
|
|
11630
|
+
const computedRatingAllowHalf = ratingAllowHalf ?? true;
|
|
11631
|
+
const computedRatingReadonly = ratingReadonly ?? true;
|
|
11632
|
+
const computedRatingColor = ratingColor ?? 'primary';
|
|
11633
|
+
const computedRatingCustomColor = computedRatingColor === 'custom' ? ratingCustomColor : undefined;
|
|
11634
|
+
const shouldRenderAvatar = Boolean(computedAvatarSrc || restAvatarProps.initials || restAvatarProps.icon);
|
|
11635
|
+
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 })] }));
|
|
11636
|
+
};
|
|
11637
|
+
|
|
11593
11638
|
const Toolbar = ({ items, size = 'm', variant = 'default', position = 'top', fullWidth = false, fixed = false, shadow = true, rounded = true, className, children, }) => {
|
|
11594
11639
|
const [openDropdown, setOpenDropdown] = React.useState(null);
|
|
11595
11640
|
const mapSizeToButtonSize = (size) => {
|
|
@@ -12140,5 +12185,5 @@ const toggleTheme = () => {
|
|
|
12140
12185
|
console.log('toggleTheme called');
|
|
12141
12186
|
};
|
|
12142
12187
|
|
|
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 };
|
|
12188
|
+
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
12189
|
//# sourceMappingURL=index.esm.js.map
|