@uppy/react: refactor to ESM (#3780)

This commit is contained in:
Antoine du Hamel 2022-05-25 12:20:49 +02:00
parent c223a1f204
commit b4e5d86370
No known key found for this signature in database
GPG key ID: 21D900FFDB233756
21 changed files with 317 additions and 125 deletions

View file

@ -220,6 +220,7 @@ module.exports = {
'packages/@uppy/onedrive/src/**/*.js',
'packages/@uppy/progress-bar/src/**/*.js',
'packages/@uppy/provider-views/src/**/*.js',
'packages/@uppy/react/src/**/*.js',
'packages/@uppy/redux-dev-tools/src/**/*.js',
'packages/@uppy/screen-capture/src/**/*.js',
'packages/@uppy/status-bar/src/**/*.js',

View file

@ -53,7 +53,7 @@ export default class Dashboard extends UIPlugin {
this.defaultLocale = locale
// set default options
// set default options, must be kept in sync with packages/@uppy/react/src/DashboardModal.js
const defaultOptions = {
target: 'body',
metaFields: [],

View file

@ -22,7 +22,7 @@ export default class DragDrop extends UIPlugin {
this.defaultLocale = locale
// Default options
// Default options, must be kept in sync with @uppy/react/src/DragDrop.js.
const defaultOpts = {
target: null,
inputName: 'files[]',

View file

@ -16,7 +16,7 @@ export default class FileInput extends UIPlugin {
this.defaultLocale = locale
// Default options
// Default options, must be kept in sync with @uppy/react/src/FileInput.js.
const defaultOptions = {
target: null,
pretty: true,

View file

@ -16,7 +16,7 @@ export default class ProgressBar extends UIPlugin {
this.title = 'Progress Bar'
this.type = 'progressindicator'
// set default options
// set default options, must kept in sync with @uppy/react/src/ProgressBar.js
const defaultOptions = {
target: 'body',
fixed: false,

View file

@ -1,7 +0,0 @@
exports.Dashboard = require('./lib/Dashboard')
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')

View file

@ -1,7 +0,0 @@
export { default as Dashboard } from './lib/Dashboard.js'
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'

View file

@ -3,9 +3,9 @@
"description": "React component wrappers around Uppy's official UI plugins.",
"version": "2.2.1",
"license": "MIT",
"main": "index.js",
"module": "index.mjs",
"main": "lib/index.js",
"types": "types/index.d.ts",
"type": "module",
"keywords": [
"file uploader",
"uppy",

View file

@ -1,22 +1,21 @@
const React = require('react')
const DashboardPlugin = require('@uppy/dashboard')
const basePropTypes = require('./propTypes').dashboard
const getHTMLProps = require('./getHTMLProps')
const nonHtmlPropsHaveChanged = require('./nonHtmlPropsHaveChanged')
const h = React.createElement
import { createElement as h, Component } from 'react'
import DashboardPlugin from '@uppy/dashboard'
import { dashboard as basePropTypes } from './propTypes.js'
import getHTMLProps from './getHTMLProps.js'
import nonHtmlPropsHaveChanged from './nonHtmlPropsHaveChanged.js'
/**
* React Component that renders a Dashboard for an Uppy instance. This component
* renders the Dashboard inline, so you can put it anywhere you want.
*/
class Dashboard extends React.Component {
class Dashboard extends Component {
componentDidMount () {
this.installPlugin()
}
componentDidUpdate (prevProps) {
// eslint-disable-next-line react/destructuring-assignment
if (prevProps.uppy !== this.props.uppy) {
this.uninstallPlugin(prevProps)
this.installPlugin()
@ -69,4 +68,4 @@ Dashboard.defaultProps = {
inline: true,
}
module.exports = Dashboard
export default Dashboard

View file

@ -1,34 +1,33 @@
const React = require('react')
const PropTypes = require('prop-types')
const DashboardPlugin = require('@uppy/dashboard')
const basePropTypes = require('./propTypes').dashboard
const getHTMLProps = require('./getHTMLProps')
const nonHtmlPropsHaveChanged = require('./nonHtmlPropsHaveChanged')
const h = React.createElement
import { createElement as h, Component } from 'react'
import PropTypes from 'prop-types'
import DashboardPlugin from '@uppy/dashboard'
import { cssSize, locale, metaFields, plugins, uppy as uppyPropType } from './propTypes.js'
import getHTMLProps from './getHTMLProps.js'
import nonHtmlPropsHaveChanged from './nonHtmlPropsHaveChanged.js'
/**
* React Component that renders a Dashboard for an Uppy instance in a Modal
* dialog. Visibility of the Modal is toggled using the `open` prop.
*/
class DashboardModal extends React.Component {
class DashboardModal extends Component {
componentDidMount () {
this.installPlugin()
}
componentDidUpdate (prevProps) {
if (prevProps.uppy !== this.props.uppy) {
const { uppy, open, onRequestClose } = this.props
if (prevProps.uppy !== uppy) {
this.uninstallPlugin(prevProps)
this.installPlugin()
} else if (nonHtmlPropsHaveChanged(this, prevProps)) {
const options = { ...this.props, onRequestCloseModal: this.props.onRequestClose }
const options = { ...this.props, onRequestCloseModal: onRequestClose }
delete options.uppy
this.plugin.setOptions(options)
}
if (prevProps.open && !this.props.open) {
if (prevProps.open && !open) {
this.plugin.closeModal()
} else if (!prevProps.open && this.props.open) {
} else if (!prevProps.open && open) {
this.plugin.openModal()
}
}
@ -38,11 +37,82 @@ class DashboardModal extends React.Component {
}
installPlugin () {
const { uppy } = this.props
const {
uppy,
target,
open,
onRequestClose,
closeModalOnClickOutside,
disablePageScrollWhenModalOpen,
inline,
plugins, // eslint-disable-line no-shadow
width,
height,
showProgressDetails,
note,
metaFields, // eslint-disable-line no-shadow
proudlyDisplayPoweredByUppy,
autoOpenFileEditor,
animateOpenClose,
browserBackButtonClose,
closeAfterFinish,
disableStatusBar,
disableInformer,
disableThumbnailGenerator,
disableLocalFiles,
disabled,
hideCancelButton,
hidePauseResumeButton,
hideProgressAfterFinish,
hideRetryButton,
hideUploadButton,
showLinkToFileUploadResult,
showRemoveButtonAfterComplete,
showSelectedFiles,
waitForThumbnailsBeforeUpload,
fileManagerSelectionType,
theme,
thumbnailType,
thumbnailWidth,
locale, // eslint-disable-line no-shadow
} = this.props
const options = {
id: 'react:DashboardModal',
...this.props,
onRequestCloseModal: this.props.onRequestClose,
target,
closeModalOnClickOutside,
disablePageScrollWhenModalOpen,
inline,
plugins,
width,
height,
showProgressDetails,
note,
metaFields,
proudlyDisplayPoweredByUppy,
autoOpenFileEditor,
animateOpenClose,
browserBackButtonClose,
closeAfterFinish,
disableStatusBar,
disableInformer,
disableThumbnailGenerator,
disableLocalFiles,
disabled,
hideCancelButton,
hidePauseResumeButton,
hideProgressAfterFinish,
hideRetryButton,
hideUploadButton,
showLinkToFileUploadResult,
showRemoveButtonAfterComplete,
showSelectedFiles,
waitForThumbnailsBeforeUpload,
fileManagerSelectionType,
theme,
thumbnailType,
thumbnailWidth,
locale,
onRequestCloseModal: onRequestClose,
}
if (!options.target) {
@ -53,7 +123,7 @@ class DashboardModal extends React.Component {
uppy.use(DashboardPlugin, options)
this.plugin = uppy.getPlugin(options.id)
if (this.props.open) {
if (open) {
this.plugin.openModal()
}
}
@ -78,12 +148,85 @@ class DashboardModal extends React.Component {
}
DashboardModal.propTypes = {
uppy: uppyPropType.isRequired,
target: typeof window !== 'undefined' ? PropTypes.instanceOf(window.HTMLElement) : PropTypes.any,
open: PropTypes.bool,
onRequestClose: PropTypes.func,
closeModalOnClickOutside: PropTypes.bool,
disablePageScrollWhenModalOpen: PropTypes.bool,
...basePropTypes,
inline: PropTypes.bool,
plugins,
width: cssSize,
height: cssSize,
showProgressDetails: PropTypes.bool,
note: PropTypes.string,
metaFields,
proudlyDisplayPoweredByUppy: PropTypes.bool,
autoOpenFileEditor: PropTypes.bool,
animateOpenClose: PropTypes.bool,
browserBackButtonClose: PropTypes.bool,
closeAfterFinish: PropTypes.bool,
disableStatusBar: PropTypes.bool,
disableInformer: PropTypes.bool,
disableThumbnailGenerator: PropTypes.bool,
disableLocalFiles: PropTypes.bool,
disabled: PropTypes.bool,
hideCancelButton: PropTypes.bool,
hidePauseResumeButton: PropTypes.bool,
hideProgressAfterFinish: PropTypes.bool,
hideRetryButton: PropTypes.bool,
hideUploadButton: PropTypes.bool,
showLinkToFileUploadResult: PropTypes.bool,
showRemoveButtonAfterComplete: PropTypes.bool,
showSelectedFiles: PropTypes.bool,
waitForThumbnailsBeforeUpload: PropTypes.bool,
fileManagerSelectionType: PropTypes.string,
theme: PropTypes.string,
// pass-through to ThumbnailGenerator
thumbnailType: PropTypes.string,
thumbnailWidth: PropTypes.number,
locale,
}
// Must be kept in sync with @uppy/dashboard/src/Dashboard.jsx.
DashboardModal.defaultProps = {
metaFields: [],
plugins: [],
inline: false,
width: 750,
height: 550,
thumbnailWidth: 280,
thumbnailType: 'image/jpeg',
waitForThumbnailsBeforeUpload: false,
showLinkToFileUploadResult: false,
showProgressDetails: false,
hideUploadButton: false,
hideCancelButton: false,
hideRetryButton: false,
hidePauseResumeButton: false,
hideProgressAfterFinish: false,
note: null,
closeModalOnClickOutside: false,
closeAfterFinish: false,
disableStatusBar: false,
disableInformer: false,
disableThumbnailGenerator: false,
disablePageScrollWhenModalOpen: true,
animateOpenClose: true,
fileManagerSelectionType: 'files',
proudlyDisplayPoweredByUppy: true,
showSelectedFiles: true,
showRemoveButtonAfterComplete: false,
browserBackButtonClose: false,
theme: 'light',
autoOpenFileEditor: false,
disabled: false,
disableLocalFiles: false,
// extra
open: undefined,
target: undefined,
locale: null,
onRequestClose: undefined,
}
module.exports = DashboardModal
export default DashboardModal

View file

@ -1,22 +1,22 @@
const React = require('react')
const DragDropPlugin = require('@uppy/drag-drop')
const propTypes = require('./propTypes')
const getHTMLProps = require('./getHTMLProps')
const nonHtmlPropsHaveChanged = require('./nonHtmlPropsHaveChanged')
const h = React.createElement
import { createElement as h, Component } from 'react'
import PropTypes from 'prop-types'
import DragDropPlugin from '@uppy/drag-drop'
import * as propTypes from './propTypes.js'
import getHTMLProps from './getHTMLProps.js'
import nonHtmlPropsHaveChanged from './nonHtmlPropsHaveChanged.js'
/**
* React component that renders an area in which files can be dropped to be
* uploaded.
*/
class DragDrop extends React.Component {
class DragDrop extends Component {
componentDidMount () {
this.installPlugin()
}
componentDidUpdate (prevProps) {
// eslint-disable-next-line react/destructuring-assignment
if (prevProps.uppy !== this.props.uppy) {
this.uninstallPlugin(prevProps)
this.installPlugin()
@ -32,10 +32,21 @@ class DragDrop extends React.Component {
}
installPlugin () {
const { uppy } = this.props
const {
uppy,
locale,
inputName,
width,
height,
note,
} = this.props
const options = {
id: 'react:DragDrop',
...this.props,
locale,
inputName,
width,
height,
note,
target: this.container,
}
delete options.uppy
@ -65,10 +76,20 @@ class DragDrop extends React.Component {
}
DragDrop.propTypes = {
uppy: propTypes.uppy,
uppy: propTypes.uppy.isRequired,
locale: propTypes.locale,
inputName: PropTypes.string,
width: PropTypes.string,
height: PropTypes.string,
note: PropTypes.string,
}
// Must be kept in sync with @uppy/drag-drop/src/DragDrop.jsx.
DragDrop.defaultProps = {
locale: null,
inputName: 'files[]',
width: '100%',
height: '100%',
note: null,
}
module.exports = DragDrop
export default DragDrop

View file

@ -1,21 +1,20 @@
const PropTypes = require('prop-types')
const React = require('react')
const FileInputPlugin = require('@uppy/file-input')
const propTypes = require('./propTypes')
const h = React.createElement
import { createElement as h, Component } from 'react'
import PropTypes from 'prop-types'
import FileInputPlugin from '@uppy/file-input'
import * as propTypes from './propTypes.js'
/**
* React component that renders an area in which files can be dropped to be
* uploaded.
*/
class FileInput extends React.Component {
class FileInput extends Component {
componentDidMount () {
this.installPlugin()
}
componentDidUpdate (prevProps) {
// eslint-disable-next-line react/destructuring-assignment
if (prevProps.uppy !== this.props.uppy) {
this.uninstallPlugin(prevProps)
this.installPlugin()
@ -27,10 +26,12 @@ class FileInput extends React.Component {
}
installPlugin () {
const { uppy } = this.props
const { uppy, locale, pretty, inputName } = this.props
const options = {
id: 'react:FileInput',
...this.props,
locale,
pretty,
inputName,
target: this.container,
}
delete options.uppy
@ -57,12 +58,16 @@ class FileInput extends React.Component {
}
FileInput.propTypes = {
uppy: propTypes.uppy,
uppy: propTypes.uppy.isRequired,
locale: propTypes.locale,
pretty: PropTypes.bool,
inputName: PropTypes.string,
}
// Must be kept in sync with @uppy/file-input/src/FileInput.jsx
FileInput.defaultProps = {
locale: undefined,
pretty: true,
inputName: 'files[]',
}
module.exports = FileInput
export default FileInput

View file

@ -1,22 +1,21 @@
const React = require('react')
const PropTypes = require('prop-types')
const ProgressBarPlugin = require('@uppy/progress-bar')
const uppyPropType = require('./propTypes').uppy
const getHTMLProps = require('./getHTMLProps')
const nonHtmlPropsHaveChanged = require('./nonHtmlPropsHaveChanged')
const h = React.createElement
import { createElement as h, Component } from 'react'
import PropTypes from 'prop-types'
import ProgressBarPlugin from '@uppy/progress-bar'
import { uppy as uppyPropType } from './propTypes.js'
import getHTMLProps from './getHTMLProps.js'
import nonHtmlPropsHaveChanged from './nonHtmlPropsHaveChanged.js'
/**
* React component that renders a progress bar at the top of the page.
*/
class ProgressBar extends React.Component {
class ProgressBar extends Component {
componentDidMount () {
this.installPlugin()
}
componentDidUpdate (prevProps) {
// eslint-disable-next-line react/destructuring-assignment
if (prevProps.uppy !== this.props.uppy) {
this.uninstallPlugin(prevProps)
this.installPlugin()
@ -32,10 +31,11 @@ class ProgressBar extends React.Component {
}
installPlugin () {
const { uppy } = this.props
const { uppy, fixed, hideAfterFinish } = this.props
const options = {
id: 'react:ProgressBar',
...this.props,
fixed,
hideAfterFinish,
target: this.container,
}
delete options.uppy
@ -65,11 +65,14 @@ class ProgressBar extends React.Component {
}
ProgressBar.propTypes = {
uppy: uppyPropType,
uppy: uppyPropType.isRequired,
fixed: PropTypes.bool,
hideAfterFinish: PropTypes.bool,
}
// Must be kept in sync with @uppy/progress-bar/src/ProgressBar.jsx
ProgressBar.defaultProps = {
fixed: false,
hideAfterFinish: true,
}
module.exports = ProgressBar
export default ProgressBar

View file

@ -1,23 +1,22 @@
const React = require('react')
const PropTypes = require('prop-types')
const StatusBarPlugin = require('@uppy/status-bar')
const uppyPropType = require('./propTypes').uppy
const getHTMLProps = require('./getHTMLProps')
const nonHtmlPropsHaveChanged = require('./nonHtmlPropsHaveChanged')
const h = React.createElement
import { createElement as h, Component } from 'react'
import PropTypes from 'prop-types'
import StatusBarPlugin from '@uppy/status-bar'
import { uppy as uppyPropType } from './propTypes.js'
import getHTMLProps from './getHTMLProps.js'
import nonHtmlPropsHaveChanged from './nonHtmlPropsHaveChanged.js'
/**
* React component that renders a status bar containing upload progress and speed,
* processing progress and pause/resume/cancel controls.
*/
class StatusBar extends React.Component {
class StatusBar extends Component {
componentDidMount () {
this.installPlugin()
}
componentDidUpdate (prevProps) {
// eslint-disable-next-line react/destructuring-assignment
if (prevProps.uppy !== this.props.uppy) {
this.uninstallPlugin(prevProps)
this.installPlugin()
@ -33,10 +32,25 @@ class StatusBar extends React.Component {
}
installPlugin () {
const { uppy } = this.props
const {
uppy,
hideUploadButton,
hideRetryButton,
hidePauseResumeButton,
hideCancelButton,
showProgressDetails,
hideAfterFinish,
doneButtonHandler,
} = this.props
const options = {
id: 'react:StatusBar',
...this.props,
hideUploadButton,
hideRetryButton,
hidePauseResumeButton,
hideCancelButton,
showProgressDetails,
hideAfterFinish,
doneButtonHandler,
target: this.container,
}
delete options.uppy
@ -66,11 +80,24 @@ class StatusBar extends React.Component {
}
StatusBar.propTypes = {
uppy: uppyPropType,
hideAfterFinish: PropTypes.bool,
uppy: uppyPropType.isRequired,
hideUploadButton: PropTypes.bool,
hideRetryButton: PropTypes.bool,
hidePauseResumeButton: PropTypes.bool,
hideCancelButton: PropTypes.bool,
showProgressDetails: PropTypes.bool,
hideAfterFinish: PropTypes.bool,
doneButtonHandler: PropTypes.func,
}
// Must be kept in sync with @uppy/status-bar/src/_StatusBar.jsx.
StatusBar.defaultProps = {
hideUploadButton: false,
hideRetryButton: false,
hidePauseResumeButton: false,
hideCancelButton: false,
showProgressDetails: false,
hideAfterFinish: true,
doneButtonHandler: null,
}
module.exports = StatusBar
export default StatusBar

View file

@ -1,10 +1,8 @@
const React = require('react')
const PropTypes = require('prop-types')
const uppyPropType = require('./propTypes').uppy
import { createElement as h, Component } from 'react'
import PropTypes from 'prop-types'
import { uppy as uppyPropType } from './propTypes.js'
const h = React.createElement
class UppyWrapper extends React.Component {
class UppyWrapper extends Component {
constructor (props) {
super(props)
@ -16,7 +14,8 @@ class UppyWrapper extends React.Component {
}
componentDidUpdate (prevProps) {
if (prevProps.uppy !== this.props.uppy) {
const { uppy } = this.props
if (prevProps.uppy !== uppy) {
this.uninstallPlugin(prevProps)
this.installPlugin()
}
@ -27,17 +26,18 @@ class UppyWrapper extends React.Component {
}
installPlugin () {
const plugin = this.props.uppy
.getPlugin(this.props.plugin)
const { plugin, uppy } = this.props
const pluginObj = uppy
.getPlugin(plugin)
plugin.mount(this.container, plugin)
pluginObj.mount(this.container, pluginObj)
}
uninstallPlugin (props = this.props) {
const plugin = props.uppy
.getPlugin(this.props.plugin)
plugin.unmount()
uninstallPlugin ({ uppy } = this.props) {
const { plugin } = this.props
uppy
.getPlugin(plugin)
.unmount()
}
refContainer (container) {
@ -50,8 +50,8 @@ class UppyWrapper extends React.Component {
}
UppyWrapper.propTypes = {
uppy: uppyPropType,
uppy: uppyPropType.isRequired,
plugin: PropTypes.string.isRequired,
}
module.exports = UppyWrapper
export default UppyWrapper

View file

@ -261,4 +261,4 @@ const getHTMLProps = (props) => {
)
}
module.exports = getHTMLProps
export default getHTMLProps

View file

@ -0,0 +1,7 @@
export { default as Dashboard } from './Dashboard.js'
export { default as DashboardModal } from './DashboardModal.js'
export { default as DragDrop } from './DragDrop.js'
export { default as ProgressBar } from './ProgressBar.js'
export { default as StatusBar } from './StatusBar.js'
export { default as FileInput } from './FileInput.js'
export { default as useUppy } from './useUppy.js'

View file

@ -3,7 +3,7 @@
// TODO: replace with `Object.hasOwn` when dropping support for older browsers.
const hasOwn = (obj, key) => Object.prototype.hasOwnProperty.call(obj, key)
module.exports = function nonHtmlPropsHaveChanged (component, prevProps) {
export default function nonHtmlPropsHaveChanged (component, prevProps) {
return Object.keys(component.props)
// TODO: replace `validProps` with an exported `Symbol('htmlProps')`.
.some(key => !hasOwn(component.validProps, key) && component.props[key] !== prevProps[key])

View file

@ -1,8 +1,8 @@
const PropTypes = require('prop-types')
const UppyCore = require('@uppy/core').Uppy
import PropTypes from 'prop-types'
import { Uppy as UppyCore } from '@uppy/core'
// The `uppy` prop receives the Uppy core instance.
const uppy = PropTypes.instanceOf(UppyCore).isRequired
const uppy = PropTypes.instanceOf(UppyCore)
// A list of plugins to mount inside this component.
const plugins = PropTypes.arrayOf(PropTypes.string)
@ -51,7 +51,7 @@ const dashboard = {
locale,
}
module.exports = {
export {
uppy,
locale,
dashboard,

View file

@ -1,7 +1,7 @@
const { useEffect, useRef } = require('react')
const UppyCore = require('@uppy/core').Uppy
import { useEffect, useRef } from 'react'
import { Uppy as UppyCore } from '@uppy/core'
module.exports = function useUppy (factory) {
export default function useUppy (factory) {
if (typeof factory !== 'function') {
throw new TypeError('useUppy: expected a function that returns a new Uppy instance')
}

View file

@ -85,7 +85,7 @@ export default class StatusBar extends UIPlugin {
this.defaultLocale = locale
// set default options
// set default options, must be kept in sync with @uppy/react/src/StatusBar.js
const defaultOptions = {
target: 'body',
hideUploadButton: false,