import React, { FunctionComponent, useEffect, useRef, useState } from 'react' import { View, Text, TextInput, TouchableOpacity } from 'react-native'; import Icon from '../icon' import { IComponent, ComponentDefaults } from '../utils/typings' import { useConfig } from '../configprovider'; import searchbarStyles from './styles'; type TIconDirection = 'in-left' | 'out-left' | 'in-right' | 'out-right' export interface SearchBarProps extends IComponent { /** 文本值 */ value?: number | string /** 输入框占位提示文字 */ placeholder?: string /** 搜索框形状,可选值为 round */ shape?: 'square' | 'round' /** 是否禁用输入框 */ disabled?: boolean /** 最大输入长度 */ maxLength?: number /** 是否启用清除图标,点击清除图标后会清空输入框 */ clearable?: boolean /** 搜索框外部背景色 */ background?: string /** 搜索框背景色 */ inputBackground?: string /** 输入框内容对齐方式 */ align?: string /** 是否将输入框设为只读状态,只读状态下无法输入内容 */ readOnly?: boolean /** 是否自动聚焦,iOS 系统不支持该属性 */ autoFocus?: boolean /** 搜索框左侧文本 */ label?: React.ReactNode /** 输入框内 左icon */ leftinIcon?: React.ReactNode /** 输入框内 右icon */ rightinIcon?: React.ReactNode /** 输入框外 左icon */ leftoutIcon?: React.ReactNode /** 输入框外 右icon */ rightoutIcon?: React.ReactNode /** 取消按钮文字 */ actionText?: React.ReactNode /** 确定搜索时触发 */ onSearch?: (val: string) => void /** 输入框内容变化时触发 */ onChange?: (value: string, event: Event) => void /** 输入框获得焦点时触发 */ onFocus?: (value: string, event: Event) => void /** 输入框失去焦点时触发 */ onBlur?: (value: string, event: Event) => void /** 点击清除按钮后触发 */ onClear?: (event: Event) => void /** 点击取消按钮后触发 */ onCancel?: () => void /** 点击输入框内左侧图标时触发 */ onClickLeftinIcon?: (value: string, event: Event) => void /** 点击输入框外左侧图标时触发 */ onClickLeftoutIcon?: (value: string, event: Event) => void /** 点击输入框内右侧图标时触发 */ onClickRightinIcon?: (value: string, event: Event) => void /** 点击输入框外右侧图标时触发 */ onClickRightoutIcon?: (value: string, event: Event) => void } const defaultProps = { ...ComponentDefaults, placeholder: '', shape: 'square', disabled: false, maxLength: 9999, clearable: true, align: 'left', readonly: true, autoFocus: false, label: '', leftinIcon: , } as SearchBarProps export const SearchBar: FunctionComponent< Partial & Omit< React.HTMLAttributes, 'onChange' | 'onFocus' | 'onBlur' > > = (props) => { const { theme } = useConfig(); const mStyles = searchbarStyles(theme); const searchRef = useRef(null) const [value, setValue] = useState(() => props.value) const { placeholder, shape, disabled, maxLength, clearable, align, readOnly, autoFocus, label, actionText, leftinIcon, rightinIcon, leftoutIcon, rightoutIcon, onChange, onFocus, onBlur, onClear, onCancel, onSearch, onClickLeftinIcon, onClickLeftoutIcon, onClickRightinIcon, onClickRightoutIcon, iconClassPrefix, iconFontClassName, } = { ...defaultProps, ...props, } const alignClass = `${align}` const change = (event: Event) => { const { text } = event?.nativeEvent as any onChange && onChange?.(text, event) setValue(text) } const focus = (event: Event) => { const { text } = event?.nativeEvent as any onFocus && onFocus?.(text, event) } const blur = (event: Event) => { const searchSelf: HTMLInputElement | null = searchRef.current searchSelf && searchSelf.blur() const { text } = event?.nativeEvent as any onBlur && onBlur?.(text, event) } useEffect(() => { setValue(props.value) }, [props.value]) useEffect(() => { if (autoFocus) { const searchSelf: HTMLInputElement | null = searchRef.current searchSelf && searchSelf.focus() } }, [autoFocus]) const renderField = () => { return ( change(e)} onFocus={(e: any) => focus(e)} onBlur={(e: any) => blur(e)} /> ) } const renderLeftinIcon = () => { if (!leftinIcon) return null return ( clickLeftIcon('in-left', e)} > {leftinIcon} ) } const renderLeftoutIcon = () => { if (!leftoutIcon) return null return ( clickLeftIcon('out-left', e)} > {leftoutIcon} ) } const clickLeftIcon = (flag: TIconDirection, event: Event) => { if (flag === 'in-left') { onClickLeftinIcon && onClickLeftinIcon(value as string, event) } else { onClickLeftoutIcon && onClickLeftoutIcon(value as string, event) } } const renderRightinIcon = () => { if (!rightinIcon) return null return ( clickRightIcon('in-right', e)} style={mStyles.nut_search_icon_marginH} > {rightinIcon} ) } const renderRightoutIcon = () => { if (!rightoutIcon) return null return ( clickRightIcon('out-right', e)} style={mStyles.nut_search_out_marginleft} > {rightoutIcon} ) } const clickRightIcon = (flag: TIconDirection, event: Event) => { if (flag === 'in-left') { onClickRightinIcon && onClickRightinIcon(value as string, event) } else { onClickRightoutIcon && onClickRightoutIcon(value as string, event) } } const handleClear = () => { return ( clearaVal(e)} style={mStyles.nut_search_clear_marginright} > ) } const clearaVal = (event: Event) => { if (disabled || readOnly) { return } setValue('') onClear && onClear(event) } const renderRightLabel = () => { if (actionText) { return ( {actionText} ) } return null } const onKeypress = (e: React.KeyboardEvent) => { if (e.key === 'Enter') { const event = e.nativeEvent if (typeof event.cancelable !== 'boolean' || event.cancelable) { event.preventDefault() } onSearch && onSearch(value as string) } } const cancel = () => { onCancel && onCancel() } const renderLabel = () => { if (label) { return {label} } return null } return ( {renderLeftoutIcon()} {renderLabel()} {renderLeftinIcon()} {renderField()} {renderRightinIcon()} {(clearable && value) ? handleClear(): null} {renderRightoutIcon()} {renderRightLabel()} ) } SearchBar.defaultProps = defaultProps SearchBar.displayName = 'NutSearchBar'