@designbasekorea/ui 0.1.42 → 0.1.44
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.css +1 -1
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +8 -0
- package/dist/index.esm.css +1 -1
- package/dist/index.esm.css.map +1 -1
- package/dist/index.esm.js +107 -5
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +107 -5
- 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 +107 -5
- package/dist/index.umd.js.map +1 -1
- package/package.json +1 -1
package/dist/index.esm.js
CHANGED
|
@@ -8144,10 +8144,48 @@ const Masonry = ({ images, columns = 3, spacing = 'm', ratio = 'auto', fit = 'co
|
|
|
8144
8144
|
})), currentIndex: selectedImageIndex, isOpen: true, onOpenChange: handleLightboxClose, onImageChange: handleLightboxNavigate }))] }));
|
|
8145
8145
|
};
|
|
8146
8146
|
|
|
8147
|
-
const SearchBar = ({ value, defaultValue = '', placeholder = '검색...', size = 'm', variant = 'default', disabled = false, readOnly = false, fullWidth = false, searchIcon: SearchIconComponent = SearchIcon, clearIcon: ClearIconComponent = CloseIcon, onChange, onSearch, onFocus, onBlur, onKeyDown, className, ...props }) => {
|
|
8147
|
+
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 }) => {
|
|
8148
8148
|
const [internalValue, setInternalValue] = useState(defaultValue);
|
|
8149
|
+
const [recentSearches, setRecentSearches] = useState([]);
|
|
8150
|
+
const [showRecentSearches, setShowRecentSearches] = useState(false);
|
|
8151
|
+
const [currentSuggestion, setCurrentSuggestion] = useState(0);
|
|
8152
|
+
const [isFocused, setIsFocused] = useState(false);
|
|
8149
8153
|
const inputRef = useRef(null);
|
|
8154
|
+
const suggestionIntervalRef = useRef(null);
|
|
8150
8155
|
const currentValue = value !== undefined ? value : internalValue;
|
|
8156
|
+
// 최근 검색어 로드
|
|
8157
|
+
useEffect(() => {
|
|
8158
|
+
if (enableRecentSearches) {
|
|
8159
|
+
try {
|
|
8160
|
+
const stored = localStorage.getItem(recentSearchesKey);
|
|
8161
|
+
if (stored) {
|
|
8162
|
+
setRecentSearches(JSON.parse(stored));
|
|
8163
|
+
}
|
|
8164
|
+
}
|
|
8165
|
+
catch (error) {
|
|
8166
|
+
console.warn('최근 검색어를 불러올 수 없습니다:', error);
|
|
8167
|
+
}
|
|
8168
|
+
}
|
|
8169
|
+
}, [enableRecentSearches, recentSearchesKey]);
|
|
8170
|
+
// 추천 검색어 롤링 (포커스 없이도 계속)
|
|
8171
|
+
useEffect(() => {
|
|
8172
|
+
if (suggestedSearches.length > 0 && !currentValue) {
|
|
8173
|
+
suggestionIntervalRef.current = setInterval(() => {
|
|
8174
|
+
setCurrentSuggestion(prev => (prev + 1) % suggestedSearches.length);
|
|
8175
|
+
}, suggestionRollingInterval);
|
|
8176
|
+
}
|
|
8177
|
+
else {
|
|
8178
|
+
if (suggestionIntervalRef.current) {
|
|
8179
|
+
clearInterval(suggestionIntervalRef.current);
|
|
8180
|
+
suggestionIntervalRef.current = null;
|
|
8181
|
+
}
|
|
8182
|
+
}
|
|
8183
|
+
return () => {
|
|
8184
|
+
if (suggestionIntervalRef.current) {
|
|
8185
|
+
clearInterval(suggestionIntervalRef.current);
|
|
8186
|
+
}
|
|
8187
|
+
};
|
|
8188
|
+
}, [suggestedSearches.length, currentValue, suggestionRollingInterval]);
|
|
8151
8189
|
useEffect(() => {
|
|
8152
8190
|
if (value !== undefined) {
|
|
8153
8191
|
setInternalValue(value);
|
|
@@ -8163,9 +8201,24 @@ const SearchBar = ({ value, defaultValue = '', placeholder = '검색...', size =
|
|
|
8163
8201
|
onChange?.('');
|
|
8164
8202
|
inputRef.current?.focus();
|
|
8165
8203
|
};
|
|
8166
|
-
const handleSearch = () => {
|
|
8167
|
-
|
|
8168
|
-
|
|
8204
|
+
const handleSearch = (searchValue) => {
|
|
8205
|
+
const searchTerm = searchValue || currentValue.trim();
|
|
8206
|
+
if (searchTerm) {
|
|
8207
|
+
onSearch?.(searchTerm);
|
|
8208
|
+
// 최근 검색어 저장
|
|
8209
|
+
if (enableRecentSearches) {
|
|
8210
|
+
const newRecentSearches = [
|
|
8211
|
+
searchTerm,
|
|
8212
|
+
...recentSearches.filter(item => item !== searchTerm)
|
|
8213
|
+
].slice(0, 10); // 최대 10개
|
|
8214
|
+
setRecentSearches(newRecentSearches);
|
|
8215
|
+
try {
|
|
8216
|
+
localStorage.setItem(recentSearchesKey, JSON.stringify(newRecentSearches));
|
|
8217
|
+
}
|
|
8218
|
+
catch (error) {
|
|
8219
|
+
console.warn('최근 검색어를 저장할 수 없습니다:', error);
|
|
8220
|
+
}
|
|
8221
|
+
}
|
|
8169
8222
|
}
|
|
8170
8223
|
};
|
|
8171
8224
|
const handleKeyDown = (e) => {
|
|
@@ -8174,6 +8227,49 @@ const SearchBar = ({ value, defaultValue = '', placeholder = '검색...', size =
|
|
|
8174
8227
|
}
|
|
8175
8228
|
onKeyDown?.(e);
|
|
8176
8229
|
};
|
|
8230
|
+
const handleFocus = (e) => {
|
|
8231
|
+
setIsFocused(true);
|
|
8232
|
+
setShowRecentSearches(enableRecentSearches && recentSearches.length > 0);
|
|
8233
|
+
onFocus?.(e);
|
|
8234
|
+
};
|
|
8235
|
+
const handleBlur = (e) => {
|
|
8236
|
+
setIsFocused(false);
|
|
8237
|
+
// 약간의 지연을 두어 클릭 이벤트가 처리되도록 함
|
|
8238
|
+
setTimeout(() => {
|
|
8239
|
+
setShowRecentSearches(false);
|
|
8240
|
+
}, 200);
|
|
8241
|
+
onBlur?.(e);
|
|
8242
|
+
};
|
|
8243
|
+
const handleRecentSearchClick = (searchTerm) => {
|
|
8244
|
+
setInternalValue(searchTerm);
|
|
8245
|
+
onChange?.(searchTerm);
|
|
8246
|
+
setShowRecentSearches(false);
|
|
8247
|
+
handleSearch(searchTerm);
|
|
8248
|
+
};
|
|
8249
|
+
const handleRemoveRecentSearch = (searchTerm) => {
|
|
8250
|
+
const newRecentSearches = recentSearches.filter(item => item !== searchTerm);
|
|
8251
|
+
setRecentSearches(newRecentSearches);
|
|
8252
|
+
try {
|
|
8253
|
+
localStorage.setItem(recentSearchesKey, JSON.stringify(newRecentSearches));
|
|
8254
|
+
}
|
|
8255
|
+
catch (error) {
|
|
8256
|
+
console.warn('최근 검색어를 삭제할 수 없습니다:', error);
|
|
8257
|
+
}
|
|
8258
|
+
};
|
|
8259
|
+
const handleClearAllRecentSearches = () => {
|
|
8260
|
+
setRecentSearches([]);
|
|
8261
|
+
try {
|
|
8262
|
+
localStorage.removeItem(recentSearchesKey);
|
|
8263
|
+
}
|
|
8264
|
+
catch (error) {
|
|
8265
|
+
console.warn('최근 검색어를 모두 삭제할 수 없습니다:', error);
|
|
8266
|
+
}
|
|
8267
|
+
};
|
|
8268
|
+
const handleSuggestionClick = (suggestion) => {
|
|
8269
|
+
setInternalValue(suggestion);
|
|
8270
|
+
onChange?.(suggestion);
|
|
8271
|
+
handleSearch(suggestion);
|
|
8272
|
+
};
|
|
8177
8273
|
const classes = clsx('designbase-search-bar', `designbase-search-bar--${size}`, `designbase-search-bar--${variant}`, {
|
|
8178
8274
|
'designbase-search-bar--disabled': disabled,
|
|
8179
8275
|
'designbase-search-bar--readonly': readOnly,
|
|
@@ -8184,7 +8280,13 @@ const SearchBar = ({ value, defaultValue = '', placeholder = '검색...', size =
|
|
|
8184
8280
|
'designbase-search-bar__input--disabled': disabled,
|
|
8185
8281
|
'designbase-search-bar__input--readonly': readOnly,
|
|
8186
8282
|
});
|
|
8187
|
-
|
|
8283
|
+
// 현재 플레이스홀더 (추천 검색어가 있으면 롤링)
|
|
8284
|
+
const currentPlaceholder = suggestedSearches.length > 0 && !currentValue
|
|
8285
|
+
? suggestedSearches[currentSuggestion]
|
|
8286
|
+
: placeholder;
|
|
8287
|
+
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', {
|
|
8288
|
+
'designbase-search-bar__suggestion-item--active': index === currentSuggestion
|
|
8289
|
+
}), onClick: () => handleSuggestionClick(suggestion), children: suggestion }, index))) })] }))] }));
|
|
8188
8290
|
};
|
|
8189
8291
|
SearchBar.displayName = 'SearchBar';
|
|
8190
8292
|
|