基于 mantineUI 的自定义 AutoComplete组件封装

172 阅读1分钟

基于 mantineUI 的自定义 AutoComplete组件封装,扩展了高亮和清除等 API

/**
 * @author lee
 * @date 2023-06-21 18:25:40
 * @desc 基于 mantine 的 Autocomplete 组件,
 * 继承 Autocomplete 所有 props,并扩展清除和高亮展示属性
 */
import React, { FC, useCallback, useState, forwardRef } from 'react'
import { Box, createStyles, Autocomplete, AutocompleteProps } from '@mantine/core'
import { IconFont } from 'src/components/Iconfont'
import { useAdapter } from 'src/components/Adapter'

interface IProps extends AutocompleteProps {
  clear?: boolean
  mark?: boolean
  markColor?: string
}
const useStyle = createStyles(() => {
  return {
    itemComponent: {
      cursor: 'pointer',
      padding: '8rem 16rem',
      lineHeight: '40rem',
      '&:hover': {
        backgroundColor: 'var(--color-card-3)',
      },
    },
  }
})

/**
 * @desc Custom AutoComplete
 * @param props extends AutocompleteProps
 * @param clear clear all input value
 * @param mark hightLight
 * @param markColor hightLight text color
 * @returns HTMLDivElement
 */
const CustomAutocomplete: FC<IProps> = props => {
  const [search, setSearch] = useState('')
  const [focus, setFocus] = useState(false)
  const { classes } = useStyle()
  const { isH5 } = useAdapter()
  const { children, onChange, clear = false, mark = false, markColor = 'var(--color-brand-1)' } = props

  const handleValChange = useCallback(
    (val: string) => {
      setSearch(val)
      onChange && onChange(val)
    },
    [search]
  )
  const AutoCompleteItem = forwardRef<HTMLDivElement, any>(({ value, ...others }, ref) => {
    const itemComponent = value.replace(search, `<span style="color: ${markColor}">${search}</span>`)
    return (
      <Box
        ref={ref}
        {...others}
        className={`${classes.itemComponent} ${isH5 ? 'hfs-12' : 'fs-12'} itemComponent ellipsis`}
      >
        {mark ? <Box dangerouslySetInnerHTML={{ __html: itemComponent }} /> : <Box>{value}</Box>}
      </Box>
    )
  })
  const RightSection = () => (
    <Box
      className="flex ai-c"
      onClick={() => {
        setSearch('')
        onChange && onChange('')
      }}
    >
      <IconFont
        name="icon-a-24px-tips-error-fill"
        fontSize={isH5 ? '16px' : '16rem'}
        color="#b8bdcc"
        fontStyle={{
          visibility: 'inherit',
          cursor: 'pointer',
        }}
      />
    </Box>
  )
  return (
    <Autocomplete
      {...props}
      rightSection={clear && focus && search ? <RightSection /> : null}
      value={search}
      onChange={val => handleValChange(val)}
      onFocus={() => setFocus(true)}
      itemComponent={props?.itemComponent ? props?.itemComponent : AutoCompleteItem}
    >
      {children}
    </Autocomplete>
  )
}
export default CustomAutocomplete