wip
This commit is contained in:
parent
0ca16459a4
commit
196819270b
@ -73,5 +73,13 @@
|
||||
"composer fix",
|
||||
"git add"
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/classnames": "^2.2.10",
|
||||
"@types/react": "^16.9.35",
|
||||
"@types/react-dom": "^16.9.8",
|
||||
"classnames": "^2.2.6",
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1"
|
||||
}
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -5,7 +5,8 @@
|
||||
"module": "es2015",
|
||||
"moduleResolution": "node",
|
||||
"strict": true,
|
||||
"experimentalDecorators": true
|
||||
"experimentalDecorators": true,
|
||||
"jsx": "react"
|
||||
},
|
||||
"include": [
|
||||
"resources/assets/js/**/*"
|
||||
|
78
yarn.lock
78
yarn.lock
@ -772,6 +772,11 @@
|
||||
dependencies:
|
||||
moment "^2.10.2"
|
||||
|
||||
"@types/classnames@^2.2.10":
|
||||
version "2.2.10"
|
||||
resolved "https://registry.yarnpkg.com/@types/classnames/-/classnames-2.2.10.tgz#cc658ca319b6355399efc1f5b9e818f1a24bf999"
|
||||
integrity sha512-1UzDldn9GfYYEsWWnn/P4wkTlkZDH7lDb0wBMGbtIQc9zXEQq7FlKBdZUn6OBqD8sKZZ2RQO2mAjGpXiDGoRmQ==
|
||||
|
||||
"@types/color-name@^1.1.1":
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0"
|
||||
@ -828,6 +833,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-13.5.0.tgz#4e498dbf355795a611a87ae5ef811a8660d42662"
|
||||
integrity sha512-Onhn+z72D2O2Pb2ql2xukJ55rglumsVo1H6Fmyi8mlU9SvKdBk/pUSUAiBY/d9bAOF7VVWajX3sths/+g6ZiAQ==
|
||||
|
||||
"@types/prop-types@*":
|
||||
version "15.7.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7"
|
||||
integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==
|
||||
|
||||
"@types/q@^1.5.1":
|
||||
version "1.5.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8"
|
||||
@ -838,6 +848,21 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.4.tgz#a59e851c1ba16c0513ea123830dd639a0a15cb6a"
|
||||
integrity sha512-+wYo+L6ZF6BMoEjtf8zB2esQsqdV6WsjRK/GP9WOgLPrq87PbNWgIxS76dS5uvl/QXtHGakZmwTznIfcPXcKlQ==
|
||||
|
||||
"@types/react-dom@^16.9.8":
|
||||
version "16.9.8"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.9.8.tgz#fe4c1e11dfc67155733dfa6aa65108b4971cb423"
|
||||
integrity sha512-ykkPQ+5nFknnlU6lDd947WbQ6TE3NNzbQAkInC2EKY1qeYdTKp7onFusmYZb+ityzx2YviqT6BXSu+LyWWJwcA==
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react@*", "@types/react@^16.9.35":
|
||||
version "16.9.46"
|
||||
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.46.tgz#f0326cd7adceda74148baa9bff6e918632f5069e"
|
||||
integrity sha512-dbHzO3aAq1lB3jRQuNpuZ/mnu+CdD3H0WVaaBQA8LTT3S33xhVBUj232T8M3tAhSWJs/D/UqORYUlJNl/8VQZg==
|
||||
dependencies:
|
||||
"@types/prop-types" "*"
|
||||
csstype "^3.0.2"
|
||||
|
||||
"@types/sizzle@*":
|
||||
version "2.3.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/sizzle/-/sizzle-2.3.2.tgz#a811b8c18e2babab7d542b3365887ae2e4d9de47"
|
||||
@ -1937,6 +1962,11 @@ class-utils@^0.3.5:
|
||||
isobject "^3.0.0"
|
||||
static-extend "^0.1.1"
|
||||
|
||||
classnames@^2.2.6:
|
||||
version "2.2.6"
|
||||
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce"
|
||||
integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==
|
||||
|
||||
clean-css@4.2.x, clean-css@^4.1.3:
|
||||
version "4.2.2"
|
||||
resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.2.tgz#8519abda724b3e759bc79d196369906925d81a3f"
|
||||
@ -2489,6 +2519,11 @@ csso@^4.0.2:
|
||||
dependencies:
|
||||
css-tree "1.0.0-alpha.37"
|
||||
|
||||
csstype@^3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.2.tgz#ee5ff8f208c8cd613b389f7b222c9801ca62b3f7"
|
||||
integrity sha512-ofovWglpqoqbfLNOTBNZLSbMuGrblAf1efvvArGKOZMBrIoJeu5UsAipQolkijtyQx5MtAzT/J9IHj/CEY1mJw==
|
||||
|
||||
currently-unhandled@^0.4.1:
|
||||
version "0.4.1"
|
||||
resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea"
|
||||
@ -4988,7 +5023,7 @@ longest-streak@^2.0.1:
|
||||
resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-2.0.4.tgz#b8599957da5b5dab64dee3fe316fa774597d90e4"
|
||||
integrity sha512-vM6rUVCVUJJt33bnmHiZEvr7wPT78ztX7rojL+LW51bHtLh6HTjx84LA5W4+oa6aKEJA7jJu5LR6vQRBpA5DVg==
|
||||
|
||||
loose-envify@^1.0.0:
|
||||
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
|
||||
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
|
||||
@ -6499,6 +6534,15 @@ promise-inflight@^1.0.1:
|
||||
resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3"
|
||||
integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM=
|
||||
|
||||
prop-types@^15.6.2:
|
||||
version "15.7.2"
|
||||
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
|
||||
integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
|
||||
dependencies:
|
||||
loose-envify "^1.4.0"
|
||||
object-assign "^4.1.1"
|
||||
react-is "^16.8.1"
|
||||
|
||||
property-expr@^1.5.0:
|
||||
version "1.5.1"
|
||||
resolved "https://registry.yarnpkg.com/property-expr/-/property-expr-1.5.1.tgz#22e8706894a0c8e28d58735804f6ba3a3673314f"
|
||||
@ -6639,6 +6683,30 @@ raw-body@2.4.0:
|
||||
iconv-lite "0.4.24"
|
||||
unpipe "1.0.0"
|
||||
|
||||
react-dom@^16.13.1:
|
||||
version "16.13.1"
|
||||
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.13.1.tgz#c1bd37331a0486c078ee54c4740720993b2e0e7f"
|
||||
integrity sha512-81PIMmVLnCNLO/fFOQxdQkvEq/+Hfpv24XNJfpyZhTRfO0QcmQIF/PgCa1zCOj2w1hrn12MFLyaJ/G0+Mxtfag==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
object-assign "^4.1.1"
|
||||
prop-types "^15.6.2"
|
||||
scheduler "^0.19.1"
|
||||
|
||||
react-is@^16.8.1:
|
||||
version "16.13.1"
|
||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
|
||||
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
|
||||
|
||||
react@^16.13.1:
|
||||
version "16.13.1"
|
||||
resolved "https://registry.yarnpkg.com/react/-/react-16.13.1.tgz#2e818822f1a9743122c063d6410d85c1e3afe48e"
|
||||
integrity sha512-YMZQQq32xHLX0bz5Mnibv1/LHb3Sqzngu7xstSM+vrkE5Kzr9xE0yMByK5kMoTK30YVJE61WfbxIFFvfeDKT1w==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
object-assign "^4.1.1"
|
||||
prop-types "^15.6.2"
|
||||
|
||||
read-pkg-up@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07"
|
||||
@ -7091,6 +7159,14 @@ sax@~1.2.4:
|
||||
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
|
||||
integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
|
||||
|
||||
scheduler@^0.19.1:
|
||||
version "0.19.1"
|
||||
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.19.1.tgz#4f3e2ed2c1a7d65681f4c854fa8c5a1ccb40f196"
|
||||
integrity sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
object-assign "^4.1.1"
|
||||
|
||||
schema-utils@^0.4.5:
|
||||
version "0.4.7"
|
||||
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.4.7.tgz#ba74f597d2be2ea880131746ee17d0a093c68187"
|
||||
|
Loading…
Reference in New Issue
Block a user