wip
This commit is contained in:
@@ -2,6 +2,9 @@ import Vue from 'vue';
|
||||
import TagInput from './components/TagInput.vue';
|
||||
import MetadataPreview from './components/MetadataPreview.vue';
|
||||
import { fetchGet, ResponseError } from './fetch';
|
||||
import * as React from 'react';
|
||||
import * as ReactDOM from 'react-dom';
|
||||
import TagInput2 from './components/TagInput2';
|
||||
|
||||
export const bus = new Vue({ name: 'EventBus' });
|
||||
|
||||
@@ -66,3 +69,8 @@ new Vue({
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
ReactDOM.render(
|
||||
React.createElement(TagInput2, { id: 'tagInput2', name: 'tags2', value: '', isInvalid: false }),
|
||||
document.querySelector('#tagInput2')
|
||||
);
|
||||
|
10
resources/assets/js/components/TagInput.scss
vendored
Normal file
10
resources/assets/js/components/TagInput.scss
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
:local {
|
||||
.tag-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.tag-input {
|
||||
border: 0;
|
||||
outline: 0;
|
||||
}
|
||||
}
|
76
resources/assets/js/components/TagInput2.tsx
Normal file
76
resources/assets/js/components/TagInput2.tsx
Normal file
@@ -0,0 +1,76 @@
|
||||
import * as React from 'react';
|
||||
import { useState, useRef } from 'react';
|
||||
import * as classNames from 'classnames';
|
||||
const styles = require('./TagInput.scss'); // TODO: 読めてない
|
||||
|
||||
type TagInputProps = {
|
||||
id: string;
|
||||
name: string;
|
||||
value: string;
|
||||
isInvalid: boolean;
|
||||
};
|
||||
|
||||
const TagInput: React.FC<TagInputProps> = ({ id, name, value, isInvalid }) => {
|
||||
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) {
|
||||
setTags(tags.concat(buffer.trim()));
|
||||
setBuffer('');
|
||||
}
|
||||
event.preventDefault();
|
||||
break;
|
||||
case 'Unidentified':
|
||||
// 実際にテキストボックスに入力されている文字を見に行く (フォールバック処理)
|
||||
const nativeEvent = event.nativeEvent;
|
||||
if (nativeEvent.srcElement && (nativeEvent.srcElement as HTMLInputElement).value.slice(-1) == ' ') {
|
||||
setTags(tags.concat(buffer.trim()));
|
||||
setBuffer('');
|
||||
event.preventDefault();
|
||||
}
|
||||
break;
|
||||
}
|
||||
} 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}
|
||||
className={classNames('list-inline-item', 'badge', 'badge-primary', styles.tagItem)}
|
||||
onClick={() => removeTag(i)}
|
||||
>
|
||||
<span className="oi oi-tag" /> {tag} | x
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<input
|
||||
id={id}
|
||||
ref={inputRef}
|
||||
type="text"
|
||||
className={styles.tagInput}
|
||||
value={buffer}
|
||||
onChange={(e) => setBuffer(e.target.value)}
|
||||
onKeyDown={onKeyDown}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TagInput;
|
@@ -40,6 +40,7 @@
|
||||
<div class="form-group col-sm-12">
|
||||
<label for="tagInput"><span class="oi oi-tags"></span> タグ</label>
|
||||
<tag-input id="tagInput" name="tags" value="{{ old('tags') ?? $defaults['tags'] }}" :is-invalid="{{ $errors->has('tags') ? 'true' : 'false' }}"></tag-input>
|
||||
<div id="tagInput2"></div>
|
||||
<small class="form-text text-muted">
|
||||
Tab, Enter, 半角スペースのいずれかで入力確定します。
|
||||
</small>
|
||||
|
Reference in New Issue
Block a user