Procházet zdrojové kódy

Added FileInput component to React (#2706)

Co-authored-by: Artur Paikin <artur@arturpaikin.com>
Andrew před 4 roky
rodič
revize
80b5ace47d

+ 6 - 1
examples/react-example/App.js

@@ -3,7 +3,7 @@ const React = require('react')
 const Uppy = require('@uppy/core')
 const Tus = require('@uppy/tus')
 const GoogleDrive = require('@uppy/google-drive')
-const { Dashboard, DashboardModal, DragDrop, ProgressBar } = require('@uppy/react')
+const { Dashboard, DashboardModal, DragDrop, ProgressBar, FileInput } = require('@uppy/react')
 
 module.exports = class App extends React.Component {
   constructor (props) {
@@ -93,6 +93,11 @@ module.exports = class App extends React.Component {
           uppy={this.uppy}
           hideAfterFinish={false}
         />
+
+        <h2>File Input</h2>
+        <FileInput
+          uppy={this.uppy}
+        />
       </div>
     )
   }

+ 1 - 1
packages/@uppy/react/index.js

@@ -3,5 +3,5 @@ exports.DashboardModal = require('./lib/DashboardModal')
 exports.DragDrop = require('./lib/DragDrop')
 exports.ProgressBar = require('./lib/ProgressBar')
 exports.StatusBar = require('./lib/StatusBar')
-
+exports.FileInput = require('./lib/FileInput')
 exports.useUppy = require('./lib/useUppy')

+ 1 - 1
packages/@uppy/react/index.mjs

@@ -3,5 +3,5 @@ export { default as DashboardModal } from './lib/DashboardModal.js'
 export { default as DragDrop } from './lib/DragDrop.js'
 export { default as ProgressBar } from './lib/ProgressBar.js'
 export { default as StatusBar } from './lib/StatusBar.js'
-
+export { default as FileInput } from './lib/FileInput.js'
 export { default as useUppy } from './lib/useUppy.js'

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

@@ -27,6 +27,7 @@
     "@uppy/progress-bar": "file:../progress-bar",
     "@uppy/status-bar": "file:../status-bar",
     "@uppy/utils": "file:../utils",
+    "@uppy/file-input": "file:../file-input",
     "prop-types": "^15.6.1"
   },
   "peerDependencies": {

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

@@ -0,0 +1,12 @@
+import { ToUppyProps } from './CommonTypes'
+import FileInput = require('@uppy/file-input')
+
+export type FileInputProps = ToUppyProps<FileInput.FileInputOptions>
+
+/**
+ * React component that renders an area in which files can be dropped to be
+ * uploaded.
+ */
+declare const FileInputComponent: React.ComponentType<FileInputProps>;
+export default FileInputComponent;
+

+ 67 - 0
packages/@uppy/react/src/FileInput.js

@@ -0,0 +1,67 @@
+const PropTypes = require('prop-types')
+const React = require('react')
+const FileInputPlugin = require('@uppy/file-input')
+const propTypes = require('./propTypes')
+
+const h = React.createElement
+
+/**
+ * React component that renders an area in which files can be dropped to be
+ * uploaded.
+ */
+
+class FileInput extends React.Component {
+  componentDidMount () {
+    this.installPlugin()
+  }
+
+  componentDidUpdate (prevProps) {
+    if (prevProps.uppy !== this.props.uppy) {
+      this.uninstallPlugin(prevProps)
+      this.installPlugin()
+    }
+  }
+
+  componentWillUnmount () {
+    this.uninstallPlugin()
+  }
+
+  installPlugin () {
+    const uppy = this.props.uppy
+    const options = Object.assign(
+      { id: 'react:FileInput' },
+      this.props,
+      { target: this.container }
+    )
+    delete options.uppy
+
+    uppy.use(FileInputPlugin, options)
+
+    this.plugin = uppy.getPlugin(options.id)
+  }
+
+  uninstallPlugin (props = this.props) {
+    const uppy = props.uppy
+
+    uppy.removePlugin(this.plugin)
+  }
+
+  render () {
+    return h('div', {
+      ref: (container) => {
+        this.container = container
+      }
+    })
+  }
+}
+
+FileInput.propTypes = {
+  uppy: propTypes.uppy,
+  locale: propTypes.locale,
+  pretty: PropTypes.bool,
+  inputName: PropTypes.string
+}
+FileInput.defaultProps = {
+}
+
+module.exports = FileInput

+ 35 - 0
packages/@uppy/react/src/FileInput.test.js

@@ -0,0 +1,35 @@
+const h = require('react').createElement
+const { mount, configure } = require('enzyme')
+const ReactAdapter = require('enzyme-adapter-react-16')
+const Uppy = require('@uppy/core')
+
+beforeAll(() => {
+  configure({ adapter: new ReactAdapter() })
+})
+
+jest.mock('@uppy/file-input', () => require('./__mocks__/FileInputPlugin'))
+
+const FileInput = require('./FileInput')
+
+describe('react <FileInput />', () => {
+  it('can be mounted and unmounted', () => {
+    const oninstall = jest.fn()
+    const onuninstall = jest.fn()
+    const uppy = new Uppy()
+    const input = mount((
+      <FileInput
+        uppy={uppy}
+        onInstall={oninstall}
+        onUninstall={onuninstall}
+      />
+    ))
+
+    expect(oninstall).toHaveBeenCalled()
+    expect(onuninstall).not.toHaveBeenCalled()
+
+    input.unmount()
+
+    expect(oninstall).toHaveBeenCalled()
+    expect(onuninstall).toHaveBeenCalled()
+  })
+})

+ 18 - 0
packages/@uppy/react/src/__mocks__/FileInputPlugin.js

@@ -0,0 +1,18 @@
+const { Plugin } = require('@uppy/core')
+
+module.exports = class FileInput extends Plugin {
+  constructor (uppy, opts) {
+    super(uppy, opts)
+
+    this.id = this.opts.id
+    this.type = 'acquirer'
+  }
+
+  install () {
+    if (this.opts.onInstall) this.opts.onInstall()
+  }
+
+  uninstall () {
+    if (this.opts.onUninstall) this.opts.onUninstall()
+  }
+}

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

@@ -5,6 +5,7 @@ export { default as DashboardModal } from '../src/DashboardModal'
 export { default as DragDrop } from '../src/DragDrop'
 export { default as ProgressBar } from '../src/ProgressBar'
 export { default as StatusBar } from '../src/StatusBar'
+export { default as FileInput } from '../src/FileInput'
 
 import useUppy = require('../src/useUppy')
-export { useUppy }
+export { useUppy }

+ 51 - 0
website/src/docs/react-fileinput.md

@@ -0,0 +1,51 @@
+---
+title: "&lt;FileInput />"
+type: docs
+module: "@uppy/react"
+permalink: docs/react/file-input/
+alias: docs/react/fileinput/
+order: 4
+category: "React"
+---
+
+The `<FileInput />` component wraps the [`@uppy/file-input`](/docs/file-input/) plugin.
+
+## Installation
+
+Install from NPM:
+
+```shell
+npm install @uppy/react
+```
+
+```js
+// Either:
+import FileInput from '@uppy/react/lib/FileInput';
+// Or:
+import { FileInput } from '@uppy/react';
+```
+
+## CSS
+
+The `FileInput` component includes some simple styles. You can also choose not to use it and provide your own styles instead:
+
+```js
+import '@uppy/core/dist/style.css'
+import '@uppy/file-input/dist/style.css'
+```
+
+Import general Core styles from `@uppy/core/dist/style.css` first, then add the Drag & Drop styles from `@uppy/file-input/dist/style.css`. A minified version is also available as `style.min.css` at the same path. The way to do import depends on your build system.
+
+## Props
+
+The `<FileInput />` component supports all [FileInput](/docs/file-input/) options as props. Additionally, an Uppy instance must be provided in the `uppy={}` prop: see [Initializing Uppy](/docs/react/initializing) for details.
+
+```js
+// assuming `this.uppy` contains an Uppy instance:
+
+<FileInput
+  uppy={this.uppy}
+  pretty={true}
+  inputName='files[]'
+/>
+```