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

相关推荐
子兮曰21 小时前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰21 小时前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万21 小时前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝21 小时前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋1 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁1 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
汉堡大王95271 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大1 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师1 天前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端
沙蒿同学1 天前
我用 Go 搭了一条 AI Agent 流水线:从 1 张商品图到一整套淘宝详情页
前端·javascript·后端