2020-05-17 17:11:35 +09:00
|
|
|
import * as React from 'react';
|
|
|
|
import { useState, useRef } from 'react';
|
|
|
|
import * as classNames from 'classnames';
|
|
|
|
|
|
|
|
type TagInputProps = {
|
|
|
|
id: string;
|
|
|
|
name: string;
|
|
|
|
value: string;
|
|
|
|
isInvalid: boolean;
|
|
|
|
};
|
|
|
|
|
2020-08-13 01:57:09 +09:00
|
|
|
export const TagInput: React.FC<TagInputProps> = ({ id, name, value, isInvalid }) => {
|
2020-05-17 17:11:35 +09:00
|
|
|
const [tags, setTags] = useState(value.trim() !== '' ? value.trim().split(' ') : []);
|
|
|
|
const [buffer, setBuffer] = useState('');
|
|
|
|
const containerClass = classNames('form-control', 'h-auto', { 'is-invalid': isInvalid });
|
|
|
|
const inputRef = useRef<HTMLInputElement>(null);
|
|
|
|
const removeTag = (index: number) => {
|
|
|
|
setTags(tags.filter((v, i) => i != index));
|
|
|
|
};
|
|
|
|
const onKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
|
|
|
|
if (buffer.trim() !== '') {
|
|
|
|
switch (event.key) {
|
|
|
|
case 'Tab':
|
|
|
|
case 'Enter':
|
|
|
|
case ' ':
|
|
|
|
if ((event as any).isComposing !== true) {
|
2020-08-12 23:06:17 +09:00
|
|
|
setTags(tags.concat(buffer.trim().replace(/\s+/g, '_')));
|
2020-05-17 17:11:35 +09:00
|
|
|
setBuffer('');
|
|
|
|
}
|
|
|
|
event.preventDefault();
|
|
|
|
break;
|
2020-08-12 23:06:17 +09:00
|
|
|
case 'Unidentified': {
|
2020-05-17 17:11:35 +09:00
|
|
|
// 実際にテキストボックスに入力されている文字を見に行く (フォールバック処理)
|
|
|
|
const nativeEvent = event.nativeEvent;
|
|
|
|
if (nativeEvent.srcElement && (nativeEvent.srcElement as HTMLInputElement).value.slice(-1) == ' ') {
|
2020-08-12 23:06:17 +09:00
|
|
|
setTags(tags.concat(buffer.trim().replace(/\s+/g, '_')));
|
2020-05-17 17:11:35 +09:00
|
|
|
setBuffer('');
|
|
|
|
event.preventDefault();
|
|
|
|
}
|
|
|
|
break;
|
2020-08-12 23:06:17 +09:00
|
|
|
}
|
2020-05-17 17:11:35 +09:00
|
|
|
}
|
|
|
|
} else if (event.key === 'Enter') {
|
|
|
|
// 誤爆防止
|
|
|
|
event.preventDefault();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
return (
|
|
|
|
<div className={containerClass} onClick={() => inputRef.current?.focus()}>
|
|
|
|
<input name={name} type="hidden" value={tags.join(' ')} />
|
|
|
|
<ul className="list-inline d-inline">
|
|
|
|
{tags.map((tag, i) => (
|
|
|
|
<li
|
|
|
|
key={i}
|
2020-08-12 23:05:38 +09:00
|
|
|
className={classNames('list-inline-item', 'badge', 'badge-primary', 'tis-tag-input-item')}
|
2020-05-17 17:11:35 +09:00
|
|
|
onClick={() => removeTag(i)}
|
|
|
|
>
|
|
|
|
<span className="oi oi-tag" /> {tag} | x
|
|
|
|
</li>
|
|
|
|
))}
|
|
|
|
</ul>
|
|
|
|
<input
|
|
|
|
id={id}
|
|
|
|
ref={inputRef}
|
|
|
|
type="text"
|
2020-08-12 23:05:38 +09:00
|
|
|
className="tis-tag-input-field"
|
2020-05-17 17:11:35 +09:00
|
|
|
value={buffer}
|
|
|
|
onChange={(e) => setBuffer(e.target.value)}
|
|
|
|
onKeyDown={onKeyDown}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
};
|