react-vite-themes
Version:
A test/experimental React theme system created for learning purposes. Features atomic design components, SCSS variables, and dark/light theme support. Not intended for production use.
39 lines (38 loc) • 2.5 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import React, { useState, useRef, useEffect } from 'react';
import { Input } from '../Input';
import { Icon } from '../Icon';
import { Button } from '../Button';
import './SearchBar.scss';
export const SearchBar = ({ placeholder = 'Search...', value, defaultValue, onSearch, onClear, onChange, loading = false, disabled = false, size = 'md', variant = 'default', showClearButton = true, debounceMs = 300, className = '', ...props }) => {
const [inputValue, setInputValue] = useState(value || defaultValue || '');
const debounceTimeoutRef = useRef(undefined);
// Update internal state when value prop changes
useEffect(() => {
if (value !== undefined) {
setInputValue(value);
}
}, [value]);
const handleInputChange = (newValue) => {
setInputValue(newValue);
onChange?.(newValue);
// Debounce search
if (debounceTimeoutRef.current) {
clearTimeout(debounceTimeoutRef.current);
}
debounceTimeoutRef.current = setTimeout(() => {
onSearch?.(newValue);
}, debounceMs);
};
const handleClear = () => {
setInputValue('');
onChange?.('');
onClear?.();
onSearch?.('');
};
const handleSubmit = (e) => {
e.preventDefault();
onSearch?.(inputValue);
};
return (_jsx("form", { className: `search-bar search-bar--${size} search-bar--${variant} ${className}`, onSubmit: handleSubmit, ...props, children: _jsxs("div", { className: "search-bar__container", children: [_jsxs("div", { className: "search-bar__input-wrapper", children: [_jsx(Icon, { name: "search", className: "search-bar__search-icon", size: size === 'sm' ? 'sm' : size === 'lg' ? 'lg' : 'md' }), _jsx(Input, { type: "text", value: inputValue, onChange: handleInputChange, placeholder: placeholder, disabled: disabled, size: size, variant: variant, className: "search-bar__input", "aria-label": "Search", role: "searchbox" }), loading && (_jsx(Icon, { name: "spinner", className: "search-bar__loading-icon", size: size === 'sm' ? 'sm' : size === 'lg' ? 'lg' : 'md' }))] }), showClearButton && inputValue && !loading && (_jsx(Button, { type: "button", colorScheme: "ghost", size: size, onClick: handleClear, className: "search-bar__clear-button", "aria-label": "Clear search", children: _jsx(Icon, { name: "x", size: size === 'sm' ? 'sm' : size === 'lg' ? 'lg' : 'md' }) }))] }) }));
};