import React from 'react'; import { useState, useRef } from 'react'; import classNames from 'classnames'; type TagInputProps = { id: string; name: string; values: string[]; isInvalid: boolean; onChange?: (newValues: string[]) => void; }; export const TagInput: React.FC = ({ id, name, values, isInvalid, onChange }) => { const [buffer, setBuffer] = useState(''); const containerClass = classNames('form-control', 'h-auto', { 'is-invalid': isInvalid }); const inputRef = useRef(null); const removeTag = (index: number) => { onChange && onChange(values.filter((v, i) => i != index)); }; const onKeyDown = (event: React.KeyboardEvent) => { if (buffer.trim() !== '') { switch (event.key) { case 'Tab': case 'Enter': case ' ': if ((event as any).isComposing !== true) { onChange && onChange(values.concat(buffer.trim().replace(/\s+/g, '_'))); setBuffer(''); } event.preventDefault(); break; case 'Unidentified': { // 実際にテキストボックスに入力されている文字を見に行く (フォールバック処理) const nativeEvent = event.nativeEvent; if (nativeEvent.srcElement && (nativeEvent.srcElement as HTMLInputElement).value.slice(-1) == ' ') { onChange && onChange(values.concat(buffer.trim().replace(/\s+/g, '_'))); setBuffer(''); event.preventDefault(); } break; } } } else if (event.key === 'Enter') { // 誤爆防止 event.preventDefault(); } }; return (
inputRef.current?.focus()}>
    {values.map((tag, i) => (
  • removeTag(i)} > {tag} | x
  • ))}
  • setBuffer(e.target.value)} onKeyDown={onKeyDown} />
); };