浏览代码

core: force `new` keyword (#2949)

* Force Uppy initialization with new keyword, remove run()

* update some types

* update docs and examples

* Update packages/@uppy/core/src/index.js

Co-authored-by: Antoine du Hamel <duhamelantoine1995@gmail.com>

* Update packages/@uppy/core/types/index.d.ts

Co-authored-by: Antoine du Hamel <duhamelantoine1995@gmail.com>

* add new in tests

* Move all types to ESM syntax and fix all issues

* Add back e2e build script and revert uppy docs commit

Co-authored-by: Antoine du Hamel <duhamelantoine1995@gmail.com>
Co-authored-by: Murderlon <merlijn@soverin.net>
Artur Paikin 3 年之前
父节点
当前提交
a8003c873e
共有 79 个文件被更改,包括 1454 次插入1763 次删除
  1. 1 1
      BACKLOG.md
  2. 1 1
      CHANGELOG.md
  3. 3 3
      bin/locale-packs.js
  4. 10 8
      examples/svelte-example/src/App.svelte
  5. 796 1133
      package-lock.json
  6. 1 0
      package.json
  7. 10 10
      packages/@uppy/aws-s3-multipart/types/index.d.ts
  8. 10 9
      packages/@uppy/aws-s3-multipart/types/index.test-d.ts
  9. 5 7
      packages/@uppy/aws-s3/types/index.d.ts
  10. 5 4
      packages/@uppy/aws-s3/types/index.test-d.ts
  11. 7 9
      packages/@uppy/box/types/index.d.ts
  12. 1 0
      packages/@uppy/companion/package.json
  13. 1 1
      packages/@uppy/companion/src/companion.js
  14. 1 4
      packages/@uppy/core/src/index.js
  15. 9 9
      packages/@uppy/core/src/index.test.js
  16. 252 222
      packages/@uppy/core/types/index.d.ts
  17. 26 21
      packages/@uppy/core/types/index.test-d.ts
  18. 9 9
      packages/@uppy/dashboard/types/index.d.ts
  19. 7 7
      packages/@uppy/dashboard/types/index.test-d.ts
  20. 6 6
      packages/@uppy/drag-drop/types/index.d.ts
  21. 8 8
      packages/@uppy/drag-drop/types/index.test-d.ts
  22. 4 4
      packages/@uppy/drop-target/types/index.d.ts
  23. 7 9
      packages/@uppy/dropbox/types/index.d.ts
  24. 7 9
      packages/@uppy/facebook/types/index.d.ts
  25. 6 6
      packages/@uppy/file-input/types/index.d.ts
  26. 5 5
      packages/@uppy/form/types/index.d.ts
  27. 4 4
      packages/@uppy/golden-retriever/types/index.d.ts
  28. 7 9
      packages/@uppy/google-drive/types/index.d.ts
  29. 4 4
      packages/@uppy/google-drive/types/index.test-d.ts
  30. 1 1
      packages/@uppy/image-editor/README.md
  31. 6 6
      packages/@uppy/image-editor/types/index.d.ts
  32. 5 5
      packages/@uppy/informer/types/index.d.ts
  33. 7 9
      packages/@uppy/instagram/types/index.d.ts
  34. 7 9
      packages/@uppy/onedrive/types/index.d.ts
  35. 5 5
      packages/@uppy/progress-bar/types/index.d.ts
  36. 5 5
      packages/@uppy/provider-views/types/index.d.ts
  37. 1 0
      packages/@uppy/react/package.json
  38. 1 4
      packages/@uppy/react/src/CommonTypes.d.ts
  39. 2 1
      packages/@uppy/react/src/Dashboard.d.ts
  40. 1 1
      packages/@uppy/react/src/DashboardModal.d.ts
  41. 1 1
      packages/@uppy/react/src/DragDrop.d.ts
  42. 1 1
      packages/@uppy/react/src/FileInput.d.ts
  43. 1 1
      packages/@uppy/react/src/ProgressBar.d.ts
  44. 1 1
      packages/@uppy/react/src/StatusBar.d.ts
  45. 2 2
      packages/@uppy/react/src/useUppy.d.ts
  46. 1 3
      packages/@uppy/react/types/index.d.ts
  47. 23 21
      packages/@uppy/react/types/index.test-d.tsx
  48. 4 4
      packages/@uppy/redux-dev-tools/types/index.d.ts
  49. 4 4
      packages/@uppy/screen-capture/types/index.d.ts
  50. 8 8
      packages/@uppy/screen-capture/types/index.test-d.ts
  51. 6 6
      packages/@uppy/status-bar/types/index.d.ts
  52. 4 3
      packages/@uppy/store-default/types/index.d.ts
  53. 1 1
      packages/@uppy/store-default/types/index.test-d.ts
  54. 5 4
      packages/@uppy/store-redux/types/index.d.ts
  55. 1 1
      packages/@uppy/store-redux/types/index.test-d.ts
  56. 6 5
      packages/@uppy/thumbnail-generator/types/index.d.ts
  57. 6 8
      packages/@uppy/transloadit/types/index.d.ts
  58. 7 6
      packages/@uppy/transloadit/types/index.test-d.ts
  59. 5 5
      packages/@uppy/tus/types/index.d.ts
  60. 1 1
      packages/@uppy/unsplash/README.md
  61. 6 8
      packages/@uppy/unsplash/types/index.d.ts
  62. 7 9
      packages/@uppy/url/types/index.d.ts
  63. 4 3
      packages/@uppy/vue/types/dashboard-modal.d.ts
  64. 4 3
      packages/@uppy/vue/types/dashboard.d.ts
  65. 4 2
      packages/@uppy/vue/types/drag-drop.d.ts
  66. 3 2
      packages/@uppy/vue/types/progress-bar.d.ts
  67. 3 2
      packages/@uppy/vue/types/status-bar.d.ts
  68. 6 6
      packages/@uppy/webcam/types/index.d.ts
  69. 5 5
      packages/@uppy/webcam/types/index.test-d.ts
  70. 7 6
      packages/@uppy/xhr-upload/types/index.d.ts
  71. 6 5
      packages/@uppy/xhr-upload/types/index.test-d.ts
  72. 1 1
      packages/@uppy/zoom/README.md
  73. 7 9
      packages/@uppy/zoom/types/index.d.ts
  74. 26 26
      packages/uppy/types/index.d.ts
  75. 4 5
      packages/uppy/types/index.test-d.ts
  76. 15 15
      private/remark-lint-uppy/package.json
  77. 2 0
      website/src/_posts/2019-04-liftoff-09.md
  78. 1 1
      website/src/docs/react-dashboard.md
  79. 1 1
      website/src/docs/react-initializing.md

+ 1 - 1
BACKLOG.md

@@ -1,6 +1,6 @@
 # Backlog
 
-<!--lint disable no-literal-urls-->
+<!--lint disable no-literal-urls no-undefined-references-->
 
 This is our roadmap which contains a list of todos.
 

+ 1 - 1
CHANGELOG.md

@@ -1,6 +1,6 @@
 # Changelog
 
-<!--lint disable no-literal-urls-->
+<!--lint disable no-literal-urls no-undefined-references-->
 
 This is our changelog which contains planned todos and past dones.
 

+ 3 - 3
bin/locale-packs.js

@@ -169,13 +169,13 @@ function createTypeScriptLocale (plugin, pluginName) {
   const localePath = path.join(__dirname, '..', 'packages', '@uppy', pluginName, 'types', 'generatedLocale.d.ts')
 
   const localeTypes
-    = `${'import Uppy = require(\'@uppy/core\')\n'
+    = `${'import type { Locale } from \'@uppy/core\'\n'
     + '\n'
-    + `type ${pluginClassName}Locale = Uppy.Locale` + '<\n'}${
+    + `type ${pluginClassName}Locale = Locale` + '<\n'}${
       allowedStringTypes}\n`
     + `>\n`
     + `\n`
-    + `export = ${pluginClassName}Locale\n`
+    + `export default ${pluginClassName}Locale\n`
 
   fs.writeFileSync(localePath, localeTypes)
 }

+ 10 - 8
examples/svelte-example/src/App.svelte

@@ -1,15 +1,17 @@
 <script lang="ts">
-	import { Dashboard, DashboardModal, DragDrop, ProgressBar } from "@uppy/svelte"
-	import Uppy from "@uppy/core"
+	import { Dashboard, DashboardModal, DragDrop, ProgressBar } from '@uppy/svelte'
+	import Uppy from '@uppy/core'
 	import Webcam from '@uppy/webcam'
 	import XHRUpload from '@uppy/xhr-upload'
 
-	let createUppy = () => Uppy().use(Webcam).use(XHRUpload, {
-		bundle: true,
-		endpoint: 'http://localhost:9967/upload',
-		metaFields: ['something'],
-		fieldName: 'files'
-	})
+	const createUppy = () => {
+		return new Uppy().use(Webcam).use(XHRUpload, {
+			bundle: true,
+			endpoint: 'http://localhost:9967/upload',
+			metaFields: ['something'],
+			fieldName: 'files',
+		})
+	}
 
 	let uppy1 = createUppy()
 	let uppy2 = createUppy() 

文件差异内容过多而无法显示
+ 796 - 1133
package-lock.json


+ 1 - 0
package.json

@@ -163,6 +163,7 @@
     "start": "npm-run-all --parallel watch start:companion web:start",
     "test:companion": "npm run --prefix ./packages/@uppy/companion test",
     "test:endtoend:build-ci": "bash ./bin/endtoend-build-ci",
+    "test:endtoend:build": "bash ./bin/endtoend-build",
     "test:endtoend:local": "npm run test:endtoend:build && wdio test/endtoend/wdio.local.conf.js",
     "test:endtoend:providers": "npm run test:endtoend:build && . ./test/endtoend/providers/env.sh && wdio test/endtoend/wdio.local.conf.js --spec test/endtoend/providers/provider.*.test.js",
     "test:endtoend:prepare-ci": "npm-run-all --parallel --race test:endtoend:registry test:endtoend:build-ci",

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

@@ -1,4 +1,4 @@
-import Uppy = require('@uppy/core')
+import type { PluginOptions, BasePlugin, UppyFile } from '@uppy/core'
 
 type MaybePromise<T> = T | Promise<T>
 
@@ -9,27 +9,27 @@ declare module AwsS3Multipart {
     ETag?: string
   }
 
-  interface AwsS3MultipartOptions extends Uppy.PluginOptions {
+  interface AwsS3MultipartOptions extends PluginOptions {
     companionHeaders?: { [type: string]: string }
     companionUrl?: string
-    getChunkSize?: (file: Uppy.UppyFile) => number
+    getChunkSize?: (file: UppyFile) => number
     createMultipartUpload?: (
-      file: Uppy.UppyFile
+      file: UppyFile
     ) => MaybePromise<{ uploadId: string; key: string }>
     listParts?: (
-      file: Uppy.UppyFile,
+      file: UppyFile,
       opts: { uploadId: string; key: string }
     ) => MaybePromise<AwsS3Part[]>
     prepareUploadPart?: (
-      file: Uppy.UppyFile,
+      file: UppyFile,
       partData: { uploadId: string; key: string; body: Blob; number: number }
     ) => MaybePromise<{ url: string, headers?: { [k: string]: string } }>
     abortMultipartUpload?: (
-      file: Uppy.UppyFile,
+      file: UppyFile,
       opts: { uploadId: string; key: string }
     ) => MaybePromise<void>
     completeMultipartUpload?: (
-      file: Uppy.UppyFile,
+      file: UppyFile,
       opts: { uploadId: string; key: string; parts: AwsS3Part[] }
     ) => MaybePromise<{ location?: string }>
     timeout?: number
@@ -38,8 +38,8 @@ declare module AwsS3Multipart {
   }
 }
 
-declare class AwsS3Multipart extends Uppy.Plugin<
+declare class AwsS3Multipart extends BasePlugin<
   AwsS3Multipart.AwsS3MultipartOptions
 > {}
 
-export = AwsS3Multipart
+export default AwsS3Multipart

+ 10 - 9
packages/@uppy/aws-s3-multipart/types/index.test-d.ts

@@ -1,22 +1,23 @@
 import { expectError, expectType } from 'tsd'
-import Uppy = require('@uppy/core')
-import AwsS3Multipart = require('../')
+import Uppy from '@uppy/core'
+import type { UppyFile } from '@uppy/core'
+import AwsS3Multipart from '../'
 
 {
-  const uppy = Uppy()
+  const uppy = new Uppy()
   uppy.use(AwsS3Multipart, {
     createMultipartUpload (file) {
-      expectType<Uppy.UppyFile>(file)
+      expectType<UppyFile>(file)
       return { uploadId: '', key: '' }
     },
     listParts (file, opts) {
-      expectType<Uppy.UppyFile>(file)
+      expectType<UppyFile>(file)
       expectType<string>(opts.uploadId)
       expectType<string>(opts.key)
       return []
     },
     prepareUploadPart (file, part) {
-      expectType<Uppy.UppyFile>(file)
+      expectType<UppyFile>(file)
       expectType<string>(part.uploadId)
       expectType<string>(part.key)
       expectType<Blob>(part.body)
@@ -24,12 +25,12 @@ import AwsS3Multipart = require('../')
       return { url: '' }
     },
     abortMultipartUpload (file, opts) {
-      expectType<Uppy.UppyFile>(file)
+      expectType<UppyFile>(file)
       expectType<string>(opts.uploadId)
       expectType<string>(opts.key)
     },
     completeMultipartUpload (file, opts) {
-      expectType<Uppy.UppyFile>(file)
+      expectType<UppyFile>(file)
       expectType<string>(opts.uploadId)
       expectType<string>(opts.key)
       expectType<AwsS3Multipart.AwsS3Part>(opts.parts[0])
@@ -39,7 +40,7 @@ import AwsS3Multipart = require('../')
 }
 
 {
-  const uppy = Uppy()
+  const uppy = new Uppy()
   expectError(uppy.use(AwsS3Multipart, { getChunkSize: 100 }))
   expectError(uppy.use(AwsS3Multipart, { getChunkSize: () => 'not a number' }))
   uppy.use(AwsS3Multipart, { getChunkSize: () => 100 })

+ 5 - 7
packages/@uppy/aws-s3/types/index.d.ts

@@ -1,4 +1,4 @@
-import Uppy = require('@uppy/core')
+import type { PluginOptions, BasePlugin, UppyFile } from '@uppy/core'
 
 type MaybePromise<T> = T | Promise<T>
 
@@ -10,17 +10,15 @@ declare module AwsS3 {
     headers?: { [type: string]: string }
   }
 
-  interface AwsS3Options extends Uppy.PluginOptions {
+  interface AwsS3Options extends PluginOptions {
     companionUrl?: string
-    getUploadParameters?: (
-      file: Uppy.UppyFile
-    ) => MaybePromise<AwsS3UploadParameters>
+    getUploadParameters?: (file: UppyFile) => MaybePromise<AwsS3UploadParameters>
     metaFields?: string[]
     timeout?: number
     limit?: number
   }
 }
 
-declare class AwsS3 extends Uppy.Plugin<AwsS3.AwsS3Options> {}
+declare class AwsS3 extends BasePlugin<AwsS3.AwsS3Options> {}
 
-export = AwsS3
+export default AwsS3

+ 5 - 4
packages/@uppy/aws-s3/types/index.test-d.ts

@@ -1,12 +1,13 @@
 import { expectType } from 'tsd'
-import Uppy = require('@uppy/core')
-import AwsS3 = require('../')
+import Uppy from '@uppy/core'
+import type { UppyFile } from '@uppy/core'
+import AwsS3 from '../'
 
 {
-  const uppy = Uppy()
+  const uppy = new Uppy()
   uppy.use(AwsS3, {
     getUploadParameters (file) {
-      expectType<Uppy.UppyFile>(file)
+      expectType<UppyFile>(file)
       return { url: '' }
     }
   })

+ 7 - 9
packages/@uppy/box/types/index.d.ts

@@ -1,17 +1,15 @@
-import Uppy = require('@uppy/core')
-import CompanionClient = require('@uppy/companion-client')
+import type { PluginOptions, PluginTarget, UIPlugin } from '@uppy/core'
+import type { PublicProviderOptions, TokenStorage } from '@uppy/companion-client'
 
 declare module Box {
-  interface BoxOptions
-    extends Uppy.PluginOptions,
-      CompanionClient.PublicProviderOptions {
+  interface BoxOptions extends PluginOptions, PublicProviderOptions {
     replaceTargetContent?: boolean
-    target?: Uppy.PluginTarget
+    target?: PluginTarget
     title?: string
-    storage?: CompanionClient.TokenStorage
+    storage?: TokenStorage
   }
 }
 
-declare class Box extends Uppy.Plugin<Box.BoxOptions> {}
+declare class Box extends UIPlugin<Box.BoxOptions> {}
 
-export = Box
+export default Box

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

@@ -52,6 +52,7 @@
     "jsonwebtoken": "8.5.1",
     "lodash": "^4.17.20",
     "mime-types": "2.1.25",
+    "moment": "^2.29.1",
     "moment-timezone": "^0.5.31",
     "morgan": "1.10.0",
     "ms": "2.1.2",

+ 1 - 1
packages/@uppy/companion/src/companion.js

@@ -111,7 +111,7 @@ module.exports.app = (options = {}) => {
   app.get('/:providerName/list/:id?', middlewares.hasSessionAndProvider, middlewares.verifyToken, controllers.list)
   app.post('/:providerName/get/:id', middlewares.hasSessionAndProvider, middlewares.verifyToken, controllers.get)
   app.get('/:providerName/thumbnail/:id', middlewares.hasSessionAndProvider, middlewares.cookieAuthToken, middlewares.verifyToken, controllers.thumbnail)
-  // @ts-ignore
+  // @ts-ignore Type instantiation is excessively deep and possibly infinite.
   app.get('/search/:searchProviderName/list', middlewares.hasSearchQuery, middlewares.loadSearchProviderToken, controllers.list)
   app.post('/search/:searchProviderName/get/:id', middlewares.loadSearchProviderToken, controllers.get)
 

+ 1 - 4
packages/@uppy/core/src/index.js

@@ -1720,11 +1720,8 @@ class Uppy {
   }
 }
 
-module.exports = function core (opts) {
-  return new Uppy(opts)
-}
-
 // Expose class constructor.
+module.exports = Uppy
 module.exports.Uppy = Uppy
 module.exports.UIPlugin = UIPlugin
 module.exports.BasePlugin = BasePlugin

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

@@ -31,27 +31,27 @@ describe('src/Core', () => {
   })
 
   it('should expose a class', () => {
-    const core = Core()
+    const core = new Core()
     expect(core.constructor.name).toEqual('Uppy')
   })
 
   it('should have a string `id` option that defaults to "uppy"', () => {
-    const core = Core()
+    const core = new Core()
     expect(core.getID()).toEqual('uppy')
 
-    const core2 = Core({ id: 'profile' })
+    const core2 = new Core({ id: 'profile' })
     expect(core2.getID()).toEqual('profile')
   })
 
   describe('plugins', () => {
     it('should add a plugin to the plugin stack', () => {
-      const core = Core()
+      const core = new Core()
       core.use(AcquirerPlugin1)
       expect(Object.keys(core.plugins.acquirer).length).toEqual(1)
     })
 
     it('should prevent the same plugin from being added more than once', () => {
-      const core = Core()
+      const core = new Core()
       core.use(AcquirerPlugin1)
 
       expect(() => {
@@ -60,7 +60,7 @@ describe('src/Core', () => {
     })
 
     it('should not be able to add an invalid plugin', () => {
-      const core = Core()
+      const core = new Core()
 
       expect(() => {
         core.use(InvalidPlugin)
@@ -68,13 +68,13 @@ describe('src/Core', () => {
     })
 
     it('should not be able to add a plugin that has no id', () => {
-      const core = Core()
+      const core = new Core()
 
       expect(() => core.use(InvalidPluginWithoutId)).toThrowErrorMatchingSnapshot()
     })
 
     it('should not be able to add a plugin that has no type', () => {
-      const core = Core()
+      const core = new Core()
 
       expect(() => core.use(InvalidPluginWithoutType)).toThrowErrorMatchingSnapshot()
     })
@@ -1564,7 +1564,7 @@ describe('src/Core', () => {
 
     it('should throw if allowedFileTypes is not an array', () => {
       try {
-        const core = Core({
+        const core = new Core({
           restrictions: {
             allowedFileTypes: 'image/gif',
           },

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

@@ -1,243 +1,273 @@
-import UppyUtils = require('@uppy/utils')
+import * as UppyUtils from "@uppy/utils"
 
-declare module Uppy {
-  // Utility types
-  type OmitKey<T, Key> = Pick<T, Exclude<keyof T, Key>>
+// Utility types
+type OmitKey<T, Key> = Pick<T, Exclude<keyof T, Key>>
 
-  // These are defined in @uppy/utils instead of core so it can be used there without creating import cycles
-  export type UppyFile<
-    TMeta extends IndexedObject<any> = {},
-    TBody extends IndexedObject<any> = {}
-  > = UppyUtils.UppyFile<TMeta, TBody>
-  export type Store = UppyUtils.Store
-  export type InternalMetadata = UppyUtils.InternalMetadata
+type UploadHandler = (fileIDs: string[]) => Promise<void>
 
-  interface IndexedObject<T> {
-    [key: string]: T
-    [key: number]: T
-  }
+// Replace the `meta` property type with one that allows omitting internal metadata addFile() will add that
+type UppyFileWithoutMeta<TMeta, TBody> = OmitKey<
+  UppyFile<TMeta, TBody>,
+  "meta"
+>
 
-  interface UploadedUppyFile<TMeta, TBody> extends UppyFile<TMeta, TBody> {
-    uploadURL: string
-  }
+type LocaleStrings<TNames extends string> = {
+  [K in TNames]?: string | { [n: number]: string }
+}
 
-  interface FailedUppyFile<TMeta, TBody> extends UppyFile<TMeta, TBody> {
-    error: string
-  }
+type LogLevel = "info" | "warning" | "error"
 
-  // Replace the `meta` property type with one that allows omitting internal metadata; addFile() will add that
-  type UppyFileWithoutMeta<TMeta, TBody> = OmitKey<
-    UppyFile<TMeta, TBody>,
-    'meta'
-  >
-  interface AddFileOptions<
-    TMeta = IndexedObject<any>,
-    TBody = IndexedObject<any>
-  > extends Partial<UppyFileWithoutMeta<TMeta, TBody>> {
-    // `.data` is the only required property here.
-    data: Blob | File
-    meta?: Partial<InternalMetadata> & TMeta
-  }
+// This hack accepts _any_ string for `Event`, but also tricks VSCode and friends into providing autocompletions
+// for the names listed. https://github.com/microsoft/TypeScript/issues/29729#issuecomment-505826972
+type LiteralUnion<T extends U, U = string> = T | (U & Record<never, never>)
 
-  interface PluginOptions {
-    id?: string
-  }
-  interface DefaultPluginOptions extends PluginOptions {
-    [prop: string]: any
-  }
+type Event = LiteralUnion<
+  | "file-added"
+  | "file-removed"
+  | "upload"
+  | "upload-progress"
+  | "upload-success"
+  | "complete"
+  | "error"
+  | "upload-error"
+  | "upload-retry"
+  | "info-visible"
+  | "info-hidden"
+  | "cancel-all"
+  | "restriction-failed"
+  | "reset-progress"
+>
 
-  type PluginTarget = string | Element | typeof Plugin
+// These are defined in @uppy/utils instead of core so it can be used there without creating import cycles
+export type UppyFile<
+  TMeta extends IndexedObject<any> = {},
+  TBody extends IndexedObject<any> = {}
+> = UppyUtils.UppyFile<TMeta, TBody>
 
-  class Plugin<TOptions extends PluginOptions = DefaultPluginOptions> {
-    id: string
-    uppy: Uppy
-    type: string
-    constructor(uppy: Uppy, opts?: TOptions)
-    setOptions(update: Partial<TOptions>): void
-    getPluginState(): object
-    setPluginState(update: IndexedObject<any>): object
-    update(state?: object): void
-    mount(target: PluginTarget, plugin: typeof Plugin): void
-    render(state: object): void
-    addTarget<TPlugin extends Plugin>(plugin: TPlugin): void
-    unmount(): void
-    install(): void
-    uninstall(): void
-  }
+export type Store = UppyUtils.Store
 
-  type LocaleStrings<TNames extends string> = {
-    [K in TNames]?: string | { [n: number]: string }
-  }
-  interface Locale<TNames extends string = string> {
-    strings: LocaleStrings<TNames>
-    pluralize?: (n: number) => number
-  }
+export type InternalMetadata = UppyUtils.InternalMetadata
 
-  interface Restrictions {
-    maxFileSize?: number | null
-    minFileSize?: number | null
-    maxTotalFileSize?: number | null
-    maxNumberOfFiles?: number | null
-    minNumberOfFiles?: number | null
-    allowedFileTypes?: string[] | null
-  }
+export interface IndexedObject<T> {
+  [key: string]: T
+  [key: number]: T
+}
+
+export interface UploadedUppyFile<TMeta, TBody> extends UppyFile<TMeta, TBody> {
+  uploadURL: string
+}
+
+export interface FailedUppyFile<TMeta, TBody> extends UppyFile<TMeta, TBody> {
+  error: string
+}
+
+export interface AddFileOptions<
+  TMeta = IndexedObject<any>,
+  TBody = IndexedObject<any>
+> extends Partial<UppyFileWithoutMeta<TMeta, TBody>> {
+  // `.data` is the only required property here.
+  data: Blob | File
+  meta?: Partial<InternalMetadata> & TMeta
+}
 
-  interface UppyOptions<TMeta extends IndexedObject<any> = {}> {
-    id?: string
-    autoProceed?: boolean
-    allowMultipleUploads?: boolean
-    debug?: boolean
-    restrictions?: Restrictions
-    meta?: TMeta
-    onBeforeFileAdded?: (
-      currentFile: UppyFile<TMeta>,
-      files: { [key: string]: UppyFile<TMeta> }
-    ) => UppyFile<TMeta> | boolean | undefined
-    onBeforeUpload?: (files: {
-      [key: string]: UppyFile<TMeta>
-    }) => { [key: string]: UppyFile<TMeta> } | boolean
-    locale?: Locale
-    store?: Store
-    infoTimeout?: number
+export interface PluginOptions {
+  id?: string
+}
+
+export interface DefaultPluginOptions extends PluginOptions {
+  [prop: string]: any
+}
+
+export class BasePlugin<TOptions extends PluginOptions = DefaultPluginOptions> {
+  id: string
+  uppy: Uppy
+  type: string
+  constructor(uppy: Uppy, opts?: TOptions)
+  setOptions(update: Partial<TOptions>): void
+  getPluginState(): object
+  setPluginState(update: IndexedObject<any>): object
+  install(): void
+  uninstall(): void
+}
+
+export class UIPlugin<TOptions extends PluginOptions = DefaultPluginOptions> extends BasePlugin<TOptions> {
+  id: string
+  uppy: Uppy
+  type: string
+  constructor(uppy: Uppy, opts?: TOptions)
+  update(state?: object): void
+  mount(target: PluginTarget, plugin: typeof UIPlugin): void
+  render(state: object): void
+  addTarget<TPlugin extends UIPlugin>(plugin: TPlugin): void
+  unmount(): void
+}
+
+export type PluginTarget =
+  | string
+  | Element
+  | typeof BasePlugin
+  | typeof UIPlugin
+
+export interface Locale<TNames extends string = string> {
+  strings: LocaleStrings<TNames>
+  pluralize?: (n: number) => number
+}
+
+export interface Restrictions {
+  maxFileSize?: number | null
+  minFileSize?: number | null
+  maxTotalFileSize?: number | null
+  maxNumberOfFiles?: number | null
+  minNumberOfFiles?: number | null
+  allowedFileTypes?: string[] | null
+}
+
+export interface UppyOptions<TMeta extends IndexedObject<any> = {}> {
+  id?: string
+  autoProceed?: boolean
+  allowMultipleUploads?: boolean
+  debug?: boolean
+  restrictions?: Restrictions
+  meta?: TMeta
+  onBeforeFileAdded?: (
+    currentFile: UppyFile<TMeta>,
+    files: { [key: string]: UppyFile<TMeta> }
+  ) => UppyFile<TMeta> | boolean | undefined
+  onBeforeUpload?: (files: {
+    [key: string]: UppyFile<TMeta>
+  }) => { [key: string]: UppyFile<TMeta> } | boolean
+  locale?: Locale
+  store?: Store
+  infoTimeout?: number
+}
+
+export interface UploadResult<
+  TMeta extends IndexedObject<any> = {},
+  TBody extends IndexedObject<any> = {}
+> {
+  successful: UploadedUppyFile<TMeta, TBody>[]
+  failed: FailedUppyFile<TMeta, TBody>[]
+}
+
+export interface State<
+  TMeta extends IndexedObject<any> = {},
+  TBody extends IndexedObject<any> = {}
+> extends IndexedObject<any> {
+  capabilities?: { resumableUploads?: boolean }
+  currentUploads: {}
+  error?: string
+  files: {
+    [key: string]:
+      | UploadedUppyFile<TMeta, TBody>
+      | FailedUppyFile<TMeta, TBody>
+  }
+  info?: {
+    isHidden: boolean
+    type: string
+    message: string
+    details: string
   }
+  plugins?: IndexedObject<any>
+  totalProgress: number
+}
+
+type UploadSuccessCallback<T> = (file: UppyFile<T>, body: any, uploadURL: string) => void
+type UploadCompleteCallback<T> = (result: UploadResult<T>) => void
 
-  interface UploadResult<
+export class Uppy {
+  constructor(opts?: UppyOptions)
+  on<TMeta extends IndexedObject<any> = {}>(event: 'upload-success', callback: UploadSuccessCallback<TMeta>): this
+  on<TMeta extends IndexedObject<any> = {}>(event: 'complete', callback: UploadCompleteCallback<TMeta>): this
+  on(event: Event, callback: (...args: any[]) => void): this
+  once<TMeta extends IndexedObject<any> = {}>(event: 'upload-success', callback: UploadSuccessCallback<TMeta>): this
+  once<TMeta extends IndexedObject<any> = {}>(event: 'complete', callback: UploadCompleteCallback<TMeta>): this
+  once(event: Event, callback: (...args: any[]) => void): this
+  off(event: Event, callback: (...args: any[]) => void): this
+  off(event: Event, callback: (...args: any[]) => void): this
+  /**
+   * For use by plugins only.
+   */
+  emit(event: Event, ...args: any[]): void
+  updateAll(state: object): void
+  setOptions(update: Partial<UppyOptions>): void
+  setState(patch: object): void
+  getState<TMeta extends IndexedObject<any> = {}>(): State<TMeta>
+  readonly state: State
+  setFileState(fileID: string, state: object): void
+  resetProgress(): void
+  addPreProcessor(fn: UploadHandler): void
+  removePreProcessor(fn: UploadHandler): void
+  addPostProcessor(fn: UploadHandler): void
+  removePostProcessor(fn: UploadHandler): void
+  addUploader(fn: UploadHandler): void
+  removeUploader(fn: UploadHandler): void
+  setMeta<TMeta extends IndexedObject<any> = {}>(data: TMeta): void
+  setFileMeta<TMeta extends IndexedObject<any> = {}>(
+    fileID: string,
+    data: TMeta
+  ): void
+  getFile<
     TMeta extends IndexedObject<any> = {},
     TBody extends IndexedObject<any> = {}
-  > {
-    successful: UploadedUppyFile<TMeta, TBody>[]
-    failed: FailedUppyFile<TMeta, TBody>[]
-  }
-
-  interface State<
+  >(fileID: string): UppyFile<TMeta, TBody>
+  getFiles<
     TMeta extends IndexedObject<any> = {},
     TBody extends IndexedObject<any> = {}
-  > extends IndexedObject<any> {
-    capabilities?: { resumableUploads?: boolean }
-    currentUploads: {}
-    error?: string
-    files: {
-      [key: string]:
-        | UploadedUppyFile<TMeta, TBody>
-        | FailedUppyFile<TMeta, TBody>
-    }
-    info?: {
-      isHidden: boolean
-      type: string
-      message: string
-      details: string
-    }
-    plugins?: IndexedObject<any>
-    totalProgress: number
-  }
-
-  type LogLevel = 'info' | 'warning' | 'error'
-
-  // This hack accepts _any_ string for `Event`, but also tricks VSCode and friends into providing autocompletions
-  // for the names listed. https://github.com/microsoft/TypeScript/issues/29729#issuecomment-505826972
-  type LiteralUnion<T extends U, U = string> = T | (U & Record<never, never>);
-
-  type Event = LiteralUnion<'file-added' | 'file-removed' | 'upload' | 'upload-progress' | 'upload-success' | 'complete' | 'error' | 'upload-error' |
-               'upload-retry' | 'info-visible' | 'info-hidden' | 'cancel-all' | 'restriction-failed' | 'reset-progress'>;
-
-  type UploadHandler = (fileIDs: string[]) => Promise<void>
-
-  type UploadSuccessCallback<T> = (file: UppyFile<T>, body: any, uploadURL: string) => void
-  type UploadCompleteCallback<T> = (result: UploadResult<T>) => void
-
-  class Uppy {
-    constructor(opts?: UppyOptions)
-    on<TMeta extends IndexedObject<any> = {}>(event: 'upload-success', callback: UploadSuccessCallback<TMeta>): this
-    on<TMeta extends IndexedObject<any> = {}>(event: 'complete', callback: UploadCompleteCallback<TMeta>): this
-    on(event: Event, callback: (...args: any[]) => void): this
-    once<TMeta extends IndexedObject<any> = {}>(event: 'upload-success', callback: UploadSuccessCallback<TMeta>): this
-    once<TMeta extends IndexedObject<any> = {}>(event: 'complete', callback: UploadCompleteCallback<TMeta>): this
-    once(event: Event, callback: (...args: any[]) => void): this
-    off(event: Event, callback: (...args: any[]) => void): this
-    /**
-     * For use by plugins only.
-     */
-    emit(event: Event, ...args: any[]): void
-    updateAll(state: object): void
-    setOptions(update: Partial<UppyOptions>): void
-    setState(patch: object): void
-    getState<TMeta extends IndexedObject<any> = {}>(): State<TMeta>
-    readonly state: State
-    setFileState(fileID: string, state: object): void
-    resetProgress(): void
-    addPreProcessor(fn: UploadHandler): void
-    removePreProcessor(fn: UploadHandler): void
-    addPostProcessor(fn: UploadHandler): void
-    removePostProcessor(fn: UploadHandler): void
-    addUploader(fn: UploadHandler): void
-    removeUploader(fn: UploadHandler): void
-    setMeta<TMeta extends IndexedObject<any> = {}>(data: TMeta): void
-    setFileMeta<TMeta extends IndexedObject<any> = {}>(
-      fileID: string,
-      data: TMeta
-    ): void
-    getFile<
-      TMeta extends IndexedObject<any> = {},
-      TBody extends IndexedObject<any> = {}
-    >(fileID: string): UppyFile<TMeta, TBody>
-    getFiles<
-      TMeta extends IndexedObject<any> = {},
-      TBody extends IndexedObject<any> = {}
-    >(): Array<UppyFile<TMeta, TBody>>
-    getObjectOfFilesPerState(): {
-      newFiles: Array<UppyFile>,
-      startedFiles: Array<UppyFile>,
-      uploadStartedFiles: Array<UppyFile>,
-      pausedFiles: Array<UppyFile>,
-      completeFiles: Array<UppyFile>,
-      erroredFiles: Array<UppyFile>,
-      inProgressFiles: Array<UppyFile>,
-      inProgressNotPausedFiles: Array<UppyFile>,
-      processingFiles: Array<UppyFile>,
-
-      isUploadStarted: boolean,
-      isAllComplete: boolean,
-      isAllErrored: boolean,
-      isAllPaused: boolean,
-      isUploadInProgress: boolean,
-      isSomeGhost: boolean,
-    }
-    addFile<TMeta extends IndexedObject<any> = {}>(
-      file: AddFileOptions<TMeta>
-    ): string
-    removeFile(fileID: string): void
-    pauseResume(fileID: string): boolean
-    pauseAll(): void
-    resumeAll(): void
-    retryAll<TMeta extends IndexedObject<any> = {}>(): Promise<UploadResult<TMeta>>
-    cancelAll(): void
-    retryUpload<TMeta extends IndexedObject<any> = {}>(fileID: string): Promise<UploadResult<TMeta>>
-    reset(): void
-    getID(): string
-    use<TOptions, TInstance extends Plugin<TOptions>>(
-      pluginClass: new (uppy: this, opts: TOptions) => TInstance,
-      opts?: TOptions
-    ): this
-    getPlugin(name: string): Plugin
-    iteratePlugins(callback: (plugin: Plugin) => void): void
-    removePlugin(instance: Plugin): void
-    close(): void
-    logout(): void
-    info(
-      message: string | { message: string; details: string },
-      type?: LogLevel,
-      duration?: number
-    ): void
-    hideInfo(): void
-    log(msg: string, type?: LogLevel): void
-    restore<TMeta extends IndexedObject<any> = {}>(
-      uploadID: string
-    ): Promise<UploadResult<TMeta>>
-    addResultData(uploadID: string, data: object): void
-    upload<TMeta extends IndexedObject<any> = {}>(): Promise<UploadResult<TMeta>>
+  >(): Array<UppyFile<TMeta, TBody>>
+  getObjectOfFilesPerState(): {
+    newFiles: Array<UppyFile>
+    startedFiles: Array<UppyFile>
+    uploadStartedFiles: Array<UppyFile>
+    pausedFiles: Array<UppyFile>
+    completeFiles: Array<UppyFile>
+    erroredFiles: Array<UppyFile>
+    inProgressFiles: Array<UppyFile>
+    inProgressNotPausedFiles: Array<UppyFile>
+    processingFiles: Array<UppyFile>
+    isUploadStarted: boolean
+    isAllComplete: boolean
+    isAllErrored: boolean
+    isAllPaused: boolean
+    isUploadInProgress: boolean
+    isSomeGhost: boolean
   }
+  addFile<TMeta extends IndexedObject<any> = {}>(
+    file: AddFileOptions<TMeta>
+  ): string
+  removeFile(fileID: string): void
+  pauseResume(fileID: string): boolean
+  pauseAll(): void
+  resumeAll(): void
+  retryAll<TMeta extends IndexedObject<any> = {}>(): Promise<
+    UploadResult<TMeta>
+  >
+  cancelAll(): void
+  retryUpload<TMeta extends IndexedObject<any> = {}>(
+    fileID: string
+  ): Promise<UploadResult<TMeta>>
+  reset(): void
+  getID(): string
+  use<TOptions, TInstance extends UIPlugin | BasePlugin<TOptions>>(
+    pluginClass: new (uppy: this, opts: TOptions) => TInstance,
+    opts?: TOptions
+  ): this
+  getPlugin<TPlugin extends UIPlugin | BasePlugin>(name: string): TPlugin
+  iteratePlugins(callback: (plugin: UIPlugin | BasePlugin) => void): void
+  removePlugin(instance: UIPlugin | BasePlugin): void
+  close(): void
+  logout(): void
+  info(
+    message: string | { message: string; details: string },
+    type?: LogLevel,
+    duration?: number
+  ): void
+  hideInfo(): void
+  log(msg: string, type?: LogLevel): void
+  restore<TMeta extends IndexedObject<any> = {}>(
+    uploadID: string
+  ): Promise<UploadResult<TMeta>>
+  addResultData(uploadID: string, data: object): void
+  upload<TMeta extends IndexedObject<any> = {}>(): Promise<UploadResult<TMeta>>
 }
 
-declare function Uppy(opts?: Uppy.UppyOptions): Uppy.Uppy
-
-export = Uppy
+export default Uppy

+ 26 - 21
packages/@uppy/core/types/index.test-d.ts

@@ -1,28 +1,29 @@
 import { expectError, expectType } from 'tsd'
-import Uppy = require('../')
-import DefaultStore = require('@uppy/store-default')
+import Uppy, { UIPlugin } from '../'
+import type { UploadedUppyFile, FailedUppyFile, PluginOptions } from '../'
+import DefaultStore from '@uppy/store-default'
 
 {
-  const uppy = Uppy()
+  const uppy = new Uppy()
   uppy.addFile({
     data: new Blob([new ArrayBuffer(1024)], {
       type: 'application/octet-stream'
     })
   })
 
-  uppy.upload().then(result => {
-    expectType<Uppy.UploadedUppyFile<{}, {}>>(result.successful[0])
-    expectType<Uppy.FailedUppyFile<{}, {}>>(result.failed[0])
+  uppy.upload().then((result) => {
+    expectType<UploadedUppyFile<{}, {}>>(result.successful[0])
+    expectType<FailedUppyFile<{}, {}>>(result.failed[0])
   })
 }
 
 {
   const store = DefaultStore()
-  const uppy = Uppy({ store })
+  new Uppy({ store })
 }
 
 {
-  const uppy = Uppy()
+  const uppy = new Uppy()
   // this doesn't exist but type checking works anyway :)
   const f = uppy.getFile('virtual')
   if (f && f.progress && f.progress.uploadStarted === null) {
@@ -40,13 +41,13 @@ import DefaultStore = require('@uppy/store-default')
   type ResponseBody = {
     averageColor: string
   }
-  const uppy = Uppy()
+  const uppy = new Uppy()
   const f = uppy.getFile<Meta, ResponseBody>('virtual')!
   expectType<ResponseBody>(f.response!.body)
 }
 
 {
-  const uppy = Uppy()
+  const uppy = new Uppy()
   uppy.addFile({
     name: 'empty.json',
     data: new Blob(['null'], { type: 'application/json' }),
@@ -55,11 +56,11 @@ import DefaultStore = require('@uppy/store-default')
 }
 
 {
-  interface SomeOptions extends Uppy.PluginOptions {
+  interface SomeOptions extends PluginOptions {
     types: 'are checked'
   }
-  class SomePlugin extends Uppy.Plugin<SomeOptions> {}
-  const typedUppy = Uppy()
+  class SomePlugin extends UIPlugin<SomeOptions> {}
+  const typedUppy = new Uppy()
 
   expectError(typedUppy.use(SomePlugin, { types: 'error' }))
 
@@ -67,7 +68,7 @@ import DefaultStore = require('@uppy/store-default')
 }
 
 {
-  const uppy = Uppy()
+  const uppy = new Uppy()
   // can emit events with internal event types
   uppy.emit('upload')
   uppy.emit('complete', () => {})
@@ -90,7 +91,7 @@ import DefaultStore = require('@uppy/store-default')
 }
 
 {
-  const uppy = Uppy()
+  const uppy = new Uppy()
   uppy.setOptions({
     restrictions: {
       allowedFileTypes: ['.png']
@@ -101,13 +102,17 @@ import DefaultStore = require('@uppy/store-default')
 }
 
 {
-  interface TestOptions extends Uppy.PluginOptions {
+  interface TestOptions extends PluginOptions {
     testOption: string
   }
-  class TestPlugin extends Uppy.Plugin<TestOptions> {}
+  class TestPlugin extends UIPlugin<TestOptions> {
+  }
+
+  const strict = new Uppy().use(TestPlugin, { testOption: 'hello' })
+
+  strict.getPlugin<TestPlugin>('TestPlugin').setOptions({ testOption: 'world' })
+
+  expectError(strict.getPlugin<TestPlugin>('TestPlugin').setOptions({ testOption: 0 }))
 
-  const strict = Uppy().use(TestPlugin, { testOption: 'hello' })
-  ;(strict.getPlugin('TestPlugin') as TestPlugin).setOptions({ testOption: 'world' })
-  expectError((strict.getPlugin('TestPlugin') as TestPlugin).setOptions({ testOption: 0 }))
-  expectError((strict.getPlugin('TestPlugin') as TestPlugin).setOptions({ unknownKey: false }))
+  expectError(strict.getPlugin<TestPlugin>('TestPlugin').setOptions({ unknownKey: false }))
 }

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

@@ -1,6 +1,6 @@
-import Uppy = require('@uppy/core')
-import StatusBar = require('@uppy/status-bar')
-import DashboardLocale = require('./generatedLocale')
+import type { PluginOptions, UIPlugin, PluginTarget, UppyFile } from '@uppy/core'
+import type StatusBar from '@uppy/status-bar'
+import DashboardLocale from './generatedLocale'
 
 type FieldRenderOptions = {
   value: string,
@@ -17,7 +17,7 @@ interface MetaField {
 }
 
 declare module Dashboard {
-  interface DashboardOptions extends Uppy.PluginOptions {
+  interface DashboardOptions extends PluginOptions {
     animateOpenClose?: boolean
     browserBackButtonClose?: boolean
     closeAfterFinish?: boolean
@@ -35,7 +35,7 @@ declare module Dashboard {
     hideUploadButton?: boolean
     inline?: boolean
     locale?: DashboardLocale & StatusBar.StatusBarLocale
-    metaFields?: MetaField[] | ((file: Uppy.UppyFile) => MetaField[])
+    metaFields?: MetaField[] | ((file: UppyFile) => MetaField[])
     note?: string | null
     onRequestCloseModal?: () => void
     plugins?: string[]
@@ -46,7 +46,7 @@ declare module Dashboard {
     showSelectedFiles?: boolean
     showRemoveButtonAfterComplete?: boolean
     replaceTargetContent?: boolean
-    target?: Uppy.PluginTarget
+    target?: PluginTarget
     theme?: 'auto' | 'dark' | 'light'
     thumbnailWidth?: number
     trigger?: string
@@ -57,8 +57,8 @@ declare module Dashboard {
   }
 }
 
-declare class Dashboard extends Uppy.Plugin<Dashboard.DashboardOptions> {
-  addTarget (plugin: Uppy.Plugin): HTMLElement
+declare class Dashboard extends UIPlugin<Dashboard.DashboardOptions> {
+  addTarget (plugin: UIPlugin): HTMLElement
   hideAllPanels (): void
   openModal (): void
   closeModal (): void
@@ -68,4 +68,4 @@ declare class Dashboard extends Uppy.Plugin<Dashboard.DashboardOptions> {
   uninstall (): void
 }
 
-export = Dashboard
+export default Dashboard

+ 7 - 7
packages/@uppy/dashboard/types/index.test-d.ts

@@ -1,21 +1,21 @@
 import { expectType, expectError } from 'tsd'
-import Uppy = require('@uppy/core')
-import Dashboard = require('../')
+import Uppy from '@uppy/core'
+import Dashboard from '../'
 
 {
-  const uppy = Uppy()
+  const uppy = new Uppy()
   uppy.use(Dashboard, {
     target: 'body'
   })
 
-  const plugin = uppy.getPlugin('Dashboard') as Dashboard
+  const plugin = uppy.getPlugin<Dashboard>('Dashboard')
   plugin.openModal()
   expectType<boolean>(plugin.isModalOpen())
   plugin.closeModal()
 }
 
 {
-  const uppy = Uppy()
+  const uppy = new Uppy()
   uppy.use(Dashboard, {
     width: '100%',
     height: 700,
@@ -51,7 +51,7 @@ import Dashboard = require('../')
 }
 
 {
-  const uppy = Uppy()
+  const uppy = new Uppy()
   uppy.use(Dashboard, {
     locale: {
       strings: {
@@ -79,6 +79,6 @@ import Dashboard = require('../')
   }))
 }
 {
-  const uppy = Uppy()
+  const uppy = new Uppy()
   expectError(uppy.use(Dashboard, { height: {} }))
 }

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

@@ -1,10 +1,10 @@
-import Uppy = require('@uppy/core')
-import DragDropLocale = require('./generatedLocale')
+import type { PluginOptions, UIPlugin, PluginTarget } from '@uppy/core'
+import DragDropLocale from './generatedLocale'
 
 declare module DragDrop {
-  interface DragDropOptions extends Uppy.PluginOptions {
+  interface DragDropOptions extends PluginOptions {
     replaceTargetContent?: boolean
-    target?: Uppy.PluginTarget
+    target?: PluginTarget
     inputName?: string
     allowMultipleFiles?: boolean
     width?: string | number
@@ -17,6 +17,6 @@ declare module DragDrop {
   }
 }
 
-declare class DragDrop extends Uppy.Plugin<DragDrop.DragDropOptions> {}
+declare class DragDrop extends UIPlugin<DragDrop.DragDropOptions> {}
 
-export = DragDrop
+export default DragDrop

+ 8 - 8
packages/@uppy/drag-drop/types/index.test-d.ts

@@ -1,9 +1,9 @@
-import Uppy = require("@uppy/core");
+import Uppy from "@uppy/core"
 
-import DragDrop = require("../");
+import DragDrop from "../"
 
 {
-  const uppy = Uppy();
+  const uppy = new Uppy();
 
   uppy.use(DragDrop, {
     replaceTargetContent: true,
@@ -16,11 +16,11 @@ import DragDrop = require("../");
     locale: {
       strings: {
         dropHereOr: "test",
-        browse: "test"
-      }
+        browse: "test",
+      },
     },
-    onDragOver: event => event.clientX,
-    onDragLeave: event => event.clientY,
-    onDrop: event => event
+    onDragOver: (event) => event.clientX,
+    onDragLeave: (event) => event.clientY,
+    onDrop: (event) => event,
   });
 }

+ 4 - 4
packages/@uppy/drop-target/types/index.d.ts

@@ -1,11 +1,11 @@
-import Uppy = require('@uppy/core')
+import type { PluginOptions, BasePlugin} from '@uppy/core'
 
 declare module DropTarget {
-  interface DropTargetOptions extends Uppy.PluginOptions {
+  interface DropTargetOptions extends PluginOptions {
     target: string | Element
   }
 }
 
-declare class DropTarget extends Uppy.Plugin<DropTarget.DropTargetOptions> {}
+declare class DropTarget extends BasePlugin<DropTarget.DropTargetOptions> {}
 
-export = DropTarget
+export default DropTarget

+ 7 - 9
packages/@uppy/dropbox/types/index.d.ts

@@ -1,17 +1,15 @@
-import Uppy = require('@uppy/core')
-import CompanionClient = require('@uppy/companion-client')
+import type { PluginOptions, UIPlugin, PluginTarget } from '@uppy/core'
+import type { PublicProviderOptions, TokenStorage } from '@uppy/companion-client'
 
 declare module Dropbox {
-  interface DropboxOptions
-    extends Uppy.PluginOptions,
-      CompanionClient.PublicProviderOptions {
+  interface DropboxOptions extends PluginOptions, PublicProviderOptions {
     replaceTargetContent?: boolean
-    target?: Uppy.PluginTarget
+    target?: PluginTarget
     title?: string
-    storage?: CompanionClient.TokenStorage
+    storage?: TokenStorage
   }
 }
 
-declare class Dropbox extends Uppy.Plugin<Dropbox.DropboxOptions> {}
+declare class Dropbox extends UIPlugin<Dropbox.DropboxOptions> {}
 
-export = Dropbox
+export default Dropbox

+ 7 - 9
packages/@uppy/facebook/types/index.d.ts

@@ -1,17 +1,15 @@
-import Uppy = require('@uppy/core')
-import CompanionClient = require('@uppy/companion-client')
+import type { PluginOptions, UIPlugin, PluginTarget } from '@uppy/core'
+import type { PublicProviderOptions, TokenStorage } from '@uppy/companion-client'
 
 declare module Facebook {
-  interface FacebookOptions
-    extends Uppy.PluginOptions,
-      CompanionClient.PublicProviderOptions {
+  interface FacebookOptions extends PluginOptions, PublicProviderOptions {
     replaceTargetContent?: boolean
-    target?: Uppy.PluginTarget
+    target?: PluginTarget
     title?: string
-    storage?: CompanionClient.TokenStorage
+    storage?: TokenStorage
   }
 }
 
-declare class Facebook extends Uppy.Plugin<Facebook.FacebookOptions> {}
+declare class Facebook extends UIPlugin<Facebook.FacebookOptions> {}
 
-export = Facebook
+export default Facebook

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

@@ -1,16 +1,16 @@
-import Uppy = require('@uppy/core')
-import FileInputLocale = require('./generatedLocale')
+import type { PluginOptions, UIPlugin, PluginTarget } from '@uppy/core'
+import FileInputLocale from './generatedLocale'
 
 declare module FileInput {
-  export interface FileInputOptions extends Uppy.PluginOptions {
+  export interface FileInputOptions extends PluginOptions {
     replaceTargetContent?: boolean
-    target?: Uppy.PluginTarget
+    target?: PluginTarget
     pretty?: boolean
     inputName?: string
     locale?: FileInputLocale
   }
 }
 
-declare class FileInput extends Uppy.Plugin<FileInput.FileInputOptions> {}
+declare class FileInput extends UIPlugin<FileInput.FileInputOptions> {}
 
-export = FileInput
+export default FileInput

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

@@ -1,9 +1,9 @@
-import Uppy = require('@uppy/core')
+import type { PluginOptions, PluginTarget, BasePlugin } from '@uppy/core'
 
 declare module Form {
-  interface FormOptions extends Uppy.PluginOptions {
+  interface FormOptions extends PluginOptions {
     replaceTargetContent?: boolean
-    target?: Uppy.PluginTarget
+    target?: PluginTarget
     resultName?: string
     getMetaFromForm?: boolean
     addResultToForm?: boolean
@@ -12,6 +12,6 @@ declare module Form {
   }
 }
 
-declare class Form extends Uppy.Plugin<Form.FormOptions> {}
+declare class Form extends BasePlugin<Form.FormOptions> {}
 
-export = Form
+export default Form

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

@@ -1,15 +1,15 @@
-import Uppy = require('@uppy/core')
+import type { PluginOptions, BasePlugin } from '@uppy/core'
 
 declare module GoldenRetriever {
-  interface GoldenRetrieverOptions extends Uppy.PluginOptions {
+  interface GoldenRetrieverOptions extends PluginOptions {
     expires?: number
     serviceWorker?: boolean
     indexedDB?: any
   }
 }
 
-declare class GoldenRetriever extends Uppy.Plugin<
+declare class GoldenRetriever extends BasePlugin<
   GoldenRetriever.GoldenRetrieverOptions
 > {}
 
-export = GoldenRetriever
+export default GoldenRetriever

+ 7 - 9
packages/@uppy/google-drive/types/index.d.ts

@@ -1,17 +1,15 @@
-import Uppy = require('@uppy/core')
-import CompanionClient = require('@uppy/companion-client')
+import type { PluginOptions, UIPlugin, PluginTarget } from '@uppy/core'
+import type { PublicProviderOptions, TokenStorage } from '@uppy/companion-client'
 
 declare module GoogleDrive {
-  interface GoogleDriveOptions
-    extends Uppy.PluginOptions,
-      CompanionClient.PublicProviderOptions {
+  interface GoogleDriveOptions extends PluginOptions, PublicProviderOptions {
     replaceTargetContent?: boolean
-    target?: Uppy.PluginTarget
+    target?: PluginTarget
     title?: string
-    storage?: CompanionClient.TokenStorage
+    storage?: TokenStorage
   }
 }
 
-declare class GoogleDrive extends Uppy.Plugin<GoogleDrive.GoogleDriveOptions> {}
+declare class GoogleDrive extends UIPlugin<GoogleDrive.GoogleDriveOptions> {}
 
-export = GoogleDrive
+export default GoogleDrive

+ 4 - 4
packages/@uppy/google-drive/types/index.test-d.ts

@@ -1,9 +1,9 @@
-import Uppy = require('@uppy/core')
-import GoogleDrive = require('../')
+import Uppy, { UIPlugin } from '@uppy/core'
+import GoogleDrive from '../'
 
-class SomePlugin extends Uppy.Plugin<{}> {}
+class SomePlugin extends UIPlugin<{}> {}
 
-const uppy = Uppy()
+const uppy = new Uppy()
 uppy.use(GoogleDrive, { companionUrl: '' })
 uppy.use(GoogleDrive, { target: SomePlugin, companionUrl: '' })
 uppy.use(GoogleDrive, { target: document.querySelector('#gdrive')!, companionUrl: '' })

+ 1 - 1
packages/@uppy/image-editor/README.md

@@ -20,7 +20,7 @@ import Uppy from '@uppy/core'
 import Dashboard from '@uppy/dashboard'
 import ImageEditor from '@uppy/image-editor'
 
-const uppy = Uppy()
+const uppy = new Uppy()
 uppy.use(Dashboard)
 uppy.use(ImageEditor, {
   target: Dashboard,

+ 6 - 6
packages/@uppy/image-editor/types/index.d.ts

@@ -1,5 +1,5 @@
-import Uppy = require('@uppy/core')
-import ImageEditorLocale = require('./generatedLocale')
+import type { PluginOptions, UIPlugin, PluginTarget } from '@uppy/core'
+import ImageEditorLocale from './generatedLocale'
 
 declare module ImageEditor {
   type Actions = {
@@ -14,15 +14,15 @@ declare module ImageEditor {
     cropWidescreenVertical: boolean
   }
 
-  export interface ImageEditorOptions extends Uppy.PluginOptions {
+  export interface ImageEditorOptions extends PluginOptions {
     cropperOptions?: object
     actions?: Actions
     quality?: number
-    target?: Uppy.PluginTarget
+    target?: PluginTarget
     locale?: ImageEditorLocale
   }
 }
 
-declare class ImageEditor extends Uppy.Plugin<ImageEditor.ImageEditorOptions> {}
+declare class ImageEditor extends UIPlugin<ImageEditor.ImageEditorOptions> {}
 
-export = ImageEditor
+export default ImageEditor

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

@@ -1,12 +1,12 @@
-import Uppy = require('@uppy/core')
+import type { PluginOptions, UIPlugin, PluginTarget } from '@uppy/core'
 
 declare module Informer {
-  interface InformerOptions extends Uppy.PluginOptions {
+  interface InformerOptions extends PluginOptions {
     replaceTargetContent?: boolean
-    target?: Uppy.PluginTarget
+    target?: PluginTarget
   }
 }
 
-declare class Informer extends Uppy.Plugin<Informer.InformerOptions> {}
+declare class Informer extends UIPlugin<Informer.InformerOptions> {}
 
-export = Informer
+export default Informer

+ 7 - 9
packages/@uppy/instagram/types/index.d.ts

@@ -1,17 +1,15 @@
-import Uppy = require('@uppy/core')
-import CompanionClient = require('@uppy/companion-client')
+import type { PluginOptions, UIPlugin, PluginTarget } from '@uppy/core'
+import type { PublicProviderOptions, TokenStorage } from '@uppy/companion-client'
 
 declare module Instagram {
-  interface InstagramOptions
-    extends Uppy.PluginOptions,
-      CompanionClient.PublicProviderOptions {
+  interface InstagramOptions extends PluginOptions, PublicProviderOptions {
     replaceTargetContent?: boolean
-    target?: Uppy.PluginTarget
+    target?: PluginTarget
     title?: string
-    storage?: CompanionClient.TokenStorage
+    storage?: TokenStorage
   }
 }
 
-declare class Instagram extends Uppy.Plugin<Instagram.InstagramOptions> {}
+declare class Instagram extends UIPlugin<Instagram.InstagramOptions> {}
 
-export = Instagram
+export default Instagram

+ 7 - 9
packages/@uppy/onedrive/types/index.d.ts

@@ -1,17 +1,15 @@
-import Uppy = require('@uppy/core')
-import CompanionClient = require('@uppy/companion-client')
+import type { PluginOptions, UIPlugin, PluginTarget } from '@uppy/core'
+import type { PublicProviderOptions, TokenStorage } from '@uppy/companion-client'
 
 declare module OneDrive {
-  interface OneDriveOptions
-    extends Uppy.PluginOptions,
-      CompanionClient.PublicProviderOptions {
+  interface OneDriveOptions extends PluginOptions, PublicProviderOptions {
     replaceTargetContent?: boolean
-    target?: Uppy.PluginTarget
+    target?: PluginTarget
     title?: string
-    storage?: CompanionClient.TokenStorage
+    storage?: TokenStorage
   }
 }
 
-declare class OneDrive extends Uppy.Plugin<OneDrive.OneDriveOptions> {}
+declare class OneDrive extends UIPlugin<OneDrive.OneDriveOptions> {}
 
-export = OneDrive
+export default OneDrive

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

@@ -1,14 +1,14 @@
-import Uppy = require('@uppy/core')
+import type { PluginOptions, UIPlugin, PluginTarget } from '@uppy/core'
 
 declare module ProgressBar {
-  interface ProgressBarOptions extends Uppy.PluginOptions {
+  interface ProgressBarOptions extends PluginOptions {
     replaceTargetContent?: boolean
-    target?: Uppy.PluginTarget
+    target?: PluginTarget
     hideAfterFinish?: boolean
     fixed?: boolean
   }
 }
 
-declare class ProgressBar extends Uppy.Plugin<ProgressBar.ProgressBarOptions> {}
+declare class ProgressBar extends UIPlugin<ProgressBar.ProgressBarOptions> {}
 
-export = ProgressBar
+export default ProgressBar

+ 5 - 5
packages/@uppy/provider-views/types/index.d.ts

@@ -1,8 +1,8 @@
-import CompanionClient = require('@uppy/companion-client')
-import Uppy = require('@uppy/core')
+import type { UIPlugin } from '@uppy/core'
+import type { Provider } from '@uppy/companion-client'
 
 interface ProviderViewOptions {
-    provider: CompanionClient.Provider
+    provider: Provider
     viewType?: 'list' | 'grid'
     showTitles?: boolean
     showFilter?: boolean
@@ -15,8 +15,8 @@ interface OnFirstRenderer {
 
 
 declare class ProviderView {
-    constructor (plugin: Uppy.Plugin & OnFirstRenderer, opts: ProviderViewOptions)
+    constructor (plugin: UIPlugin & OnFirstRenderer, opts: ProviderViewOptions)
     // @todo add other provider view methods
 }
 
-export = ProviderView
+export default ProviderView

+ 1 - 0
packages/@uppy/react/package.json

@@ -31,6 +31,7 @@
     "prop-types": "^15.6.1"
   },
   "devDependencies": {
+    "@types/react": "^17.0.13",
     "enzyme": "3.11.0",
     "enzyme-adapter-react-16": "1.15.2",
     "react": "^16.8.6",

+ 1 - 4
packages/@uppy/react/src/CommonTypes.d.ts

@@ -1,7 +1,4 @@
-import UppyCore = require('@uppy/core');
-
-export type Uppy = UppyCore.Uppy
-export type Locale = UppyCore.Locale
+import type { Uppy } from '@uppy/core'
 
 // Helper to exclude a key
 export type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>

+ 2 - 1
packages/@uppy/react/src/Dashboard.d.ts

@@ -1,5 +1,6 @@
+import * as React from 'react'
 import { Omit, ToUppyProps } from './CommonTypes'
-import Dashboard = require('@uppy/dashboard')
+import Dashboard from '@uppy/dashboard'
 
 // This type is mapped into `DashboardProps` below so IntelliSense doesn't display this big mess of nested types
 type DashboardPropsInner = Omit<

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

@@ -1,5 +1,5 @@
 import { Omit, ToUppyProps } from './CommonTypes'
-import Dashboard = require('@uppy/dashboard')
+import Dashboard from '@uppy/dashboard'
 
 // This type is mapped into `DashboardModalProps` below so IntelliSense doesn't display this big mess of nested types
 type DashboardModalPropsInner = {

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

@@ -1,5 +1,5 @@
 import { ToUppyProps } from './CommonTypes'
-import DragDrop = require('@uppy/drag-drop')
+import DragDrop from '@uppy/drag-drop'
 
 export type DragDropProps = ToUppyProps<DragDrop.DragDropOptions>  & React.BaseHTMLAttributes<HTMLDivElement>
 

+ 1 - 1
packages/@uppy/react/src/FileInput.d.ts

@@ -1,5 +1,5 @@
 import { ToUppyProps } from './CommonTypes'
-import FileInput = require('@uppy/file-input')
+import FileInput from '@uppy/file-input'
 
 export type FileInputProps = ToUppyProps<FileInput.FileInputOptions>
 

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

@@ -1,5 +1,5 @@
 import { ToUppyProps } from './CommonTypes'
-import ProgressBar = require('@uppy/progress-bar')
+import ProgressBar from '@uppy/progress-bar'
 
 export type ProgressBarProps = ToUppyProps<ProgressBar.ProgressBarOptions> & React.BaseHTMLAttributes<HTMLDivElement>
 

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

@@ -1,5 +1,5 @@
 import { ToUppyProps } from './CommonTypes'
-import StatusBar = require('@uppy/status-bar')
+import StatusBar from '@uppy/status-bar'
 
 export type StatusBarProps = ToUppyProps<StatusBar.StatusBarOptions>  & React.BaseHTMLAttributes<HTMLDivElement>
 

+ 2 - 2
packages/@uppy/react/src/useUppy.d.ts

@@ -1,5 +1,5 @@
-import Uppy = require("@uppy/core")
+import type Uppy from "@uppy/core"
 
-declare function useUppy(factory: () => Uppy.Uppy): Uppy.Uppy
+declare function useUppy(factory: () => Uppy): Uppy
 
 export = useUppy

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

@@ -1,5 +1,3 @@
-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'
@@ -8,4 +6,4 @@ export { default as StatusBar } from '../src/StatusBar'
 export { default as FileInput } from '../src/FileInput'
 
 import useUppy = require('../src/useUppy')
-export { useUppy }
+export { useUppy }

+ 23 - 21
packages/@uppy/react/types/index.test-d.tsx

@@ -1,27 +1,27 @@
-import React = require('react')
-import Uppy = require('@uppy/core')
-import { expectType, expectError } from 'tsd'
-import * as components from '../'
+import * as React from "react"
+import Uppy from "@uppy/core"
+import { expectType, expectError } from "tsd"
+import * as components from "../"
 
 const { useUppy } = components
 
-const uppy = Uppy()
+const uppy = new Uppy()
 
-function TestComponent() {
+{
+  function TestComponent() {
     return (
-        <components.Dashboard
-            uppy={uppy}
-            closeAfterFinish
-            hideCancelButton
-        />
+      <components.Dashboard uppy={uppy} closeAfterFinish hideCancelButton />
     )
+  }
 }
 
 // inline option should be removed from proptypes because it is always overridden
 // by the component
-expectError(<components.Dashboard inline />)
-expectError(<components.DashboardModal inline />)
-expectError(<components.DashboardModal replaceTargetContent />)
+{
+  expectError(<components.Dashboard inline />)
+  expectError(<components.DashboardModal inline />)
+  expectError(<components.DashboardModal replaceTargetContent />)
+}
 
 {
   const el = (
@@ -36,8 +36,8 @@ expectError(<components.DashboardModal replaceTargetContent />)
           // `%{browse}` is replaced with a link that opens the system file selection dialog.
           dropHereOr: "Drop here or %{browse}",
           // Used as the label for the link that opens the system file selection dialog.
-          browse: "browse"
-        }
+          browse: "browse",
+        },
       }}
     />
   )
@@ -50,7 +50,7 @@ expectError(<components.DashboardModal replaceTargetContent />)
       open
       animateOpenClose
       onRequestClose={() => {
-        alert('no')
+        alert("no")
       }}
     />
   )
@@ -59,8 +59,10 @@ expectError(<components.DashboardModal replaceTargetContent />)
   expectError(<components.DashboardModal onRequestCloseModal />)
 }
 
-function TestHook () {
-  expectType<Uppy.Uppy>(useUppy(() => uppy))
-  expectType<Uppy.Uppy>(useUppy(() => Uppy()))
-  expectError(useUppy(uppy))
+{
+  function TestHook() {
+    expectType<Uppy>(useUppy(() => uppy))
+    expectType<Uppy>(useUppy(() => new Uppy()))
+    expectError(useUppy(uppy))
+  }
 }

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

@@ -1,11 +1,11 @@
-import Uppy = require('@uppy/core')
+import type { PluginOptions, UIPlugin } from '@uppy/core'
 
 declare module ReduxDevTools {
-  interface ReduxDevToolsOptions extends Uppy.PluginOptions {}
+  interface ReduxDevToolsOptions extends PluginOptions {}
 }
 
-declare class ReduxDevTools extends Uppy.Plugin<
+declare class ReduxDevTools extends UIPlugin<
   ReduxDevTools.ReduxDevToolsOptions
 > {}
 
-export = ReduxDevTools
+export default ReduxDevTools

+ 4 - 4
packages/@uppy/screen-capture/types/index.d.ts

@@ -1,4 +1,4 @@
-import Uppy = require('@uppy/core');
+import type { PluginOptions, UIPlugin } from '@uppy/core'
 
 declare module ScreenCapture {
   // https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints#Properties_of_shared_screen_tracks
@@ -12,13 +12,13 @@ declare module ScreenCapture {
     });
   }
 
-  export interface ScreenCaptureOptions extends Uppy.PluginOptions {
+  export interface ScreenCaptureOptions extends PluginOptions {
     displayMediaConstraints?: DisplayMediaStreamConstraints,
     userMediaConstraints?: MediaStreamConstraints,
     preferredVideoMimeType?: string
   }
 }
 
-declare class ScreenCapture extends Uppy.Plugin<ScreenCapture.ScreenCaptureOptions> {}
+declare class ScreenCapture extends UIPlugin<ScreenCapture.ScreenCaptureOptions> {}
 
-export = ScreenCapture;
+export default ScreenCapture

+ 8 - 8
packages/@uppy/screen-capture/types/index.test-d.ts

@@ -1,21 +1,21 @@
 import { expectError } from 'tsd'
-import Uppy = require('@uppy/core')
-import ScreenCapture = require('../')
+import Uppy from '@uppy/core'
+import ScreenCapture from '../'
 
 {
-  Uppy().use(ScreenCapture)
-  Uppy().use(ScreenCapture, {})
-  Uppy().use(ScreenCapture, { preferredVideoMimeType: 'video/mp4' })
-  expectError(Uppy().use(ScreenCapture, { preferredVideoMimeType: 10 }))
+  new Uppy().use(ScreenCapture)
+  new Uppy().use(ScreenCapture, {})
+  new Uppy().use(ScreenCapture, { preferredVideoMimeType: 'video/mp4' })
+  expectError(new Uppy().use(ScreenCapture, { preferredVideoMimeType: 10 }))
 }
 
 {
-  Uppy().use(ScreenCapture, {
+  new Uppy().use(ScreenCapture, {
     displayMediaConstraints: {
       video: { displaySurface: 'window' }
     }
   })
-  expectError(Uppy().use(ScreenCapture, {
+  expectError(new Uppy().use(ScreenCapture, {
     displayMediaConstraints: {
       video: { displaySurface: 'some nonsense' }
     }

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

@@ -1,12 +1,12 @@
-import Uppy = require('@uppy/core')
-import GeneratedLocale = require('./generatedLocale')
+import type { PluginOptions, UIPlugin, PluginTarget } from '@uppy/core'
+import GeneratedLocale from './generatedLocale'
 
 declare module StatusBar {
   export type StatusBarLocale = GeneratedLocale
 
-  export interface StatusBarOptions extends Uppy.PluginOptions {
+  export interface StatusBarOptions extends PluginOptions {
     replaceTargetContent?: boolean
-    target?: Uppy.PluginTarget
+    target?: PluginTarget
     showProgressDetails?: boolean
     hideUploadButton?: boolean
     hideAfterFinish?: boolean
@@ -18,6 +18,6 @@ declare module StatusBar {
   }
 }
 
-declare class StatusBar extends Uppy.Plugin<StatusBar.StatusBarOptions> {}
+declare class StatusBar extends UIPlugin<StatusBar.StatusBarOptions> {}
 
-export = StatusBar
+export default StatusBar

+ 4 - 3
packages/@uppy/store-default/types/index.d.ts

@@ -1,6 +1,6 @@
-import UppyUtils = require('@uppy/utils')
+import type { Store } from '@uppy/utils'
 
-declare class DefaultStore implements UppyUtils.Store {
+declare class DefaultStore implements Store {
   constructor ()
   getState (): object
   setState (patch: object): void
@@ -8,4 +8,5 @@ declare class DefaultStore implements UppyUtils.Store {
 }
 
 declare function createDefaultStore (): DefaultStore
-export = createDefaultStore
+
+export default createDefaultStore

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

@@ -1,4 +1,4 @@
-import DefaultStore = require('../')
+import DefaultStore from '../'
 
 const store = DefaultStore()
 

+ 5 - 4
packages/@uppy/store-redux/types/index.d.ts

@@ -1,5 +1,5 @@
-import UppyUtils = require('@uppy/utils')
-import { Reducer, Middleware, Store as Redux } from 'redux'
+import type { Store } from '@uppy/utils'
+import type { Reducer, Middleware, Store as Redux } from 'redux'
 
 declare namespace ReduxStore {
   interface ReduxStoreOptions {
@@ -8,7 +8,7 @@ declare namespace ReduxStore {
     selector?: (state: any) => object
   }
 
-  interface ReduxStore extends UppyUtils.Store {
+  interface ReduxStore extends Store {
     constructor (opts: ReduxStoreOptions): ReduxStore
     getState (): object
     setState (patch: object): void
@@ -19,8 +19,9 @@ declare namespace ReduxStore {
   const middleware: Middleware
   const STATE_UPDATE: string
 }
+
 declare function ReduxStore (
   opts: ReduxStore.ReduxStoreOptions
 ): ReduxStore.ReduxStore
 
-export = ReduxStore
+export default ReduxStore

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

@@ -1,5 +1,5 @@
 import { createStore, combineReducers } from 'redux'
-import ReduxStore = require('../')
+import ReduxStore from '../'
 
 const reducer = combineReducers({
   uppy: ReduxStore.reducer

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

@@ -1,8 +1,9 @@
-import Uppy = require('@uppy/core')
-import ThumbnailGeneratorLocale = require('./generatedLocale')
+import type { PluginOptions, UIPlugin } from '@uppy/core'
+
+import ThumbnailGeneratorLocale from './generatedLocale'
 
 declare module ThumbnailGenerator {
-  interface ThumbnailGeneratorOptions extends Uppy.PluginOptions {
+  interface ThumbnailGeneratorOptions extends PluginOptions {
     thumbnailWidth?: number,
     thumbnailHeight?: number,
     thumbnailType?: string, 
@@ -12,8 +13,8 @@ declare module ThumbnailGenerator {
   }
 }
 
-declare class ThumbnailGenerator extends Uppy.Plugin<
+declare class ThumbnailGenerator extends UIPlugin<
   ThumbnailGenerator.ThumbnailGeneratorOptions
 > {}
 
-export = ThumbnailGenerator
+export default ThumbnailGenerator

+ 6 - 8
packages/@uppy/transloadit/types/index.d.ts

@@ -1,5 +1,5 @@
-import Uppy = require('@uppy/core')
-import TransloaditLocale = require('./generatedLocale')
+import type { PluginOptions, UppyFile, BasePlugin } from '@uppy/core'
+import TransloaditLocale from './generatedLocale'
 
 declare module Transloadit {
   interface AssemblyParameters {
@@ -19,7 +19,7 @@ declare module Transloadit {
     signature?: string
   }
 
-  interface TransloaditOptionsBase extends Uppy.PluginOptions {
+  interface TransloaditOptionsBase extends PluginOptions {
     service?: string
     errorReporting?: boolean
     waitForEncoding?: boolean
@@ -34,16 +34,14 @@ declare module Transloadit {
   type TransloaditOptions = TransloaditOptionsBase &
     (
       | {
-          getAssemblyOptions?: (
-            file: Uppy.UppyFile
-          ) => AssemblyOptions | Promise<AssemblyOptions>
+          getAssemblyOptions?: (file: UppyFile) => AssemblyOptions | Promise<AssemblyOptions>
         }
       | AssemblyOptions)
 }
 
-declare class Transloadit extends Uppy.Plugin<Transloadit.TransloaditOptions> {
+declare class Transloadit extends BasePlugin<Transloadit.TransloaditOptions> {
   static COMPANION: string
   static COMPANION_PATTERN: RegExp
 }
 
-export = Transloadit
+export default Transloadit

+ 7 - 6
packages/@uppy/transloadit/types/index.test-d.ts

@@ -1,6 +1,7 @@
 import { expectError, expectType } from 'tsd'
-import Uppy = require('@uppy/core')
-import Transloadit = require('../')
+import Uppy from '@uppy/core'
+import type { UppyFile } from '@uppy/core'
+import Transloadit from '../'
 
 expectType<string>(Transloadit.COMPANION)
 expectType<RegExp>(Transloadit.COMPANION_PATTERN)
@@ -10,10 +11,10 @@ const validParams = {
 }
 
 {
-  const uppy = Uppy()
+  const uppy = new Uppy()
   uppy.use(Transloadit, {
     getAssemblyOptions (file) {
-      expectType<Uppy.UppyFile>(file)
+      expectType<UppyFile>(file)
       return { params: validParams }
     },
     waitForEncoding: false,
@@ -27,7 +28,7 @@ const validParams = {
 }
 
 {
-  const uppy = Uppy()
+  const uppy = new Uppy()
   // must be bools
   expectError(
     uppy.use(Transloadit, { waitForEncoding: null, params: validParams })
@@ -38,7 +39,7 @@ const validParams = {
 }
 
 {
-  const uppy = Uppy()
+  const uppy = new Uppy()
   // params.auth.key must be string
   expectError(uppy.use(Transloadit, { params: {} }))
   expectError(uppy.use(Transloadit, { params: { auth: {} } }))

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

@@ -1,5 +1,5 @@
-import Uppy = require('@uppy/core')
-import { UploadOptions } from 'tus-js-client'
+import type { PluginOptions, BasePlugin } from '@uppy/core'
+import type { UploadOptions } from 'tus-js-client'
 
 declare module Tus {
   type TusUploadOptions = Pick<UploadOptions, Exclude<keyof UploadOptions,
@@ -13,7 +13,7 @@ declare module Tus {
     | 'uploadSize'
   >>
 
-  export interface TusOptions extends Uppy.PluginOptions, TusUploadOptions {
+  export interface TusOptions extends PluginOptions, TusUploadOptions {
     metaFields?: string[] | null
     limit?: number
     useFastRemoteRetry?: boolean
@@ -21,6 +21,6 @@ declare module Tus {
   }
 }
 
-declare class Tus extends Uppy.Plugin<Tus.TusOptions> {}
+declare class Tus extends BasePlugin<Tus.TusOptions> {}
 
-export = Tus
+export default Tus

+ 1 - 1
packages/@uppy/unsplash/README.md

@@ -17,7 +17,7 @@ Uppy is being developed by the folks at [Transloadit](https://transloadit.com),
 import Uppy from '@uppy/core'
 import Unsplash from '@uppy/unsplash'
 
-const uppy = Uppy()
+const uppy = new Uppy()
 uppy.use(Unsplash, {
   // Options
 })

+ 6 - 8
packages/@uppy/unsplash/types/index.d.ts

@@ -1,16 +1,14 @@
-import Uppy = require('@uppy/core')
-import CompanionClient = require('@uppy/companion-client')
+import type { PluginOptions, UIPlugin, PluginTarget } from '@uppy/core'
+import type { RequestClientOptions } from '@uppy/companion-client'
 
 declare module Unsplash {
-  interface UnsplashOptions
-    extends Uppy.PluginOptions,
-      CompanionClient.RequestClientOptions {
+  interface UnsplashOptions extends PluginOptions, RequestClientOptions {
     replaceTargetContent?: boolean
-    target?: Uppy.PluginTarget
+    target?: PluginTarget
     title?: string
   }
 }
 
-declare class Unsplash extends Uppy.Plugin<Unsplash.UnsplashOptions> {}
+declare class Unsplash extends UIPlugin<Unsplash.UnsplashOptions> {}
 
-export = Unsplash
+export default Unsplash

+ 7 - 9
packages/@uppy/url/types/index.d.ts

@@ -1,18 +1,16 @@
-import Uppy = require('@uppy/core')
-import CompanionClient = require('@uppy/companion-client')
-import UrlLocale = require('./generatedLocale')
+import type { PluginOptions, UIPlugin, PluginTarget } from '@uppy/core'
+import type { RequestClientOptions } from '@uppy/companion-client'
+import UrlLocale from './generatedLocale'
 
 declare module Url {
-  export interface UrlOptions
-    extends Uppy.PluginOptions,
-      CompanionClient.RequestClientOptions {
+  export interface UrlOptions extends PluginOptions, RequestClientOptions {
     replaceTargetContent?: boolean
-    target?: Uppy.PluginTarget
+    target?: PluginTarget
     title?: string
     locale?: UrlLocale
   }
 }
 
-declare class Url extends Uppy.Plugin<Url.UrlOptions> {}
+declare class Url extends UIPlugin<Url.UrlOptions> {}
 
-export = Url
+export default Url

+ 4 - 3
packages/@uppy/vue/types/dashboard-modal.d.ts

@@ -1,13 +1,14 @@
 import Vue from 'vue';
-import { Uppy, Plugin } from '@uppy/core';
-import * as DashboardPlugin from '@uppy/dashboard';
+import type { Uppy, UIPlugin, BasePlugin } from '@uppy/core';
+import type DashboardPlugin from '@uppy/dashboard';
+
 interface Data {
     plugin: DashboardPlugin;
 }
 interface Props {
     uppy: Uppy;
     props: Object;
-    plugins: Plugin[];
+    plugins: Array<UIPlugin | BasePlugin>
     open: boolean;
 }
 interface Methods {

+ 4 - 3
packages/@uppy/vue/types/dashboard.d.ts

@@ -1,13 +1,14 @@
 import Vue from 'vue';
-import { Uppy, Plugin } from '@uppy/core';
-import * as DashboardPlugin from '@uppy/dashboard';
+import type { Uppy, UIPlugin, BasePlugin } from '@uppy/core';
+import type DashboardPlugin from '@uppy/dashboard';
+
 interface Data {
     plugin: DashboardPlugin;
 }
 interface Props {
     uppy: Uppy;
     props: Object;
-    plugins: Plugin[];
+    plugins: Array<UIPlugin | BasePlugin>
 }
 interface Methods {
     installPlugin(): void;

+ 4 - 2
packages/@uppy/vue/types/drag-drop.d.ts

@@ -1,7 +1,8 @@
 import Vue from 'vue';
-import { Uppy, Plugin } from '@uppy/core';
+import type { Uppy, UIPlugin, BasePlugin } from '@uppy/core';
+
 interface Data {
-    plugin: Plugin;
+    plugin: UIPlugin | BasePlugin;
 }
 interface Props {
     uppy: Uppy;
@@ -12,4 +13,5 @@ interface Methods {
     uninstallPlugin(uppy: Uppy): void;
 }
 declare const _default: import("vue/types/vue").ExtendedVue<Vue, Data, Methods, unknown, Props>;
+
 export default _default;

+ 3 - 2
packages/@uppy/vue/types/progress-bar.d.ts

@@ -1,7 +1,8 @@
 import Vue from 'vue';
-import { Uppy, Plugin } from '@uppy/core';
+import type { Uppy, UIPlugin, BasePlugin } from '@uppy/core';
+
 interface Data {
-    plugin: Plugin;
+    plugin: UIPlugin | BasePlugin;
 }
 interface Props {
     uppy: Uppy;

+ 3 - 2
packages/@uppy/vue/types/status-bar.d.ts

@@ -1,7 +1,8 @@
 import Vue from 'vue';
-import { Uppy, Plugin } from '@uppy/core';
+import type { Uppy, UIPlugin, BasePlugin } from '@uppy/core';
+
 interface Data {
-    plugin: Plugin;
+    plugin: UIPlugin | BasePlugin;
 }
 interface Props {
     uppy: Uppy;

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

@@ -1,5 +1,5 @@
-import Uppy = require('@uppy/core')
-import WebcamLocale = require('./generatedLocale')
+import type { PluginOptions, UIPlugin, PluginTarget } from '@uppy/core'
+import WebcamLocale from './generatedLocale'
 
 declare module Webcam {
   export type WebcamMode =
@@ -8,9 +8,9 @@ declare module Webcam {
     | 'audio-only'
     | 'picture'
 
-  export interface WebcamOptions extends Uppy.PluginOptions {
+  export interface WebcamOptions extends PluginOptions {
     replaceTargetContent?: boolean
-    target?: Uppy.PluginTarget
+    target?: PluginTarget
     onBeforeSnapshot?: () => Promise<void>
     countdown?: number | boolean
     mirror?: boolean
@@ -23,6 +23,6 @@ declare module Webcam {
   }
 }
 
-declare class Webcam extends Uppy.Plugin<Webcam.WebcamOptions> {}
+declare class Webcam extends UIPlugin<Webcam.WebcamOptions> {}
 
-export = Webcam
+export default Webcam

+ 5 - 5
packages/@uppy/webcam/types/index.test-d.ts

@@ -1,15 +1,15 @@
 import { expectError } from 'tsd'
-import Uppy = require('@uppy/core')
-import Webcam = require('../')
+import Uppy from '@uppy/core'
+import Webcam from '../'
 
 {
-  Uppy().use(Webcam, {
+  new Uppy().use(Webcam, {
     modes: ['video-only']
   })
 }
 
 {
-  Uppy().use(Webcam, {
+ new Uppy().use(Webcam, {
     modes: ['video-only'],
     videoConstraints: {
       width: { min: 420, ideal: 420, max: 1920 },
@@ -19,7 +19,7 @@ import Webcam = require('../')
 }
 
 {
-  expectError(Uppy().use(Webcam, {
+  expectError(new Uppy().use(Webcam, {
     modes: ['video-only'],
     videoConstraints: {
       width: 'not a number har har'

+ 7 - 6
packages/@uppy/xhr-upload/types/index.d.ts

@@ -1,15 +1,16 @@
-import Uppy = require('@uppy/core')
-import XHRUploadLocale = require('./generatedLocale')
+import type { PluginOptions, BasePlugin, UppyFile } from '@uppy/core'
+import XHRUploadLocale from './generatedLocale'
 
 declare module XHRUpload {
   type Headers = {
     [name: string]: string | number
   }
-  export interface XHRUploadOptions extends Uppy.PluginOptions {
+  
+  export interface XHRUploadOptions extends PluginOptions {
     limit?: number
     bundle?: boolean
     formData?: boolean
-    headers?: Headers | ((file: Uppy.UppyFile) => Headers)
+    headers?: Headers | ((file: UppyFile) => Headers)
     metaFields?: string[]
     fieldName?: string
     timeout?: number
@@ -22,6 +23,6 @@ declare module XHRUpload {
   }
 }
 
-declare class XHRUpload extends Uppy.Plugin<XHRUpload.XHRUploadOptions> {}
+declare class XHRUpload extends BasePlugin<XHRUpload.XHRUploadOptions> {}
 
-export = XHRUpload
+export default XHRUpload

+ 6 - 5
packages/@uppy/xhr-upload/types/index.test-d.ts

@@ -1,8 +1,8 @@
-import Uppy = require('@uppy/core')
-import XHRUpload = require('../')
+import Uppy from '@uppy/core'
+import XHRUpload from '../'
 
 {
-  Uppy().use(XHRUpload, {
+  new Uppy().use(XHRUpload, {
     bundle: false,
     formData: true,
     endpoint: 'xyz'
@@ -10,11 +10,12 @@ import XHRUpload = require('../')
 }
 
 {
-  Uppy().use(XHRUpload, {
+  new Uppy().use(XHRUpload, {
     endpoint: '/upload',
     method: 'post'
   })
-  Uppy().use(XHRUpload, {
+
+  new Uppy().use(XHRUpload, {
     endpoint: '/upload',
     method: 'PUT'
   })

+ 1 - 1
packages/@uppy/zoom/README.md

@@ -17,7 +17,7 @@ Uppy is being developed by the folks at [Transloadit](https://transloadit.com),
 import Uppy from '@uppy/core'
 import Zoom from '@uppy/zoom'
 
-const uppy = Uppy()
+const uppy = new Uppy()
 uppy.use(Zoom, {
   // Options
 })

+ 7 - 9
packages/@uppy/zoom/types/index.d.ts

@@ -1,17 +1,15 @@
-import Uppy = require('@uppy/core')
-import CompanionClient = require('@uppy/companion-client')
+import type { PluginOptions, UIPlugin, PluginTarget } from '@uppy/core'
+import type { TokenStorage, PublicProviderOptions } from '@uppy/companion-client'
 
 declare module Zoom {
-  interface ZoomOptions
-    extends Uppy.PluginOptions,
-      CompanionClient.PublicProviderOptions {
+  interface ZoomOptions extends PluginOptions, PublicProviderOptions {
     replaceTargetContent?: boolean
-    target?: Uppy.PluginTarget
+    target?: PluginTarget
     title?: string
-    storage?: CompanionClient.TokenStorage
+    storage?: TokenStorage
   }
 }
 
-declare class Zoom extends Uppy.Plugin<Zoom.ZoomOptions> {}
+declare class Zoom extends UIPlugin<Zoom.ZoomOptions> {}
 
-export = Zoom
+export default Zoom

+ 26 - 26
packages/uppy/types/index.d.ts

@@ -3,65 +3,65 @@
 // Definitions by: taoqf <https://github.com/taoqf>
 
 // Core
-import Core = require('@uppy/core');
+import Core from '@uppy/core';
 export { Core };
 
 // Stores
-import DefaultStore = require('@uppy/store-default');
+import DefaultStore from '@uppy/store-default';
 export { DefaultStore };
-import ReduxStore = require('@uppy/store-redux');
+import ReduxStore from '@uppy/store-redux';
 export { ReduxStore };
 
 // UI plugins
-import Dashboard = require('@uppy/dashboard');
+import Dashboard from '@uppy/dashboard';
 export { Dashboard };
-import DragDrop = require('@uppy/drag-drop');
+import DragDrop from '@uppy/drag-drop';
 export { DragDrop };
-import DropTarget = require('@uppy/drop-target');
+import DropTarget from '@uppy/drop-target';
 export { DropTarget };
-import FileInput = require('@uppy/file-input');
+import FileInput from '@uppy/file-input';
 export { FileInput };
-import Informer = require('@uppy/informer');
+import Informer from '@uppy/informer';
 export { Informer };
-import ProgressBar = require('@uppy/progress-bar');
+import ProgressBar from '@uppy/progress-bar';
 export { ProgressBar };
-import StatusBar = require('@uppy/status-bar');
+import StatusBar from '@uppy/status-bar';
 export { StatusBar };
 
 // Acquirers
-import Dropbox = require('@uppy/dropbox');
+import Dropbox from '@uppy/dropbox';
 export { Dropbox };
-import Box = require('@uppy/box');
+import Box from '@uppy/box';
 export { Box };
-import GoogleDrive = require('@uppy/google-drive');
+import GoogleDrive from '@uppy/google-drive';
 export { GoogleDrive };
-import Instagram = require('@uppy/instagram');
+import Instagram from '@uppy/instagram';
 export { Instagram };
-import Url = require('@uppy/url');
+import Url from '@uppy/url';
 export { Url };
-import Webcam = require('@uppy/webcam');
+import Webcam from '@uppy/webcam';
 export { Webcam };
-import ScreenCapture = require('@uppy/screen-capture');
+import ScreenCapture from '@uppy/screen-capture';
 export { ScreenCapture };
 
 // Uploaders
-import AwsS3 = require('@uppy/aws-s3');
+import AwsS3 from '@uppy/aws-s3';
 export { AwsS3 };
-import AwsS3Multipart = require('@uppy/aws-s3-multipart');
+import AwsS3Multipart from '@uppy/aws-s3-multipart';
 export { AwsS3Multipart };
-import Transloadit = require('@uppy/transloadit');
+import Transloadit from '@uppy/transloadit';
 export { Transloadit };
-import Tus = require('@uppy/tus');
+import Tus from '@uppy/tus';
 export { Tus };
-import XHRUpload = require('@uppy/xhr-upload');
+import XHRUpload from '@uppy/xhr-upload';
 export { XHRUpload };
 
 // Miscellaneous
-import Form = require('@uppy/form');
+import Form from '@uppy/form';
 export { Form };
-import GoldenRetriever = require('@uppy/golden-retriever');
+import GoldenRetriever from '@uppy/golden-retriever';
 export { GoldenRetriever };
-import ReduxDevTools = require('@uppy/redux-dev-tools');
+import ReduxDevTools from '@uppy/redux-dev-tools';
 export { ReduxDevTools };
-import ThumbnailGenerator = require('@uppy/thumbnail-generator');
+import ThumbnailGenerator from '@uppy/thumbnail-generator';
 export { ThumbnailGenerator };

+ 4 - 5
packages/uppy/types/index.test-d.ts

@@ -1,7 +1,7 @@
 import * as Uppy from '../';
 
 (() => {
-  const uppy = Uppy.Core({ autoProceed: false });
+  const uppy = new Uppy.Core({ autoProceed: false });
   uppy.use(Uppy.Dashboard, { trigger: '#up_load_file_01' });
   uppy.use(Uppy.DragDrop, { target: '#ttt' });
   uppy.use(Uppy.XHRUpload, {
@@ -15,13 +15,12 @@ import * as Uppy from '../';
 })();
 
 (() => {
-  const uppy = Uppy.Core({ autoProceed: false })
+  new Uppy.Core({ autoProceed: false })
     .use(Uppy.Dashboard, { trigger: '#select-files' })
     .use(Uppy.GoogleDrive, { target: Uppy.Dashboard, companionUrl: 'https://companion.uppy.io' })
     .use(Uppy.Instagram, { target: Uppy.Dashboard, companionUrl: 'https://companion.uppy.io' })
     .use(Uppy.Webcam, { target: Uppy.Dashboard })
-    .use(Uppy.ScreenCapture, { target: Uppy.Dashboard })
-    .use(Uppy.Zoom, { target: Uppy.Dashboard })
+    .use(Uppy.ScreenCapture)
     .use(Uppy.Tus, { endpoint: 'https://tusd.tusdemo.net/files/' })
     .on('complete', (result) => {
       console.log('Upload result:', result);
@@ -29,7 +28,7 @@ import * as Uppy from '../';
 })();
 
 (() => {
-  const uppy = Uppy.Core();
+  const uppy = new Uppy.Core();
   uppy.use(Uppy.DragDrop, { target: '.UppyDragDrop' });
   uppy.use(Uppy.Tus, { endpoint: '//tusd.tusdemo.net/files/' });
 })();

+ 15 - 15
private/remark-lint-uppy/package.json

@@ -2,21 +2,21 @@
   "name": "remark-lint-uppy",
   "version": "0.0.1",
   "dependencies": {
-    "remark-frontmatter": "^2.0.0",
-    "remark-lint": "^7.0.0",
-    "remark-lint-final-newline": "^1.0.4",
-    "remark-lint-hard-break-spaces": "^2.0.0",
-    "remark-lint-no-auto-link-without-protocol": "^2.0.0",
-    "remark-lint-no-blockquote-without-marker": "^3.0.0",
-    "remark-lint-no-duplicate-definitions": "^2.0.0",
-    "remark-lint-no-heading-content-indent": "^2.0.0",
-    "remark-lint-no-inline-padding": "^2.0.0",
-    "remark-lint-no-literal-urls": "^2.0.0",
-    "remark-lint-no-shortcut-reference-image": "^2.0.0",
-    "remark-lint-no-shortcut-reference-link": "^2.0.0",
-    "remark-lint-no-undefined-references": "^2.0.0",
-    "remark-lint-no-unused-definitions": "^2.0.0",
-    "remark-lint-ordered-list-marker-style": "^2.0.0"
+    "remark-frontmatter": "^3.0.0",
+    "remark-lint": "^8.0.0",
+    "remark-lint-final-newline": "^1.0.5",
+    "remark-lint-hard-break-spaces": "^2.0.1",
+    "remark-lint-no-auto-link-without-protocol": "^2.0.1",
+    "remark-lint-no-blockquote-without-marker": "^4.0.0",
+    "remark-lint-no-duplicate-definitions": "^2.0.1",
+    "remark-lint-no-heading-content-indent": "^3.0.0",
+    "remark-lint-no-inline-padding": "^3.0.0",
+    "remark-lint-no-literal-urls": "^2.0.1",
+    "remark-lint-no-shortcut-reference-image": "^2.0.1",
+    "remark-lint-no-shortcut-reference-link": "^2.0.1",
+    "remark-lint-no-undefined-references": "^3.0.0",
+    "remark-lint-no-unused-definitions": "^2.0.1",
+    "remark-lint-ordered-list-marker-style": "^2.0.1"
   },
   "private": true
 }

+ 2 - 0
website/src/_posts/2019-04-liftoff-09.md

@@ -7,6 +7,8 @@ series: 30 Days to Liftoff
 seriesSuffix: 'of 30'
 ---
 
+<!--lint disable no-undefined-references-->
+
 The entire team is starting to get into its groove as the Uppy channel in our Slack workspace is looking livelier than ever. Let's dive straight into Day 9 of our 30 Days to Liftoff!
 
 <center><img width="400" src="/images/blog/30daystoliftoff/day09.jpg"><br /><br /></center>

+ 1 - 1
website/src/docs/react-dashboard.md

@@ -52,7 +52,7 @@ import { Dashboard } from '@uppy/react'
 
 function Uploader () {
   const uppy = React.useMemo(() => {
-    return Uppy()
+    return new Uppy()
       .use(Webcam) // `id` defaults to "Webcam". Note: no `target` option!
       // or
       .use(Webcam, { id: 'MyWebcam' }) // `id` is… "MyWebcam"

+ 1 - 1
website/src/docs/react-initializing.md

@@ -48,7 +48,7 @@ import { DashboardModal } from '@uppy/react'
 class MyComponent extends React.Component {
   constructor (props) {
     super(props)
-    this.uppy = Uppy()
+    this.uppy = new Uppy()
       .use(Transloadit, {})
   }
 

部分文件因为文件数量过多而无法显示