@chayns-components/core
Version:
A set of beautiful React components for developing your own applications with chayns.
208 lines • 7.31 kB
JavaScript
import { AnimatePresence } from 'motion/react';
import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react';
import Icon from '../icon/Icon';
import Input, { InputSize } from '../input/Input';
import { StyledMotionSearchInputContentWrapper, StyledMotionSearchInputIconWrapper, StyledMotionSearchInputIconWrapperContent, StyledSearchInput, StyledSearchInputIconTrigger, StyledSearchInputPseudoElement } from './SearchInput.styles';
import { useTheme } from 'styled-components';
import { useElementSize } from '../../hooks/element';
import { useKeyboardFocusHighlighting } from '../../hooks/useKeyboardFocusHighlighting';
const SearchInput = /*#__PURE__*/forwardRef(({
iconColor,
isActive,
onActiveChange,
onChange,
onKeyDown,
placeholder,
shouldUseAbsolutePositioning = false,
size = InputSize.Medium,
value,
shouldEnableKeyboardHighlighting,
width: widthValue
}, ref) => {
const [isSearchInputActive, setIsSearchInputActive] = useState(isActive ?? (typeof value === 'string' && value.trim() !== ''));
const inputRef = useRef(null);
const pseudoRef = useRef(null);
const iconTriggerRef = useRef(null);
const parentWidth = useElementSize(pseudoRef);
const theme = useTheme();
const shouldShowKeyboardHighlighting = useKeyboardFocusHighlighting(shouldEnableKeyboardHighlighting);
const handleBackIconClick = useCallback(() => setIsSearchInputActive(false), []);
const handleSearchIconClick = useCallback(() => setIsSearchInputActive(true), []);
const handleIconTriggerClick = useCallback(() => {
if (isSearchInputActive) {
handleBackIconClick();
return;
}
handleSearchIconClick();
}, [handleBackIconClick, handleSearchIconClick, isSearchInputActive]);
const handleIconTriggerKeyDown = useCallback(event => {
if (event.key === 'Enter' || event.key === ' ') {
event.preventDefault();
handleIconTriggerClick();
}
}, [handleIconTriggerClick]);
const handleInputKeyDown = useCallback(event => {
if (event.key === 'Escape') {
event.preventDefault();
setIsSearchInputActive(false);
iconTriggerRef.current?.focus();
}
if (typeof onKeyDown === 'function') {
onKeyDown(event);
}
}, [onActiveChange, onKeyDown]);
useEffect(() => {
if (typeof onActiveChange === 'function') {
onActiveChange(isSearchInputActive);
}
}, [isSearchInputActive, onActiveChange]);
useEffect(() => {
if (isSearchInputActive) {
inputRef.current?.focus();
}
}, [isSearchInputActive]);
useEffect(() => {
if (typeof isActive === 'boolean') {
setIsSearchInputActive(isActive);
}
}, [isActive]);
useImperativeHandle(ref, () => ({
focus: () => inputRef.current?.focus(),
blur: () => inputRef.current?.blur()
}), []);
const width = useMemo(() => widthValue ?? parentWidth?.width, [parentWidth?.width, widthValue]);
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(StyledSearchInput, {
className: "beta-chayns-search-input",
$size: size,
$shouldUseAbsolutePositioning: shouldUseAbsolutePositioning
}, shouldUseAbsolutePositioning ? /*#__PURE__*/React.createElement(AnimatePresence, {
initial: false
}, isSearchInputActive && /*#__PURE__*/React.createElement(StyledMotionSearchInputContentWrapper, {
$shouldUseAbsolutePositioning: shouldUseAbsolutePositioning,
$shouldShowKeyboardHighlighting: shouldShowKeyboardHighlighting,
animate: {
opacity: 1,
width
},
exit: {
opacity: 0,
width: 0
},
initial: {
opacity: 0,
width: 0
},
key: "searchInputContentWrapper",
transition: {
duration: 0.25,
type: 'tween'
}
}, /*#__PURE__*/React.createElement(Input, {
onChange: onChange,
onKeyDown: handleInputKeyDown,
placeholder: placeholder,
ref: inputRef,
shouldEnableKeyboardHighlighting: shouldEnableKeyboardHighlighting,
shouldShowClearIcon: true,
size: size,
value: value
})), /*#__PURE__*/React.createElement(StyledSearchInputIconTrigger, {
ref: iconTriggerRef,
id: isSearchInputActive ? 'search-input-backIcon' : 'search-input-searchIcon',
tabIndex: 0,
onClick: handleIconTriggerClick,
onKeyDown: handleIconTriggerKeyDown,
$shouldShowKeyboardHighlighting: shouldShowKeyboardHighlighting
}, /*#__PURE__*/React.createElement(StyledMotionSearchInputIconWrapperContent, {
animate: {
opacity: 1
},
exit: {
opacity: 0,
position: 'absolute'
},
initial: {
opacity: 0
},
key: isSearchInputActive ? 'backIcon' : 'searchIcon',
transition: {
duration: 0.3
},
$shouldShowKeyboardHighlighting: shouldShowKeyboardHighlighting
}, /*#__PURE__*/React.createElement(Icon, {
key: "icon",
color: iconColor,
tabIndex: -1,
icons: isSearchInputActive ? ['fa fa-xmark'] : ['fa fa-search']
})))) : /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(StyledMotionSearchInputIconWrapper, null, /*#__PURE__*/React.createElement(AnimatePresence, {
initial: false
}, /*#__PURE__*/React.createElement(StyledSearchInputIconTrigger, {
ref: iconTriggerRef,
id: isSearchInputActive ? 'search-input-backIcon' : 'search-input-searchIcon',
tabIndex: 0,
onClick: handleIconTriggerClick,
onKeyDown: handleIconTriggerKeyDown,
$shouldShowKeyboardHighlighting: shouldShowKeyboardHighlighting
}, /*#__PURE__*/React.createElement(StyledMotionSearchInputIconWrapperContent, {
animate: {
opacity: 1
},
exit: {
opacity: 0,
position: 'absolute'
},
initial: {
opacity: 0
},
key: isSearchInputActive ? 'backIcon' : 'searchIcon',
transition: {
duration: 0.3
},
$shouldShowKeyboardHighlighting: shouldShowKeyboardHighlighting
}, /*#__PURE__*/React.createElement(Icon, {
key: "icon",
color: iconColor,
tabIndex: -1,
icons: isSearchInputActive ? ['fa fa-arrow-left'] : ['fa fa-search']
}))))), /*#__PURE__*/React.createElement(AnimatePresence, {
initial: false
}, isSearchInputActive && /*#__PURE__*/React.createElement(StyledMotionSearchInputContentWrapper, {
$shouldUseAbsolutePositioning: shouldUseAbsolutePositioning,
$shouldShowKeyboardHighlighting: shouldShowKeyboardHighlighting,
animate: {
opacity: 1,
width: '100%'
},
exit: {
opacity: 0,
width: 0
},
initial: {
opacity: 0,
width: 0
},
key: "searchInputContentWrapper",
transition: {
duration: 0.3
}
}, /*#__PURE__*/React.createElement(Input, {
key: "input",
leftElement: /*#__PURE__*/React.createElement(Icon, {
color: theme.text,
icons: ['far fa-search']
}),
onChange: onChange,
onKeyDown: handleInputKeyDown,
placeholder: placeholder,
ref: inputRef,
shouldEnableKeyboardHighlighting: shouldEnableKeyboardHighlighting,
shouldShowClearIcon: true,
size: size,
value: value
}))))), /*#__PURE__*/React.createElement(StyledSearchInputPseudoElement, {
ref: pseudoRef
}));
});
SearchInput.displayName = 'SearchInput';
export default SearchInput;
//# sourceMappingURL=SearchInput.js.map