react+antd Input回车输入生成tag组件

EditableTagGroup.tsx:

javascript 复制代码
import React, { useState, useRef, useEffect } from 'react'
import { Input, Tag, Tooltip, message } from 'antd'
import { CloseCircleFilled } from '@ant-design/icons'
import isEqual from 'lodash/isEqual'
import { useTranslation } from 'react-i18next'
import './index.scss'

interface ITagProps {
  value?: string[]
  onChange?: (value: string[]) => void
}

const EditableTagGroup: React.FC<ITagProps> = ({ value = [], onChange }: any) => {
  const [tags, setTags] = useState<any>(value)
  const [inputValue, setInputValue] = useState<string>('')
  const inputRef = useRef<any>(null)
  const { t } = useTranslation()

  // Sync props.value to state when it changes
  useEffect(() => {
    if (!isEqual(value, tags)) {
      setTags(value)
    }
  }, [value])

  // Notify parent component when tags change
  // useEffect(() => {
  //   if (onChange && !isEqual(value, tags)) {
  //     console.log(value, tags)
  //     onChange(tags)
  //   }
  // }, [tags])

  const handleClose = (removedTag: any) => {
    const newTags = tags.filter((tag: any) => tag.id !== removedTag.id)
    setTags(newTags)
    onChange(newTags)
  }

  const inputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setInputValue(e.target.value)
  }

  const isValidEntityToken = (t: string): boolean => {
    const re = /^(?:\p{Script=Han}|[A-Za-z])+$/u
    return t.length >= 1 && t.length <= 64 && re.test(t)
  }

  const addTag = (e: React.KeyboardEvent<HTMLInputElement>) => {
    const value = (e.target as HTMLInputElement).value
    if (value) {
      if (isValidEntityToken(value)) {
        let now = Date.now()
        const newTags = [...tags, { id: now, text: value }]
        setTags(newTags)
        setInputValue('')
        onChange(newTags)
      } else {
        message.info(t('models.entityTypesWarning'))
      }
    }
  }

  const clickEdit = () => {
    inputRef.current?.focus()
  }

  const renderTags = () => {
    return (
      <>
        {tags?.map((tag: any, index: any) => {
          const isLongTag = tag.text.length > 20
          const tagElem = (
            <Tag key={tag.id} onClose={() => handleClose(tag)} closeIcon={<CloseCircleFilled className="close-icon" />}>
              {isLongTag ? `${tag.text.slice(0, 20)}...` : tag.text}
            </Tag>
          )

          return isLongTag ? (
            <Tooltip title={tag.text} key={tag.id}>
              {tagElem}
            </Tooltip>
          ) : (
            tagElem
          )
        })}
      </>
    )
  }

  return (
    <div className="editable" onClick={clickEdit}>
      <div className="show">{renderTags()}</div>
      <Input
        className="input"
        ref={inputRef}
        placeholder={t('models.entityTypesPlaceholder')}
        onPressEnter={addTag}
        value={inputValue}
        onChange={inputChange}
      />
    </div>
  )
}

export default EditableTagGroup

index.scss:

css 复制代码
.editable {
  height: 100px;
  border-radius: 2px;
  background-color: rgba(255, 255, 255, 1);
  border: 1px solid #d9d9d9;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  &:focus-within,
  &:hover {
    border-color: rgba(22, 119, 254, 1);
    box-shadow: 0 0 4px 0 rgba(10, 42, 97, 0.2);
  }
  .ant-input {
    border: none;
    height: 32px;
    &:hover,
    &:focus {
      box-shadow: none;
      border: none;
    }
  }
  .show {
    flex: 1;
    min-height: '47px';
    overflow: auto;
    padding: 5px 5px;
    .ant-tag {
      color: #5a5e66;
      padding: 2px 8px;
      margin: 0 4px 4px 0;
      font-size: 12px;
      border: none;
      border-radius: 3px;
      background-color: rgba(240, 242, 245, 1);
      .close-icon {
        color: rgba(192, 196, 204, 1);
        margin-left: 2px;
        font-size: 12px;
      }
    }
  }
}

参考链接:

https://blog.csdn.net/qq_49464155/article/details/123247090

相关推荐
xiaofeichaichai4 小时前
Webpack
前端·webpack·node.js
问心无愧05134 小时前
ctf show web入门111
android·前端·笔记
唐某人丶5 小时前
模型越来越强,我们还需要 Agent 工程吗?—— 从价值重估到 Harness 实践
前端·agent·ai编程
智码看视界5 小时前
现代Web开发基础:全栈工程师的起航点
前端·后端·c5全栈
JS菌5 小时前
手写一个 AI Agent 全栈项目:从沙箱执行到子智能体的完整实现
前端·人工智能·后端
excel6 小时前
HLS TS 文件损坏的元凶:Git 提交与拉取
前端
Aphasia3116 小时前
https连接传输流程
前端·面试
徐小夕6 小时前
万字长文!千万级文档 RAG 知识库系统落地实践
前端·算法·github
threelab7 小时前
Three.js 物理模拟着色器 | 三维可视化 / AI 提示词
开发语言·前端·javascript·人工智能·3d·着色器