Quellcode durchsuchen

@uppy/drag-drop: refactor to TypeScript (#4983)

Antoine du Hamel vor 1 Jahr
Ursprung
Commit
536d614437

+ 1 - 0
packages/@uppy/drag-drop/.npmignore

@@ -0,0 +1 @@
+tsconfig.*

+ 82 - 57
packages/@uppy/drag-drop/src/DragDrop.jsx → packages/@uppy/drag-drop/src/DragDrop.tsx

@@ -1,55 +1,69 @@
-import { UIPlugin } from '@uppy/core'
+import { UIPlugin, type Uppy } from '@uppy/core'
+import type { DefinePluginOpts } from '@uppy/core/lib/BasePlugin.ts'
+import type { UIPluginOptions } from '@uppy/core/lib/UIPlugin.ts'
+import type { Body, Meta } from '@uppy/utils/lib/UppyFile'
+import type { ChangeEvent } from 'preact/compat'
 import toArray from '@uppy/utils/lib/toArray'
 import isDragDropSupported from '@uppy/utils/lib/isDragDropSupported'
 import getDroppedFiles from '@uppy/utils/lib/getDroppedFiles'
-import { h } from 'preact'
+import { h, type ComponentChild } from 'preact'
 
+// eslint-disable-next-line @typescript-eslint/ban-ts-comment
+// @ts-ignore We don't want TS to generate types for the package.json
 import packageJson from '../package.json'
-import locale from './locale.js'
+import locale from './locale.ts'
+
+interface DragDropOptions extends UIPluginOptions {
+  inputName?: string
+  allowMultipleFiles?: boolean
+  width?: string | number
+  height?: string | number
+  note?: string
+  onDragOver?: (event: DragEvent) => void
+  onDragLeave?: (event: DragEvent) => void
+  onDrop?: (event: DragEvent) => void
+}
+
+// Default options, must be kept in sync with @uppy/react/src/DragDrop.js.
+const defaultOptions = {
+  inputName: 'files[]',
+  width: '100%',
+  height: '100%',
+} satisfies Partial<DragDropOptions>
 
 /**
  * Drag & Drop plugin
  *
  */
-export default class DragDrop extends UIPlugin {
+export default class DragDrop<M extends Meta, B extends Body> extends UIPlugin<
+  DefinePluginOpts<DragDropOptions, keyof typeof defaultOptions>,
+  M,
+  B
+> {
   static VERSION = packageJson.version
 
-  constructor (uppy, opts) {
-    super(uppy, opts)
+  // Check for browser dragDrop support
+  private isDragDropSupported = isDragDropSupported()
+
+  private removeDragOverClassTimeout: ReturnType<typeof setTimeout>
+
+  private fileInputRef: HTMLInputElement
+
+  constructor(uppy: Uppy<M, B>, opts?: DragDropOptions) {
+    super(uppy, {
+      ...defaultOptions,
+      ...opts,
+    })
     this.type = 'acquirer'
     this.id = this.opts.id || 'DragDrop'
     this.title = 'Drag & Drop'
 
     this.defaultLocale = locale
 
-    // Default options, must be kept in sync with @uppy/react/src/DragDrop.js.
-    const defaultOpts = {
-      target: null,
-      inputName: 'files[]',
-      width: '100%',
-      height: '100%',
-      note: null,
-    }
-
-    // Merge default options with the ones set by user
-    this.opts = { ...defaultOpts, ...opts }
-
     this.i18nInit()
-
-    // Check for browser dragDrop support
-    this.isDragDropSupported = isDragDropSupported()
-    this.removeDragOverClassTimeout = null
-
-    // Bind `this` to class methods
-    this.onInputChange = this.onInputChange.bind(this)
-    this.handleDragOver = this.handleDragOver.bind(this)
-    this.handleDragLeave = this.handleDragLeave.bind(this)
-    this.handleDrop = this.handleDrop.bind(this)
-    this.addFiles = this.addFiles.bind(this)
-    this.render = this.render.bind(this)
   }
 
-  addFiles (files) {
+  private addFiles = (files: File[]) => {
     const descriptors = files.map((file) => ({
       source: this.id,
       name: file.name,
@@ -58,8 +72,8 @@ export default class DragDrop extends UIPlugin {
       meta: {
         // path of the file relative to the ancestor directory the user selected.
         // e.g. 'docs/Old Prague/airbnb.pdf'
-        relativePath: file.relativePath || null,
-      },
+        relativePath: (file as any).relativePath || null,
+      } as any as M,
     }))
 
     try {
@@ -69,8 +83,8 @@ export default class DragDrop extends UIPlugin {
     }
   }
 
-  onInputChange (event) {
-    const files = toArray(event.target.files)
+  private onInputChange = (event: ChangeEvent) => {
+    const files = toArray((event.target as HTMLInputElement).files!)
     if (files.length > 0) {
       this.uppy.log('[DragDrop] Files selected through input')
       this.addFiles(files)
@@ -82,21 +96,22 @@ export default class DragDrop extends UIPlugin {
     // ___Why not use value="" on <input/> instead?
     //    Because if we use that method of clearing the input,
     //    Chrome will not trigger change if we drop the same file twice (Issue #768).
+    // @ts-expect-error TS freaks out, but this is fine
     // eslint-disable-next-line no-param-reassign
     event.target.value = null
   }
 
-  handleDragOver (event) {
+  private handleDragOver = (event: DragEvent) => {
     event.preventDefault()
     event.stopPropagation()
 
     // Check if the "type" of the datatransfer object includes files. If not, deny drop.
-    const { types } = event.dataTransfer
-    const hasFiles = types.some(type => type === 'Files')
+    const { types } = event.dataTransfer!
+    const hasFiles = types.some((type) => type === 'Files')
     const { allowNewUpload } = this.uppy.getState()
     if (!hasFiles || !allowNewUpload) {
       // eslint-disable-next-line no-param-reassign
-      event.dataTransfer.dropEffect = 'none'
+      event.dataTransfer!.dropEffect = 'none'
       clearTimeout(this.removeDragOverClassTimeout)
       return
     }
@@ -106,7 +121,7 @@ export default class DragDrop extends UIPlugin {
     // https://github.com/transloadit/uppy/issues/1978)
     //
     // eslint-disable-next-line no-param-reassign
-    event.dataTransfer.dropEffect = 'copy'
+    event.dataTransfer!.dropEffect = 'copy'
 
     clearTimeout(this.removeDragOverClassTimeout)
     this.setPluginState({ isDraggingOver: true })
@@ -114,7 +129,7 @@ export default class DragDrop extends UIPlugin {
     this.opts.onDragOver?.(event)
   }
 
-  handleDragLeave (event) {
+  private handleDragLeave = (event: DragEvent) => {
     event.preventDefault()
     event.stopPropagation()
 
@@ -128,7 +143,7 @@ export default class DragDrop extends UIPlugin {
     this.opts.onDragLeave?.(event)
   }
 
-  handleDrop = async (event) => {
+  private handleDrop = async (event: DragEvent) => {
     event.preventDefault()
     event.stopPropagation()
     clearTimeout(this.removeDragOverClassTimeout)
@@ -136,12 +151,12 @@ export default class DragDrop extends UIPlugin {
     // Remove dragover class
     this.setPluginState({ isDraggingOver: false })
 
-    const logDropError = (error) => {
+    const logDropError = (error: any) => {
       this.uppy.log(error, 'error')
     }
 
     // Add all dropped files
-    const files = await getDroppedFiles(event.dataTransfer, { logDropError })
+    const files = await getDroppedFiles(event.dataTransfer!, { logDropError })
     if (files.length > 0) {
       this.uppy.log('[DragDrop] Files dropped')
       this.addFiles(files)
@@ -150,47 +165,57 @@ export default class DragDrop extends UIPlugin {
     this.opts.onDrop?.(event)
   }
 
-  renderHiddenFileInput () {
+  private renderHiddenFileInput() {
     const { restrictions } = this.uppy.opts
     return (
       <input
         className="uppy-DragDrop-input"
         type="file"
         hidden
-        ref={(ref) => { this.fileInputRef = ref }}
+        ref={(ref) => {
+          this.fileInputRef = ref!
+        }}
         name={this.opts.inputName}
         multiple={restrictions.maxNumberOfFiles !== 1}
+        // @ts-expect-error We actually want to coerce the array to a string (or keep it as null/undefined)
         accept={restrictions.allowedFileTypes}
         onChange={this.onInputChange}
       />
     )
   }
 
-  static renderArrowSvg () {
+  private static renderArrowSvg() {
     return (
-      <svg aria-hidden="true" focusable="false" className="uppy-c-icon uppy-DragDrop-arrow" width="16" height="16" viewBox="0 0 16 16">
+      <svg
+        aria-hidden="true"
+        focusable="false"
+        className="uppy-c-icon uppy-DragDrop-arrow"
+        width="16"
+        height="16"
+        viewBox="0 0 16 16"
+      >
         <path d="M11 10V0H5v10H2l6 6 6-6h-3zm0 0" fillRule="evenodd" />
       </svg>
     )
   }
 
-  renderLabel () {
+  private renderLabel() {
     return (
       <div className="uppy-DragDrop-label">
         {this.i18nArray('dropHereOr', {
-          browse: <span className="uppy-DragDrop-browse">{this.i18n('browse')}</span>,
+          browse: (
+            <span className="uppy-DragDrop-browse">{this.i18n('browse')}</span>
+          ) as any,
         })}
       </div>
     )
   }
 
-  renderNote () {
-    return (
-      <span className="uppy-DragDrop-note">{this.opts.note}</span>
-    )
+  private renderNote() {
+    return <span className="uppy-DragDrop-note">{this.opts.note}</span>
   }
 
-  render () {
+  render(): ComponentChild {
     const dragDropClass = `uppy-u-reset
       uppy-DragDrop-container
       ${this.isDragDropSupported ? 'uppy-DragDrop--isDragDropSupported' : ''}
@@ -222,7 +247,7 @@ export default class DragDrop extends UIPlugin {
     )
   }
 
-  install () {
+  install(): void {
     const { target } = this.opts
 
     this.setPluginState({
@@ -234,7 +259,7 @@ export default class DragDrop extends UIPlugin {
     }
   }
 
-  uninstall () {
+  uninstall(): void {
     this.unmount()
   }
 }

+ 0 - 1
packages/@uppy/drag-drop/src/index.js

@@ -1 +0,0 @@
-export { default } from './DragDrop.jsx'

+ 1 - 0
packages/@uppy/drag-drop/src/index.ts

@@ -0,0 +1 @@
+export { default } from './DragDrop.tsx'

+ 0 - 0
packages/@uppy/drag-drop/src/locale.js → packages/@uppy/drag-drop/src/locale.ts


+ 25 - 0
packages/@uppy/drag-drop/tsconfig.build.json

@@ -0,0 +1,25 @@
+{
+  "extends": "../../../tsconfig.shared",
+  "compilerOptions": {
+    "noImplicitAny": false,
+    "outDir": "./lib",
+    "paths": {
+      "@uppy/utils/lib/*": ["../utils/src/*"],
+      "@uppy/core": ["../core/src/index.js"],
+      "@uppy/core/lib/*": ["../core/src/*"]
+    },
+    "resolveJsonModule": false,
+    "rootDir": "./src",
+    "skipLibCheck": true
+  },
+  "include": ["./src/**/*.*"],
+  "exclude": ["./src/**/*.test.ts"],
+  "references": [
+    {
+      "path": "../utils/tsconfig.build.json"
+    },
+    {
+      "path": "../core/tsconfig.build.json"
+    }
+  ]
+}

+ 21 - 0
packages/@uppy/drag-drop/tsconfig.json

@@ -0,0 +1,21 @@
+{
+  "extends": "../../../tsconfig.shared",
+  "compilerOptions": {
+    "emitDeclarationOnly": false,
+    "noEmit": true,
+    "paths": {
+      "@uppy/utils/lib/*": ["../utils/src/*"],
+      "@uppy/core": ["../core/src/index.js"],
+      "@uppy/core/lib/*": ["../core/src/*"],
+    },
+  },
+  "include": ["./package.json", "./src/**/*.*"],
+  "references": [
+    {
+      "path": "../utils/tsconfig.build.json",
+    },
+    {
+      "path": "../core/tsconfig.build.json",
+    },
+  ],
+}