From 196819270b79c1c8fc0d5db67711195271f13a45 Mon Sep 17 00:00:00 2001 From: shibafu Date: Sun, 17 May 2020 17:11:35 +0900 Subject: [PATCH] wip --- package.json | 8 ++ resources/assets/js/checkin.ts | 8 ++ resources/assets/js/components/TagInput.scss | 10 +++ resources/assets/js/components/TagInput2.tsx | 76 ++++++++++++++++++ resources/views/ejaculation/checkin.blade.php | 1 + tsconfig.json | 5 +- yarn.lock | 78 ++++++++++++++++++- 7 files changed, 183 insertions(+), 3 deletions(-) create mode 100644 resources/assets/js/components/TagInput.scss create mode 100644 resources/assets/js/components/TagInput2.tsx diff --git a/package.json b/package.json index 63acde8..c8b40b4 100644 --- a/package.json +++ b/package.json @@ -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" } } diff --git a/resources/assets/js/checkin.ts b/resources/assets/js/checkin.ts index 4a1bf50..45bbd2a 100644 --- a/resources/assets/js/checkin.ts +++ b/resources/assets/js/checkin.ts @@ -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') +); diff --git a/resources/assets/js/components/TagInput.scss b/resources/assets/js/components/TagInput.scss new file mode 100644 index 0000000..b2f85af --- /dev/null +++ b/resources/assets/js/components/TagInput.scss @@ -0,0 +1,10 @@ +:local { + .tag-item { + cursor: pointer; + } + + .tag-input { + border: 0; + outline: 0; + } +} diff --git a/resources/assets/js/components/TagInput2.tsx b/resources/assets/js/components/TagInput2.tsx new file mode 100644 index 0000000..1d6c124 --- /dev/null +++ b/resources/assets/js/components/TagInput2.tsx @@ -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 = ({ 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(null); + const removeTag = (index: number) => { + setTags(tags.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) { + 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 ( +
inputRef.current?.focus()}> + +
    + {tags.map((tag, i) => ( +
  • removeTag(i)} + > + {tag} | x +
  • + ))} +
+ setBuffer(e.target.value)} + onKeyDown={onKeyDown} + /> +
+ ); +}; + +export default TagInput; diff --git a/resources/views/ejaculation/checkin.blade.php b/resources/views/ejaculation/checkin.blade.php index 611ae85..1ae063f 100644 --- a/resources/views/ejaculation/checkin.blade.php +++ b/resources/views/ejaculation/checkin.blade.php @@ -40,6 +40,7 @@
+
Tab, Enter, 半角スペースのいずれかで入力確定します。 diff --git a/tsconfig.json b/tsconfig.json index d2d1b2c..4801f69 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,9 +5,10 @@ "module": "es2015", "moduleResolution": "node", "strict": true, - "experimentalDecorators": true + "experimentalDecorators": true, + "jsx": "react" }, "include": [ "resources/assets/js/**/*" ] -} \ No newline at end of file +} diff --git a/yarn.lock b/yarn.lock index e287e43..d26d05d 100644 --- a/yarn.lock +++ b/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"