Kaynağa Gözat

Merge branch 'master' into feature/tl-preset

Renée Kooi 6 yıl önce
ebeveyn
işleme
dd718ac02e
100 değiştirilmiş dosya ile 1105 ekleme ve 640 silme
  1. 35 2
      CHANGELOG.md
  2. 1 1
      LICENSE
  3. 33 29
      README.md
  4. 1 1
      bin/build-js.js
  5. 1 1
      bin/release
  6. 1 1
      bin/upload-to-cdn.sh
  7. 2 2
      examples/cdn-example/index.html
  8. 2 2
      examples/uppy-with-companion/client/index.html
  9. 146 124
      package-lock.json
  10. 1 1
      package.json
  11. 4 4
      packages/@uppy/aws-s3-multipart/package.json
  12. 21 17
      packages/@uppy/aws-s3-multipart/types/index.d.ts
  13. 5 5
      packages/@uppy/aws-s3/package.json
  14. 18 14
      packages/@uppy/aws-s3/types/index.d.ts
  15. 1 1
      packages/@uppy/companion/package.json
  16. 0 1
      packages/@uppy/companion/src/server/Uploader.js
  17. 2 1
      packages/@uppy/companion/src/server/controllers/callback.js
  18. 3 3
      packages/@uppy/companion/src/server/controllers/get.js
  19. 6 6
      packages/@uppy/companion/src/server/controllers/url.js
  20. 44 6
      packages/@uppy/companion/src/server/helpers/utils.js
  21. 5 5
      packages/@uppy/companion/src/server/logger.js
  22. 3 2
      packages/@uppy/companion/src/server/middlewares.js
  23. 0 24
      packages/@uppy/companion/src/uppy.js
  24. 2 2
      packages/@uppy/core/package.json
  25. 2 0
      packages/@uppy/core/src/index.js
  26. 6 6
      packages/@uppy/core/src/index.test.js
  27. 35 0
      packages/@uppy/core/src/supportsUploadProgress.js
  28. 28 0
      packages/@uppy/core/src/supportsUploadProgress.test.js
  29. 1 1
      packages/@uppy/core/types/index.d.ts
  30. 9 9
      packages/@uppy/dashboard/package.json
  31. 2 1
      packages/@uppy/dashboard/src/style.scss
  32. 27 23
      packages/@uppy/dashboard/types/index.d.ts
  33. 4 4
      packages/@uppy/drag-drop/package.json
  34. 52 55
      packages/@uppy/drag-drop/src/style.scss
  35. 13 9
      packages/@uppy/drag-drop/types/index.d.ts
  36. 5 5
      packages/@uppy/dropbox/package.json
  37. 4 2
      packages/@uppy/dropbox/src/index.js
  38. 10 6
      packages/@uppy/dropbox/types/index.d.ts
  39. 4 4
      packages/@uppy/file-input/package.json
  40. 2 1
      packages/@uppy/file-input/src/style.scss
  41. 10 6
      packages/@uppy/file-input/types/index.d.ts
  42. 4 4
      packages/@uppy/form/package.json
  43. 13 9
      packages/@uppy/form/types/index.d.ts
  44. 4 4
      packages/@uppy/golden-retriever/package.json
  45. 11 7
      packages/@uppy/golden-retriever/types/index.d.ts
  46. 5 5
      packages/@uppy/google-drive/package.json
  47. 4 2
      packages/@uppy/google-drive/src/index.js
  48. 10 6
      packages/@uppy/google-drive/types/index.d.ts
  49. 4 4
      packages/@uppy/informer/package.json
  50. 2 2
      packages/@uppy/informer/src/style.scss
  51. 15 11
      packages/@uppy/informer/types/index.d.ts
  52. 5 5
      packages/@uppy/instagram/package.json
  53. 2 1
      packages/@uppy/instagram/src/index.js
  54. 10 6
      packages/@uppy/instagram/types/index.d.ts
  55. 4 4
      packages/@uppy/progress-bar/package.json
  56. 2 1
      packages/@uppy/progress-bar/src/style.scss
  57. 10 6
      packages/@uppy/progress-bar/types/index.d.ts
  58. 4 4
      packages/@uppy/provider-views/package.json
  59. 11 11
      packages/@uppy/provider-views/src/index.js
  60. 2 1
      packages/@uppy/provider-views/src/style.scss
  61. 8 8
      packages/@uppy/react/package.json
  62. 6 0
      packages/@uppy/react/src/CommonTypes.d.ts
  63. 33 0
      packages/@uppy/react/src/Dashboard.d.ts
  64. 16 0
      packages/@uppy/react/src/DashboardModal.d.ts
  65. 13 0
      packages/@uppy/react/src/DragDrop.d.ts
  66. 13 0
      packages/@uppy/react/src/ProgressBar.d.ts
  67. 14 0
      packages/@uppy/react/src/StatusBar.d.ts
  68. 7 0
      packages/@uppy/react/types/index.d.ts
  69. 3 3
      packages/@uppy/redux-dev-tools/package.json
  70. 8 4
      packages/@uppy/redux-dev-tools/types/index.d.ts
  71. 4 4
      packages/@uppy/status-bar/package.json
  72. 15 2
      packages/@uppy/status-bar/src/StatusBar.js
  73. 3 1
      packages/@uppy/status-bar/src/index.js
  74. 8 3
      packages/@uppy/status-bar/src/style.scss
  75. 11 7
      packages/@uppy/status-bar/types/index.d.ts
  76. 2 1
      packages/@uppy/store-default/types/index.d.ts
  77. 8 1
      packages/@uppy/store-redux/types/index.d.ts
  78. 4 4
      packages/@uppy/thumbnail-generator/package.json
  79. 9 5
      packages/@uppy/thumbnail-generator/types/index.d.ts
  80. 6 6
      packages/@uppy/transloadit/package.json
  81. 28 24
      packages/@uppy/transloadit/types/index.d.ts
  82. 4 4
      packages/@uppy/tus/package.json
  83. 14 10
      packages/@uppy/tus/types/index.d.ts
  84. 4 4
      packages/@uppy/url/package.json
  85. 2 1
      packages/@uppy/url/src/style.scss
  86. 10 6
      packages/@uppy/url/types/index.d.ts
  87. 1 1
      packages/@uppy/utils/package.json
  88. 2 1
      packages/@uppy/utils/src/getFileType.js
  89. 4 0
      packages/@uppy/utils/src/getFileType.test.js
  90. 4 4
      packages/@uppy/webcam/package.json
  91. 2 1
      packages/@uppy/webcam/src/style.scss
  92. 17 12
      packages/@uppy/webcam/types/index.d.ts
  93. 4 4
      packages/@uppy/xhr-upload/package.json
  94. 18 14
      packages/@uppy/xhr-upload/types/index.d.ts
  95. 4 0
      packages/uppy/bundle.js
  96. 27 23
      packages/uppy/package.json
  97. 3 1
      packages/uppy/types/index.d.ts
  98. 1 0
      test/endtoend/create-react-app/src/App.js
  99. 1 1
      website/src/_posts/2018-10-0.28.md
  100. 91 0
      website/src/_posts/2018-12-0.29.md

+ 35 - 2
CHANGELOG.md

@@ -106,9 +106,9 @@ What we need to do to release Uppy 1.0
 
 
 # next
 # next
 
 
-## 0.29.0
+## 0.30.0
 
 
-- [ ] add polyfils to uppy bundle and a note about that in uppy readme.md
+- [ ] add polyfils to uppy bundle 
 - [ ] dashboard: allow minimizing the Dashboard during upload (Uppy then becomes just a tiny progress indicator) (@arturi)
 - [ ] dashboard: allow minimizing the Dashboard during upload (Uppy then becomes just a tiny progress indicator) (@arturi)
 - [ ] core: customizing metadata fields, boolean metadata; see #809, #454 and related (@arturi)
 - [ ] core: customizing metadata fields, boolean metadata; see #809, #454 and related (@arturi)
 - [ ] goldenretriever: confirmation before restore, add “ghost” files #443 #257 (@arturi)
 - [ ] goldenretriever: confirmation before restore, add “ghost” files #443 #257 (@arturi)
@@ -122,6 +122,39 @@ What we need to do to release Uppy 1.0
 - [ ] server: bump minor and deprecate that on npm in favour of @uppy/companion (@ifedapoolarewaju)
 - [ ] server: bump minor and deprecate that on npm in favour of @uppy/companion (@ifedapoolarewaju)
 - [ ] companion: rename `serverUrl` and `serverPattern` to `companionUrl` and `companionAllowedHosts` (@ifedapoolarewaju)
 - [ ] companion: rename `serverUrl` and `serverPattern` to `companionUrl` and `companionAllowedHosts` (@ifedapoolarewaju)
 
 
