DocSpace-client/packages/shared/components/search-input/SearchInput.tsx

156 lines
3.7 KiB
TypeScript

import React from "react";
import { ReactSVG } from "react-svg";
import CrossIconReactSvgUrl from "PUBLIC_DIR/images/cross.react.svg?url";
import SearchIconReactSvgUrl from "PUBLIC_DIR/images/search.react.svg?url";
import { InputBlock } from "../input-block";
import { InputSize, InputType } from "../text-input";
import StyledSearchInput from "./SearchInput.styled";
import { SearchInputProps } from "./SearchInput.types";
const SearchInput = ({
forwardedRef,
value,
autoRefresh,
refreshTimeout,
showClearButton,
onClearSearch,
onChange,
size,
className,
style,
scale,
onClick,
id,
name,
isDisabled,
placeholder,
children,
}: SearchInputProps) => {
const timerId = React.useRef<null | ReturnType<typeof setTimeout>>(null);
const prevValue = React.useRef(value);
const [inputValue, setInputValue] = React.useState(value);
const onClearSearchAction = React.useCallback(() => {
setInputValue("");
onClearSearch?.();
}, [onClearSearch]);
const setSearchTimer = React.useCallback(
(v: string) => {
if (timerId.current) clearTimeout(timerId.current);
timerId.current = setTimeout(() => {
onChange?.(v);
if (timerId.current) clearTimeout(timerId.current);
timerId.current = null;
}, refreshTimeout);
},
[onChange, refreshTimeout],
);
const onInputChange = React.useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => {
setInputValue(e.target.value);
if (autoRefresh) setSearchTimer(e.target.value);
},
[autoRefresh, setSearchTimer],
);
React.useEffect(() => {
if (prevValue.current !== value) {
prevValue.current = value;
setInputValue(value);
}
}, [value]);
const getClearButtonSize = () => {
let clearButtonSize = 16;
switch (size) {
case InputSize.base:
clearButtonSize = !!inputValue || showClearButton ? 12 : 16;
break;
case InputSize.middle:
clearButtonSize = !!inputValue || showClearButton ? 16 : 18;
break;
case InputSize.big:
clearButtonSize = !!inputValue || showClearButton ? 18 : 22;
break;
case InputSize.huge:
clearButtonSize = !!inputValue || showClearButton ? 22 : 24;
break;
default:
break;
}
return clearButtonSize;
};
const getIconNode = () => {
const showCrossIcon = !!inputValue || showClearButton;
const iconNode = (
<ReactSVG
className="icon-button_svg not-selectable"
src={showCrossIcon ? CrossIconReactSvgUrl : SearchIconReactSvgUrl}
/>
);
return iconNode;
};
const clearButtonSize = getClearButtonSize();
const iconNode = getIconNode();
return (
<StyledSearchInput
className={className}
style={style}
isScale={scale}
data-testid="search-input"
>
<InputBlock
className="search-input-block"
forwardedRef={forwardedRef}
onClick={onClick}
id={id}
name={name}
isDisabled={isDisabled}
type={InputType.text}
iconNode={iconNode}
iconButtonClassName={
!!inputValue || showClearButton ? "search-cross" : "search-loupe"
}
isIconFill
iconSize={clearButtonSize}
onIconClick={
!!inputValue || showClearButton ? onClearSearchAction : undefined
}
size={size}
scale
value={inputValue}
placeholder={placeholder}
onChange={onInputChange}
>
{children}
</InputBlock>
</StyledSearchInput>
);
};
SearchInput.defaultProps = {
autoRefresh: true,
value: "",
scale: false,
isDisabled: false,
refreshTimeout: 1000,
showClearButton: false,
};
export { SearchInput };