UNPKG

@chayns-components/core

Version:

A set of beautiful React components for developing your own applications with chayns.

208 lines • 7.31 kB
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