From 7c220b1a925db59365097ab41c4cf2c5cf750ca4 Mon Sep 17 00:00:00 2001 From: Paul Kinlan Date: Fri, 29 Jun 2018 16:37:48 +0100 Subject: [PATCH] Adding in Drag and Drop support to fix #45 (#56) * Merging file drop * Fixing double drop --- codecs/mozjpeg_enc/package-lock.json | 358 +++++++++--------- .../app/custom-els/FileDrop/index.ts | 116 ++++++ .../custom-els/FileDrop/missing-types.d.ts | 20 + .../app/custom-els/FileDrop/styles.css | 3 + src/components/app/index.tsx | 65 ++-- src/components/app/style.scss | 23 +- src/components/output/index.tsx | 10 +- 7 files changed, 386 insertions(+), 209 deletions(-) create mode 100644 src/components/app/custom-els/FileDrop/index.ts create mode 100644 src/components/app/custom-els/FileDrop/missing-types.d.ts create mode 100644 src/components/app/custom-els/FileDrop/styles.css diff --git a/codecs/mozjpeg_enc/package-lock.json b/codecs/mozjpeg_enc/package-lock.json index 2523147c..da66a524 100644 --- a/codecs/mozjpeg_enc/package-lock.json +++ b/codecs/mozjpeg_enc/package-lock.json @@ -21,8 +21,8 @@ "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", "dev": true, "requires": { - "delegates": "1.0.0", - "readable-stream": "2.3.5" + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" } }, "balanced-match": { @@ -43,7 +43,7 @@ "integrity": "sha1-ysMo977kVzDUBLaSID/LWQ4XLV4=", "dev": true, "requires": { - "readable-stream": "2.3.5" + "readable-stream": "^2.0.5" } }, "block-stream": { @@ -52,7 +52,7 @@ "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", "dev": true, "requires": { - "inherits": "2.0.3" + "inherits": "~2.0.0" } }, "brace-expansion": { @@ -61,7 +61,7 @@ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "requires": { - "balanced-match": "1.0.0", + "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, @@ -72,8 +72,8 @@ "dev": true, "requires": { "base64-js": "0.0.8", - "ieee754": "1.1.8", - "isarray": "1.0.0" + "ieee754": "^1.1.4", + "isarray": "^1.0.0" } }, "buffer-crc32": { @@ -88,10 +88,10 @@ "integrity": "sha512-Cg8/ZSBEa8ZVY9HspcGUYaK63d/bN7rqS3CYCzEGUxuYv6UlmcjzDUz2fCFFHyTvUW5Pk0I+3hkA3iXlIj6guA==", "dev": true, "requires": { - "get-proxy": "2.1.0", - "isurl": "1.0.0", - "tunnel-agent": "0.6.0", - "url-to-options": "1.0.1" + "get-proxy": "^2.0.0", + "isurl": "^1.0.0-alpha5", + "tunnel-agent": "^0.6.0", + "url-to-options": "^1.0.1" } }, "code-point-at": { @@ -106,7 +106,7 @@ "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", "dev": true, "requires": { - "graceful-readlink": "1.0.1" + "graceful-readlink": ">= 1.0.0" } }, "concat-map": { @@ -121,8 +121,8 @@ "integrity": "sha1-q6CXR9++TD5w52am5BWG4YWfxvI=", "dev": true, "requires": { - "ini": "1.3.5", - "proto-list": "1.2.4" + "ini": "^1.3.4", + "proto-list": "~1.2.1" } }, "console-control-strings": { @@ -158,14 +158,14 @@ "integrity": "sha1-eu3YVCflqS2s/lVnSnxQXpbQH50=", "dev": true, "requires": { - "decompress-tar": "4.1.1", - "decompress-tarbz2": "4.1.1", - "decompress-targz": "4.1.1", - "decompress-unzip": "4.0.1", - "graceful-fs": "4.1.11", - "make-dir": "1.2.0", - "pify": "2.3.0", - "strip-dirs": "2.1.0" + "decompress-tar": "^4.0.0", + "decompress-tarbz2": "^4.0.0", + "decompress-targz": "^4.0.0", + "decompress-unzip": "^4.0.1", + "graceful-fs": "^4.1.10", + "make-dir": "^1.0.0", + "pify": "^2.3.0", + "strip-dirs": "^2.0.0" }, "dependencies": { "pify": { @@ -182,7 +182,7 @@ "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", "dev": true, "requires": { - "mimic-response": "1.0.0" + "mimic-response": "^1.0.0" } }, "decompress-tar": { @@ -191,9 +191,9 @@ "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==", "dev": true, "requires": { - "file-type": "5.2.0", - "is-stream": "1.1.0", - "tar-stream": "1.5.5" + "file-type": "^5.2.0", + "is-stream": "^1.1.0", + "tar-stream": "^1.5.2" } }, "decompress-tarbz2": { @@ -202,11 +202,11 @@ "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==", "dev": true, "requires": { - "decompress-tar": "4.1.1", - "file-type": "6.2.0", - "is-stream": "1.1.0", - "seek-bzip": "1.0.5", - "unbzip2-stream": "1.2.5" + "decompress-tar": "^4.1.0", + "file-type": "^6.1.0", + "is-stream": "^1.1.0", + "seek-bzip": "^1.0.5", + "unbzip2-stream": "^1.0.9" }, "dependencies": { "file-type": { @@ -223,9 +223,9 @@ "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==", "dev": true, "requires": { - "decompress-tar": "4.1.1", - "file-type": "5.2.0", - "is-stream": "1.1.0" + "decompress-tar": "^4.1.1", + "file-type": "^5.2.0", + "is-stream": "^1.1.0" } }, "decompress-unzip": { @@ -234,10 +234,10 @@ "integrity": "sha1-3qrM39FK6vhVePczroIQ+bSEj2k=", "dev": true, "requires": { - "file-type": "3.9.0", - "get-stream": "2.3.1", - "pify": "2.3.0", - "yauzl": "2.9.1" + "file-type": "^3.8.0", + "get-stream": "^2.2.0", + "pify": "^2.3.0", + "yauzl": "^2.4.2" }, "dependencies": { "file-type": { @@ -252,8 +252,8 @@ "integrity": "sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=", "dev": true, "requires": { - "object-assign": "4.1.1", - "pinkie-promise": "2.0.1" + "object-assign": "^4.0.1", + "pinkie-promise": "^2.0.0" } }, "pify": { @@ -282,17 +282,17 @@ "integrity": "sha512-DpO9K1sXAST8Cpzb7kmEhogJxymyVUd5qz/vCOSyvwtp2Klj2XcDt5YUuasgxka44SxF0q5RriKIwJmQHG2AuA==", "dev": true, "requires": { - "caw": "2.0.1", - "content-disposition": "0.5.2", - "decompress": "4.2.0", - "ext-name": "5.0.0", + "caw": "^2.0.0", + "content-disposition": "^0.5.2", + "decompress": "^4.0.0", + "ext-name": "^5.0.0", "file-type": "5.2.0", - "filenamify": "2.0.0", - "get-stream": "3.0.0", - "got": "7.1.0", - "make-dir": "1.2.0", - "p-event": "1.3.0", - "pify": "3.0.0" + "filenamify": "^2.0.0", + "get-stream": "^3.0.0", + "got": "^7.0.0", + "make-dir": "^1.0.0", + "p-event": "^1.0.0", + "pify": "^3.0.0" } }, "duplexer3": { @@ -307,7 +307,7 @@ "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", "dev": true, "requires": { - "once": "1.4.0" + "once": "^1.4.0" } }, "error-ex": { @@ -316,7 +316,7 @@ "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", "dev": true, "requires": { - "is-arrayish": "0.2.1" + "is-arrayish": "^0.2.1" } }, "escape-string-regexp": { @@ -331,7 +331,7 @@ "integrity": "sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==", "dev": true, "requires": { - "mime-db": "1.33.0" + "mime-db": "^1.28.0" } }, "ext-name": { @@ -340,8 +340,8 @@ "integrity": "sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==", "dev": true, "requires": { - "ext-list": "2.2.2", - "sort-keys-length": "1.0.1" + "ext-list": "^2.0.0", + "sort-keys-length": "^1.0.0" } }, "extend": { @@ -356,7 +356,7 @@ "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", "dev": true, "requires": { - "pend": "1.2.0" + "pend": "~1.2.0" } }, "file-type": { @@ -377,9 +377,9 @@ "integrity": "sha1-vRYiYsC26Uv7zc8Zo7uzdk94VpU=", "dev": true, "requires": { - "filename-reserved-regex": "2.0.0", - "strip-outer": "1.0.0", - "trim-repeated": "1.0.0" + "filename-reserved-regex": "^2.0.0", + "strip-outer": "^1.0.0", + "trim-repeated": "^1.0.0" } }, "fs.realpath": { @@ -394,10 +394,10 @@ "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "inherits": "2.0.3", - "mkdirp": "0.5.1", - "rimraf": "2.6.2" + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" } }, "fstream-ignore": { @@ -406,9 +406,9 @@ "integrity": "sha1-nDHa40dnAY/h0kmyTa2mfQktoQU=", "dev": true, "requires": { - "fstream": "1.0.11", - "inherits": "2.0.3", - "minimatch": "3.0.4" + "fstream": "^1.0.0", + "inherits": "2", + "minimatch": "^3.0.0" } }, "gauge": { @@ -417,14 +417,14 @@ "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "dev": true, "requires": { - "aproba": "1.2.0", - "console-control-strings": "1.1.0", - "has-unicode": "2.0.1", - "object-assign": "4.1.1", - "signal-exit": "3.0.2", - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wide-align": "1.1.2" + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" } }, "get-proxy": { @@ -433,7 +433,7 @@ "integrity": "sha512-zmZIaQTWnNQb4R4fJUEp/FC51eZsc6EkErspy3xtIYStaq8EB/hDIWipxsal+E8rz0qD7f2sL/NA9Xee4RInJw==", "dev": true, "requires": { - "npm-conf": "1.1.3" + "npm-conf": "^1.1.0" } }, "get-stream": { @@ -448,12 +448,12 @@ "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } }, "got": { @@ -462,20 +462,20 @@ "integrity": "sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==", "dev": true, "requires": { - "decompress-response": "3.3.0", - "duplexer3": "0.1.4", - "get-stream": "3.0.0", - "is-plain-obj": "1.1.0", - "is-retry-allowed": "1.1.0", - "is-stream": "1.1.0", - "isurl": "1.0.0", - "lowercase-keys": "1.0.0", - "p-cancelable": "0.3.0", - "p-timeout": "1.2.1", - "safe-buffer": "5.1.1", - "timed-out": "4.0.1", - "url-parse-lax": "1.0.0", - "url-to-options": "1.0.1" + "decompress-response": "^3.2.0", + "duplexer3": "^0.1.4", + "get-stream": "^3.0.0", + "is-plain-obj": "^1.1.0", + "is-retry-allowed": "^1.0.0", + "is-stream": "^1.0.0", + "isurl": "^1.0.0-alpha5", + "lowercase-keys": "^1.0.0", + "p-cancelable": "^0.3.0", + "p-timeout": "^1.1.1", + "safe-buffer": "^5.0.1", + "timed-out": "^4.0.0", + "url-parse-lax": "^1.0.0", + "url-to-options": "^1.0.1" } }, "graceful-fs": { @@ -502,7 +502,7 @@ "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", "dev": true, "requires": { - "has-symbol-support-x": "1.4.2" + "has-symbol-support-x": "^1.4.1" } }, "has-unicode": { @@ -529,8 +529,8 @@ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" + "once": "^1.3.0", + "wrappy": "1" } }, "inherits": { @@ -557,7 +557,7 @@ "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, "requires": { - "number-is-nan": "1.0.1" + "number-is-nan": "^1.0.0" } }, "is-natural-number": { @@ -602,8 +602,8 @@ "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", "dev": true, "requires": { - "has-to-string-tag-x": "1.4.1", - "is-object": "1.0.1" + "has-to-string-tag-x": "^1.2.0", + "is-object": "^1.0.1" } }, "load-json-file": { @@ -612,10 +612,10 @@ "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "parse-json": "2.2.0", - "pify": "2.3.0", - "strip-bom": "3.0.0" + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" }, "dependencies": { "pify": { @@ -638,7 +638,7 @@ "integrity": "sha512-aNUAa4UMg/UougV25bbrU4ZaaKNjJ/3/xnvg/twpmKROPdKZPZ9wGgI0opdZzO8q/zUFawoUuixuOv33eZ61Iw==", "dev": true, "requires": { - "pify": "3.0.0" + "pify": "^3.0.0" } }, "mime-db": { @@ -659,7 +659,7 @@ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { - "brace-expansion": "1.1.11" + "brace-expansion": "^1.1.7" } }, "minimist": { @@ -697,16 +697,16 @@ "integrity": "sha1-7DqP3gcZC2ny/kNMOVo+aUaEG1Y=", "dev": true, "requires": { - "download": "6.2.5", - "extend": "3.0.1", - "load-json-file": "2.0.0", - "minimist": "1.2.0", - "mkdirp": "0.5.1", - "npm-cache-filename": "1.0.2", - "npmlog": "4.1.2", - "rimraf": "2.6.2", - "tar-pack": "3.4.1", - "write-json-file": "2.3.0" + "download": "^6.2.2", + "extend": "^3.0.1", + "load-json-file": "^2.0.0", + "minimist": "^1.2.0", + "mkdirp": "^0.5.1", + "npm-cache-filename": "^1.0.2", + "npmlog": "^4.1.0", + "rimraf": "^2.6.1", + "tar-pack": "^3.4.0", + "write-json-file": "^2.2.0" } }, "npm-cache-filename": { @@ -721,8 +721,8 @@ "integrity": "sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==", "dev": true, "requires": { - "config-chain": "1.1.11", - "pify": "3.0.0" + "config-chain": "^1.1.11", + "pify": "^3.0.0" } }, "npmlog": { @@ -731,10 +731,10 @@ "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "dev": true, "requires": { - "are-we-there-yet": "1.1.4", - "console-control-strings": "1.1.0", - "gauge": "2.7.4", - "set-blocking": "2.0.0" + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" } }, "number-is-nan": { @@ -755,7 +755,7 @@ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "requires": { - "wrappy": "1.0.2" + "wrappy": "1" } }, "p-cancelable": { @@ -770,7 +770,7 @@ "integrity": "sha1-jmtPT2XHK8W2/ii3XtqHT5akoIU=", "dev": true, "requires": { - "p-timeout": "1.2.1" + "p-timeout": "^1.1.1" } }, "p-finally": { @@ -785,7 +785,7 @@ "integrity": "sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y=", "dev": true, "requires": { - "p-finally": "1.0.0" + "p-finally": "^1.0.0" } }, "parse-json": { @@ -794,7 +794,7 @@ "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", "dev": true, "requires": { - "error-ex": "1.3.1" + "error-ex": "^1.2.0" } }, "path-is-absolute": { @@ -827,7 +827,7 @@ "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", "dev": true, "requires": { - "pinkie": "2.0.4" + "pinkie": "^2.0.0" } }, "prepend-http": { @@ -854,13 +854,13 @@ "integrity": "sha512-tK0yDhrkygt/knjowCUiWP9YdV7c5R+8cR0r/kt9ZhBU906Fs6RpQJCEilamRJj1Nx2rWI6LkW9gKqjTkshhEw==", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.0.3", + "util-deprecate": "~1.0.1" } }, "rimraf": { @@ -869,7 +869,7 @@ "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", "dev": true, "requires": { - "glob": "7.1.2" + "glob": "^7.0.5" } }, "safe-buffer": { @@ -884,7 +884,7 @@ "integrity": "sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w=", "dev": true, "requires": { - "commander": "2.8.1" + "commander": "~2.8.1" } }, "set-blocking": { @@ -905,7 +905,7 @@ "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", "dev": true, "requires": { - "is-plain-obj": "1.1.0" + "is-plain-obj": "^1.0.0" } }, "sort-keys-length": { @@ -914,7 +914,7 @@ "integrity": "sha1-nLb09OnkgVWmqgZx7dM2/xR5oYg=", "dev": true, "requires": { - "sort-keys": "1.1.2" + "sort-keys": "^1.0.0" } }, "string-width": { @@ -923,9 +923,9 @@ "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" } }, "string_decoder": { @@ -934,7 +934,7 @@ "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", "dev": true, "requires": { - "safe-buffer": "5.1.1" + "safe-buffer": "~5.1.0" } }, "strip-ansi": { @@ -943,7 +943,7 @@ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" } }, "strip-bom": { @@ -958,7 +958,7 @@ "integrity": "sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==", "dev": true, "requires": { - "is-natural-number": "4.0.1" + "is-natural-number": "^4.0.1" } }, "strip-outer": { @@ -967,7 +967,7 @@ "integrity": "sha1-qsC6YNLpDF1PJ1/Yhp/ZotMQ/7g=", "dev": true, "requires": { - "escape-string-regexp": "1.0.5" + "escape-string-regexp": "^1.0.2" } }, "tar": { @@ -976,9 +976,9 @@ "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", "dev": true, "requires": { - "block-stream": "0.0.9", - "fstream": "1.0.11", - "inherits": "2.0.3" + "block-stream": "*", + "fstream": "^1.0.2", + "inherits": "2" } }, "tar-pack": { @@ -987,14 +987,14 @@ "integrity": "sha512-PPRybI9+jM5tjtCbN2cxmmRU7YmqT3Zv/UDy48tAh2XRkLa9bAORtSWLkVc13+GJF+cdTh1yEnHEk3cpTaL5Kg==", "dev": true, "requires": { - "debug": "2.6.9", - "fstream": "1.0.11", - "fstream-ignore": "1.0.5", - "once": "1.4.0", - "readable-stream": "2.3.5", - "rimraf": "2.6.2", - "tar": "2.2.1", - "uid-number": "0.0.6" + "debug": "^2.2.0", + "fstream": "^1.0.10", + "fstream-ignore": "^1.0.5", + "once": "^1.3.3", + "readable-stream": "^2.1.4", + "rimraf": "^2.5.1", + "tar": "^2.2.1", + "uid-number": "^0.0.6" } }, "tar-stream": { @@ -1003,10 +1003,10 @@ "integrity": "sha512-mQdgLPc/Vjfr3VWqWbfxW8yQNiJCbAZ+Gf6GDu1Cy0bdb33ofyiNGBtAY96jHFhDuivCwgW1H9DgTON+INiXgg==", "dev": true, "requires": { - "bl": "1.2.1", - "end-of-stream": "1.4.1", - "readable-stream": "2.3.5", - "xtend": "4.0.1" + "bl": "^1.0.0", + "end-of-stream": "^1.0.0", + "readable-stream": "^2.0.0", + "xtend": "^4.0.0" } }, "through": { @@ -1027,7 +1027,7 @@ "integrity": "sha1-42RqLqTokTEr9+rObPsFOAvAHCE=", "dev": true, "requires": { - "escape-string-regexp": "1.0.5" + "escape-string-regexp": "^1.0.2" } }, "tunnel-agent": { @@ -1036,7 +1036,7 @@ "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", "dev": true, "requires": { - "safe-buffer": "5.1.1" + "safe-buffer": "^5.0.1" } }, "uid-number": { @@ -1051,8 +1051,8 @@ "integrity": "sha512-izD3jxT8xkzwtXRUZjtmRwKnZoeECrfZ8ra/ketwOcusbZEp4mjULMnJOCfTDZBgGQAAY1AJ/IgxcwkavcX9Og==", "dev": true, "requires": { - "buffer": "3.6.0", - "through": "2.3.8" + "buffer": "^3.0.1", + "through": "^2.3.6" } }, "url-parse-lax": { @@ -1061,7 +1061,7 @@ "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", "dev": true, "requires": { - "prepend-http": "1.0.4" + "prepend-http": "^1.0.1" } }, "url-to-options": { @@ -1082,7 +1082,7 @@ "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", "dev": true, "requires": { - "string-width": "1.0.2" + "string-width": "^1.0.2" } }, "wrappy": { @@ -1097,9 +1097,9 @@ "integrity": "sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA==", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "imurmurhash": "0.1.4", - "signal-exit": "3.0.2" + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" } }, "write-json-file": { @@ -1108,12 +1108,12 @@ "integrity": "sha1-K2TIozAE1UuGmMdtWFp3zrYdoy8=", "dev": true, "requires": { - "detect-indent": "5.0.0", - "graceful-fs": "4.1.11", - "make-dir": "1.2.0", - "pify": "3.0.0", - "sort-keys": "2.0.0", - "write-file-atomic": "2.3.0" + "detect-indent": "^5.0.0", + "graceful-fs": "^4.1.2", + "make-dir": "^1.0.0", + "pify": "^3.0.0", + "sort-keys": "^2.0.0", + "write-file-atomic": "^2.0.0" }, "dependencies": { "sort-keys": { @@ -1122,7 +1122,7 @@ "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", "dev": true, "requires": { - "is-plain-obj": "1.1.0" + "is-plain-obj": "^1.0.0" } } } @@ -1139,8 +1139,8 @@ "integrity": "sha1-qBmB6nCleUYTOIPwKcWCGok1mn8=", "dev": true, "requires": { - "buffer-crc32": "0.2.13", - "fd-slicer": "1.0.1" + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.0.1" } } } diff --git a/src/components/app/custom-els/FileDrop/index.ts b/src/components/app/custom-els/FileDrop/index.ts new file mode 100644 index 00000000..7719c239 --- /dev/null +++ b/src/components/app/custom-els/FileDrop/index.ts @@ -0,0 +1,116 @@ +import { bind } from '../../../../lib/util'; +import './styles.css'; + +function firstMatchingItem(list: DataTransferItemList, acceptVal: string): DataTransferItem | undefined { + // Split accepts values by ',' then by '/'. Trim everything & lowercase. + const accepts = acceptVal.toLowerCase().split(',').map(accept => { + return accept.trim().split('/').map(part => part.trim()); + }).filter(acceptParts => acceptParts.length === 2); // Filter invalid values + + return Array.from(list).find(item => { + if (item.kind !== 'file') return false; + + // 'Parse' the type. + const [typeMain, typeSub] = item.type.toLowerCase().split('/').map(s => s.trim()); + + for (const [acceptMain, acceptSub] of accepts) { + // Look for an exact match, or a partial match if * is accepted, eg image/*. + if (typeMain === acceptMain && (acceptSub === '*' || typeSub === acceptSub)) { + return true; + } + } + return false; + }); +} + +interface FileDropEventInit extends EventInit { + file: File; +} + +export class FileDropEvent extends Event { + private _file: File; + constructor(typeArg: string, eventInitDict: FileDropEventInit) { + super(typeArg, eventInitDict); + this._file = eventInitDict.file; + } + + get file(): File { + return this._file; + } +} + +/* + Example Usage. + + [everything in here is a drop target.] + + + dropElement.addEventListner('dropfile', (event) => console.log(event.detail)) +*/ +export class FileDrop extends HTMLElement { + + private _dragEnterCount = 0; + + constructor() { + super(); + this.addEventListener('dragover', (event) => event.preventDefault()); + this.addEventListener('drop', this._onDrop); + this.addEventListener('dragenter', this._onDragEnter); + this.addEventListener('dragend', () => this._reset()); + this.addEventListener('dragleave', this._onDragLeave); + } + + get accept() { + return this.getAttribute('accept') || ''; + } + + set accept(val: string) { + this.setAttribute('accept', val); + } + + @bind + private _onDragEnter(event: DragEvent) { + this._dragEnterCount++; + if (this._dragEnterCount > 1) return; + + // We don't have data, attempt to get it and if it matches, set the correct state. + const dragDataItem = firstMatchingItem(event.dataTransfer.items, this.accept); + if (dragDataItem) { + this.classList.add('drop-valid'); + } else { + this.classList.add('drop-invalid'); + } + } + + @bind + private _onDragLeave() { + this._dragEnterCount--; + if (this._dragEnterCount === 0) { + this._reset(); + } + } + + @bind + private _onDrop(event: DragEvent) { + event.preventDefault(); + this._reset(); + const dragDataItem = firstMatchingItem(event.dataTransfer.items, this.accept); + if (!dragDataItem) return; + + const file = dragDataItem.getAsFile(); + if (file === null) return; + + this.dispatchEvent(new FileDropEvent('filedrop', { file })); + } + + private _reset() { + this._dragEnterCount = 0; + this.classList.remove('drop-valid'); + this.classList.remove('drop-invalid'); + } +} + +customElements.define('file-drop', FileDrop); diff --git a/src/components/app/custom-els/FileDrop/missing-types.d.ts b/src/components/app/custom-els/FileDrop/missing-types.d.ts new file mode 100644 index 00000000..17dbc047 --- /dev/null +++ b/src/components/app/custom-els/FileDrop/missing-types.d.ts @@ -0,0 +1,20 @@ +import { FileDropEvent, FileDrop } from "."; + + +declare global { + + interface HTMLElementEventMap { + 'filedrop': FileDropEvent; + } + + namespace JSX { + interface IntrinsicElements { + 'file-drop': FileDropAttributes; + } + + interface FileDropAttributes extends HTMLAttributes { + accept?: string; + onfiledrop?: ((this: FileDrop, ev: FileDropEvent) => any) | null; + } + } +} \ No newline at end of file diff --git a/src/components/app/custom-els/FileDrop/styles.css b/src/components/app/custom-els/FileDrop/styles.css new file mode 100644 index 00000000..ffb6888d --- /dev/null +++ b/src/components/app/custom-els/FileDrop/styles.css @@ -0,0 +1,3 @@ +file-drop { + display: block; +} diff --git a/src/components/app/index.tsx b/src/components/app/index.tsx index 07c8345d..c80c087f 100644 --- a/src/components/app/index.tsx +++ b/src/components/app/index.tsx @@ -3,6 +3,8 @@ import { bind, bitmapToImageData } from '../../lib/util'; import * as style from './style.scss'; import Output from '../output'; import Options from '../options'; +import { FileDropEvent } from './custom-els/FileDrop'; +import './custom-els/FileDrop'; import * as mozJPEG from '../../codecs/mozjpeg/encoder'; import * as identity from '../../codecs/identity/encoder'; @@ -104,6 +106,17 @@ export default class App extends Component { const fileInput = event.target as HTMLInputElement; const file = fileInput.files && fileInput.files[0]; if (!file) return; + await this.updateFile(file); + } + + @bind + async onFileDrop(event: FileDropEvent) { + const { file } = event; + if (!file) return; + await this.updateFile(file); + } + + async updateFile(file: File) { this.setState({ loading: true }); try { const bmp = await createImageBitmap(file); @@ -112,7 +125,7 @@ export default class App extends Component { this.setState({ source: { data, bmp, file }, error: undefined, - loading: false + loading: false, }); } catch (err) { this.setState({ error: 'IMAGE_INVALID', loading: false }); @@ -173,29 +186,33 @@ export default class App extends Component { loading = loading || images.some(image => image.loading); return ( -
- {(leftImageBmp && rightImageBmp) ? ( - - ) : ( -
-

Select an image

- -
- )} - {images.map((image, index) => ( - {encoderMap[image.encoderState.type].label} - ))} - {images.map((image, index) => ( - - ))} - {loading && Loading...} - {error && Error: {error}} -
+ +
+ {(leftImageBmp && rightImageBmp) ? ( + + ) : ( +
+

Select an image

+ +
+ )} + {images.map((image, index) => ( + + {encoderMap[image.encoderState.type].label} + + ))} + {images.map((image, index) => ( + + ))} + {loading && Loading...} + {error && Error: {error}} +
+
); } } diff --git a/src/components/app/style.scss b/src/components/app/style.scss index 640fd092..693dea9a 100644 --- a/src/components/app/style.scss +++ b/src/components/app/style.scss @@ -46,7 +46,7 @@ Note: These styles are temporary. They will be replaced before going live. font-size: 150%; text-align: center; } - + input { display: inline-block; width: 16em; @@ -60,3 +60,24 @@ Note: These styles are temporary. They will be replaced before going live. cursor: pointer; } } + +:global { + file-drop { + overflow: hidden; + touch-action: none; + height:100%; + width:100%; + + &.drop-valid { + transition: opacity 200ms ease-in-out, background-color 200ms; + opacity: 0.5; + background-color:green; + } + + &.drop-invalid { + transition: opacity 200ms ease-in-out, background-color 200ms; + opacity: 0.5; + background-color:red; + } + } +} \ No newline at end of file diff --git a/src/components/output/index.tsx b/src/components/output/index.tsx index 45105381..2d83ae87 100644 --- a/src/components/output/index.tsx +++ b/src/components/output/index.tsx @@ -30,12 +30,12 @@ export default class Output extends Component { } } - componentWillReceiveProps({ leftImg, rightImg }: Props) { - if (leftImg !== this.props.leftImg && this.canvasLeft) { - drawBitmapToCanvas(this.canvasLeft, leftImg); + componentDidUpdate(prevProps: Props) { + if (prevProps.leftImg !== this.props.leftImg && this.canvasLeft) { + drawBitmapToCanvas(this.canvasLeft, this.props.leftImg); } - if (rightImg !== this.props.rightImg && this.canvasRight) { - drawBitmapToCanvas(this.canvasRight, rightImg); + if (prevProps.rightImg !== this.props.rightImg && this.canvasRight) { + drawBitmapToCanvas(this.canvasRight, this.props.rightImg); } }