+## 0.29.0
+
+| Package | Version | Package | Version |
+|-|-|-|-|
+| @uppy/aws-s3-multipart | 0.29.0 | @uppy/progress-bar | 0.29.0 |
+| @uppy/aws-s3 | 0.29.0 | @uppy/provider-views | 0.29.0 |
+| @uppy/companion | 0.16.0 | @uppy/react | 0.29.0 |
+| @uppy/core | 0.29.0 | @uppy/redux-dev-tools | 0.29.0 |
+| @uppy/dashboard | 0.29.0 | @uppy/status-bar | 0.29.0 |
+| @uppy/drag-drop | 0.29.0 | @uppy/thumbnail-generator | 0.29.0 |
+| @uppy/dropbox | 0.29.0 | @uppy/transloadit | 0.29.0 |
+| @uppy/file-input | 0.29.0 | @uppy/tus | 0.29.0 |
+| @uppy/form | 0.29.0 | @uppy/url | 0.29.0 |
+| @uppy/golden-retriever | 0.29.0 | @uppy/utils | 0.29.0 |
+| @uppy/google-drive | 0.29.0 | @uppy/webcam | 0.29.0 |
+| @uppy/informer | 0.29.0 | @uppy/xhr-upload | 0.29.0 |
+| @uppy/instagram | 0.29.0 | uppy | 0.29.0 |
+
+- @uppy/core: ⚠️ **breaking** Separate Core and Plugin styles — @uppy/core styles and plugins (@uppy/webcam, for example) now have to be included separately (#1167 / @arturi)
+- @uppy/core: Don't pass removed file IDs to next upload step, fixes (#1148 / @goto-bus-stop)
+- @uppy/core: Fixed getFileType() when passed a file with an upper case extension (#1169 / @jderrough)
+- @uppy/xhr-upload: Add `responseType` option — allows configuring the XMLHttpRequest `.responseType` value (#1150 / @goto-bus-stop)
+- @uppy/companion: Use `createCipheriv` instead of deprecated `createCipher` (#1149 / @goto-bus-stop)
+- @uppy/companion: Store Provider instances on `this.provider` instead of `this[this.id]` (@goto-bus-stop / #1174)
+- @uppy/companion: Pin grant to known stable version (@ifedapoolarewaju / #1165)
+- @uppy/companion: Fix — socket does not handle server.path option (#1142 / @tranvansang)
+- @uppy/status-bar: Use file sizes for progress calculations (#1153 / @goto-bus-stop)
+- @uppy/webcam: Fix a bug with Webcam video overflowing its container (68730f8a1bf731898d46883e00fed937d3ab54ab / @arturi)
+- docs: Add `triggerUploadOnSubmit` to Form docs, add docs about options of hiding upload/pause/resume/cancel buttons; talk about bundler-less polyfill use (@goto-bus-stop, @arturi)
+- @uppy/dashboard: Better center pause/resume/cancel icons (@arturi / 5112ecf1f48bec9c67309244120fce5f005241ce)
+- @uppy/react: Allow Dashboard props width and height to accept a string for 100% (#1129 / craigcbrunner)
+- Added note about uppy bundle polyfils in uppy readme.md (@goto-bus-stop)
+
 ## 0.28.0
 ## 0.28.0
 
 
 | Package | Version | Package | Version |
 | Package | Version | Package | Version |

+ 1 - 1
LICENSE

@@ -1,6 +1,6 @@
 The MIT License (MIT)
 The MIT License (MIT)
 
 
-Copyright (c) 2018 Transloadit
+Copyright (c) 2018 Transloadit (https://transloadit.com)
 
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 of this software and associated documentation files (the "Software"), to deal

+ 33 - 29
README.md

@@ -65,7 +65,7 @@ $ npm install @uppy/core @uppy/dashboard @uppy/tus
 
 
 We recommend installing from npm and then using a module bundler such as [Webpack](http://webpack.github.io/), [Browserify](http://browserify.org/) or [Rollup.js](http://rollupjs.org/).
 We recommend installing from npm and then using a module bundler such as [Webpack](http://webpack.github.io/), [Browserify](http://browserify.org/) or [Rollup.js](http://rollupjs.org/).
 
 
-Add CSS [uppy.min.css](https://transloadit.edgly.net/releases/uppy/v0.28.0/dist/uppy.min.css), either to `<head>` of your HTML page or include in JS, if your bundler of choice supports it — transforms and plugins are available for Browserify and Webpack.
+Add CSS [uppy.min.css](https://transloadit.edgly.net/releases/uppy/v0.29.0/dist/uppy.min.css), either to `<head>` of your HTML page or include in JS, if your bundler of choice supports it — transforms and plugins are available for Browserify and Webpack.
 
 
 Alternatively, you can also use a pre-built bundle from Transloadit's CDN: Edgly. In that case `Uppy` will attach itself to the global `window.Uppy` object.
 Alternatively, you can also use a pre-built bundle from Transloadit's CDN: Edgly. In that case `Uppy` will attach itself to the global `window.Uppy` object.
 
 
@@ -73,10 +73,10 @@ Alternatively, you can also use a pre-built bundle from Transloadit's CDN: Edgly
 
 
 ```html
 ```html
 <!-- 1. Add CSS to `<head>` -->
 <!-- 1. Add CSS to `<head>` -->
-<link href="https://transloadit.edgly.net/releases/uppy/v0.28.0/dist/uppy.min.css" rel="stylesheet">
+<link href="https://transloadit.edgly.net/releases/uppy/v0.29.0/dist/uppy.min.css" rel="stylesheet">
 
 
 <!-- 2. Add JS before the closing `</body>` -->
 <!-- 2. Add JS before the closing `</body>` -->
-<script src="https://transloadit.edgly.net/releases/uppy/v0.28.0/dist/uppy.min.js"></script>
+<script src="https://transloadit.edgly.net/releases/uppy/v0.29.0/dist/uppy.min.js"></script>
 
 
 <!-- 3. Initialize -->
 <!-- 3. Initialize -->
 <div class="UppyDragDrop"></div>
 <div class="UppyDragDrop"></div>
@@ -163,7 +163,7 @@ If you're using Uppy via a script tag, you can load the polyfills from [JSDelivr
 ```html
 ```html
 <script src="https://cdn.jsdelivr.net/npm/es6-promise@4.2.5/dist/es6-promise.auto.min.js"></script>
 <script src="https://cdn.jsdelivr.net/npm/es6-promise@4.2.5/dist/es6-promise.auto.min.js"></script>
 <script src="https://cdn.jsdelivr.net/npm/whatwg-fetch@3.0.0/dist/fetch.umd.min.js"></script>
 <script src="https://cdn.jsdelivr.net/npm/whatwg-fetch@3.0.0/dist/fetch.umd.min.js"></script>
-<script src="https://transloadit.edgly.net/releases/uppy/v0.28.0/dist/uppy.min.js"></script>
+<script src="https://transloadit.edgly.net/releases/uppy/v0.29.0/dist/uppy.min.js"></script>
 ```
 ```
 
 
 ## FAQ
 ## FAQ
@@ -228,53 +228,57 @@ Use Uppy in your project? [Let us know](https://github.com/transloadit/uppy/issu
 :---: |:---: |:---: |:---: |:---: |:---: |
 :---: |:---: |:---: |:---: |:---: |:---: |
 [kiloreux](https://github.com/kiloreux) |[sadovnychyi](https://github.com/sadovnychyi) |[richardwillars](https://github.com/richardwillars) |[zcallan](https://github.com/zcallan) |[wilkoklak](https://github.com/wilkoklak) |[oliverpool](https://github.com/oliverpool) |
 [kiloreux](https://github.com/kiloreux) |[sadovnychyi](https://github.com/sadovnychyi) |[richardwillars](https://github.com/richardwillars) |[zcallan](https://github.com/zcallan) |[wilkoklak](https://github.com/wilkoklak) |[oliverpool](https://github.com/oliverpool) |
 
 
-[<img alt="nqst" src="https://avatars0.githubusercontent.com/u/375537?v=4&s=117" width="117">](https://github.com/nqst) |[<img alt="janko-m" src="https://avatars2.githubusercontent.com/u/795488?v=4&s=117" width="117">](https://github.com/janko-m) |[<img alt="DJWassink" src="https://avatars3.githubusercontent.com/u/1822404?v=4&s=117" width="117">](https://github.com/DJWassink) |[<img alt="taoqf" src="https://avatars3.githubusercontent.com/u/15901911?v=4&s=117" width="117">](https://github.com/taoqf) |[<img alt="bertho-zero" src="https://avatars0.githubusercontent.com/u/8525267?v=4&s=117" width="117">](https://github.com/bertho-zero) |[<img alt="frederikhors" src="https://avatars3.githubusercontent.com/u/41120635?v=4&s=117" width="117">](https://github.com/frederikhors) |
+[<img alt="nqst" src="https://avatars0.githubusercontent.com/u/375537?v=4&s=117" width="117">](https://github.com/nqst) |[<img alt="janko-m" src="https://avatars2.githubusercontent.com/u/795488?v=4&s=117" width="117">](https://github.com/janko-m) |[<img alt="DJWassink" src="https://avatars3.githubusercontent.com/u/1822404?v=4&s=117" width="117">](https://github.com/DJWassink) |[<img alt="taoqf" src="https://avatars3.githubusercontent.com/u/15901911?v=4&s=117" width="117">](https://github.com/taoqf) |[<img alt="gavboulton" src="https://avatars0.githubusercontent.com/u/3900826?v=4&s=117" width="117">](https://github.com/gavboulton) |[<img alt="bertho-zero" src="https://avatars0.githubusercontent.com/u/8525267?v=4&s=117" width="117">](https://github.com/bertho-zero) |
 :---: |:---: |:---: |:---: |:---: |:---: |
 :---: |:---: |:---: |:---: |:---: |:---: |
-[nqst](https://github.com/nqst) |[janko-m](https://github.com/janko-m) |[DJWassink](https://github.com/DJWassink) |[taoqf](https://github.com/taoqf) |[bertho-zero](https://github.com/bertho-zero) |[frederikhors](https://github.com/frederikhors) |
+[nqst](https://github.com/nqst) |[janko-m](https://github.com/janko-m) |[DJWassink](https://github.com/DJWassink) |[taoqf](https://github.com/taoqf) |[gavboulton](https://github.com/gavboulton) |[bertho-zero](https://github.com/bertho-zero) |
 
 
-[<img alt="pauln" src="https://avatars3.githubusercontent.com/u/574359?v=4&s=117" width="117">](https://github.com/pauln) |[<img alt="toadkicker" src="https://avatars1.githubusercontent.com/u/523330?v=4&s=117" width="117">](https://github.com/toadkicker) |[<img alt="gavboulton" src="https://avatars0.githubusercontent.com/u/3900826?v=4&s=117" width="117">](https://github.com/gavboulton) |[<img alt="ogtfaber" src="https://avatars2.githubusercontent.com/u/320955?v=4&s=117" width="117">](https://github.com/ogtfaber) |[<img alt="mrbatista" src="https://avatars0.githubusercontent.com/u/6544817?v=4&s=117" width="117">](https://github.com/mrbatista) |[<img alt="sunil-shrestha" src="https://avatars3.githubusercontent.com/u/2129058?v=4&s=117" width="117">](https://github.com/sunil-shrestha) |
+[<img alt="frederikhors" src="https://avatars3.githubusercontent.com/u/41120635?v=4&s=117" width="117">](https://github.com/frederikhors) |[<img alt="pauln" src="https://avatars3.githubusercontent.com/u/574359?v=4&s=117" width="117">](https://github.com/pauln) |[<img alt="toadkicker" src="https://avatars1.githubusercontent.com/u/523330?v=4&s=117" width="117">](https://github.com/toadkicker) |[<img alt="mrbatista" src="https://avatars0.githubusercontent.com/u/6544817?v=4&s=117" width="117">](https://github.com/mrbatista) |[<img alt="phitranphitranphitran" src="https://avatars2.githubusercontent.com/u/14257077?v=4&s=117" width="117">](https://github.com/phitranphitranphitran) |[<img alt="sunil-shrestha" src="https://avatars3.githubusercontent.com/u/2129058?v=4&s=117" width="117">](https://github.com/sunil-shrestha) |
 :---: |:---: |:---: |:---: |:---: |:---: |
 :---: |:---: |:---: |:---: |:---: |:---: |
-[pauln](https://github.com/pauln) |[toadkicker](https://github.com/toadkicker) |[gavboulton](https://github.com/gavboulton) |[ogtfaber](https://github.com/ogtfaber) |[mrbatista](https://github.com/mrbatista) |[sunil-shrestha](https://github.com/sunil-shrestha) |
+[frederikhors](https://github.com/frederikhors) |[pauln](https://github.com/pauln) |[toadkicker](https://github.com/toadkicker) |[mrbatista](https://github.com/mrbatista) |[phitranphitranphitran](https://github.com/phitranphitranphitran) |[sunil-shrestha](https://github.com/sunil-shrestha) |
 
 
-[<img alt="ap--" src="https://avatars1.githubusercontent.com/u/1463443?v=4&s=117" width="117">](https://github.com/ap--) |[<img alt="tim-kos" src="https://avatars1.githubusercontent.com/u/15005?v=4&s=117" width="117">](https://github.com/tim-kos) |[<img alt="phitranphitranphitran" src="https://avatars2.githubusercontent.com/u/14257077?v=4&s=117" width="117">](https://github.com/phitranphitranphitran) |[<img alt="rosenfeld" src="https://avatars1.githubusercontent.com/u/32246?v=4&s=117" width="117">](https://github.com/rosenfeld) |[<img alt="Burkes" src="https://avatars2.githubusercontent.com/u/9220052?v=4&s=117" width="117">](https://github.com/Burkes) |[<img alt="Martin005" src="https://avatars0.githubusercontent.com/u/10096404?v=4&s=117" width="117">](https://github.com/Martin005) |
+[<img alt="tranvansang" src="https://avatars1.githubusercontent.com/u/13043196?v=4&s=117" width="117">](https://github.com/tranvansang) |[<img alt="ap--" src="https://avatars1.githubusercontent.com/u/1463443?v=4&s=117" width="117">](https://github.com/ap--) |[<img alt="tim-kos" src="https://avatars1.githubusercontent.com/u/15005?v=4&s=117" width="117">](https://github.com/tim-kos) |[<img alt="ogtfaber" src="https://avatars2.githubusercontent.com/u/320955?v=4&s=117" width="117">](https://github.com/ogtfaber) |[<img alt="btrice" src="https://avatars2.githubusercontent.com/u/4358225?v=4&s=117" width="117">](https://github.com/btrice) |[<img alt="pekala" src="https://avatars1.githubusercontent.com/u/4643658?v=4&s=117" width="117">](https://github.com/pekala) |
 :---: |:---: |:---: |:---: |:---: |:---: |
 :---: |:---: |:---: |:---: |:---: |:---: |
-[ap--](https://github.com/ap--) |[tim-kos](https://github.com/tim-kos) |[phitranphitranphitran](https://github.com/phitranphitranphitran) |[rosenfeld](https://github.com/rosenfeld) |[Burkes](https://github.com/Burkes) |[Martin005](https://github.com/Martin005) |
+[tranvansang](https://github.com/tranvansang) |[ap--](https://github.com/ap--) |[tim-kos](https://github.com/tim-kos) |[ogtfaber](https://github.com/ogtfaber) |[btrice](https://github.com/btrice) |[pekala](https://github.com/pekala) |
 
 
-[<img alt="btrice" src="https://avatars2.githubusercontent.com/u/4358225?v=4&s=117" width="117">](https://github.com/btrice) |[<img alt="richartkeil" src="https://avatars0.githubusercontent.com/u/8680858?v=4&s=117" width="117">](https://github.com/richartkeil) |[<img alt="richmeij" src="https://avatars0.githubusercontent.com/u/9741858?v=4&s=117" width="117">](https://github.com/richmeij) |[<img alt="pekala" src="https://avatars1.githubusercontent.com/u/4643658?v=4&s=117" width="117">](https://github.com/pekala) |[<img alt="ThomasG77" src="https://avatars2.githubusercontent.com/u/642120?v=4&s=117" width="117">](https://github.com/ThomasG77) |[<img alt="zhuangya" src="https://avatars2.githubusercontent.com/u/499038?v=4&s=117" width="117">](https://github.com/zhuangya) |
+[<img alt="Martin005" src="https://avatars0.githubusercontent.com/u/10096404?v=4&s=117" width="117">](https://github.com/Martin005) |[<img alt="martiuslim" src="https://avatars2.githubusercontent.com/u/17944339?v=4&s=117" width="117">](https://github.com/martiuslim) |[<img alt="msand" src="https://avatars2.githubusercontent.com/u/1131362?v=4&s=117" width="117">](https://github.com/msand) |[<img alt="richartkeil" src="https://avatars0.githubusercontent.com/u/8680858?v=4&s=117" width="117">](https://github.com/richartkeil) |[<img alt="Burkes" src="https://avatars2.githubusercontent.com/u/9220052?v=4&s=117" width="117">](https://github.com/Burkes) |[<img alt="rosenfeld" src="https://avatars1.githubusercontent.com/u/32246?v=4&s=117" width="117">](https://github.com/rosenfeld) |
 :---: |:---: |:---: |:---: |:---: |:---: |
 :---: |:---: |:---: |:---: |:---: |:---: |
-[btrice](https://github.com/btrice) |[richartkeil](https://github.com/richartkeil) |[richmeij](https://github.com/richmeij) |[pekala](https://github.com/pekala) |[ThomasG77](https://github.com/ThomasG77) |[zhuangya](https://github.com/zhuangya) |
+[Martin005](https://github.com/Martin005) |[martiuslim](https://github.com/martiuslim) |[msand](https://github.com/msand) |[richartkeil](https://github.com/richartkeil) |[Burkes](https://github.com/Burkes) |[rosenfeld](https://github.com/rosenfeld) |
 
 
-[<img alt="fortrieb" src="https://avatars0.githubusercontent.com/u/4126707?v=4&s=117" width="117">](https://github.com/fortrieb) |[<img alt="muhammadInam" src="https://avatars1.githubusercontent.com/u/7801708?v=4&s=117" width="117">](https://github.com/muhammadInam) |[<img alt="martiuslim" src="https://avatars2.githubusercontent.com/u/17944339?v=4&s=117" width="117">](https://github.com/martiuslim) |[<img alt="ajschmidt8" src="https://avatars0.githubusercontent.com/u/7400326?v=4&s=117" width="117">](https://github.com/ajschmidt8) |[<img alt="asmt3" src="https://avatars1.githubusercontent.com/u/1777709?v=4&s=117" width="117">](https://github.com/asmt3) |[<img alt="tuoxiansp" src="https://avatars1.githubusercontent.com/u/3960056?v=4&s=117" width="117">](https://github.com/tuoxiansp) |
+[<img alt="ThomasG77" src="https://avatars2.githubusercontent.com/u/642120?v=4&s=117" width="117">](https://github.com/ThomasG77) |[<img alt="zhuangya" src="https://avatars2.githubusercontent.com/u/499038?v=4&s=117" width="117">](https://github.com/zhuangya) |[<img alt="fortrieb" src="https://avatars0.githubusercontent.com/u/4126707?v=4&s=117" width="117">](https://github.com/fortrieb) |[<img alt="muhammadInam" src="https://avatars1.githubusercontent.com/u/7801708?v=4&s=117" width="117">](https://github.com/muhammadInam) |[<img alt="richmeij" src="https://avatars0.githubusercontent.com/u/9741858?v=4&s=117" width="117">](https://github.com/richmeij) |[<img alt="ajschmidt8" src="https://avatars0.githubusercontent.com/u/7400326?v=4&s=117" width="117">](https://github.com/ajschmidt8) |
 :---: |:---: |:---: |:---: |:---: |:---: |
 :---: |:---: |:---: |:---: |:---: |:---: |
-[fortrieb](https://github.com/fortrieb) |[muhammadInam](https://github.com/muhammadInam) |[martiuslim](https://github.com/martiuslim) |[ajschmidt8](https://github.com/ajschmidt8) |[asmt3](https://github.com/asmt3) |[tuoxiansp](https://github.com/tuoxiansp) |
+[ThomasG77](https://github.com/ThomasG77) |[zhuangya](https://github.com/zhuangya) |[fortrieb](https://github.com/fortrieb) |[muhammadInam](https://github.com/muhammadInam) |[richmeij](https://github.com/richmeij) |[ajschmidt8](https://github.com/ajschmidt8) |
 
 
-[<img alt="functino" src="https://avatars0.githubusercontent.com/u/415498?v=4&s=117" width="117">](https://github.com/functino) |[<img alt="radarhere" src="https://avatars2.githubusercontent.com/u/3112309?v=4&s=117" width="117">](https://github.com/radarhere) |[<img alt="azeemba" src="https://avatars0.githubusercontent.com/u/2160795?v=4&s=117" width="117">](https://github.com/azeemba) |[<img alt="bducharme" src="https://avatars2.githubusercontent.com/u/4173569?v=4&s=117" width="117">](https://github.com/bducharme) |[<img alt="chao" src="https://avatars2.githubusercontent.com/u/55872?v=4&s=117" width="117">](https://github.com/chao) |[<img alt="csprance" src="https://avatars0.githubusercontent.com/u/7902617?v=4&s=117" width="117">](https://github.com/csprance) |
+[<img alt="asmt3" src="https://avatars1.githubusercontent.com/u/1777709?v=4&s=117" width="117">](https://github.com/asmt3) |[<img alt="tuoxiansp" src="https://avatars1.githubusercontent.com/u/3960056?v=4&s=117" width="117">](https://github.com/tuoxiansp) |[<img alt="functino" src="https://avatars0.githubusercontent.com/u/415498?v=4&s=117" width="117">](https://github.com/functino) |[<img alt="radarhere" src="https://avatars2.githubusercontent.com/u/3112309?v=4&s=117" width="117">](https://github.com/radarhere) |[<img alt="azeemba" src="https://avatars0.githubusercontent.com/u/2160795?v=4&s=117" width="117">](https://github.com/azeemba) |[<img alt="bducharme" src="https://avatars2.githubusercontent.com/u/4173569?v=4&s=117" width="117">](https://github.com/bducharme) |
 :---: |:---: |:---: |:---: |:---: |:---: |
 :---: |:---: |:---: |:---: |:---: |:---: |
-[functino](https://github.com/functino) |[radarhere](https://github.com/radarhere) |[azeemba](https://github.com/azeemba) |[bducharme](https://github.com/bducharme) |[chao](https://github.com/chao) |[csprance](https://github.com/csprance) |
+[asmt3](https://github.com/asmt3) |[tuoxiansp](https://github.com/tuoxiansp) |[functino](https://github.com/functino) |[radarhere](https://github.com/radarhere) |[azeemba](https://github.com/azeemba) |[bducharme](https://github.com/bducharme) |
 
 
-[<img alt="cbush06" src="https://avatars0.githubusercontent.com/u/15720146?v=4&s=117" width="117">](https://github.com/cbush06) |[<img alt="danmichaelo" src="https://avatars1.githubusercontent.com/u/434495?v=4&s=117" width="117">](https://github.com/danmichaelo) |[<img alt="mrboomer" src="https://avatars0.githubusercontent.com/u/5942912?v=4&s=117" width="117">](https://github.com/mrboomer) |[<img alt="yoldar" src="https://avatars3.githubusercontent.com/u/1597578?v=4&s=117" width="117">](https://github.com/yoldar) |[<img alt="lowsprofile" src="https://avatars1.githubusercontent.com/u/11029687?v=4&s=117" width="117">](https://github.com/lowsprofile) |[<img alt="FWirtz" src="https://avatars1.githubusercontent.com/u/6052785?v=4&s=117" width="117">](https://github.com/FWirtz) |
+[<img alt="chao" src="https://avatars2.githubusercontent.com/u/55872?v=4&s=117" width="117">](https://github.com/chao) |[<img alt="csprance" src="https://avatars0.githubusercontent.com/u/7902617?v=4&s=117" width="117">](https://github.com/csprance) |[<img alt="cbush06" src="https://avatars0.githubusercontent.com/u/15720146?v=4&s=117" width="117">](https://github.com/cbush06) |[<img alt="danmichaelo" src="https://avatars1.githubusercontent.com/u/434495?v=4&s=117" width="117">](https://github.com/danmichaelo) |[<img alt="mrboomer" src="https://avatars0.githubusercontent.com/u/5942912?v=4&s=117" width="117">](https://github.com/mrboomer) |[<img alt="yoldar" src="https://avatars3.githubusercontent.com/u/1597578?v=4&s=117" width="117">](https://github.com/yoldar) |
 :---: |:---: |:---: |:---: |:---: |:---: |
 :---: |:---: |:---: |:---: |:---: |:---: |
-[cbush06](https://github.com/cbush06) |[danmichaelo](https://github.com/danmichaelo) |[mrboomer](https://github.com/mrboomer) |[yoldar](https://github.com/yoldar) |[lowsprofile](https://github.com/lowsprofile) |[FWirtz](https://github.com/FWirtz) |
+[chao](https://github.com/chao) |[csprance](https://github.com/csprance) |[cbush06](https://github.com/cbush06) |[danmichaelo](https://github.com/danmichaelo) |[mrboomer](https://github.com/mrboomer) |[yoldar](https://github.com/yoldar) |
 
 
-[<img alt="geoffappleford" src="https://avatars2.githubusercontent.com/u/731678?v=4&s=117" width="117">](https://github.com/geoffappleford) |[<img alt="gjungb" src="https://avatars0.githubusercontent.com/u/3391068?v=4&s=117" width="117">](https://github.com/gjungb) |[<img alt="JacobMGEvans" src="https://avatars1.githubusercontent.com/u/27247160?v=4&s=117" width="117">](https://github.com/JacobMGEvans) |[<img alt="jcjmcclean" src="https://avatars3.githubusercontent.com/u/1822574?v=4&s=117" width="117">](https://github.com/jcjmcclean) |[<img alt="vith" src="https://avatars1.githubusercontent.com/u/3265539?v=4&s=117" width="117">](https://github.com/vith) |[<img alt="jessica-coursera" src="https://avatars1.githubusercontent.com/u/35155465?v=4&s=117" width="117">](https://github.com/jessica-coursera) |
+[<img alt="lowsprofile" src="https://avatars1.githubusercontent.com/u/11029687?v=4&s=117" width="117">](https://github.com/lowsprofile) |[<img alt="FWirtz" src="https://avatars1.githubusercontent.com/u/6052785?v=4&s=117" width="117">](https://github.com/FWirtz) |[<img alt="geoffappleford" src="https://avatars2.githubusercontent.com/u/731678?v=4&s=117" width="117">](https://github.com/geoffappleford) |[<img alt="gjungb" src="https://avatars0.githubusercontent.com/u/3391068?v=4&s=117" width="117">](https://github.com/gjungb) |[<img alt="JacobMGEvans" src="https://avatars1.githubusercontent.com/u/27247160?v=4&s=117" width="117">](https://github.com/JacobMGEvans) |[<img alt="jcjmcclean" src="https://avatars3.githubusercontent.com/u/1822574?v=4&s=117" width="117">](https://github.com/jcjmcclean) |
 :---: |:---: |:---: |:---: |:---: |:---: |
 :---: |:---: |:---: |:---: |:---: |:---: |
-[geoffappleford](https://github.com/geoffappleford) |[gjungb](https://github.com/gjungb) |[JacobMGEvans](https://github.com/JacobMGEvans) |[jcjmcclean](https://github.com/jcjmcclean) |[vith](https://github.com/vith) |[jessica-coursera](https://github.com/jessica-coursera) |
+[lowsprofile](https://github.com/lowsprofile) |[FWirtz](https://github.com/FWirtz) |[geoffappleford](https://github.com/geoffappleford) |[gjungb](https://github.com/gjungb) |[JacobMGEvans](https://github.com/JacobMGEvans) |[jcjmcclean](https://github.com/jcjmcclean) |
 
 
-[<img alt="firesharkstudios" src="https://avatars1.githubusercontent.com/u/17069637?v=4&s=117" width="117">](https://github.com/firesharkstudios) |[<img alt="dviry" src="https://avatars3.githubusercontent.com/u/1230260?v=4&s=117" width="117">](https://github.com/dviry) |[<img alt="leods92" src="https://avatars0.githubusercontent.com/u/879395?v=4&s=117" width="117">](https://github.com/leods92) |[<img alt="lucaperret" src="https://avatars1.githubusercontent.com/u/1887122?v=4&s=117" width="117">](https://github.com/lucaperret) |[<img alt="mperrando" src="https://avatars2.githubusercontent.com/u/525572?v=4&s=117" width="117">](https://github.com/mperrando) |[<img alt="mnafees" src="https://avatars1.githubusercontent.com/u/1763885?v=4&s=117" width="117">](https://github.com/mnafees) |
+[<img alt="vith" src="https://avatars1.githubusercontent.com/u/3265539?v=4&s=117" width="117">](https://github.com/vith) |[<img alt="jessica-coursera" src="https://avatars1.githubusercontent.com/u/35155465?v=4&s=117" width="117">](https://github.com/jessica-coursera) |[<img alt="jderrough" src="https://avatars3.githubusercontent.com/u/1108358?v=4&s=117" width="117">](https://github.com/jderrough) |[<img alt="firesharkstudios" src="https://avatars1.githubusercontent.com/u/17069637?v=4&s=117" width="117">](https://github.com/firesharkstudios) |[<img alt="dviry" src="https://avatars3.githubusercontent.com/u/1230260?v=4&s=117" width="117">](https://github.com/dviry) |[<img alt="leods92" src="https://avatars0.githubusercontent.com/u/879395?v=4&s=117" width="117">](https://github.com/leods92) |
 :---: |:---: |:---: |:---: |:---: |:---: |
 :---: |:---: |:---: |:---: |:---: |:---: |
-[firesharkstudios](https://github.com/firesharkstudios) |[dviry](https://github.com/dviry) |[leods92](https://github.com/leods92) |[lucaperret](https://github.com/lucaperret) |[mperrando](https://github.com/mperrando) |[mnafees](https://github.com/mnafees) |
+[vith](https://github.com/vith) |[jessica-coursera](https://github.com/jessica-coursera) |[jderrough](https://github.com/jderrough) |[firesharkstudios](https://github.com/firesharkstudios) |[dviry](https://github.com/dviry) |[leods92](https://github.com/leods92) |
 
 
-[<img alt="phillipalexander" src="https://avatars0.githubusercontent.com/u/1577682?v=4&s=117" width="117">](https://github.com/phillipalexander) |[<img alt="luarmr" src="https://avatars3.githubusercontent.com/u/817416?v=4&s=117" width="117">](https://github.com/luarmr) |[<img alt="phobos101" src="https://avatars2.githubusercontent.com/u/7114944?v=4&s=117" width="117">](https://github.com/phobos101) |[<img alt="fortunto2" src="https://avatars1.githubusercontent.com/u/1236751?v=4&s=117" width="117">](https://github.com/fortunto2) |[<img alt="sergei-zelinsky" src="https://avatars2.githubusercontent.com/u/19428086?v=4&s=117" width="117">](https://github.com/sergei-zelinsky) |[<img alt="tomsaleeba" src="https://avatars0.githubusercontent.com/u/1773838?v=4&s=117" width="117">](https://github.com/tomsaleeba) |
+[<img alt="lucaperret" src="https://avatars1.githubusercontent.com/u/1887122?v=4&s=117" width="117">](https://github.com/lucaperret) |[<img alt="mperrando" src="https://avatars2.githubusercontent.com/u/525572?v=4&s=117" width="117">](https://github.com/mperrando) |[<img alt="mnafees" src="https://avatars1.githubusercontent.com/u/1763885?v=4&s=117" width="117">](https://github.com/mnafees) |[<img alt="phillipalexander" src="https://avatars0.githubusercontent.com/u/1577682?v=4&s=117" width="117">](https://github.com/phillipalexander) |[<img alt="luarmr" src="https://avatars3.githubusercontent.com/u/817416?v=4&s=117" width="117">](https://github.com/luarmr) |[<img alt="phobos101" src="https://avatars2.githubusercontent.com/u/7114944?v=4&s=117" width="117">](https://github.com/phobos101) |
 :---: |:---: |:---: |:---: |:---: |:---: |
 :---: |:---: |:---: |:---: |:---: |:---: |
-[phillipalexander](https://github.com/phillipalexander) |[luarmr](https://github.com/luarmr) |[phobos101](https://github.com/phobos101) |[fortunto2](https://github.com/fortunto2) |[sergei-zelinsky](https://github.com/sergei-zelinsky) |[tomsaleeba](https://github.com/tomsaleeba) |
+[lucaperret](https://github.com/lucaperret) |[mperrando](https://github.com/mperrando) |[mnafees](https://github.com/mnafees) |[phillipalexander](https://github.com/phillipalexander) |[luarmr](https://github.com/luarmr) |[phobos101](https://github.com/phobos101) |
 
 
-[<img alt="tranvansang" src="https://avatars1.githubusercontent.com/u/13043196?v=4&s=117" width="117">](https://github.com/tranvansang) |[<img alt="vially" src="https://avatars1.githubusercontent.com/u/433598?v=4&s=117" width="117">](https://github.com/vially) |[<img alt="eltercero" src="https://avatars0.githubusercontent.com/u/545235?v=4&s=117" width="117">](https://github.com/eltercero) |[<img alt="xhocquet" src="https://avatars2.githubusercontent.com/u/8116516?v=4&s=117" width="117">](https://github.com/xhocquet) |[<img alt="avalla" src="https://avatars1.githubusercontent.com/u/986614?v=4&s=117" width="117">](https://github.com/avalla) |[<img alt="bartvde" src="https://avatars3.githubusercontent.com/u/319678?v=4&s=117" width="117">](https://github.com/bartvde) |
+[<img alt="fortunto2" src="https://avatars1.githubusercontent.com/u/1236751?v=4&s=117" width="117">](https://github.com/fortunto2) |[<img alt="sergei-zelinsky" src="https://avatars2.githubusercontent.com/u/19428086?v=4&s=117" width="117">](https://github.com/sergei-zelinsky) |[<img alt="tomsaleeba" src="https://avatars0.githubusercontent.com/u/1773838?v=4&s=117" width="117">](https://github.com/tomsaleeba) |[<img alt="vially" src="https://avatars1.githubusercontent.com/u/433598?v=4&s=117" width="117">](https://github.com/vially) |[<img alt="eltercero" src="https://avatars0.githubusercontent.com/u/545235?v=4&s=117" width="117">](https://github.com/eltercero) |[<img alt="xhocquet" src="https://avatars2.githubusercontent.com/u/8116516?v=4&s=117" width="117">](https://github.com/xhocquet) |
 :---: |:---: |:---: |:---: |:---: |:---: |
 :---: |:---: |:---: |:---: |:---: |:---: |
-[tranvansang](https://github.com/tranvansang) |[vially](https://github.com/vially) |[eltercero](https://github.com/eltercero) |[xhocquet](https://github.com/xhocquet) |[avalla](https://github.com/avalla) |[bartvde](https://github.com/bartvde) |
+[fortunto2](https://github.com/fortunto2) |[sergei-zelinsky](https://github.com/sergei-zelinsky) |[tomsaleeba](https://github.com/tomsaleeba) |[vially](https://github.com/vially) |[eltercero](https://github.com/eltercero) |[xhocquet](https://github.com/xhocquet) |
 
 
-[<img alt="c0b41" src="https://avatars1.githubusercontent.com/u/2834954?v=4&s=117" width="117">](https://github.com/c0b41) |[<img alt="franckl" src="https://avatars0.githubusercontent.com/u/3875803?v=4&s=117" width="117">](https://github.com/franckl) |[<img alt="luntta" src="https://avatars0.githubusercontent.com/u/14221637?v=4&s=117" width="117">](https://github.com/luntta) |[<img alt="rhymes" src="https://avatars3.githubusercontent.com/u/146201?v=4&s=117" width="117">](https://github.com/rhymes) |[<img alt="amitport" src="https://avatars1.githubusercontent.com/u/1131991?v=4&s=117" width="117">](https://github.com/amitport) |
-:---: |:---: |:---: |:---: |:---: |
-[c0b41](https://github.com/c0b41) |[franckl](https://github.com/franckl) |[luntta](https://github.com/luntta) |[rhymes](https://github.com/rhymes) |[amitport](https://github.com/amitport) |
+[<img alt="avalla" src="https://avatars1.githubusercontent.com/u/986614?v=4&s=117" width="117">](https://github.com/avalla) |[<img alt="bartvde" src="https://avatars3.githubusercontent.com/u/319678?v=4&s=117" width="117">](https://github.com/bartvde) |[<img alt="c0b41" src="https://avatars1.githubusercontent.com/u/2834954?v=4&s=117" width="117">](https://github.com/c0b41) |[<img alt="craigcbrunner" src="https://avatars3.githubusercontent.com/u/2780521?v=4&s=117" width="117">](https://github.com/craigcbrunner) |[<img alt="franckl" src="https://avatars0.githubusercontent.com/u/3875803?v=4&s=117" width="117">](https://github.com/franckl) |[<img alt="luntta" src="https://avatars0.githubusercontent.com/u/14221637?v=4&s=117" width="117">](https://github.com/luntta) |
+:---: |:---: |:---: |:---: |:---: |:---: |
+[avalla](https://github.com/avalla) |[bartvde](https://github.com/bartvde) |[c0b41](https://github.com/c0b41) |[craigcbrunner](https://github.com/craigcbrunner) |[franckl](https://github.com/franckl) |[luntta](https://github.com/luntta) |
+
+[<img alt="rhymes" src="https://avatars3.githubusercontent.com/u/146201?v=4&s=117" width="117">](https://github.com/rhymes) |[<img alt="amitport" src="https://avatars1.githubusercontent.com/u/1131991?v=4&s=117" width="117">](https://github.com/amitport) |
+:---: |:---: |
+[rhymes](https://github.com/rhymes) |[amitport](https://github.com/amitport) |
 <!--/contributors-->
 <!--/contributors-->
 
 
 ## License
 ## License

+ 1 - 1
bin/build-js.js

@@ -15,7 +15,7 @@ function handleErr (err) {
 }
 }
 
 
 function buildUppyBundle (minify) {
 function buildUppyBundle (minify) {
-  var src = path.join(srcPath, 'index.js')
+  var src = path.join(srcPath, 'bundle.js')
   var bundleFile = minify ? 'uppy.min.js' : 'uppy.js'
   var bundleFile = minify ? 'uppy.min.js' : 'uppy.js'
 
 
   var b = browserify(src, { debug: true, standalone: 'Uppy' })
   var b = browserify(src, { debug: true, standalone: 'Uppy' })

+ 1 - 1
bin/release

@@ -37,7 +37,7 @@ if ! which jq; then
   exit 1
   exit 1
 fi
 fi
 
 
-perm="$(npm profile get --json | jq .tfa.mode -r)"
+perm="$(npm profile get --json | jq .tfa.mode? -r)"
 if [ "$perm" == "auth-and-writes" ]; then
 if [ "$perm" == "auth-and-writes" ]; then
   echo "Two-factor auth is enabled for publishing. This doesn't work well with lerna."
   echo "Two-factor auth is enabled for publishing. This doesn't work well with lerna."
   echo "Temporarily switch to authentication-only 2FA using the link below:"
   echo "Temporarily switch to authentication-only 2FA using the link below:"

+ 1 - 1
bin/upload-to-cdn.sh

@@ -8,7 +8,7 @@
 #  - Checks if a tag is being built (on Travis - otherwise opts to continue execution regardless)
 #  - Checks if a tag is being built (on Travis - otherwise opts to continue execution regardless)
 #  - Installs AWS CLI if needed
 #  - Installs AWS CLI if needed
 #  - Assumed a fully built uppy is in root dir (unless a specific tag was specified, then it's fetched from npm)
 #  - Assumed a fully built uppy is in root dir (unless a specific tag was specified, then it's fetched from npm)
-#  - Runs npm pack, and stores files to e.g. https://transloadit.edgly.net/releases/uppy/v0.28.0/dist/uppy.css
+#  - Runs npm pack, and stores files to e.g. https://transloadit.edgly.net/releases/uppy/v0.29.0/dist/uppy.css
 #  - Uses local package by default, if [version] argument was specified, takes package from npm
 #  - Uses local package by default, if [version] argument was specified, takes package from npm
 #
 #
 # Run as:
 # Run as:

+ 2 - 2
examples/cdn-example/index.html

@@ -4,11 +4,11 @@
     <title></title>
     <title></title>
     <meta charset="UTF-8">
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1">
     <meta name="viewport" content="width=device-width, initial-scale=1">
-    <link href="https://transloadit.edgly.net/releases/uppy/v0.28.0/dist/uppy.min.css" rel="stylesheet">
+    <link href="https://transloadit.edgly.net/releases/uppy/v0.29.0/dist/uppy.min.css" rel="stylesheet">
   </head>
   </head>
   <body>
   <body>
     <button id="uppyModalOpener">Open Modal</button>
     <button id="uppyModalOpener">Open Modal</button>
-    <script src="https://transloadit.edgly.net/releases/uppy/v0.28.0/dist/uppy.min.js"></script>
+    <script src="https://transloadit.edgly.net/releases/uppy/v0.29.0/dist/uppy.min.js"></script>
     <script>
     <script>
       const uppy = Uppy.Core({debug: true, autoProceed: false})
       const uppy = Uppy.Core({debug: true, autoProceed: false})
         .use(Uppy.Dashboard, { trigger: '#uppyModalOpener' })
         .use(Uppy.Dashboard, { trigger: '#uppyModalOpener' })

+ 2 - 2
examples/uppy-with-companion/client/index.html

@@ -4,11 +4,11 @@
     <title></title>
     <title></title>
     <meta charset="UTF-8">
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1">
     <meta name="viewport" content="width=device-width, initial-scale=1">
-    <link href="https://transloadit.edgly.net/releases/uppy/v0.28.0/dist/uppy.min.css" rel="stylesheet">
+    <link href="https://transloadit.edgly.net/releases/uppy/v0.29.0/dist/uppy.min.css" rel="stylesheet">
   </head>
   </head>
   <body>
   <body>
     <button id="uppyModalOpener">Open Modal</button>
     <button id="uppyModalOpener">Open Modal</button>
-    <script src="https://transloadit.edgly.net/releases/uppy/v0.28.0/dist/uppy.min.js"></script>
+    <script src="https://transloadit.edgly.net/releases/uppy/v0.29.0/dist/uppy.min.js"></script>
     <script>
     <script>
       const uppy = Uppy.Core({debug: true, autoProceed: false})
       const uppy = Uppy.Core({debug: true, autoProceed: false})
         .use(Uppy.Dashboard, { trigger: '#uppyModalOpener' })
         .use(Uppy.Dashboard, { trigger: '#uppyModalOpener' })

Dosya farkı çok büyük olduğundan ihmal edildi
+ 146 - 124
package-lock.json


+ 1 - 1
package.json

@@ -9,6 +9,7 @@
   "pre-commit": "lint-staged",
   "pre-commit": "lint-staged",
   "license": "MIT",
   "license": "MIT",
   "devDependencies": {
   "devDependencies": {
+    "@types/react": "^16.4.18",
     "aliasify": "^2.1.0",
     "aliasify": "^2.1.0",
     "autoprefixer": "^7.2.6",
     "autoprefixer": "^7.2.6",
     "babel-cli": "^6.26.0",
     "babel-cli": "^6.26.0",
@@ -31,7 +32,6 @@
     "disc": "^1.3.3",
     "disc": "^1.3.3",
     "enzyme": "^3.7.0",
     "enzyme": "^3.7.0",
     "enzyme-adapter-react-16": "^1.6.0",
     "enzyme-adapter-react-16": "^1.6.0",
-    "es6-promise": "^4.2.5",
     "eslint": "^3.19.0",
     "eslint": "^3.19.0",
     "eslint-config-standard": "^10.2.1",
     "eslint-config-standard": "^10.2.1",
     "eslint-config-standard-preact": "^1.1.6",
     "eslint-config-standard-preact": "^1.1.6",

+ 4 - 4
packages/@uppy/aws-s3-multipart/package.json

@@ -1,7 +1,7 @@
 {
 {
   "name": "@uppy/aws-s3-multipart",
   "name": "@uppy/aws-s3-multipart",
   "description": "Upload to Amazon S3 with Uppy and S3's Multipart upload strategy",
   "description": "Upload to Amazon S3 with Uppy and S3's Multipart upload strategy",
-  "version": "0.28.0",
+  "version": "0.29.0",
   "license": "MIT",
   "license": "MIT",
   "main": "lib/index.js",
   "main": "lib/index.js",
   "jsnext:main": "src/index.js",
   "jsnext:main": "src/index.js",
@@ -25,13 +25,13 @@
   },
   },
   "dependencies": {
   "dependencies": {
     "@uppy/companion-client": "0.27.2",
     "@uppy/companion-client": "0.27.2",
-    "@uppy/utils": "0.28.0",
+    "@uppy/utils": "0.29.0",
     "resolve-url": "^0.2.1"
     "resolve-url": "^0.2.1"
   },
   },
   "devDependencies": {
   "devDependencies": {
-    "@uppy/core": "0.28.0"
+    "@uppy/core": "0.29.0"
   },
   },
   "peerDependencies": {
   "peerDependencies": {
-    "@uppy/core": "^0.27.0"
+    "@uppy/core": "^0.29.0"
   }
   }
 }
 }

+ 21 - 17
packages/@uppy/aws-s3-multipart/types/index.d.ts

@@ -1,28 +1,32 @@
 import { Plugin, PluginOptions, Uppy, UppyFile } from '@uppy/core';
 import { Plugin, PluginOptions, Uppy, UppyFile } from '@uppy/core';
 
 
-export interface AwsS3Part {
-  PartNumber: number;
-  Size: number;
-  ETag: string;
-}
+declare module AwsS3Multipart {
+  interface AwsS3Part {
+    PartNumber?: number;
+    Size?: number;
+    ETag?: string;
+  }
 
 
-export interface AwsS3MultipartOptions extends PluginOptions {
-  serverUrl: string;
-  createMultipartUpload(file: UppyFile): Promise<{uploadId: string, key: string}>;
-  listParts(file: UppyFile, opts: {uploadId: string, key: string}): Promise<AwsS3Part>;
-  prepareUploadPart(file: UppyFile, partData: {uploadId: string, key: string, body: Blob, number: number}): Promise<{url: string}>;
-  abortMultipartUpload(file: UppyFile, opts: {uploadId: string, key: string}): Promise<void>;
-  completeMultipartUpload(file: UppyFile, opts: {uploadId: string, key: string, parts: AwsS3Part[]}): Promise<{location?: string}>;
-  timeout: number;
-  limit: number;
+  interface AwsS3MultipartOptions extends PluginOptions {
+    serverUrl: string;
+    createMultipartUpload(file: UppyFile): Promise<{ uploadId: string, key: string }>;
+    listParts(file: UppyFile, opts: { uploadId: string, key: string }): Promise<AwsS3Part[]>;
+    prepareUploadPart(file: UppyFile, partData: { uploadId: string, key: string, body: Blob, number: number }): Promise<{ url: string }>;
+    abortMultipartUpload(file: UppyFile, opts: { uploadId: string, key: string }): Promise<void>;
+    completeMultipartUpload(file: UppyFile, opts: { uploadId: string, key: string, parts: AwsS3Part[] }): Promise<{ location?: string }>;
+    timeout: number;
+    limit: number;
+  }
 }
 }
 
 
-export default class AwsS3Multipart extends Plugin {
-  constructor(uppy: Uppy, opts: Partial<AwsS3MultipartOptions>);
+declare class AwsS3Multipart extends Plugin {
+  constructor(uppy: Uppy, opts: Partial<AwsS3Multipart.AwsS3MultipartOptions>);
 }
 }
 
 
+export = AwsS3Multipart;
+
 declare module '@uppy/core' {
 declare module '@uppy/core' {
   export interface Uppy {
   export interface Uppy {
-    use(pluginClass: typeof AwsS3Multipart, opts: Partial<AwsS3MultipartOptions>): Uppy;
+    use(pluginClass: typeof AwsS3Multipart, opts: Partial<AwsS3Multipart.AwsS3MultipartOptions>): Uppy;
   }
   }
 }
 }

+ 5 - 5
packages/@uppy/aws-s3/package.json

@@ -1,7 +1,7 @@
 {
 {
   "name": "@uppy/aws-s3",
   "name": "@uppy/aws-s3",
   "description": "Upload to Amazon S3 with Uppy",
   "description": "Upload to Amazon S3 with Uppy",
-  "version": "0.28.0",
+  "version": "0.29.0",
   "license": "MIT",
   "license": "MIT",
   "main": "lib/index.js",
   "main": "lib/index.js",
   "jsnext:main": "src/index.js",
   "jsnext:main": "src/index.js",
@@ -24,14 +24,14 @@
   },
   },
   "dependencies": {
   "dependencies": {
     "@uppy/companion-client": "0.27.2",
     "@uppy/companion-client": "0.27.2",
-    "@uppy/utils": "0.28.0",
-    "@uppy/xhr-upload": "0.28.0",
+    "@uppy/utils": "0.29.0",
+    "@uppy/xhr-upload": "0.29.0",
     "resolve-url": "^0.2.1"
     "resolve-url": "^0.2.1"
   },
   },
   "devDependencies": {
   "devDependencies": {
-    "@uppy/core": "0.28.0"
+    "@uppy/core": "0.29.0"
   },
   },
   "peerDependencies": {
   "peerDependencies": {
-    "@uppy/core": "^0.28.0"
+    "@uppy/core": "^0.29.0"
   }
   }
 }
 }

+ 18 - 14
packages/@uppy/aws-s3/types/index.d.ts

@@ -1,25 +1,29 @@
 import { Plugin, PluginOptions, Uppy, UppyFile } from '@uppy/core';
 import { Plugin, PluginOptions, Uppy, UppyFile } from '@uppy/core';
 
 
-export interface AwsS3UploadParameters {
-  method?: string;
-  url: string;
-  fields?: { [type: string]: string };
-  headers?: { [type: string]: string };
-}
+declare module AwsS3 {
+  interface AwsS3UploadParameters {
+    method?: string;
+    url: string;
+    fields?: { [type: string]: string };
+    headers?: { [type: string]: string };
+  }
 
 
-export interface AwsS3Options extends PluginOptions {
-  serverUrl: string;
-  getUploadParameters(file: UppyFile): Promise<AwsS3UploadParameters>;
-  timeout: number;
-  limit: number;
+  interface AwsS3Options extends PluginOptions {
+    serverUrl: string;
+    getUploadParameters(file: UppyFile): Promise<AwsS3UploadParameters>;
+    timeout: number;
+    limit: number;
+  }
 }
 }
 
 
-export default class AwsS3 extends Plugin {
-  constructor(uppy: Uppy, opts: Partial<AwsS3Options>);
+declare class AwsS3 extends Plugin {
+  constructor(uppy: Uppy, opts: Partial<AwsS3.AwsS3Options>);
 }
 }
 
 
+export = AwsS3;
+
 declare module '@uppy/core' {
 declare module '@uppy/core' {
   export interface Uppy {
   export interface Uppy {
-    use(pluginClass: typeof AwsS3, opts: Partial<AwsS3Options>): Uppy;
+    use(pluginClass: typeof AwsS3, opts: Partial<AwsS3.AwsS3Options>): Uppy;
   }
   }
 }
 }

+ 1 - 1
packages/@uppy/companion/package.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "@uppy/companion",
   "name": "@uppy/companion",
-  "version": "0.15.0",
+  "version": "0.16.0",
   "description": "OAuth helper and remote fetcher for Uppy's (https://uppy.io) extensible file upload widget with support for drag&drop, resumable uploads, previews, restrictions, file processing/encoding, remote providers like Dropbox and Google Drive, S3 and more :dog:",
   "description": "OAuth helper and remote fetcher for Uppy's (https://uppy.io) extensible file upload widget with support for drag&drop, resumable uploads, previews, restrictions, file processing/encoding, remote providers like Dropbox and Google Drive, S3 and more :dog:",
   "main": "lib/uppy.js",
   "main": "lib/uppy.js",
   "types": "types/index.d.ts",
   "types": "types/index.d.ts",

+ 0 - 1
packages/@uppy/companion/src/server/Uploader.js

@@ -400,7 +400,6 @@ class Uploader {
 }
 }
 
 
 Uploader.FILE_NAME_PREFIX = 'uppy-file'
 Uploader.FILE_NAME_PREFIX = 'uppy-file'
-// @todo do a proper migration to change this name
 Uploader.STORAGE_PREFIX = 'companion'
 Uploader.STORAGE_PREFIX = 'companion'
 
 
 module.exports = Uploader
 module.exports = Uploader

+ 2 - 1
packages/@uppy/companion/src/server/controllers/callback.js

@@ -6,6 +6,7 @@ const tokenService = require('../helpers/jwt')
 const parseUrl = require('url').parse
 const parseUrl = require('url').parse
 const { hasMatch } = require('../helpers/utils')
 const { hasMatch } = require('../helpers/utils')
 const oAuthState = require('../helpers/oauth-state')
 const oAuthState = require('../helpers/oauth-state')
+const logger = require('../logger')
 
 
 /**
 /**
  *
  *
@@ -22,7 +23,7 @@ module.exports = function callback (req, res, next) {
 
 
   // TODO see if the access_token can be transported in a different way that url query params
   // TODO see if the access_token can be transported in a different way that url query params
   req.uppy.providerTokens[providerName] = req.query.access_token
   req.uppy.providerTokens[providerName] = req.query.access_token
-  req.uppy.debugLog(`Generating auth token for provider ${providerName}.`)
+  logger.debug(`Generating auth token for provider ${providerName}.`)
   const uppyAuthToken = tokenService.generateToken(req.uppy.providerTokens, req.uppy.options.secret)
   const uppyAuthToken = tokenService.generateToken(req.uppy.providerTokens, req.uppy.options.secret)
   // add the token to cookies for thumbnail/image requests
   // add the token to cookies for thumbnail/image requests
   tokenService.addToCookies(res, uppyAuthToken, req.uppy.options)
   tokenService.addToCookies(res, uppyAuthToken, req.uppy.options)

+ 3 - 3
packages/@uppy/companion/src/server/controllers/get.js

@@ -17,7 +17,7 @@ function get (req, res) {
       return res.status(400).json({error: 'unable to determine file size'})
       return res.status(400).json({error: 'unable to determine file size'})
     }
     }
 
 
-    req.uppy.debugLog('Instantiating uploader.')
+    logger.debug('Instantiating uploader.')
     const uploader = new Uploader({
     const uploader = new Uploader({
       uppyOptions: req.uppy.options,
       uppyOptions: req.uppy.options,
       endpoint: body.endpoint,
       endpoint: body.endpoint,
@@ -37,10 +37,10 @@ function get (req, res) {
 
 
     // wait till the client has connected to the socket, before starting
     // wait till the client has connected to the socket, before starting
     // the download, so that the client can receive all download/upload progress.
     // the download, so that the client can receive all download/upload progress.
-    req.uppy.debugLog('Waiting for socket connection before beginning remote download.')
+    logger.debug('Waiting for socket connection before beginning remote download.')
     // waiting for socketReady.
     // waiting for socketReady.
     uploader.onSocketReady(() => {
     uploader.onSocketReady(() => {
-      req.uppy.debugLog('Socket connection received. Starting remote download.')
+      logger.debug('Socket connection received. Starting remote download.')
       provider.download({ id, token, query: req.query }, uploader.handleChunk.bind(uploader))
       provider.download({ id, token, query: req.query }, uploader.handleChunk.bind(uploader))
     })
     })
     const response = uploader.getResponse()
     const response = uploader.getResponse()

+ 6 - 6
packages/@uppy/companion/src/server/controllers/url.js

@@ -19,10 +19,10 @@ module.exports = () => {
  * @param {object} res expressJS response object
  * @param {object} res expressJS response object
  */
  */
 const meta = (req, res) => {
 const meta = (req, res) => {
-  req.uppy.debugLog('URL file import handler running')
+  logger.debug('URL file import handler running')
 
 
   if (!validator.isURL(req.body.url, { require_protocol: true, require_tld: !req.uppy.options.debug })) {
   if (!validator.isURL(req.body.url, { require_protocol: true, require_tld: !req.uppy.options.debug })) {
-    req.uppy.debugLog('Invalid request body detected. Exiting url meta handler.')
+    logger.debug('Invalid request body detected. Exiting url meta handler.')
     return res.status(400).json({error: 'Invalid request body'})
     return res.status(400).json({error: 'Invalid request body'})
   }
   }
 
 
@@ -42,13 +42,13 @@ const meta = (req, res) => {
  * @param {object} res expressJS response object
  * @param {object} res expressJS response object
  */
  */
 const get = (req, res) => {
 const get = (req, res) => {
-  req.uppy.debugLog('URL file import handler running')
+  logger.debug('URL file import handler running')
 
 
   utils.getURLMeta(req.body.url)
   utils.getURLMeta(req.body.url)
     .then(({ size }) => {
     .then(({ size }) => {
       // @ts-ignore
       // @ts-ignore
       const { filePath } = req.uppy.options
       const { filePath } = req.uppy.options
-      req.uppy.debugLog('Instantiating uploader.')
+      logger.debug('Instantiating uploader.')
       const uploader = new Uploader({
       const uploader = new Uploader({
         uppyOptions: req.uppy.options,
         uppyOptions: req.uppy.options,
         endpoint: req.body.endpoint,
         endpoint: req.body.endpoint,
@@ -61,9 +61,9 @@ const get = (req, res) => {
         headers: req.body.headers
         headers: req.body.headers
       })
       })
 
 
-      req.uppy.debugLog('Waiting for socket connection before beginning remote download.')
+      logger.debug('Waiting for socket connection before beginning remote download.')
       uploader.onSocketReady(() => {
       uploader.onSocketReady(() => {
-        req.uppy.debugLog('Socket connection received. Starting remote download.')
+        logger.debug('Socket connection received. Starting remote download.')
         downloadURL(req.body.url, uploader.handleChunk.bind(uploader))
         downloadURL(req.body.url, uploader.handleChunk.bind(uploader))
       })
       })
 
 

+ 44 - 6
packages/@uppy/companion/src/server/helpers/utils.js

@@ -93,20 +93,58 @@ module.exports.getURLBuilder = (options) => {
 }
 }
 
 
 /**
 /**
+ * Ensure that a user-provided `secret` is 32 bytes long (the length required
+ * for an AES256 key) by hashing it with SHA256.
  *
  *
- * @param {*} input
- * @param {string} secret
+ * @param {string|Buffer} secret
+ */
+function createSecret (secret) {
+  const hash = crypto.createHash('sha256')
+  hash.update(secret)
+  return hash.digest()
+}
+
+/**
+ * Create an initialization vector for AES256.
+ *
+ * @return {Buffer}
+ */
+function createIv () {
+  return crypto.randomBytes(16)
+}
+
+/**
+ * Encrypt a buffer or string with AES256 and a random iv.
+ *
+ * @param {string} input
+ * @param {string|Buffer} secret
+ * @return {string} Ciphertext as a hex string, prefixed with 32 hex characters containing the iv.
  */
  */
 module.exports.encrypt = (input, secret) => {
 module.exports.encrypt = (input, secret) => {
-  const cipher = crypto.createCipher('aes256', secret)
-  let encrypted = cipher.update(input, 'utf8', 'hex')
+  const iv = createIv()
+  const cipher = crypto.createCipheriv('aes256', createSecret(secret), iv)
+  let encrypted = iv.toString('hex')
+  encrypted += cipher.update(input, 'utf8', 'hex')
   encrypted += cipher.final('hex')
   encrypted += cipher.final('hex')
   return encrypted
   return encrypted
 }
 }
 
 
+/**
+ * Decrypt an iv-prefixed or string with AES256. The iv should be in the first 32 hex characters.
+ *
+ * @param {string} encrypted
+ * @param {string|Buffer} secret
+ * @return {string} Decrypted value.
+ */
 module.exports.decrypt = (encrypted, secret) => {
 module.exports.decrypt = (encrypted, secret) => {
-  var decipher = crypto.createDecipher('aes256', secret)
-  var decrypted = decipher.update(encrypted, 'hex', 'utf8')
+  // Need at least 32 chars for the iv
+  if (encrypted.length < 32) {
+    throw new Error('Invalid encrypted value. Maybe it was generated with an old Companion version?')
+  }
+
+  const iv = Buffer.from(encrypted.slice(0, 32), 'hex')
+  const decipher = crypto.createDecipheriv('aes256', createSecret(secret), iv)
+  let decrypted = decipher.update(encrypted.slice(32), 'hex', 'utf8')
   decrypted += decipher.final('utf8')
   decrypted += decipher.final('utf8')
   return decrypted
   return decrypted
 }
 }

+ 5 - 5
packages/@uppy/companion/src/server/logger.js

@@ -1,7 +1,7 @@
 /**
 /**
  * INFO level log
  * INFO level log
  * @param {string} msg the message to log
  * @param {string} msg the message to log
- * @param {string} tag a unique tag to easily search for this message
+ * @param {string=} tag a unique tag to easily search for this message
  */
  */
 exports.info = (msg, tag) => {
 exports.info = (msg, tag) => {
   log(msg, tag, 'info')
   log(msg, tag, 'info')
@@ -10,7 +10,7 @@ exports.info = (msg, tag) => {
 /**
 /**
  * WARN level log
  * WARN level log
  * @param {string} msg the message to log
  * @param {string} msg the message to log
- * @param {string} tag a unique tag to easily search for this message
+ * @param {string=} tag a unique tag to easily search for this message
  */
  */
 exports.warn = (msg, tag) => {
 exports.warn = (msg, tag) => {
   log(msg, tag, 'warn')
   log(msg, tag, 'warn')
@@ -19,7 +19,7 @@ exports.warn = (msg, tag) => {
 /**
 /**
  * ERROR level log
  * ERROR level log
  * @param {string | Error} msg the message to log
  * @param {string | Error} msg the message to log
- * @param {string} tag a unique tag to easily search for this message
+ * @param {string=} tag a unique tag to easily search for this message
  */
  */
 exports.error = (msg, tag) => {
 exports.error = (msg, tag) => {
   log(msg, tag, 'error')
   log(msg, tag, 'error')
@@ -28,7 +28,7 @@ exports.error = (msg, tag) => {
 /**
 /**
  * DEBUG level log
  * DEBUG level log
  * @param {string} msg the message to log
  * @param {string} msg the message to log
- * @param {string} tag a unique tag to easily search for this message
+ * @param {string=} tag a unique tag to easily search for this message
  */
  */
 exports.debug = (msg, tag) => {
 exports.debug = (msg, tag) => {
   if (process.env.NODE_ENV !== 'production') {
   if (process.env.NODE_ENV !== 'production') {
@@ -45,5 +45,5 @@ exports.debug = (msg, tag) => {
 const log = (msg, tag, level) => {
 const log = (msg, tag, level) => {
   // @TODO add some colors based on log level
   // @TODO add some colors based on log level
   const time = new Date().toISOString()
   const time = new Date().toISOString()
-  console.log(`uppy: ${time} [${level}] ${tag} ${msg}`)
+  console.log(`uppy: ${time} [${level}] ${tag || ''} ${msg}`)
 }
 }

+ 3 - 2
packages/@uppy/companion/src/server/middlewares.js

@@ -1,13 +1,14 @@
 const tokenService = require('./helpers/jwt')
 const tokenService = require('./helpers/jwt')
+const logger = require('./logger')
 
 
 exports.hasSessionAndProvider = (req, res, next) => {
 exports.hasSessionAndProvider = (req, res, next) => {
   if (!req.session || !req.body) {
   if (!req.session || !req.body) {
-    req.uppy.debugLog('No session/body attached to req object. Exiting dispatcher.')
+    logger.debug('No session/body attached to req object. Exiting dispatcher.')
     return res.sendStatus(400)
     return res.sendStatus(400)
   }
   }
 
 
   if (!req.uppy.provider) {
   if (!req.uppy.provider) {
-    req.uppy.debugLog('No provider/provider-handler found. Exiting dispatcher.')
+    logger.debug('No provider/provider-handler found. Exiting dispatcher.')
     return res.sendStatus(400)
     return res.sendStatus(400)
   }
   }
 
 

+ 0 - 24
packages/@uppy/companion/src/uppy.js

@@ -182,29 +182,6 @@ const interceptGrantErrorResponse = interceptor((req, res) => {
   }
   }
 })
 })
 
 
-/**
- * returns a logger function, that would log a message only if
- * the debug option is set to true
- *
- * @param {{debug: boolean}} options
- * @returns {function}
- */
-const getDebugLogger = (options) => {
-  // TODO: deprecate this.
-  // TODO: add line number and originating file
-  /**
-   *
-   * @param {string} message
-   */
-  const conditonalLogger = (message) => {
-    if (options.debug) {
-      logger.debug(message, 'debugLog')
-    }
-  }
-
-  return conditonalLogger
-}
-
 /**
 /**
  *
  *
  * @param {object} options
  * @param {object} options
@@ -241,7 +218,6 @@ const getOptionsMiddleware = (options) => {
       options,
       options,
       s3Client,
       s3Client,
       authToken: req.header('uppy-auth-token'),
       authToken: req.header('uppy-auth-token'),
-      debugLog: getDebugLogger(options),
       buildURL: getURLBuilder(options)
       buildURL: getURLBuilder(options)
     }
     }
     next()
     next()

+ 2 - 2
packages/@uppy/core/package.json

@@ -1,7 +1,7 @@
 {
 {
   "name": "@uppy/core",
   "name": "@uppy/core",
   "description": "Core module for the extensible JavaScript file upload widget with support for drag&drop, resumable uploads, previews, restrictions, file processing/encoding, remote providers like Instagram, Dropbox, Google Drive, S3 and more :dog:",
   "description": "Core module for the extensible JavaScript file upload widget with support for drag&drop, resumable uploads, previews, restrictions, file processing/encoding, remote providers like Instagram, Dropbox, Google Drive, S3 and more :dog:",
-  "version": "0.28.0",
+  "version": "0.29.0",
   "license": "MIT",
   "license": "MIT",
   "main": "lib/index.js",
   "main": "lib/index.js",
   "jsnext:main": "src/index.js",
   "jsnext:main": "src/index.js",
@@ -22,7 +22,7 @@
   },
   },
   "dependencies": {
   "dependencies": {
     "@uppy/store-default": "0.27.0",
     "@uppy/store-default": "0.27.0",
-    "@uppy/utils": "0.28.0",
+    "@uppy/utils": "0.29.0",
     "cuid": "^2.1.1",
     "cuid": "^2.1.1",
     "lodash.throttle": "^4.1.1",
     "lodash.throttle": "^4.1.1",
     "mime-match": "^1.0.2",
     "mime-match": "^1.0.2",

+ 2 - 0
packages/@uppy/core/src/index.js

@@ -9,6 +9,7 @@ const getFileType = require('@uppy/utils/lib/getFileType')
 const getFileNameAndExtension = require('@uppy/utils/lib/getFileNameAndExtension')
 const getFileNameAndExtension = require('@uppy/utils/lib/getFileNameAndExtension')
 const generateFileID = require('@uppy/utils/lib/generateFileID')
 const generateFileID = require('@uppy/utils/lib/generateFileID')
 const getTimeStamp = require('@uppy/utils/lib/getTimeStamp')
 const getTimeStamp = require('@uppy/utils/lib/getTimeStamp')
+const supportsUploadProgress = require('./supportsUploadProgress')
 const Plugin = require('./Plugin') // Exported from here.
 const Plugin = require('./Plugin') // Exported from here.
 
 
 /**
 /**
@@ -118,6 +119,7 @@ class Uppy {
       currentUploads: {},
       currentUploads: {},
       allowNewUpload: true,
       allowNewUpload: true,
       capabilities: {
       capabilities: {
+        uploadProgress: supportsUploadProgress(),
         resumableUploads: false
         resumableUploads: false
       },
       },
       totalProgress: 0,
       totalProgress: 0,

+ 6 - 6
packages/@uppy/core/src/index.test.js

@@ -149,7 +149,7 @@ describe('src/Core', () => {
 
 
       const newState = {
       const newState = {
         bee: 'boo',
         bee: 'boo',
-        capabilities: { resumableUploads: false },
+        capabilities: { uploadProgress: true, resumableUploads: false },
         files: {},
         files: {},
         currentUploads: {},
         currentUploads: {},
         allowNewUpload: true,
         allowNewUpload: true,
@@ -173,7 +173,7 @@ describe('src/Core', () => {
       // current state
       // current state
       expect(stateUpdateEventMock.mock.calls[1][0]).toEqual({
       expect(stateUpdateEventMock.mock.calls[1][0]).toEqual({
         bee: 'boo',
         bee: 'boo',
-        capabilities: { resumableUploads: false },
+        capabilities: { uploadProgress: true, resumableUploads: false },
         files: {},
         files: {},
         currentUploads: {},
         currentUploads: {},
         allowNewUpload: true,
         allowNewUpload: true,
@@ -186,7 +186,7 @@ describe('src/Core', () => {
       // new state
       // new state
       expect(stateUpdateEventMock.mock.calls[1][1]).toEqual({
       expect(stateUpdateEventMock.mock.calls[1][1]).toEqual({
         bee: 'boo',
         bee: 'boo',
-        capabilities: { resumableUploads: false },
+        capabilities: { uploadProgress: true, resumableUploads: false },
         files: {},
         files: {},
         currentUploads: {},
         currentUploads: {},
         allowNewUpload: true,
         allowNewUpload: true,
@@ -204,7 +204,7 @@ describe('src/Core', () => {
       core.setState({ foo: 'bar' })
       core.setState({ foo: 'bar' })
 
 
       expect(core.getState()).toEqual({
       expect(core.getState()).toEqual({
-        capabilities: { resumableUploads: false },
+        capabilities: { uploadProgress: true, resumableUploads: false },
         files: {},
         files: {},
         currentUploads: {},
         currentUploads: {},
         allowNewUpload: true,
         allowNewUpload: true,
@@ -232,7 +232,7 @@ describe('src/Core', () => {
     expect(coreCancelEventMock.mock.calls.length).toEqual(1)
     expect(coreCancelEventMock.mock.calls.length).toEqual(1)
     expect(coreStateUpdateEventMock.mock.calls.length).toEqual(2)
     expect(coreStateUpdateEventMock.mock.calls.length).toEqual(2)
     expect(coreStateUpdateEventMock.mock.calls[1][1]).toEqual({
     expect(coreStateUpdateEventMock.mock.calls[1][1]).toEqual({
-      capabilities: { resumableUploads: false },
+      capabilities: { uploadProgress: true, resumableUploads: false },
       files: {},
       files: {},
       currentUploads: {},
       currentUploads: {},
       allowNewUpload: true,
       allowNewUpload: true,
@@ -291,7 +291,7 @@ describe('src/Core', () => {
     expect(coreCancelEventMock.mock.calls.length).toEqual(1)
     expect(coreCancelEventMock.mock.calls.length).toEqual(1)
     expect(coreStateUpdateEventMock.mock.calls.length).toEqual(1)
     expect(coreStateUpdateEventMock.mock.calls.length).toEqual(1)
     expect(coreStateUpdateEventMock.mock.calls[0][1]).toEqual({
     expect(coreStateUpdateEventMock.mock.calls[0][1]).toEqual({
-      capabilities: { resumableUploads: false },
+      capabilities: { uploadProgress: true, resumableUploads: false },
       files: {},
       files: {},
       currentUploads: {},
       currentUploads: {},
       allowNewUpload: true,
       allowNewUpload: true,

+ 35 - 0
packages/@uppy/core/src/supportsUploadProgress.js

@@ -0,0 +1,35 @@
+// Edge 15.x does not fire 'progress' events on uploads.
+// See https://github.com/transloadit/uppy/issues/945
+// And https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/12224510/
+module.exports = function supportsUploadProgress (userAgent) {
+  // Allow passing in userAgent for tests
+  if (userAgent == null) {
+    userAgent = typeof navigator !== 'undefined' ? navigator.userAgent : null
+  }
+  // Assume it works because basically everything supports progress events.
+  if (!userAgent) return true
+
+  const m = /Edge\/(\d+\.\d+)/.exec(userAgent)
+  if (!m) return true
+
+  const edgeVersion = m[1]
+  let [major, minor] = edgeVersion.split('.')
+  major = parseInt(major, 10)
+  minor = parseInt(minor, 10)
+
+  // Worked before:
+  // Edge 40.15063.0.0
+  // Microsoft EdgeHTML 15.15063
+  if (major < 15 || (major === 15 && minor < 15063)) {
+    return true
+  }
+
+  // Fixed in:
+  // Microsoft EdgeHTML 18.18218
+  if (major > 18 || (major === 18 && minor >= 18218)) {
+    return true
+  }
+
+  // other versions don't work.
+  return false
+}

+ 28 - 0
packages/@uppy/core/src/supportsUploadProgress.test.js

@@ -0,0 +1,28 @@
+const supportsUploadProgress = require('./supportsUploadProgress')
+
+describe('supportsUploadProgress', () => {
+  it('returns true in working browsers', () => {
+    // Firefox 64 (dev edition)
+    expect(supportsUploadProgress('Mozilla/5.0 (X11; Linux x86_64; rv:64.0) Gecko/20100101 Firefox/64.0')).toBe(true)
+
+    // Chromium 70
+    expect(supportsUploadProgress('Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36')).toBe(true)
+
+    // IE 11
+    expect(supportsUploadProgress('Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; rv:11.0) like Gecko')).toBe(true)
+
+    // MS Edge 14
+    expect(supportsUploadProgress('Chrome (AppleWebKit/537.1; Chrome50.0; Windows NT 6.3) AppleWebKit/537.36 (KHTML like Gecko) Chrome/51.0.2704.79 Safari/537.36 Edge/14.14393')).toBe(true)
+
+    // MS Edge 18, supposedly fixed
+    expect(supportsUploadProgress('Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36 Edge/18.18218')).toBe(true)
+  })
+
+  it('returns false in broken browsers', () => {
+    // MS Edge 15, first broken version
+    expect(supportsUploadProgress('Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36 Edge/15.15063')).toBe(false)
+
+    // MS Edge 17
+    expect(supportsUploadProgress('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 Edge/17.17134')).toBe(false)
+  })
+})

+ 1 - 1
packages/@uppy/core/types/index.d.ts

@@ -81,8 +81,8 @@ interface Locale {
 export interface UppyOptions {
 export interface UppyOptions {
   id: string;
   id: string;
   autoProceed: boolean;
   autoProceed: boolean;
+  allowMultipleUploads: boolean;
   debug: boolean;
   debug: boolean;
-  showLinkToFileUploadResult: boolean;
   restrictions: {
   restrictions: {
     maxFileSize: number | null;
     maxFileSize: number | null;
     maxNumberOfFiles: number | null;
     maxNumberOfFiles: number | null;

+ 9 - 9
packages/@uppy/dashboard/package.json

@@ -1,7 +1,7 @@
 {
 {
   "name": "@uppy/dashboard",
   "name": "@uppy/dashboard",
   "description": "Universal UI plugin for Uppy.",
   "description": "Universal UI plugin for Uppy.",
-  "version": "0.28.0",
+  "version": "0.29.0",
   "license": "MIT",
   "license": "MIT",
   "main": "lib/index.js",
   "main": "lib/index.js",
   "jsnext:main": "src/index.js",
   "jsnext:main": "src/index.js",
@@ -23,11 +23,11 @@
     "url": "git+https://github.com/transloadit/uppy.git"
     "url": "git+https://github.com/transloadit/uppy.git"
   },
   },
   "dependencies": {
   "dependencies": {
-    "@uppy/informer": "0.28.0",
-    "@uppy/provider-views": "0.28.0",
-    "@uppy/status-bar": "0.28.0",
-    "@uppy/thumbnail-generator": "0.28.0",
-    "@uppy/utils": "0.28.0",
+    "@uppy/informer": "0.29.0",
+    "@uppy/provider-views": "0.29.0",
+    "@uppy/status-bar": "0.29.0",
+    "@uppy/thumbnail-generator": "0.29.0",
+    "@uppy/utils": "0.29.0",
     "classnames": "^2.2.6",
     "classnames": "^2.2.6",
     "drag-drop": "2.13.3",
     "drag-drop": "2.13.3",
     "lodash.throttle": "^4.1.1",
     "lodash.throttle": "^4.1.1",
@@ -37,10 +37,10 @@
     "resize-observer-polyfill": "^1.5.0"
     "resize-observer-polyfill": "^1.5.0"
   },
   },
   "devDependencies": {
   "devDependencies": {
-    "@uppy/core": "0.28.0",
-    "@uppy/google-drive": "0.28.0"
+    "@uppy/core": "0.29.0",
+    "@uppy/google-drive": "0.29.0"
   },
   },
   "peerDependencies": {
   "peerDependencies": {
-    "@uppy/core": "^0.28.0"
+    "@uppy/core": "^0.29.0"
   }
   }
 }
 }

+ 2 - 1
packages/@uppy/dashboard/src/style.scss

@@ -1,4 +1,5 @@
-@import '@uppy/core/src/style.scss';
+@import '@uppy/core/src/_utils.scss';
+@import '@uppy/core/src/_variables.scss';
 @import '@uppy/informer/src/style.scss';
 @import '@uppy/informer/src/style.scss';
 @import '@uppy/status-bar/src/style.scss';
 @import '@uppy/status-bar/src/style.scss';
 @import '@uppy/provider-views/src/style.scss';
 @import '@uppy/provider-views/src/style.scss';

+ 27 - 23
packages/@uppy/dashboard/types/index.d.ts

@@ -1,29 +1,31 @@
 import { Plugin, PluginOptions, Uppy } from '@uppy/core';
 import { Plugin, PluginOptions, Uppy } from '@uppy/core';
 
 
-export interface DashboardOptions extends PluginOptions {
-  onRequestCloseModal: () => void;
-  disablePageScrollWhenModalOpen: boolean;
-  closeModalOnClickOutside: boolean;
-  trigger: string | HTMLElement;
-  inline: boolean;
-  defaultTabIcon: string;
-  hideUploadButton: boolean;
-  width: string | number;
-  height: string | number;
-  note: string;
-  showLinkToFileUploadResult: boolean;
-  proudlyDisplayPoweredByUppy: boolean;
-  metaFields: string[];
-  plugins: string[];
-  disableStatusBar: boolean;
-  showProgressDetails: boolean;
-  hideProgressAfterFinish: boolean;
-  disableInformer: boolean;
-  disableThumbnailGenerator: boolean;
+declare module Dashboard {
+  interface DashboardOptions extends PluginOptions {
+    onRequestCloseModal: () => void;
+    disablePageScrollWhenModalOpen: boolean;
+    closeModalOnClickOutside: boolean;
+    trigger: string | HTMLElement;
+    inline: boolean;
+    defaultTabIcon: string;
+    hideUploadButton: boolean;
+    width: string | number;
+    height: string | number;
+    note: string;
+    showLinkToFileUploadResult: boolean;
+    proudlyDisplayPoweredByUppy: boolean;
+    metaFields: string[];
+    plugins: string[];
+    disableStatusBar: boolean;
+    showProgressDetails: boolean;
+    hideProgressAfterFinish: boolean;
+    disableInformer: boolean;
+    disableThumbnailGenerator: boolean;
+  }
 }
 }
 
 
-export default class Dashboard extends Plugin {
-  constructor(uppy: Uppy, opts: Partial<DashboardOptions>);
+declare class Dashboard extends Plugin {
+  constructor(uppy: Uppy, opts: Partial<Dashboard.DashboardOptions>);
   addTarget(plugin: Plugin): HTMLElement;
   addTarget(plugin: Plugin): HTMLElement;
   hideAllPanels(): void;
   hideAllPanels(): void;
   openModal(): void;
   openModal(): void;
@@ -34,8 +36,10 @@ export default class Dashboard extends Plugin {
   uninstall(): void;
   uninstall(): void;
 }
 }
 
 
+export = Dashboard;
+
 declare module '@uppy/core' {
 declare module '@uppy/core' {
   export interface Uppy {
   export interface Uppy {
-    use(pluginClass: typeof Dashboard, opts: Partial<DashboardOptions>): Uppy;
+    use(pluginClass: typeof Dashboard, opts: Partial<Dashboard.DashboardOptions>): Uppy;
   }
   }
 }
 }

+ 4 - 4
packages/@uppy/drag-drop/package.json

@@ -1,7 +1,7 @@
 {
 {
   "name": "@uppy/drag-drop",
   "name": "@uppy/drag-drop",
   "description": "Droppable zone UI for Uppy. Drag and drop files into it to upload.",
   "description": "Droppable zone UI for Uppy. Drag and drop files into it to upload.",
-  "version": "0.28.0",
+  "version": "0.29.0",
   "license": "MIT",
   "license": "MIT",
   "main": "lib/index.js",
   "main": "lib/index.js",
   "jsnext:main": "src/index.js",
   "jsnext:main": "src/index.js",
@@ -26,14 +26,14 @@
     "url": "git+https://github.com/transloadit/uppy.git"
     "url": "git+https://github.com/transloadit/uppy.git"
   },
   },
   "dependencies": {
   "dependencies": {
-    "@uppy/utils": "0.28.0",
+    "@uppy/utils": "0.29.0",
     "drag-drop": "2.13.3",
     "drag-drop": "2.13.3",
     "preact": "^8.2.9"
     "preact": "^8.2.9"
   },
   },
   "devDependencies": {
   "devDependencies": {
-    "@uppy/core": "0.28.0"
+    "@uppy/core": "0.29.0"
   },
   },
   "peerDependencies": {
   "peerDependencies": {
-    "@uppy/core": "^0.28.0"
+    "@uppy/core": "^0.29.0"
   }
   }
 }
 }

+ 52 - 55
packages/@uppy/drag-drop/src/style.scss

@@ -1,62 +1,59 @@
-@import '@uppy/core/src/style.scss';
-
-// .Uppy {
-
-  .uppy-DragDrop-container {
-    display: flex;
-    align-items: center;
-    justify-content: center;
-    border-radius: 7px;
-    background-color: $color-white;
-    // cursor: pointer;
-  }
-
-  .uppy-DragDrop-inner {
-    margin: 0;
-    text-align: center;
-    padding: 80px 20px;
-    line-height: 1.4;
+@import '@uppy/core/src/_utils.scss';
+@import '@uppy/core/src/_variables.scss';
+
+.uppy-DragDrop-container {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  border-radius: 7px;
+  background-color: $color-white;
+  // cursor: pointer;
+}
+
+.uppy-DragDrop-inner {
+  margin: 0;
+  text-align: center;
+  padding: 80px 20px;
+  line-height: 1.4;
+}
+
+.uppy-DragDrop-arrow {
+  width: 60px;
+  height: 60px;
+  fill: lighten($color-gray, 30%);
+  margin-bottom: 17px;
+}
+
+  .uppy-DragDrop--is-dragdrop-supported {
+    border: 2px dashed;
+    border-color: lighten($color-gray, 10%);
   }
   }
 
 
-  .uppy-DragDrop-arrow {
-    width: 60px;
-    height: 60px;
-    fill: lighten($color-gray, 30%);
-    margin-bottom: 17px;
-  }
-
-    .uppy-DragDrop--is-dragdrop-supported {
-      border: 2px dashed;
-      border-color: lighten($color-gray, 10%);
-    }
-
-    // .uppy-DragDrop-container.is-dragdrop-supported .uppy-DragDrop-dragText {
-    //   display: inline;
-    // }
-
-    .uppy-DragDrop-container.drag {
-      border-color: $color-gray;
-      background-color: darken($color-white, 10%);
-    }
-
-    .uppy-DragDrop-container.drag .uppy-DragDrop-arrow {
-      fill: $color-gray;
-    }
-
-  .uppy-DragDrop-label {
-    display: block;
-    cursor: pointer;
-    font-size: 1.15em;
-    margin-bottom: 5px;
-  }
+  // .uppy-DragDrop-container.is-dragdrop-supported .uppy-DragDrop-dragText {
+  //   display: inline;
+  // }
 
 
-  .uppy-DragDrop-note {
-    font-size: 1em;
-    color: lighten($color-gray, 10%);
+  .uppy-DragDrop-container.drag {
+    border-color: $color-gray;
+    background-color: darken($color-white, 10%);
   }
   }
 
 
-  .uppy-DragDrop-dragText {
-    color: $color-cornflower-blue;
+  .uppy-DragDrop-container.drag .uppy-DragDrop-arrow {
+    fill: $color-gray;
   }
   }
 
 
-// }
+.uppy-DragDrop-label {
+  display: block;
+  cursor: pointer;
+  font-size: 1.15em;
+  margin-bottom: 5px;
+}
+
+.uppy-DragDrop-note {
+  font-size: 1em;
+  color: lighten($color-gray, 10%);
+}
+
+.uppy-DragDrop-dragText {
+  color: $color-cornflower-blue;
+}

+ 13 - 9
packages/@uppy/drag-drop/types/index.d.ts

@@ -1,19 +1,23 @@
 import { Plugin, PluginOptions, Uppy } from '@uppy/core';
 import { Plugin, PluginOptions, Uppy } from '@uppy/core';
 
 
-export interface DragDropOptions extends PluginOptions {
-  inputName: string;
-  allowMultipleFiles: boolean;
-  width: string;
-  height: string;
-  note: string;
+declare module DragDrop {
+  interface DragDropOptions extends PluginOptions {
+    inputName: string;
+    allowMultipleFiles: boolean;
+    width: string;
+    height: string;
+    note: string;
+  }
 }
 }
 
 
-export default class DragDrop extends Plugin {
-  constructor(uppy: Uppy, opts: Partial<DragDropOptions>);
+declare class DragDrop extends Plugin {
+  constructor(uppy: Uppy, opts: Partial<DragDrop.DragDropOptions>);
 }
 }
 
 
+export = DragDrop;
+
 declare module '@uppy/core' {
 declare module '@uppy/core' {
   export interface Uppy {
   export interface Uppy {
-    use(pluginClass: typeof DragDrop, opts: Partial<DragDropOptions>): Uppy;
+    use(pluginClass: typeof DragDrop, opts: Partial<DragDrop.DragDropOptions>): Uppy;
   }
   }
 }
 }

+ 5 - 5
packages/@uppy/dropbox/package.json

@@ -1,7 +1,7 @@
 {
 {
   "name": "@uppy/dropbox",
   "name": "@uppy/dropbox",
   "description": "Import files from Dropbox, into Uppy.",
   "description": "Import files from Dropbox, into Uppy.",
-  "version": "0.28.0",
+  "version": "0.29.0",
   "license": "MIT",
   "license": "MIT",
   "main": "lib/index.js",
   "main": "lib/index.js",
   "jsnext:main": "src/index.js",
   "jsnext:main": "src/index.js",
@@ -22,14 +22,14 @@
   },
   },
   "dependencies": {
   "dependencies": {
     "@uppy/companion-client": "0.27.2",
     "@uppy/companion-client": "0.27.2",
-    "@uppy/provider-views": "0.28.0",
-    "@uppy/utils": "0.28.0",
+    "@uppy/provider-views": "0.29.0",
+    "@uppy/utils": "0.29.0",
     "preact": "^8.2.9"
     "preact": "^8.2.9"
   },
   },
   "devDependencies": {
   "devDependencies": {
-    "@uppy/core": "0.28.0"
+    "@uppy/core": "0.29.0"
   },
   },
   "peerDependencies": {
   "peerDependencies": {
-    "@uppy/core": "^0.28.0"
+    "@uppy/core": "^0.29.0"
   }
   }
 }
 }

+ 4 - 2
packages/@uppy/dropbox/src/index.js

@@ -17,7 +17,7 @@ module.exports = class Dropbox extends Plugin {
       </svg>
       </svg>
     )
     )
 
 
-    this[this.id] = new Provider(uppy, {
+    this.provider = new Provider(uppy, {
       serverUrl: this.opts.serverUrl,
       serverUrl: this.opts.serverUrl,
       serverHeaders: this.opts.serverHeaders,
       serverHeaders: this.opts.serverHeaders,
       provider: 'dropbox'
       provider: 'dropbox'
@@ -28,7 +28,9 @@ module.exports = class Dropbox extends Plugin {
   }
   }
 
 
   install () {
   install () {
-    this.view = new ProviderViews(this)
+    this.view = new ProviderViews(this, {
+      provider: this.provider
+    })
     // Set default state for Dropbox
     // Set default state for Dropbox
     this.setPluginState({
     this.setPluginState({
       authenticated: false,
       authenticated: false,

+ 10 - 6
packages/@uppy/dropbox/types/index.d.ts

@@ -1,17 +1,21 @@
 import { Plugin, PluginOptions, Uppy } from '@uppy/core';
 import { Plugin, PluginOptions, Uppy } from '@uppy/core';
 import { ProviderOptions } from '@uppy/companion-client';
 import { ProviderOptions } from '@uppy/companion-client';
 
 
-export interface DropboxOptions extends PluginOptions, ProviderOptions {
-  serverUrl: string;
-  serverPattern: string | RegExp | Array<string | RegExp>;
+declare module Dropbox {
+  interface DropboxOptions extends PluginOptions, ProviderOptions {
+    serverUrl: string;
+    serverPattern: string | RegExp | Array<string | RegExp>;
+  }
 }
 }
 
 
-export default class Dropbox extends Plugin {
-  constructor(uppy: Uppy, opts: Partial<DropboxOptions>);
+declare class Dropbox extends Plugin {
+  constructor(uppy: Uppy, opts: Partial<Dropbox.DropboxOptions>);
 }
 }
 
 
+export = Dropbox;
+
 declare module '@uppy/core' {
 declare module '@uppy/core' {
   export interface Uppy {
   export interface Uppy {
-    use(pluginClass: typeof Dropbox, opts: Partial<DropboxOptions>): Uppy;
+    use(pluginClass: typeof Dropbox, opts: Partial<Dropbox.DropboxOptions>): Uppy;
   }
   }
 }
 }

+ 4 - 4
packages/@uppy/file-input/package.json

@@ -1,7 +1,7 @@
 {
 {
   "name": "@uppy/file-input",
   "name": "@uppy/file-input",
   "description": "Simple UI of a file input button that works with Uppy right out of the box",
   "description": "Simple UI of a file input button that works with Uppy right out of the box",
-  "version": "0.28.0",
+  "version": "0.29.0",
   "license": "MIT",
   "license": "MIT",
   "main": "lib/index.js",
   "main": "lib/index.js",
   "jsnext:main": "src/index.js",
   "jsnext:main": "src/index.js",
@@ -23,13 +23,13 @@
     "url": "git+https://github.com/transloadit/uppy.git"
     "url": "git+https://github.com/transloadit/uppy.git"
   },
   },
   "dependencies": {
   "dependencies": {
-    "@uppy/utils": "0.28.0",
+    "@uppy/utils": "0.29.0",
     "preact": "^8.2.9"
     "preact": "^8.2.9"
   },
   },
   "devDependencies": {
   "devDependencies": {
-    "@uppy/core": "0.28.0"
+    "@uppy/core": "0.29.0"
   },
   },
   "peerDependencies": {
   "peerDependencies": {
-    "@uppy/core": "^0.28.0"
+    "@uppy/core": "^0.29.0"
   }
   }
 }
 }

+ 2 - 1
packages/@uppy/file-input/src/style.scss

@@ -1,4 +1,5 @@
-@import '@uppy/core/src/style.scss';
+@import '@uppy/core/src/_utils.scss';
+@import '@uppy/core/src/_variables.scss';
 
 
 .uppy-FileInput-container {
 .uppy-FileInput-container {
   margin-bottom: 15px;
   margin-bottom: 15px;

+ 10 - 6
packages/@uppy/file-input/types/index.d.ts

@@ -1,16 +1,20 @@
 import { Plugin, PluginOptions, Uppy } from '@uppy/core';
 import { Plugin, PluginOptions, Uppy } from '@uppy/core';
 
 
-export interface FileInputOptions extends PluginOptions {
-  pretty: boolean;
-  inputName: string;
+declare module FileInput {
+  interface FileInputOptions extends PluginOptions {
+    pretty: boolean;
+    inputName: string;
+  }
 }
 }
 
 
-export default class FileInput extends Plugin {
-  constructor(uppy: Uppy, opts: Partial<FileInputOptions>);
+declare class FileInput extends Plugin {
+  constructor(uppy: Uppy, opts: Partial<FileInput.FileInputOptions>);
 }
 }
 
 
+export = FileInput;
+
 declare module '@uppy/core' {
 declare module '@uppy/core' {
   export interface Uppy {
   export interface Uppy {
-    use(pluginClass: typeof FileInput, opts: Partial<FileInputOptions>): Uppy;
+    use(pluginClass: typeof FileInput, opts: Partial<FileInput.FileInputOptions>): Uppy;
   }
   }
 }
 }

+ 4 - 4
packages/@uppy/form/package.json

@@ -1,7 +1,7 @@
 {
 {
   "name": "@uppy/form",
   "name": "@uppy/form",
   "description": "Connect Uppy to an existing HTML <form>.",
   "description": "Connect Uppy to an existing HTML <form>.",
-  "version": "0.28.0",
+  "version": "0.29.0",
   "license": "MIT",
   "license": "MIT",
   "main": "lib/index.js",
   "main": "lib/index.js",
   "jsnext:main": "src/index.js",
   "jsnext:main": "src/index.js",
@@ -21,13 +21,13 @@
     "url": "git+https://github.com/transloadit/uppy.git"
     "url": "git+https://github.com/transloadit/uppy.git"
   },
   },
   "dependencies": {
   "dependencies": {
-    "@uppy/utils": "0.28.0",
+    "@uppy/utils": "0.29.0",
     "get-form-data": "^2.0.0"
     "get-form-data": "^2.0.0"
   },
   },
   "devDependencies": {
   "devDependencies": {
-    "@uppy/core": "0.28.0"
+    "@uppy/core": "0.29.0"
   },
   },
   "peerDependencies": {
   "peerDependencies": {
-    "@uppy/core": "^0.28.0"
+    "@uppy/core": "^0.29.0"
   }
   }
 }
 }

+ 13 - 9
packages/@uppy/form/types/index.d.ts

@@ -1,19 +1,23 @@
 import { Plugin, PluginOptions, Uppy } from '@uppy/core';
 import { Plugin, PluginOptions, Uppy } from '@uppy/core';
 
 
-export interface FormOptions extends PluginOptions {
-  getMetaFromForm: boolean;
-  addResultToForm: boolean;
-  submitOnSuccess: boolean;
-  triggerUploadOnSubmit: boolean;
-  resultName: string;
+declare module Form {
+  interface FormOptions extends PluginOptions {
+    getMetaFromForm: boolean;
+    addResultToForm: boolean;
+    submitOnSuccess: boolean;
+    triggerUploadOnSubmit: boolean;
+    resultName: string;
+  }
 }
 }
 
 
-export default class Form extends Plugin {
-  constructor(uppy: Uppy, opts: Partial<FormOptions>);
+declare class Form extends Plugin {
+  constructor(uppy: Uppy, opts: Partial<Form.FormOptions>);
 }
 }
 
 
+export = Form;
+
 declare module '@uppy/core' {
 declare module '@uppy/core' {
   export interface Uppy {
   export interface Uppy {
-    use(pluginClass: typeof Form, opts: Partial<FormOptions>): Uppy;
+    use(pluginClass: typeof Form, opts: Partial<Form.FormOptions>): Uppy;
   }
   }
 }
 }

+ 4 - 4
packages/@uppy/golden-retriever/package.json

@@ -1,7 +1,7 @@
 {
 {
   "name": "@uppy/golden-retriever",
   "name": "@uppy/golden-retriever",
   "description": "The GoldenRetriever Uppy plugin saves selected files in browser cache to seamlessly resume uploding after browser crash or accidentally closed tab",
   "description": "The GoldenRetriever Uppy plugin saves selected files in browser cache to seamlessly resume uploding after browser crash or accidentally closed tab",
-  "version": "0.28.0",
+  "version": "0.29.0",
   "license": "MIT",
   "license": "MIT",
   "main": "lib/index.js",
   "main": "lib/index.js",
   "jsnext:main": "src/index.js",
   "jsnext:main": "src/index.js",
@@ -24,13 +24,13 @@
     "url": "git+https://github.com/transloadit/uppy.git"
     "url": "git+https://github.com/transloadit/uppy.git"
   },
   },
   "dependencies": {
   "dependencies": {
-    "@uppy/utils": "0.28.0",
+    "@uppy/utils": "0.29.0",
     "prettier-bytes": "^1.0.4"
     "prettier-bytes": "^1.0.4"
   },
   },
   "devDependencies": {
   "devDependencies": {
-    "@uppy/core": "0.28.0"
+    "@uppy/core": "0.29.0"
   },
   },
   "peerDependencies": {
   "peerDependencies": {
-    "@uppy/core": "^0.28.0"
+    "@uppy/core": "^0.29.0"
   }
   }
 }
 }

+ 11 - 7
packages/@uppy/golden-retriever/types/index.d.ts

@@ -1,17 +1,21 @@
 import { Plugin, PluginOptions, Uppy } from '@uppy/core';
 import { Plugin, PluginOptions, Uppy } from '@uppy/core';
 
 
-export interface GoldenRetrieverOptions extends PluginOptions {
-  expires: number;
-  serviceWorker: boolean;
-  indexedDB: any;
+declare module GoldenRetriever {
+  interface GoldenRetrieverOptions extends PluginOptions {
+    expires: number;
+    serviceWorker: boolean;
+    indexedDB: any;
+  }
 }
 }
 
 
-export default class GoldenRetriever extends Plugin {
-  constructor(uppy: Uppy, opts: Partial<GoldenRetrieverOptions>);
+declare class GoldenRetriever extends Plugin {
+  constructor(uppy: Uppy, opts: Partial<GoldenRetriever.GoldenRetrieverOptions>);
 }
 }
 
 
+export = GoldenRetriever;
+
 declare module '@uppy/core' {
 declare module '@uppy/core' {
   export interface Uppy {
   export interface Uppy {
-    use(pluginClass: typeof GoldenRetriever, opts: Partial<GoldenRetrieverOptions>): Uppy;
+    use(pluginClass: typeof GoldenRetriever, opts: Partial<GoldenRetriever.GoldenRetrieverOptions>): Uppy;
   }
   }
 }
 }

+ 5 - 5
packages/@uppy/google-drive/package.json

@@ -1,7 +1,7 @@
 {
 {
   "name": "@uppy/google-drive",
   "name": "@uppy/google-drive",
   "description": "The Google Drive plugin for Uppy lets users import files from their Google Drive account",
   "description": "The Google Drive plugin for Uppy lets users import files from their Google Drive account",
-  "version": "0.28.0",
+  "version": "0.29.0",
   "license": "MIT",
   "license": "MIT",
   "main": "lib/index.js",
   "main": "lib/index.js",
   "jsnext:main": "src/index.js",
   "jsnext:main": "src/index.js",
@@ -23,14 +23,14 @@
   },
   },
   "dependencies": {
   "dependencies": {
     "@uppy/companion-client": "0.27.2",
     "@uppy/companion-client": "0.27.2",
-    "@uppy/provider-views": "0.28.0",
-    "@uppy/utils": "0.28.0",
+    "@uppy/provider-views": "0.29.0",
+    "@uppy/utils": "0.29.0",
     "preact": "^8.2.9"
     "preact": "^8.2.9"
   },
   },
   "devDependencies": {
   "devDependencies": {
-    "@uppy/core": "0.28.0"
+    "@uppy/core": "0.29.0"
   },
   },
   "peerDependencies": {
   "peerDependencies": {
-    "@uppy/core": "^0.28.0"
+    "@uppy/core": "^0.29.0"
   }
   }
 }
 }

+ 4 - 2
packages/@uppy/google-drive/src/index.js

@@ -20,7 +20,7 @@ module.exports = class GoogleDrive extends Plugin {
       </svg>
       </svg>
     )
     )
 
 
-    this[this.id] = new Provider(uppy, {
+    this.provider = new Provider(uppy, {
       serverUrl: this.opts.serverUrl,
       serverUrl: this.opts.serverUrl,
       serverHeaders: this.opts.serverHeaders,
       serverHeaders: this.opts.serverHeaders,
       provider: 'drive',
       provider: 'drive',
@@ -32,7 +32,9 @@ module.exports = class GoogleDrive extends Plugin {
   }
   }
 
 
   install () {
   install () {
-    this.view = new DriveProviderViews(this)
+    this.view = new DriveProviderViews(this, {
+      provider: this.provider
+    })
     // Set default state for Google Drive
     // Set default state for Google Drive
     this.setPluginState({
     this.setPluginState({
       authenticated: false,
       authenticated: false,

+ 10 - 6
packages/@uppy/google-drive/types/index.d.ts

@@ -1,17 +1,21 @@
 import { Plugin, PluginOptions, Uppy } from '@uppy/core';
 import { Plugin, PluginOptions, Uppy } from '@uppy/core';
 import { ProviderOptions } from '@uppy/companion-client';
 import { ProviderOptions } from '@uppy/companion-client';
 
 
-export interface GoogleDriveOptions extends PluginOptions, ProviderOptions {
-  serverUrl: string;
-  serverPattern: string | RegExp | Array<string | RegExp>;
+declare module GoogleDrive {
+  interface GoogleDriveOptions extends PluginOptions, ProviderOptions {
+    serverUrl: string;
+    serverPattern: string | RegExp | Array<string | RegExp>;
+  }
 }
 }
 
 
-export default class GoogleDrive extends Plugin {
-  constructor(uppy: Uppy, opts: Partial<GoogleDriveOptions>);
+declare class GoogleDrive extends Plugin {
+  constructor(uppy: Uppy, opts: Partial<GoogleDrive.GoogleDriveOptions>);
 }
 }
 
 
+export = GoogleDrive;
+
 declare module '@uppy/core' {
 declare module '@uppy/core' {
   export interface Uppy {
   export interface Uppy {
-    use(pluginClass: typeof GoogleDrive, opts: Partial<GoogleDriveOptions>): Uppy;
+    use(pluginClass: typeof GoogleDrive, opts: Partial<GoogleDrive.GoogleDriveOptions>): Uppy;
   }
   }
 }
 }

+ 4 - 4
packages/@uppy/informer/package.json

@@ -1,7 +1,7 @@
 {
 {
   "name": "@uppy/informer",
   "name": "@uppy/informer",
   "description": "A notification and error pop-up bar for Uppy.",
   "description": "A notification and error pop-up bar for Uppy.",
-  "version": "0.28.0",
+  "version": "0.29.0",
   "license": "MIT",
   "license": "MIT",
   "main": "lib/index.js",
   "main": "lib/index.js",
   "jsnext:main": "src/index.js",
   "jsnext:main": "src/index.js",
@@ -24,13 +24,13 @@
     "url": "git+https://github.com/transloadit/uppy.git"
     "url": "git+https://github.com/transloadit/uppy.git"
   },
   },
   "dependencies": {
   "dependencies": {
-    "@uppy/utils": "0.28.0",
+    "@uppy/utils": "0.29.0",
     "preact": "^8.2.9"
     "preact": "^8.2.9"
   },
   },
   "devDependencies": {
   "devDependencies": {
-    "@uppy/core": "0.28.0"
+    "@uppy/core": "0.29.0"
   },
   },
   "peerDependencies": {
   "peerDependencies": {
-    "@uppy/core": "^0.28.0"
+    "@uppy/core": "^0.29.0"
   }
   }
 }
 }

+ 2 - 2
packages/@uppy/informer/src/style.scss

@@ -1,5 +1,5 @@
-@import '@uppy/core/src/style.scss';
-@import '@uppy/utils/src/microtip.scss';
+@import '@uppy/core/src/_utils.scss';
+@import '@uppy/core/src/_variables.scss';
 
 
 .uppy-Informer {
 .uppy-Informer {
   position: absolute;
   position: absolute;

+ 15 - 11
packages/@uppy/informer/types/index.d.ts

@@ -1,22 +1,26 @@
 import { Plugin, PluginOptions, Uppy } from '@uppy/core';
 import { Plugin, PluginOptions, Uppy } from '@uppy/core';
 
 
-interface Color {
-  bg: string | number;
-  text: string | number;
-}
+declare module Informer {
+  interface Color {
+    bg: string | number;
+    text: string | number;
+  }
 
 
-export interface InformerOptions extends PluginOptions {
-  typeColors: {
-    [type: string]: Color
-  };
+  interface InformerOptions extends PluginOptions {
+    typeColors: {
+      [type: string]: Color
+    };
+  }
 }
 }
 
 
-export default class Informer extends Plugin {
-  constructor(uppy: Uppy, opts: Partial<InformerOptions>);
+declare class Informer extends Plugin {
+  constructor(uppy: Uppy, opts: Partial<Informer.InformerOptions>);
 }
 }
 
 
+export = Informer;
+
 declare module '@uppy/core' {
 declare module '@uppy/core' {
   export interface Uppy {
   export interface Uppy {
-    use(pluginClass: typeof Informer, opts: Partial<InformerOptions>): Uppy;
+    use(pluginClass: typeof Informer, opts: Partial<Informer.InformerOptions>): Uppy;
   }
   }
 }
 }

+ 5 - 5
packages/@uppy/instagram/package.json

@@ -1,7 +1,7 @@
 {
 {
   "name": "@uppy/instagram",
   "name": "@uppy/instagram",
   "description": "Import photos and videos from Instagram, into Uppy.",
   "description": "Import photos and videos from Instagram, into Uppy.",
-  "version": "0.28.0",
+  "version": "0.29.0",
   "license": "MIT",
   "license": "MIT",
   "main": "lib/index.js",
   "main": "lib/index.js",
   "jsnext:main": "src/index.js",
   "jsnext:main": "src/index.js",
@@ -25,14 +25,14 @@
   },
   },
   "dependencies": {
   "dependencies": {
     "@uppy/companion-client": "0.27.2",
     "@uppy/companion-client": "0.27.2",
-    "@uppy/provider-views": "0.28.0",
-    "@uppy/utils": "0.28.0",
+    "@uppy/provider-views": "0.29.0",
+    "@uppy/utils": "0.29.0",
     "preact": "^8.2.9"
     "preact": "^8.2.9"
   },
   },
   "devDependencies": {
   "devDependencies": {
-    "@uppy/core": "0.28.0"
+    "@uppy/core": "0.29.0"
   },
   },
   "peerDependencies": {
   "peerDependencies": {
-    "@uppy/core": "^0.28.0"
+    "@uppy/core": "^0.29.0"
   }
   }
 }
 }

+ 2 - 1
packages/@uppy/instagram/src/index.js

@@ -17,7 +17,7 @@ module.exports = class Instagram extends Plugin {
       </svg>
       </svg>
     )
     )
 
 
-    this[this.id] = new Provider(uppy, {
+    this.provider = new Provider(uppy, {
       serverUrl: this.opts.serverUrl,
       serverUrl: this.opts.serverUrl,
       serverHeaders: this.opts.serverHeaders,
       serverHeaders: this.opts.serverHeaders,
       provider: 'instagram',
       provider: 'instagram',
@@ -30,6 +30,7 @@ module.exports = class Instagram extends Plugin {
 
 
   install () {
   install () {
     this.view = new ProviderViews(this, {
     this.view = new ProviderViews(this, {
+      provider: this.provider,
       viewType: 'grid',
       viewType: 'grid',
       showTitles: false,
       showTitles: false,
       showFilter: false,
       showFilter: false,

+ 10 - 6
packages/@uppy/instagram/types/index.d.ts

@@ -1,17 +1,21 @@
 import { Plugin, PluginOptions, Uppy } from '@uppy/core';
 import { Plugin, PluginOptions, Uppy } from '@uppy/core';
 import { ProviderOptions } from '@uppy/companion-client';
 import { ProviderOptions } from '@uppy/companion-client';
 
 
-export interface InstagramOptions extends PluginOptions, ProviderOptions {
-  serverUrl: string;
-  serverPattern: string | RegExp | Array<string | RegExp>;
+declare module Instagram {
+  interface InstagramOptions extends PluginOptions, ProviderOptions {
+    serverUrl: string;
+    serverPattern: string | RegExp | Array<string | RegExp>;
+  }
 }
 }
 
 
-export default class Instagram extends Plugin {
-  constructor(uppy: Uppy, opts: Partial<InstagramOptions>);
+declare class Instagram extends Plugin {
+  constructor(uppy: Uppy, opts: Partial<Instagram.InstagramOptions>);
 }
 }
 
 
+export = Instagram;
+
 declare module '@uppy/core' {
 declare module '@uppy/core' {
   export interface Uppy {
   export interface Uppy {
-    use(pluginClass: typeof Instagram, opts: Partial<InstagramOptions>): Uppy;
+    use(pluginClass: typeof Instagram, opts: Partial<Instagram.InstagramOptions>): Uppy;
   }
   }
 }
 }

+ 4 - 4
packages/@uppy/progress-bar/package.json

@@ -1,7 +1,7 @@
 {
 {
   "name": "@uppy/progress-bar",
   "name": "@uppy/progress-bar",
   "description": "A progress bar UI for Uppy",
   "description": "A progress bar UI for Uppy",
-  "version": "0.28.0",
+  "version": "0.29.0",
   "license": "MIT",
   "license": "MIT",
   "main": "lib/index.js",
   "main": "lib/index.js",
   "jsnext:main": "src/index.js",
   "jsnext:main": "src/index.js",
@@ -24,13 +24,13 @@
     "url": "git+https://github.com/transloadit/uppy.git"
     "url": "git+https://github.com/transloadit/uppy.git"
   },
   },
   "dependencies": {
   "dependencies": {
-    "@uppy/utils": "0.28.0",
+    "@uppy/utils": "0.29.0",
     "preact": "^8.2.9"
     "preact": "^8.2.9"
   },
   },
   "devDependencies": {
   "devDependencies": {
-    "@uppy/core": "0.28.0"
+    "@uppy/core": "0.29.0"
   },
   },
   "peerDependencies": {
   "peerDependencies": {
-    "@uppy/core": "^0.28.0"
+    "@uppy/core": "^0.29.0"
   }
   }
 }
 }

+ 2 - 1
packages/@uppy/progress-bar/src/style.scss

@@ -1,4 +1,5 @@
-@import '@uppy/core/src/style.scss';
+@import '@uppy/core/src/_utils.scss';
+@import '@uppy/core/src/_variables.scss';
 
 
 .uppy-ProgressBar {
 .uppy-ProgressBar {
   /* no important */
   /* no important */

+ 10 - 6
packages/@uppy/progress-bar/types/index.d.ts

@@ -1,16 +1,20 @@
 import { Plugin, PluginOptions, Uppy } from '@uppy/core';
 import { Plugin, PluginOptions, Uppy } from '@uppy/core';
 
 
-export interface ProgressBarOptions extends PluginOptions {
-  hideAfterFinish: boolean;
-  fixed: boolean;
+declare module ProgressBar {
+  interface ProgressBarOptions extends PluginOptions {
+    hideAfterFinish: boolean;
+    fixed: boolean;
+  }
 }
 }
 
 
-export default class ProgressBar extends Plugin {
-  constructor(uppy: Uppy, opts: Partial<ProgressBarOptions>);
+declare class ProgressBar extends Plugin {
+  constructor(uppy: Uppy, opts: Partial<ProgressBar.ProgressBarOptions>);
 }
 }
 
 
+export = ProgressBar;
+
 declare module '@uppy/core' {
 declare module '@uppy/core' {
   export interface Uppy {
   export interface Uppy {
-    use(pluginClass: typeof ProgressBar, opts: Partial<ProgressBarOptions>): Uppy;
+    use(pluginClass: typeof ProgressBar, opts: Partial<ProgressBar.ProgressBarOptions>): Uppy;
   }
   }
 }
 }

+ 4 - 4
packages/@uppy/provider-views/package.json

@@ -1,7 +1,7 @@
 {
 {
   "name": "@uppy/provider-views",
   "name": "@uppy/provider-views",
   "description": "View library for Uppy remote provider plugins.",
   "description": "View library for Uppy remote provider plugins.",
-  "version": "0.28.0",
+  "version": "0.29.0",
   "license": "MIT",
   "license": "MIT",
   "main": "lib/index.js",
   "main": "lib/index.js",
   "jsnext:main": "src/index.js",
   "jsnext:main": "src/index.js",
@@ -20,14 +20,14 @@
     "url": "git+https://github.com/transloadit/uppy.git"
     "url": "git+https://github.com/transloadit/uppy.git"
   },
   },
   "dependencies": {
   "dependencies": {
-    "@uppy/utils": "0.28.0",
+    "@uppy/utils": "0.29.0",
     "classnames": "^2.2.6",
     "classnames": "^2.2.6",
     "preact": "^8.2.9"
     "preact": "^8.2.9"
   },
   },
   "devDependencies": {
   "devDependencies": {
-    "@uppy/core": "0.28.0"
+    "@uppy/core": "0.29.0"
   },
   },
   "peerDependencies": {
   "peerDependencies": {
-    "@uppy/core": "^0.28.0"
+    "@uppy/core": "^0.29.0"
   }
   }
 }
 }

+ 11 - 11
packages/@uppy/provider-views/src/index.js

@@ -35,7 +35,7 @@ module.exports = class ProviderView {
    */
    */
   constructor (plugin, opts) {
   constructor (plugin, opts) {
     this.plugin = plugin
     this.plugin = plugin
-    this.Provider = plugin[plugin.id]
+    this.provider = opts.provider
 
 
     // set default options
     // set default options
     const defaultOptions = {
     const defaultOptions = {
@@ -94,7 +94,7 @@ module.exports = class ProviderView {
 
 
   checkAuth () {
   checkAuth () {
     this.plugin.setPluginState({ checkAuthInProgress: true })
     this.plugin.setPluginState({ checkAuthInProgress: true })
-    this.Provider.checkAuth()
+    this.provider.checkAuth()
       .then((authenticated) => {
       .then((authenticated) => {
         this.plugin.setPluginState({ checkAuthInProgress: false })
         this.plugin.setPluginState({ checkAuthInProgress: false })
         this.plugin.onAuth(authenticated)
         this.plugin.onAuth(authenticated)
@@ -112,7 +112,7 @@ module.exports = class ProviderView {
    */
    */
   getFolder (id, name) {
   getFolder (id, name) {
     return this._loaderWrapper(
     return this._loaderWrapper(
-      this.Provider.list(id),
+      this.provider.list(id),
       (res) => {
       (res) => {
         let folders = []
         let folders = []
         let files = []
         let files = []
@@ -158,11 +158,11 @@ module.exports = class ProviderView {
       },
       },
       remote: {
       remote: {
         serverUrl: this.plugin.opts.serverUrl,
         serverUrl: this.plugin.opts.serverUrl,
-        url: `${this.Provider.fileUrl(file.requestPath)}`,
+        url: `${this.provider.fileUrl(file.requestPath)}`,
         body: {
         body: {
           fileId: file.id
           fileId: file.id
         },
         },
-        providerOptions: this.Provider.opts
+        providerOptions: this.provider.opts
       }
       }
     }
     }
 
 
@@ -190,7 +190,7 @@ module.exports = class ProviderView {
    * Removes session token on client side.
    * Removes session token on client side.
    */
    */
   logout () {
   logout () {
-    this.Provider.logout(location.href)
+    this.provider.logout(location.href)
       .then((res) => {
       .then((res) => {
         if (res.ok) {
         if (res.ok) {
           const newState = {
           const newState = {
@@ -336,7 +336,7 @@ module.exports = class ProviderView {
     }
     }
     folders[folderId] = {loading: true, files: []}
     folders[folderId] = {loading: true, files: []}
     this.plugin.setPluginState({selectedFolders: folders})
     this.plugin.setPluginState({selectedFolders: folders})
-    return this.Provider.list(folder.requestPath).then((res) => {
+    return this.provider.list(folder.requestPath).then((res) => {
       let files = []
       let files = []
       res.items.forEach((item) => {
       res.items.forEach((item) => {
         if (!item.isFolder) {
         if (!item.isFolder) {
@@ -423,7 +423,7 @@ module.exports = class ProviderView {
 
 
   handleAuth () {
   handleAuth () {
     const authState = btoa(JSON.stringify({ origin: location.origin }))
     const authState = btoa(JSON.stringify({ origin: location.origin }))
-    const link = `${this.Provider.authUrl()}?state=${authState}`
+    const link = `${this.provider.authUrl()}?state=${authState}`
 
 
     const authWindow = window.open(link, '_blank')
     const authWindow = window.open(link, '_blank')
     const handleToken = (e) => {
     const handleToken = (e) => {
@@ -433,8 +433,8 @@ module.exports = class ProviderView {
       }
       }
       authWindow.close()
       authWindow.close()
       window.removeEventListener('message', handleToken)
       window.removeEventListener('message', handleToken)
-      this.Provider.setAuthToken(e.data.token)
-      this._loaderWrapper(this.Provider.checkAuth(), this.plugin.onAuth, this.handleError)
+      this.provider.setAuthToken(e.data.token)
+      this._loaderWrapper(this.provider.checkAuth(), this.plugin.onAuth, this.handleError)
     }
     }
     window.addEventListener('message', handleToken)
     window.addEventListener('message', handleToken)
   }
   }
@@ -466,7 +466,7 @@ module.exports = class ProviderView {
     const path = this.nextPagePath ? this.nextPagePath : null
     const path = this.nextPagePath ? this.nextPagePath : null
 
 
     if (scrollPos < 50 && path && !this._isHandlingScroll) {
     if (scrollPos < 50 && path && !this._isHandlingScroll) {
-      this.Provider.list(path)
+      this.provider.list(path)
         .then((res) => {
         .then((res) => {
           const { files, folders } = this.plugin.getPluginState()
           const { files, folders } = this.plugin.getPluginState()
           this._updateFilesAndFolders(res, files, folders)
           this._updateFilesAndFolders(res, files, folders)

+ 2 - 1
packages/@uppy/provider-views/src/style.scss

@@ -1,4 +1,5 @@
-@import '@uppy/core/src/style.scss';
+@import '@uppy/core/src/_utils.scss';
+@import '@uppy/core/src/_variables.scss';
 
 
 .uppy-DashboardContent-panelBody {
 .uppy-DashboardContent-panelBody {
   display: flex;
   display: flex;

+ 8 - 8
packages/@uppy/react/package.json

@@ -1,7 +1,7 @@
 {
 {
   "name": "@uppy/react",
   "name": "@uppy/react",
   "description": "React component wrappers around Uppy's official UI plugins.",
   "description": "React component wrappers around Uppy's official UI plugins.",
-  "version": "0.28.0",
+  "version": "0.29.0",
   "license": "MIT",
   "license": "MIT",
   "main": "index.js",
   "main": "index.js",
   "module": "index.mjs",
   "module": "index.mjs",
@@ -22,17 +22,17 @@
     "url": "git+https://github.com/transloadit/uppy.git"
     "url": "git+https://github.com/transloadit/uppy.git"
   },
   },
   "dependencies": {
   "dependencies": {
-    "@uppy/dashboard": "0.28.0",
-    "@uppy/drag-drop": "0.28.0",
-    "@uppy/progress-bar": "0.28.0",
-    "@uppy/status-bar": "0.28.0",
-    "@uppy/utils": "0.28.0",
+    "@uppy/dashboard": "0.29.0",
+    "@uppy/drag-drop": "0.29.0",
+    "@uppy/progress-bar": "0.29.0",
+    "@uppy/status-bar": "0.29.0",
+    "@uppy/utils": "0.29.0",
     "prop-types": "^15.6.1"
     "prop-types": "^15.6.1"
   },
   },
   "devDependencies": {
   "devDependencies": {
-    "@uppy/core": "0.28.0"
+    "@uppy/core": "0.29.0"
   },
   },
   "peerDependencies": {
   "peerDependencies": {
-    "@uppy/core": "^0.28.0"
+    "@uppy/core": "^0.29.0"
   }
   }
 }
 }

+ 6 - 0
packages/@uppy/react/src/CommonTypes.d.ts

@@ -0,0 +1,6 @@
+export { Uppy } from '../../core/types';
+
+export interface Locale {
+    strings: { [index: string]: string };
+    pluralize: (noun: string) => string;
+}

+ 33 - 0
packages/@uppy/react/src/Dashboard.d.ts

@@ -0,0 +1,33 @@
+import { Uppy, Locale } from './CommonTypes';
+
+interface MetaField {
+    id: string;
+    name: string;
+    placeholder?: string;
+}
+
+export interface DashboardProps {
+    uppy: Uppy;
+    inline?: boolean;
+    plugins?: Array<string>;
+    width?: number;
+    height?: number;
+    showProgressDetails?: boolean;
+    showLinkToFileUploadResult?: boolean;
+    hideUploadButton?: boolean;
+    hideProgressAfterFinish?: boolean;
+    note?: string;
+    metaFields?: Array<MetaField>;
+    proudlyDisplayPoweredByUppy?: boolean;
+    disableStatusBar?: boolean;
+    disableInformer?: boolean;
+    disableThumbnailGenerator?: boolean;
+    locale?: Locale;
+}
+
+/**
+ * React Component that renders a Dashboard for an Uppy instance. This component
+ * renders the Dashboard inline; so you can put it anywhere you want.
+ */
+declare const Dashboard: React.ComponentType<DashboardProps>;
+export default Dashboard;

+ 16 - 0
packages/@uppy/react/src/DashboardModal.d.ts

@@ -0,0 +1,16 @@
+import { DashboardProps } from './Dashboard';
+
+export interface DashboardModalProps extends DashboardProps {
+    target?: HTMLElement;
+    open?: boolean;
+    onRequestClose?: VoidFunction;
+    closeModalOnClickOutside?: boolean;
+    disablePageScrollWhenModalOpen?: boolean;
+}
+
+/**
+ * React Component that renders a Dashboard for an Uppy instance in a Modal
+ * dialog. Visibility of the Modal is toggled using the `open` prop.
+ */
+declare const DashboardModal: React.ComponentType<DashboardModalProps>;
+export default DashboardModal;

+ 13 - 0
packages/@uppy/react/src/DragDrop.d.ts

@@ -0,0 +1,13 @@
+import { Uppy, Locale } from './CommonTypes';
+
+export interface DragDropProps {
+    uppy: Uppy;
+    locale?: Locale;
+}
+
+/**
+ * React component that renders an area in which files can be dropped to be
+ * uploaded.
+ */
+declare const DragDrop: React.ComponentType<DragDropProps>;
+export default DragDrop;

+ 13 - 0
packages/@uppy/react/src/ProgressBar.d.ts

@@ -0,0 +1,13 @@
+import { Uppy } from './CommonTypes';
+
+export interface ProgressBarProps {
+    uppy: Uppy;
+    fixed?: boolean;
+    hideAfterFinish?: boolean;
+}
+
+/**
+ * React component that renders a progress bar at the top of the page.
+ */
+declare const ProgressBar: React.ComponentType<ProgressBarProps>;
+export default ProgressBar;

+ 14 - 0
packages/@uppy/react/src/StatusBar.d.ts

@@ -0,0 +1,14 @@
+import { Uppy } from './CommonTypes';
+
+export interface StatusBarProps {
+    uppy: Uppy;
+    showProgressDetails?: boolean;
+    hideAfterFinish?: boolean;
+}
+
+/**
+ * React component that renders a status bar containing upload progress and speed,
+ * processing progress and pause/resume/cancel controls.
+ */
+declare const StatusBar: React.ComponentType<StatusBarProps>;
+export default StatusBar;

+ 7 - 0
packages/@uppy/react/types/index.d.ts

@@ -0,0 +1,7 @@
+import * as React from 'react';
+
+export { default as Dashboard } from '../src/Dashboard';
+export { default as DashboardModal } from '../src/DashboardModal';
+export { default as DragDrop } from '../src/DragDrop';
+export { default as ProgressBar } from '../src/ProgressBar';
+export { default as StatusBar } from '../src/StatusBar';

+ 3 - 3
packages/@uppy/redux-dev-tools/package.json

@@ -1,7 +1,7 @@
 {
 {
   "name": "@uppy/redux-dev-tools",
   "name": "@uppy/redux-dev-tools",
   "description": "Redux developer tools plugin for Uppy that simply syncs Uppy’s state with redux-devtools browser or JS extensions, and allows for basic time travel",
   "description": "Redux developer tools plugin for Uppy that simply syncs Uppy’s state with redux-devtools browser or JS extensions, and allows for basic time travel",
-  "version": "0.28.0",
+  "version": "0.29.0",
   "license": "MIT",
   "license": "MIT",
   "main": "lib/index.js",
   "main": "lib/index.js",
   "jsnext:main": "src/index.js",
   "jsnext:main": "src/index.js",
@@ -22,9 +22,9 @@
     "url": "git+https://github.com/transloadit/uppy.git"
     "url": "git+https://github.com/transloadit/uppy.git"
   },
   },
   "devDependencies": {
   "devDependencies": {
-    "@uppy/core": "0.28.0"
+    "@uppy/core": "0.29.0"
   },
   },
   "peerDependencies": {
   "peerDependencies": {
-    "@uppy/core": "^0.28.0"
+    "@uppy/core": "^0.29.0"
   }
   }
 }
 }

+ 8 - 4
packages/@uppy/redux-dev-tools/types/index.d.ts

@@ -1,14 +1,18 @@
 import { Plugin, PluginOptions, Uppy } from '@uppy/core';
 import { Plugin, PluginOptions, Uppy } from '@uppy/core';
 
 
-export interface ReduxDevToolsOptions extends PluginOptions {
+declare module ReduxDevTools {
+  interface ReduxDevToolsOptions extends PluginOptions {
+  }
 }
 }
 
 
-export default class ReduxDevTools extends Plugin {
-  constructor(uppy: Uppy, opts: Partial<ReduxDevToolsOptions>);
+declare class ReduxDevTools extends Plugin {
+  constructor(uppy: Uppy, opts: Partial<ReduxDevTools.ReduxDevToolsOptions>);
 }
 }
 
 
+export = ReduxDevTools;
+
 declare module '@uppy/core' {
 declare module '@uppy/core' {
   export interface Uppy {
   export interface Uppy {
-    use(pluginClass: typeof ReduxDevTools, opts: Partial<ReduxDevToolsOptions>): Uppy;
+    use(pluginClass: typeof ReduxDevTools, opts: Partial<ReduxDevTools.ReduxDevToolsOptions>): Uppy;
   }
   }
 }
 }

+ 4 - 4
packages/@uppy/status-bar/package.json

@@ -1,7 +1,7 @@
 {
 {
   "name": "@uppy/status-bar",
   "name": "@uppy/status-bar",
   "description": "A progress bar for Uppy, with many bells and whistles.",
   "description": "A progress bar for Uppy, with many bells and whistles.",
-  "version": "0.28.0",
+  "version": "0.29.0",
   "license": "MIT",
   "license": "MIT",
   "main": "lib/index.js",
   "main": "lib/index.js",
   "jsnext:main": "src/index.js",
   "jsnext:main": "src/index.js",
@@ -27,16 +27,16 @@
     "url": "git+https://github.com/transloadit/uppy.git"
     "url": "git+https://github.com/transloadit/uppy.git"
   },
   },
   "dependencies": {
   "dependencies": {
-    "@uppy/utils": "0.28.0",
+    "@uppy/utils": "0.29.0",
     "classnames": "^2.2.6",
     "classnames": "^2.2.6",
     "lodash.throttle": "^4.1.1",
     "lodash.throttle": "^4.1.1",
     "preact": "^8.2.9",
     "preact": "^8.2.9",
     "prettier-bytes": "^1.0.4"
     "prettier-bytes": "^1.0.4"
   },
   },
   "devDependencies": {
   "devDependencies": {
-    "@uppy/core": "0.28.0"
+    "@uppy/core": "0.29.0"
   },
   },
   "peerDependencies": {
   "peerDependencies": {
-    "@uppy/core": "^0.28.0"
+    "@uppy/core": "^0.29.0"
   }
   }
 }
 }

+ 15 - 2
packages/@uppy/status-bar/src/StatusBar.js

@@ -80,6 +80,11 @@ module.exports = (props) => {
   } else if (uploadState === statusBarStates.STATE_COMPLETE) {
   } else if (uploadState === statusBarStates.STATE_COMPLETE) {
     progressBarContent = ProgressBarComplete(props)
     progressBarContent = ProgressBarComplete(props)
   } else if (uploadState === statusBarStates.STATE_UPLOADING) {
   } else if (uploadState === statusBarStates.STATE_UPLOADING) {
+    if (!props.supportsUploadProgress) {
+      progressMode = 'indeterminate'
+      progressValue = null
+    }
+
     progressBarContent = ProgressBarUploading(props)
     progressBarContent = ProgressBarUploading(props)
   } else if (uploadState === statusBarStates.STATE_ERROR) {
   } else if (uploadState === statusBarStates.STATE_ERROR) {
     progressValue = undefined
     progressValue = undefined
@@ -214,6 +219,12 @@ const ProgressDetails = (props) => {
   </div>
   </div>
 }
 }
 
 
+const UnknownProgressDetails = (props) => {
+  return <div class="uppy-StatusBar-statusSecondary">
+    { props.i18n('filesUploadedOfTotal', { complete: props.complete, smart_count: props.numUploads }) }
+  </div>
+}
+
 const UploadNewlyAddedFiles = (props) => {
 const UploadNewlyAddedFiles = (props) => {
   const uploadBtnClassNames = classNames(
   const uploadBtnClassNames = classNames(
     'uppy-u-reset',
     'uppy-u-reset',
@@ -248,9 +259,11 @@ const ProgressBarUploading = (props) => {
     <div class="uppy-StatusBar-content" aria-label={title} title={title}>
     <div class="uppy-StatusBar-content" aria-label={title} title={title}>
       { !props.isAllPaused ? <LoadingSpinner {...props} /> : null }
       { !props.isAllPaused ? <LoadingSpinner {...props} /> : null }
       <div class="uppy-StatusBar-status">
       <div class="uppy-StatusBar-status">
-        <div class="uppy-StatusBar-statusPrimary">{title}: {props.totalProgress}%</div>
+        <div class="uppy-StatusBar-statusPrimary">
+          {props.supportsUploadProgress ? `${title}: ${props.totalProgress}%` : title}
+        </div>
         { !props.isAllPaused && !showUploadNewlyAddedFiles && props.showProgressDetails
         { !props.isAllPaused && !showUploadNewlyAddedFiles && props.showProgressDetails
-          ? <ThrottledProgressDetails {...props} />
+          ? (props.supportsUploadProgress ? <ThrottledProgressDetails {...props} /> : <UnknownProgressDetails {...props} />)
           : null
           : null
         }
         }
         { showUploadNewlyAddedFiles ? <UploadNewlyAddedFiles {...props} /> : null }
         { showUploadNewlyAddedFiles ? <UploadNewlyAddedFiles {...props} /> : null }

+ 3 - 1
packages/@uppy/status-bar/src/index.js

@@ -222,6 +222,7 @@ module.exports = class StatusBar extends Plugin {
     const isUploadInProgress = inProgressFiles.length > 0
     const isUploadInProgress = inProgressFiles.length > 0
 
 
     const resumableUploads = capabilities.resumableUploads || false
     const resumableUploads = capabilities.resumableUploads || false
+    const supportsUploadProgress = capabilities.uploadProgress !== false
 
 
     return StatusBarUI({
     return StatusBarUI({
       error,
       error,
@@ -246,7 +247,8 @@ module.exports = class StatusBar extends Plugin {
       retryAll: this.uppy.retryAll,
       retryAll: this.uppy.retryAll,
       cancelAll: this.uppy.cancelAll,
       cancelAll: this.uppy.cancelAll,
       startUpload: this.startUpload,
       startUpload: this.startUpload,
-      resumableUploads: resumableUploads,
+      resumableUploads,
+      supportsUploadProgress,
       showProgressDetails: this.opts.showProgressDetails,
       showProgressDetails: this.opts.showProgressDetails,
       hideUploadButton: this.opts.hideUploadButton,
       hideUploadButton: this.opts.hideUploadButton,
       hideRetryButton: this.opts.hideRetryButton,
       hideRetryButton: this.opts.hideRetryButton,

+ 8 - 3
packages/@uppy/status-bar/src/style.scss

@@ -1,4 +1,5 @@
-@import '@uppy/core/src/style.scss';
+@import '@uppy/core/src/_utils.scss';
+@import '@uppy/core/src/_variables.scss';
 @import '@uppy/utils/src/microtip.scss';
 @import '@uppy/utils/src/microtip.scss';
 
 
 .uppy-StatusBar {
 .uppy-StatusBar {
@@ -63,8 +64,7 @@
   transition: background-color, width .3s ease-out;
   transition: background-color, width .3s ease-out;
 
 
   &.is-indeterminate {
   &.is-indeterminate {
-    background-color: $color-orange;
-    $stripe-color: darken($color-orange, 10%);
+    $stripe-color: rgba(0, 0, 0, 0.3);
     background-size: 64px 64px;
     background-size: 64px 64px;
     background-image: linear-gradient(45deg, $stripe-color 25%, transparent 25%, transparent 50%, $stripe-color 50%, $stripe-color 75%, transparent 75%, transparent);
     background-image: linear-gradient(45deg, $stripe-color 25%, transparent 25%, transparent 50%, $stripe-color 50%, $stripe-color 75%, transparent 75%, transparent);
     animation: uppy-StatusBar-ProgressStripes 1s linear infinite;
     animation: uppy-StatusBar-ProgressStripes 1s linear infinite;
@@ -76,6 +76,11 @@
     to { background-position: 64px 0; }
     to { background-position: 64px 0; }
   }
   }
 
 
+  .uppy-StatusBar.is-preprocessing .uppy-StatusBar-progress,
+  .uppy-StatusBar.is-postprocessing .uppy-StatusBar-progress {
+    background-color: $color-orange;
+  }
+
 .uppy-StatusBar.is-waiting .uppy-StatusBar-progress {
 .uppy-StatusBar.is-waiting .uppy-StatusBar-progress {
   display: none;
   display: none;
 }
 }

+ 11 - 7
packages/@uppy/status-bar/types/index.d.ts

@@ -1,17 +1,21 @@
 import { Plugin, PluginOptions, Uppy } from '@uppy/core';
 import { Plugin, PluginOptions, Uppy } from '@uppy/core';
 
 
-export interface StatusBarOptions extends PluginOptions {
-  showProgressDetails: boolean;
-  hideUploadButton: boolean;
-  hideAfterFinish: boolean;
+declare module StatusBar {
+  export interface StatusBarOptions extends PluginOptions {
+    showProgressDetails: boolean;
+    hideUploadButton: boolean;
+    hideAfterFinish: boolean;
+  }
 }
 }
 
 
-export default class StatusBar extends Plugin {
-  constructor(uppy: Uppy, opts: Partial<StatusBarOptions>);
+declare class StatusBar extends Plugin {
+  constructor(uppy: Uppy, opts: Partial<StatusBar.StatusBarOptions>);
 }
 }
 
 
+export = StatusBar;
+
 declare module '@uppy/core' {
 declare module '@uppy/core' {
   export interface Uppy {
   export interface Uppy {
-    use(pluginClass: typeof StatusBar, opts: Partial<StatusBarOptions>): Uppy;
+    use(pluginClass: typeof StatusBar, opts: Partial<StatusBar.StatusBarOptions>): Uppy;
   }
   }
 }
 }

+ 2 - 1
packages/@uppy/store-default/types/index.d.ts

@@ -7,4 +7,5 @@ declare class DefaultStore implements Store {
   subscribe(listener: any): () => void;
   subscribe(listener: any): () => void;
 }
 }
 
 
-export default function createDefaultStore(): DefaultStore;
+declare function createDefaultStore(): DefaultStore;
+export = createDefaultStore;

+ 8 - 1
packages/@uppy/store-redux/types/index.d.ts

@@ -14,6 +14,13 @@ declare class ReduxStore implements Store {
   subscribe(listener: any): () => void;
   subscribe(listener: any): () => void;
 }
 }
 
 
-export default function createReduxStore(opts: ReduxStoreOptions): ReduxStore;
 export const reducer: Reducer<object>;
 export const reducer: Reducer<object>;
 export const middleware: Middleware;
 export const middleware: Middleware;
+// Redux action name.
+export const STATE_UPDATE: string;
+
+// Typescript forbids the next two lines with the following error message:
+// "An export assignment cannot be used in a module with other exported elements."
+
+// declare function createReduxStore(opts: ReduxStoreOptions): ReduxStore;
+// export = createReduxStore;

+ 4 - 4
packages/@uppy/thumbnail-generator/package.json

@@ -1,7 +1,7 @@
 {
 {
   "name": "@uppy/thumbnail-generator",
   "name": "@uppy/thumbnail-generator",
   "description": "Uppy plugin that generates small previews of images to show on your upload UI.",
   "description": "Uppy plugin that generates small previews of images to show on your upload UI.",
-  "version": "0.28.0",
+  "version": "0.29.0",
   "license": "MIT",
   "license": "MIT",
   "main": "lib/index.js",
   "main": "lib/index.js",
   "jsnext:main": "src/index.js",
   "jsnext:main": "src/index.js",
@@ -23,13 +23,13 @@
     "url": "git+https://github.com/transloadit/uppy.git"
     "url": "git+https://github.com/transloadit/uppy.git"
   },
   },
   "dependencies": {
   "dependencies": {
-    "@uppy/utils": "0.28.0"
+    "@uppy/utils": "0.29.0"
   },
   },
   "devDependencies": {
   "devDependencies": {
-    "@uppy/core": "0.28.0",
+    "@uppy/core": "0.29.0",
     "namespace-emitter": "^2.0.1"
     "namespace-emitter": "^2.0.1"
   },
   },
   "peerDependencies": {
   "peerDependencies": {
-    "@uppy/core": "^0.28.0"
+    "@uppy/core": "^0.29.0"
   }
   }
 }
 }

+ 9 - 5
packages/@uppy/thumbnail-generator/types/index.d.ts

@@ -1,15 +1,19 @@
 import { Plugin, PluginOptions, Uppy } from '@uppy/core';
 import { Plugin, PluginOptions, Uppy } from '@uppy/core';
 
 
-export interface ThumbnailGeneratorOptions extends PluginOptions {
-  thumbnailWidth: number;
+declare module ThumbnailGenerator {
+  interface ThumbnailGeneratorOptions extends PluginOptions {
+    thumbnailWidth: number;
+  }
 }
 }
 
 
-export default class ThumbnailGenerator extends Plugin {
-  constructor(uppy: Uppy, opts: Partial<ThumbnailGeneratorOptions>);
+declare class ThumbnailGenerator extends Plugin {
+  constructor(uppy: Uppy, opts: Partial<ThumbnailGenerator.ThumbnailGeneratorOptions>);
 }
 }
 
 
+export = ThumbnailGenerator;
+
 declare module '@uppy/core' {
 declare module '@uppy/core' {
   export interface Uppy {
   export interface Uppy {
-    use(pluginClass: typeof ThumbnailGenerator, opts: Partial<ThumbnailGeneratorOptions>): Uppy;
+    use(pluginClass: typeof ThumbnailGenerator, opts: Partial<ThumbnailGenerator.ThumbnailGeneratorOptions>): Uppy;
   }
   }
 }
 }

+ 6 - 6
packages/@uppy/transloadit/package.json

@@ -1,7 +1,7 @@
 {
 {
   "name": "@uppy/transloadit",
   "name": "@uppy/transloadit",
   "description": "The Transloadit plugin can be used to upload files to Transloadit for all kinds of processing, such as transcoding video, resizing images, zipping/unzipping, and more",
   "description": "The Transloadit plugin can be used to upload files to Transloadit for all kinds of processing, such as transcoding video, resizing images, zipping/unzipping, and more",
-  "version": "0.28.0",
+  "version": "0.29.0",
   "license": "MIT",
   "license": "MIT",
   "main": "lib/index.js",
   "main": "lib/index.js",
   "jsnext:main": "src/index.js",
   "jsnext:main": "src/index.js",
@@ -29,16 +29,16 @@
   },
   },
   "dependencies": {
   "dependencies": {
     "@uppy/companion-client": "0.27.2",
     "@uppy/companion-client": "0.27.2",
-    "@uppy/provider-views": "0.28.0",
-    "@uppy/tus": "0.28.0",
-    "@uppy/utils": "0.28.0",
+    "@uppy/provider-views": "0.29.0",
+    "@uppy/tus": "0.29.0",
+    "@uppy/utils": "0.29.0",
     "component-emitter": "^1.2.1",
     "component-emitter": "^1.2.1",
     "socket.io-client": "^2.1.1"
     "socket.io-client": "^2.1.1"
   },
   },
   "devDependencies": {
   "devDependencies": {
-    "@uppy/core": "0.28.0"
+    "@uppy/core": "0.29.0"
   },
   },
   "peerDependencies": {
   "peerDependencies": {
-    "@uppy/core": "^0.28.0"
+    "@uppy/core": "^0.29.0"
   }
   }
 }
 }

+ 28 - 24
packages/@uppy/transloadit/types/index.d.ts

@@ -1,36 +1,40 @@
 import { Plugin, PluginOptions, Uppy, UppyFile } from '@uppy/core';
 import { Plugin, PluginOptions, Uppy, UppyFile } from '@uppy/core';
 
 
-export interface AssemblyParameters {
-  auth: { key: string };
-  template_id?: string;
-  steps?: { [step: string]: object };
-  notify_url?: string;
-  fields?: { [name: string]: number | string };
-}
+declare module Transloadit {
+  interface AssemblyParameters {
+    auth: { key: string };
+    template_id?: string;
+    steps?: { [step: string]: object };
+    notify_url?: string;
+    fields?: { [name: string]: number | string };
+  }
 
 
-export interface AssemblyOptions {
-  params: AssemblyParameters;
-  fields?: { [name: string]: number | string };
-  signature?: string;
-}
+  interface AssemblyOptions {
+    params: AssemblyParameters;
+    fields?: { [name: string]: number | string };
+    signature?: string;
+  }
 
 
-export interface TransloaditOptions extends PluginOptions {
-  params: AssemblyParameters;
-  signature: string;
-  service: string;
-  waitForEncoding: boolean;
-  waitForMetadata: boolean;
-  importFromUploadURLs: boolean;
-  alwaysRunAssembly: boolean;
-  getAssemblyOptions: (file: UppyFile) => AssemblyOptions | Promise<AssemblyOptions>;
+  interface TransloaditOptions extends PluginOptions {
+    params: AssemblyParameters;
+    signature: string;
+    service: string;
+    waitForEncoding: boolean;
+    waitForMetadata: boolean;
+    importFromUploadURLs: boolean;
+    alwaysRunAssembly: boolean;
+    getAssemblyOptions: (file: UppyFile) => AssemblyOptions | Promise<AssemblyOptions>;
+  }
 }
 }
 
 
-export default class Transloadit extends Plugin {
-  constructor(uppy: Uppy, opts: Partial<TransloaditOptions>);
+declare class Transloadit extends Plugin {
+  constructor(uppy: Uppy, opts: Partial<Transloadit.TransloaditOptions>);
 }
 }
 
 
+export = Transloadit;
+
 declare module '@uppy/core' {
 declare module '@uppy/core' {
   export interface Uppy {
   export interface Uppy {
-    use(pluginClass: typeof Transloadit, opts: Partial<TransloaditOptions>): Uppy;
+    use(pluginClass: typeof Transloadit, opts: Partial<Transloadit.TransloaditOptions>): Uppy;
   }
   }
 }
 }

+ 4 - 4
packages/@uppy/tus/package.json

@@ -1,7 +1,7 @@
 {
 {
   "name": "@uppy/tus",
   "name": "@uppy/tus",
   "description": "Resumable uploads for Uppy using Tus.io",
   "description": "Resumable uploads for Uppy using Tus.io",
-  "version": "0.28.0",
+  "version": "0.29.0",
   "license": "MIT",
   "license": "MIT",
   "main": "lib/index.js",
   "main": "lib/index.js",
   "jsnext:main": "src/index.js",
   "jsnext:main": "src/index.js",
@@ -24,13 +24,13 @@
   },
   },
   "dependencies": {
   "dependencies": {
     "@uppy/companion-client": "0.27.2",
     "@uppy/companion-client": "0.27.2",
-    "@uppy/utils": "0.28.0",
+    "@uppy/utils": "0.29.0",
     "tus-js-client": "^1.5.1"
     "tus-js-client": "^1.5.1"
   },
   },
   "devDependencies": {
   "devDependencies": {
-    "@uppy/core": "0.28.0"
+    "@uppy/core": "0.29.0"
   },
   },
   "peerDependencies": {
   "peerDependencies": {
-    "@uppy/core": "^0.28.0"
+    "@uppy/core": "^0.29.0"
   }
   }
 }
 }

+ 14 - 10
packages/@uppy/tus/types/index.d.ts

@@ -1,20 +1,24 @@
 import { Plugin, PluginOptions, Uppy } from '@uppy/core';
 import { Plugin, PluginOptions, Uppy } from '@uppy/core';
 
 
-export interface TusOptions extends PluginOptions {
-  limit: number;
-  endpoint: string;
-  uploadUrl: string;
-  useFastRemoteRetry: boolean;
-  resume: boolean;
-  autoRetry: boolean;
+declare module Tus {
+  export interface TusOptions extends PluginOptions {
+    limit: number;
+    endpoint: string;
+    uploadUrl: string;
+    useFastRemoteRetry: boolean;
+    resume: boolean;
+    autoRetry: boolean;
+  }
 }
 }
 
 
-export default class Tus extends Plugin {
-  constructor(uppy: Uppy, opts: Partial<TusOptions>);
+declare class Tus extends Plugin {
+  constructor(uppy: Uppy, opts: Partial<Tus.TusOptions>);
 }
 }
 
 
+export = Tus;
+
 declare module '@uppy/core' {
 declare module '@uppy/core' {
   export interface Uppy {
   export interface Uppy {
-    use(pluginClass: typeof Tus, opts: Partial<TusOptions>): Uppy;
+    use(pluginClass: typeof Tus, opts: Partial<Tus.TusOptions>): Uppy;
   }
   }
 }
 }

+ 4 - 4
packages/@uppy/url/package.json

@@ -1,7 +1,7 @@
 {
 {
   "name": "@uppy/url",
   "name": "@uppy/url",
   "description": "The Url plugin lets users import files from the Internet. Paste any URL and it’ll be added!",
   "description": "The Url plugin lets users import files from the Internet. Paste any URL and it’ll be added!",
-  "version": "0.28.0",
+  "version": "0.29.0",
   "license": "MIT",
   "license": "MIT",
   "main": "lib/index.js",
   "main": "lib/index.js",
   "jsnext:main": "src/index.js",
   "jsnext:main": "src/index.js",
@@ -24,13 +24,13 @@
   },
   },
   "dependencies": {
   "dependencies": {
     "@uppy/companion-client": "0.27.2",
     "@uppy/companion-client": "0.27.2",
-    "@uppy/utils": "0.28.0",
+    "@uppy/utils": "0.29.0",
     "preact": "^8.2.9"
     "preact": "^8.2.9"
   },
   },
   "devDependencies": {
   "devDependencies": {
-    "@uppy/core": "0.28.0"
+    "@uppy/core": "0.29.0"
   },
   },
   "peerDependencies": {
   "peerDependencies": {
-    "@uppy/core": "^0.28.0"
+    "@uppy/core": "^0.29.0"
   }
   }
 }
 }

+ 2 - 1
packages/@uppy/url/src/style.scss

@@ -1,4 +1,5 @@
-@import '@uppy/core/src/style.scss';
+@import '@uppy/core/src/_utils.scss';
+@import '@uppy/core/src/_variables.scss';
 
 
 .uppy-Url {
 .uppy-Url {
   width: 100%;
   width: 100%;

+ 10 - 6
packages/@uppy/url/types/index.d.ts

@@ -1,16 +1,20 @@
 import { Plugin, PluginOptions, Uppy } from '@uppy/core';
 import { Plugin, PluginOptions, Uppy } from '@uppy/core';
 
 
-export interface UrlOptions extends PluginOptions {
-  serverUrl: string;
-  // TODO inherit from ProviderOptions
+declare module Url {
+  export interface UrlOptions extends PluginOptions {
+    serverUrl: string;
+    // TODO inherit from ProviderOptions
+  }
 }
 }
 
 
-export default class Url extends Plugin {
-  constructor(uppy: Uppy, opts: Partial<UrlOptions>);
+declare class Url extends Plugin {
+  constructor(uppy: Uppy, opts: Partial<Url.UrlOptions>);
 }
 }
 
 
+export = Url;
+
 declare module '@uppy/core' {
 declare module '@uppy/core' {
   export interface Uppy {
   export interface Uppy {
-    use(pluginClass: typeof Url, opts: Partial<UrlOptions>): Uppy;
+    use(pluginClass: typeof Url, opts: Partial<Url.UrlOptions>): Uppy;
   }
   }
 }
 }

+ 1 - 1
packages/@uppy/utils/package.json

@@ -1,7 +1,7 @@
 {
 {
   "name": "@uppy/utils",
   "name": "@uppy/utils",
   "description": "Shared utility functions for Uppy Core and plugins maintained by the Uppy team.",
   "description": "Shared utility functions for Uppy Core and plugins maintained by the Uppy team.",
-  "version": "0.28.0",
+  "version": "0.29.0",
   "license": "MIT",
   "license": "MIT",
   "main": "lib/index.js",
   "main": "lib/index.js",
   "jsnext:main": "src/index.js",
   "jsnext:main": "src/index.js",

+ 2 - 1
packages/@uppy/utils/src/getFileType.js

@@ -2,7 +2,8 @@ const getFileNameAndExtension = require('./getFileNameAndExtension')
 const mimeTypes = require('./mimeTypes')
 const mimeTypes = require('./mimeTypes')
 
 
 module.exports = function getFileType (file) {
 module.exports = function getFileType (file) {
-  const fileExtension = file.name ? getFileNameAndExtension(file.name).extension : null
+  let fileExtension = file.name ? getFileNameAndExtension(file.name).extension : null
+  fileExtension = fileExtension ? fileExtension.toLowerCase() : null
 
 
   if (file.isRemote) {
   if (file.isRemote) {
     // some remote providers do not support file types
     // some remote providers do not support file types

+ 4 - 0
packages/@uppy/utils/src/getFileType.test.js

@@ -32,9 +32,13 @@ describe('getFileType', () => {
       name: 'bar.mkv',
       name: 'bar.mkv',
       data: 'sdfsfhfh329fhwihs'
       data: 'sdfsfhfh329fhwihs'
     }
     }
+    const toUpper = (file) => Object.assign({}, file, { name: file.name.toUpperCase() })
     expect(getFileType(fileMP3)).toEqual('audio/mp3')
     expect(getFileType(fileMP3)).toEqual('audio/mp3')
+    expect(getFileType(toUpper(fileMP3))).toEqual('audio/mp3')
     expect(getFileType(fileYAML)).toEqual('text/yaml')
     expect(getFileType(fileYAML)).toEqual('text/yaml')
+    expect(getFileType(toUpper(fileYAML))).toEqual('text/yaml')
     expect(getFileType(fileMKV)).toEqual('video/x-matroska')
     expect(getFileType(fileMKV)).toEqual('video/x-matroska')
+    expect(getFileType(toUpper(fileMKV))).toEqual('video/x-matroska')
   })
   })
 
 
   it('should fail gracefully if unable to detect', () => {
   it('should fail gracefully if unable to detect', () => {

+ 4 - 4
packages/@uppy/webcam/package.json

@@ -1,7 +1,7 @@
 {
 {
   "name": "@uppy/webcam",
   "name": "@uppy/webcam",
   "description": "Uppy plugin that takes photos or records videos using the device's camera.",
   "description": "Uppy plugin that takes photos or records videos using the device's camera.",
-  "version": "0.28.0",
+  "version": "0.29.0",
   "license": "MIT",
   "license": "MIT",
   "main": "lib/index.js",
   "main": "lib/index.js",
   "jsnext:main": "src/index.js",
   "jsnext:main": "src/index.js",
@@ -27,13 +27,13 @@
     "url": "git+https://github.com/transloadit/uppy.git"
     "url": "git+https://github.com/transloadit/uppy.git"
   },
   },
   "dependencies": {
   "dependencies": {
-    "@uppy/utils": "0.28.0",
+    "@uppy/utils": "0.29.0",
     "preact": "^8.2.9"
     "preact": "^8.2.9"
   },
   },
   "devDependencies": {
   "devDependencies": {
-    "@uppy/core": "0.28.0"
+    "@uppy/core": "0.29.0"
   },
   },
   "peerDependencies": {
   "peerDependencies": {
-    "@uppy/core": "^0.28.0"
+    "@uppy/core": "^0.29.0"
   }
   }
 }
 }

+ 2 - 1
packages/@uppy/webcam/src/style.scss

@@ -1,4 +1,5 @@
-@import '@uppy/core/src/style.scss';
+@import '@uppy/core/src/_utils.scss';
+@import '@uppy/core/src/_variables.scss';
 
 
 .uppy-Webcam-container {
 .uppy-Webcam-container {
   width: 100%;
   width: 100%;

+ 17 - 12
packages/@uppy/webcam/types/index.d.ts

@@ -1,21 +1,26 @@
 import { Plugin, PluginOptions, Uppy } from '@uppy/core';
 import { Plugin, PluginOptions, Uppy } from '@uppy/core';
 
 
-export type WebcamMode = 'video-audio' | 'video-only' | 'audio-only' | 'picture';
+declare module Webcam {
 
 
-export interface WebcamOptions extends PluginOptions {
-  onBeforeSnapshot?: () => Promise<void>;
-  countdown?: number | boolean;
-  mirror?: boolean;
-  facingMode?: string;
-  modes: WebcamMode[];
+    export type WebcamMode = 'video-audio' | 'video-only' | 'audio-only' | 'picture';
+
+    export interface WebcamOptions extends PluginOptions {
+        onBeforeSnapshot?: () => Promise<void>;
+        countdown?: number | boolean;
+        mirror?: boolean;
+        facingMode?: string;
+        modes: WebcamMode[];
+    }
 }
 }
 
 
-export default class Webcam extends Plugin {
-  constructor(uppy: Uppy, opts: Partial<WebcamOptions>);
+declare class Webcam extends Plugin {
+    constructor(uppy: Uppy, opts: Partial<Webcam.WebcamOptions>);
 }
 }
 
 
+export = Webcam;
+
 declare module '@uppy/core' {
 declare module '@uppy/core' {
-  export interface Uppy {
-    use(pluginClass: typeof Webcam, opts: Partial<WebcamOptions>): Uppy;
-  }
+    export interface Uppy {
+        use(pluginClass: typeof Webcam, opts: Partial<Webcam.WebcamOptions>): Uppy;
+    }
 }
 }

+ 4 - 4
packages/@uppy/xhr-upload/package.json

@@ -1,7 +1,7 @@
 {
 {
   "name": "@uppy/xhr-upload",
   "name": "@uppy/xhr-upload",
   "description": "Plain and simple classic HTML multipart form uploads with Uppy, as well as uploads using the HTTP PUT method.",
   "description": "Plain and simple classic HTML multipart form uploads with Uppy, as well as uploads using the HTTP PUT method.",
-  "version": "0.28.0",
+  "version": "0.29.0",
   "license": "MIT",
   "license": "MIT",
   "main": "lib/index.js",
   "main": "lib/index.js",
   "jsnext:main": "src/index.js",
   "jsnext:main": "src/index.js",
@@ -26,13 +26,13 @@
   },
   },
   "dependencies": {
   "dependencies": {
     "@uppy/companion-client": "0.27.2",
     "@uppy/companion-client": "0.27.2",
-    "@uppy/utils": "0.28.0",
+    "@uppy/utils": "0.29.0",
     "cuid": "^2.1.1"
     "cuid": "^2.1.1"
   },
   },
   "devDependencies": {
   "devDependencies": {
-    "@uppy/core": "0.28.0"
+    "@uppy/core": "0.29.0"
   },
   },
   "peerDependencies": {
   "peerDependencies": {
-    "@uppy/core": "^0.28.0"
+    "@uppy/core": "^0.29.0"
   }
   }
 }
 }

+ 18 - 14
packages/@uppy/xhr-upload/types/index.d.ts

@@ -1,24 +1,28 @@
 import { Plugin, PluginOptions, Uppy } from '@uppy/core';
 import { Plugin, PluginOptions, Uppy } from '@uppy/core';
 
 
-export interface XHRUploadOptions extends PluginOptions {
-  limit: string;
-  bundle: boolean;
-  formData: FormData;
-  headers: any;
-  metaFields: string[];
-  fieldName: string;
-  timeout: number;
-  responseUrlFieldName: string;
-  endpoint: string;
-  method: 'GET' | 'POST' | 'HEAD';
+declare module XHRUpload {
+  export interface XHRUploadOptions extends PluginOptions {
+    limit: string;
+    bundle: boolean;
+    formData: FormData;
+    headers: any;
+    metaFields: string[];
+    fieldName: string;
+    timeout: number;
+    responseUrlFieldName: string;
+    endpoint: string;
+    method: 'GET' | 'POST' | 'HEAD';
+  }
 }
 }
 
 
-export default class XHRUpload extends Plugin {
-  constructor(uppy: Uppy, opts: Partial<XHRUploadOptions>);
+declare class XHRUpload extends Plugin {
+  constructor(uppy: Uppy, opts: Partial<XHRUpload.XHRUploadOptions>);
 }
 }
 
 
+export = XHRUpload;
+
 declare module '@uppy/core' {
 declare module '@uppy/core' {
   export interface Uppy {
   export interface Uppy {
-    use(pluginClass: typeof XHRUpload, opts: Partial<XHRUploadOptions>): Uppy;
+    use(pluginClass: typeof XHRUpload, opts: Partial<XHRUpload.XHRUploadOptions>): Uppy;
   }
   }
 }
 }

+ 4 - 0
packages/uppy/bundle.js

@@ -0,0 +1,4 @@
+require('es6-promise/auto')
+require('whatwg-fetch')
+
+module.exports = require('./')

+ 27 - 23
packages/uppy/package.json

@@ -1,7 +1,7 @@
 {
 {
   "name": "uppy",
   "name": "uppy",
   "description": "Extensible JavaScript file upload widget with support for drag&drop, resumable uploads, previews, restrictions, file processing/encoding, remote providers like Instagram, Dropbox, Google Drive, S3 and more :dog:",
   "description": "Extensible JavaScript file upload widget with support for drag&drop, resumable uploads, previews, restrictions, file processing/encoding, remote providers like Instagram, Dropbox, Google Drive, S3 and more :dog:",
-  "version": "0.28.0",
+  "version": "0.29.0",
   "license": "MIT",
   "license": "MIT",
   "main": "index.js",
   "main": "index.js",
   "module": "index.mjs",
   "module": "index.mjs",
@@ -30,30 +30,34 @@
     "url": "git+https://github.com/transloadit/uppy.git"
     "url": "git+https://github.com/transloadit/uppy.git"
   },
   },
   "dependencies": {
   "dependencies": {
-    "@uppy/aws-s3": "0.28.0",
-    "@uppy/aws-s3-multipart": "0.28.0",
+    "@uppy/aws-s3": "0.29.0",
+    "@uppy/aws-s3-multipart": "0.29.0",
     "@uppy/companion-client": "0.27.2",
     "@uppy/companion-client": "0.27.2",
-    "@uppy/core": "0.28.0",
-    "@uppy/dashboard": "0.28.0",
-    "@uppy/drag-drop": "0.28.0",
-    "@uppy/dropbox": "0.28.0",
-    "@uppy/file-input": "0.28.0",
-    "@uppy/form": "0.28.0",
-    "@uppy/golden-retriever": "0.28.0",
-    "@uppy/google-drive": "0.28.0",
-    "@uppy/informer": "0.28.0",
-    "@uppy/instagram": "0.28.0",
-    "@uppy/progress-bar": "0.28.0",
-    "@uppy/provider-views": "0.28.0",
-    "@uppy/redux-dev-tools": "0.28.0",
-    "@uppy/status-bar": "0.28.0",
+    "@uppy/core": "0.29.0",
+    "@uppy/dashboard": "0.29.0",
+    "@uppy/drag-drop": "0.29.0",
+    "@uppy/dropbox": "0.29.0",
+    "@uppy/file-input": "0.29.0",
+    "@uppy/form": "0.29.0",
+    "@uppy/golden-retriever": "0.29.0",
+    "@uppy/google-drive": "0.29.0",
+    "@uppy/informer": "0.29.0",
+    "@uppy/instagram": "0.29.0",
+    "@uppy/progress-bar": "0.29.0",
+    "@uppy/provider-views": "0.29.0",
+    "@uppy/redux-dev-tools": "0.29.0",
+    "@uppy/status-bar": "0.29.0",
     "@uppy/store-default": "0.27.0",
     "@uppy/store-default": "0.27.0",
     "@uppy/store-redux": "0.27.0",
     "@uppy/store-redux": "0.27.0",
-    "@uppy/thumbnail-generator": "0.28.0",
-    "@uppy/transloadit": "0.28.0",
-    "@uppy/tus": "0.28.0",
-    "@uppy/url": "0.28.0",
-    "@uppy/webcam": "0.28.0",
-    "@uppy/xhr-upload": "0.28.0"
+    "@uppy/thumbnail-generator": "0.29.0",
+    "@uppy/transloadit": "0.29.0",
+    "@uppy/tus": "0.29.0",
+    "@uppy/url": "0.29.0",
+    "@uppy/webcam": "0.29.0",
+    "@uppy/xhr-upload": "0.29.0"
+  },
+  "devDependencies": {
+    "es6-promise": "4.2.5",
+    "whatwg-fetch": "3.0.0"
   }
   }
 }
 }

+ 3 - 1
packages/uppy/types/index.d.ts

@@ -6,7 +6,9 @@
 export { default as Core } from '@uppy/core';
 export { default as Core } from '@uppy/core';
 
 
 // Stores
 // Stores
-export { default as DefaultStore } from '@uppy/store-default';
+import DefaultStore = require('@uppy/store-default');
+export { DefaultStore };  // this is weird: exporting a function as something that sounds like a class name!
+// do we really mean what the line above says?
 export { default as ReduxStore } from '@uppy/store-redux';
 export { default as ReduxStore } from '@uppy/store-redux';
 
 
 // UI plugins
 // UI plugins

+ 1 - 0
test/endtoend/create-react-app/src/App.js

@@ -4,6 +4,7 @@ import Tus from '@uppy/tus'
 import GoogleDrive from '@uppy/google-drive'
 import GoogleDrive from '@uppy/google-drive'
 import { Dashboard, DashboardModal } from '@uppy/react'
 import { Dashboard, DashboardModal } from '@uppy/react'
 // import { Dashboard, DashboardModal, DragDrop, ProgressBar } from '@uppy/react'
 // import { Dashboard, DashboardModal, DragDrop, ProgressBar } from '@uppy/react'
+import '@uppy/core/dist/style.css'
 import '@uppy/dashboard/dist/style.css'
 import '@uppy/dashboard/dist/style.css'
 // import '@uppy/drag-drop/dist/style.css'
 // import '@uppy/drag-drop/dist/style.css'
 // import '@uppy/progress-bar/dist/style.css'
 // import '@uppy/progress-bar/dist/style.css'

+ 1 - 1
website/src/_posts/2018-10-0.28.md

@@ -6,7 +6,7 @@ image: "https://uppy.io/images/blog/0.28/dashboard-uploading.jpg"
 published: true
 published: true
 ---
 ---
 
 
-<img class="border"  src="/images/blog/0.28/dashboard-uploading.jpg">
+<img class="border" src="/images/blog/0.28/dashboard-uploading.jpg">
 
 
 In `0.28`, we are introducing a new “Single Upload” mode, improving on the Status Bar plugin with a spinner and different pause/resume/cancel buttons. We'll also share some progress on bringing back unified locale packs and a Transloadit Preset 🍁
 In `0.28`, we are introducing a new “Single Upload” mode, improving on the Status Bar plugin with a spinner and different pause/resume/cancel buttons. We'll also share some progress on bringing back unified locale packs and a Transloadit Preset 🍁
 
 

+ 91 - 0
website/src/_posts/2018-12-0.29.md

@@ -0,0 +1,91 @@
+---
+title: "Uppy 0.29"
+date: 2018-12-11
+author: arturi
+image: "https://uppy.io/images/blog/0.29/uppy-core-plugins-separate-styles.jpg"
+published: false
+---
+
+<img src="/images/blog/0.29/uppy-core-plugins-separate-styles.jpg">
+
+`0.29` brings bug fixes and improvements, while we are busy working on Uppy React Native support (which is already [coming to our resumable file upload protocol tus.io](https://github.com/tus/tus-js-client#react-native-support)) and a Transloadit Preset. The highlights of this release are: separating Core and plugin styles, using file sizes for progress calculation, adding a `responseType` option for XHR Upload and fixing some visual Webcam bugs.
+
+<!--more-->
+
+## Separate Core and Plugin styles
+
+**⚠️ breaking**
+
+When installing `uppy` and plugins from npm, you had to include their styles. Prior to this release, you could include only the plugin’s CSS, say, for `@uppy/webcam`:
+
+```js
+import Uppy from '@uppy/core'
+import Webcam from '@uppy/webcam'
+import '@uppy/webcam/dist/style.css'
+```
+
+Each plugin's file contained the core styles. If you added multiple plugins, the core styles ended up being duplicated. This bloated file sizes and could even break styles entirely because of CSS's precedence rules.
+
+Now you have to include “general” styles from `@uppy/core` as well:
+
+```js
+import Uppy from '@uppy/core'
+import Webcam from '@uppy/webcam'
+import '@uppy/core/dist/style.css'
+import '@uppy/webcam/dist/style.css'
+```
+
+Thus the core styles are only included once. `@uppy/core` styles must be included before plugin styles.
+
+Please [see documentation for the plugin](https://uppy.io/docs/plugins/) you are using to find out whether it requires a CSS file to work. Generally UI plugins, such as Dashboard, Webcam and Status Bar need a CSS file, while utility plugins, such as Tus or XHR Upload, don’t.
+
+⚠️ Important things to remember:
+
+1. Dashboard is a universal UI that comes with Status Bar and Informer plugins built in, and as such Dashboard styles already come with Informer and Status Bar styles.
+2. Dashboard also ships with “Remote Provider” styles — you don’t need to include anything besides `@uppy/dashboard/dist/style.css` for Google Drive, Instagram and Dropbox to work. However, Url and Webcam plugins, still have to be included manually. Here’s an example:
+
+```js
+import Uppy from '@uppy/core'
+import Dashboard from '@uppy/webcam'
+import GoogleDrive from '@uppy/google-drive'
+import Webcam from '@uppy/webcam'
+import Url from '@uppy/url'
+
+// Core and Dashboard styles, then Webcam and Url, but not for GoogleDrive —
+// those come with Dashboard
+import '@uppy/core/dist/style.css'
+import '@uppy/dashboard/dist/style.css'
+import '@uppy/webcam/dist/style.css'
+import '@uppy/url/dist/style.css'
+```
+
+## Using File Sizes For Progress Calculation
+
+When possible, file sizes are now used for calculating the total progress. Before, we’ve used uploaded percentage for each file. That meant, if you were uploading 4 files, and 3 small were already uploaded, while one very large file was still in progress, Uppy may display progress as 90%. Long story short, Uppy now has a more accurate progress bar 🚀
+
+Some internal details, if you are interested:
+
+1. If there are files without sizes, the average size of all other files is assumed for the unsized files.
+2. If there are no files with sizes, the percentage is just based on the percentages of the unsized files.
+
+<img src="/images/blog/0.29/progress-size-calculation.jpg">
+
+## responseType For XHR Upload
+
+When using XHR Upload, you can now configure the XMLHttpRequest `.responseType` value. This allows the S3 plugin to tell Firefox not to log XML errors when getting empty responses, so it finally fixes the spurious warnings that were caused by this, see [#518](https://github.com/transloadit/uppy/issues/518).
+
+Because AwsS3 now sets responseType: 'text', we can no longer use the responseXML property. We already did text based parsing for successful responses, and now do the same for error responses.
+
+## Misc Changes
+
+- @uppy/core: Don't pass removed file IDs to next upload step, fixes (#1148 / @goto-bus-stop)
+- @uppy/core: Fixed getFileType() when passed a file with an upper case extension (#1169 / @jderrough)
+- @uppy/companion: Use `createCipheriv` instead of deprecated `createCipher` (#1149 / @goto-bus-stop)
+- @uppy/companion: Store Provider instances on `this.provider` instead of `this[this.id]` (@goto-bus-stop / #1174)
+- @uppy/companion: Pin grant to known stable version (@ifedapoolarewaju / #1165)
+- @uppy/companion: Fix — socket does not handle server.path option (#1142 / @tranvansang)
+- @uppy/webcam: Fix a bug with Webcam video overflowing its container (68730f8a1bf731898d46883e00fed937d3ab54ab / @arturi)
+- docs: Add `triggerUploadOnSubmit` to Form docs, add docs about options of hiding upload/pause/resume/cancel buttons; talk about bundler-less polyfill use (@goto-bus-stop, @arturi)
+- @uppy/react: Allow Dashboard props width and height to accept a string for 100% (#1129 / craigcbrunner)
+
+See [full changelog (0.29) for more](https://github.com/transloadit/uppy/blob/master/CHANGELOG.md#0290)

Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor