import { useHotkeys } from '@mantine/hooks'; import { ChangeEvent, CSSProperties, KeyboardEvent, useRef, useState } from 'react'; import { shallow } from 'zustand/shallow'; import { useSettingsStore } from '/@/renderer/store'; import { ActionIcon, ActionIconProps } from '/@/shared/components/action-icon/action-icon'; import { Box } from '/@/shared/components/box/box'; import { Icon } from '/@/shared/components/icon/icon'; import { TextInput, TextInputProps } from '/@/shared/components/text-input/text-input'; interface SearchInputProps extends TextInputProps { buttonProps?: Partial; enableHotkey?: boolean; inputProps?: Partial; value?: string; } export const SearchInput = ({ buttonProps, enableHotkey = true, inputProps, onChange, ...props }: SearchInputProps) => { const ref = useRef(null); const binding = useSettingsStore((state) => state.hotkeys.bindings.localSearch, shallow); const [isInputMode, setIsInputMode] = useState(false); useHotkeys([ [ binding.hotkey, () => { if (enableHotkey) { setIsInputMode(true); setTimeout(() => { ref?.current?.focus(); ref?.current?.select(); }, 0); } }, ], ]); const handleEscape = (e: KeyboardEvent) => { if (e.code === 'Escape') { onChange?.({ target: { value: '' } } as ChangeEvent); if (ref.current) { ref.current.value = ''; ref.current.blur(); } setIsInputMode(false); } }; const handleClear = () => { if (ref.current) { ref.current.value = ''; ref.current.focus(); onChange?.({ target: { value: '' } } as ChangeEvent); } }; const handleButtonClick = () => { setIsInputMode(true); setTimeout(() => { ref?.current?.focus(); }, 0); }; const handleBlur = () => { const hasValue = props.value || ref.current?.value; if (!hasValue) { setIsInputMode(false); } }; const hasValue = props.value || ref.current?.value; const shouldShowInput = isInputMode || hasValue; const shouldExpand = isInputMode || hasValue; const containerStyle: CSSProperties = { display: 'inline-flex', overflow: 'hidden', position: 'relative', transition: 'width 0.3s ease-in-out', width: shouldExpand ? '200px' : '36px', }; const buttonStyle: CSSProperties = { left: 0, opacity: shouldShowInput ? 0 : 1, pointerEvents: shouldShowInput ? 'none' : 'auto', position: 'absolute', top: 0, transition: 'opacity 0.2s ease-in-out', zIndex: 10, }; const inputStyle: CSSProperties = { opacity: shouldShowInput ? 1 : 0, transition: 'opacity 0.2s ease-in-out', width: '100%', }; return ( } maw="20dvw" {...inputProps} onBlur={handleBlur} onChange={onChange} onFocus={() => setIsInputMode(true)} onKeyDown={handleEscape} ref={ref} size="sm" style={inputStyle} {...props} rightSection={ ref.current?.value ? ( ) : null } /> ); };