From 462e8c61bdd873a43467ed11c4619dc7a1136bff Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Wed, 27 Mar 2024 11:03:34 +0100 Subject: [PATCH] @uppy/react: refactor to TS (#5012) --- .eslintrc.js | 1 + packages/@uppy/core/src/Uppy.ts | 2 +- packages/@uppy/react/.npmignore | 1 + packages/@uppy/react/src/Dashboard.js | 69 ------ packages/@uppy/react/src/Dashboard.ts | 109 ++++++++++ packages/@uppy/react/src/DashboardModal.js | 157 -------------- packages/@uppy/react/src/DashboardModal.ts | 196 ++++++++++++++++++ packages/@uppy/react/src/DragDrop.js | 93 --------- packages/@uppy/react/src/DragDrop.ts | 99 +++++++++ packages/@uppy/react/src/FileInput.js | 73 ------- packages/@uppy/react/src/FileInput.ts | 89 ++++++++ packages/@uppy/react/src/ProgressBar.js | 76 ------- packages/@uppy/react/src/ProgressBar.ts | 90 ++++++++ packages/@uppy/react/src/StatusBar.js | 101 --------- packages/@uppy/react/src/StatusBar.ts | 114 ++++++++++ packages/@uppy/react/src/Wrapper.js | 57 ----- packages/@uppy/react/src/Wrapper.ts | 59 ++++++ .../src/{getHTMLProps.js => getHTMLProps.ts} | 10 +- packages/@uppy/react/src/index.js | 7 - packages/@uppy/react/src/index.ts | 7 + .../react/src/nonHtmlPropsHaveChanged.js | 3 - .../react/src/nonHtmlPropsHaveChanged.ts | 7 + .../react/src/{propTypes.js => propTypes.ts} | 35 +--- .../react/src/{useUppy.js => useUppy.ts} | 15 +- packages/@uppy/react/tsconfig.build.json | 50 +++++ packages/@uppy/react/tsconfig.json | 46 ++++ .../react/{src => types}/CommonTypes.d.ts | 0 .../@uppy/react/{src => types}/Dashboard.d.ts | 0 .../react/{src => types}/DashboardModal.d.ts | 0 .../@uppy/react/{src => types}/DragDrop.d.ts | 0 .../@uppy/react/{src => types}/FileInput.d.ts | 0 .../react/{src => types}/ProgressBar.d.ts | 0 .../@uppy/react/{src => types}/StatusBar.d.ts | 0 packages/@uppy/react/types/index.d.ts | 14 +- .../@uppy/react/{src => types}/useUppy.d.ts | 0 35 files changed, 896 insertions(+), 684 deletions(-) create mode 100644 packages/@uppy/react/.npmignore delete mode 100644 packages/@uppy/react/src/Dashboard.js create mode 100644 packages/@uppy/react/src/Dashboard.ts delete mode 100644 packages/@uppy/react/src/DashboardModal.js create mode 100644 packages/@uppy/react/src/DashboardModal.ts delete mode 100644 packages/@uppy/react/src/DragDrop.js create mode 100644 packages/@uppy/react/src/DragDrop.ts delete mode 100644 packages/@uppy/react/src/FileInput.js create mode 100644 packages/@uppy/react/src/FileInput.ts delete mode 100644 packages/@uppy/react/src/ProgressBar.js create mode 100644 packages/@uppy/react/src/ProgressBar.ts delete mode 100644 packages/@uppy/react/src/StatusBar.js create mode 100644 packages/@uppy/react/src/StatusBar.ts delete mode 100644 packages/@uppy/react/src/Wrapper.js create mode 100644 packages/@uppy/react/src/Wrapper.ts rename packages/@uppy/react/src/{getHTMLProps.js => getHTMLProps.ts} (95%) delete mode 100644 packages/@uppy/react/src/index.js create mode 100644 packages/@uppy/react/src/index.ts delete mode 100644 packages/@uppy/react/src/nonHtmlPropsHaveChanged.js create mode 100644 packages/@uppy/react/src/nonHtmlPropsHaveChanged.ts rename packages/@uppy/react/src/{propTypes.js => propTypes.ts} (52%) rename packages/@uppy/react/src/{useUppy.js => useUppy.ts} (50%) create mode 100644 packages/@uppy/react/tsconfig.build.json create mode 100644 packages/@uppy/react/tsconfig.json rename packages/@uppy/react/{src => types}/CommonTypes.d.ts (100%) rename packages/@uppy/react/{src => types}/Dashboard.d.ts (100%) rename packages/@uppy/react/{src => types}/DashboardModal.d.ts (100%) rename packages/@uppy/react/{src => types}/DragDrop.d.ts (100%) rename packages/@uppy/react/{src => types}/FileInput.d.ts (100%) rename packages/@uppy/react/{src => types}/ProgressBar.d.ts (100%) rename packages/@uppy/react/{src => types}/StatusBar.d.ts (100%) rename packages/@uppy/react/{src => types}/useUppy.d.ts (100%) diff --git a/.eslintrc.js b/.eslintrc.js index 74c9677e37..993b124f46 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -93,6 +93,7 @@ module.exports = { 'react/prefer-stateless-function': 'error', 'react/sort-comp': 'error', 'react/style-prop-object': 'error', + 'react/static-property-placement': 'off', // accessibility 'jsx-a11y/alt-text': 'error', diff --git a/packages/@uppy/core/src/Uppy.ts b/packages/@uppy/core/src/Uppy.ts index f813b22421..4be7aa2578 100644 --- a/packages/@uppy/core/src/Uppy.ts +++ b/packages/@uppy/core/src/Uppy.ts @@ -54,7 +54,7 @@ type Processor = ( uploadID: string, ) => Promise | void -type FileRemoveReason = 'user' | 'cancel-all' +type FileRemoveReason = 'user' | 'cancel-all' | 'unmount' type LogLevel = 'info' | 'warning' | 'error' | 'success' diff --git a/packages/@uppy/react/.npmignore b/packages/@uppy/react/.npmignore new file mode 100644 index 0000000000..6c816673f0 --- /dev/null +++ b/packages/@uppy/react/.npmignore @@ -0,0 +1 @@ +tsconfig.* diff --git a/packages/@uppy/react/src/Dashboard.js b/packages/@uppy/react/src/Dashboard.js deleted file mode 100644 index 5c8c9f38af..0000000000 --- a/packages/@uppy/react/src/Dashboard.js +++ /dev/null @@ -1,69 +0,0 @@ -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 Component { - componentDidMount () { - this.installPlugin() - } - - componentDidUpdate (prevProps) { - // eslint-disable-next-line react/destructuring-assignment - if (prevProps.uppy !== this.props.uppy) { - this.uninstallPlugin(prevProps) - this.installPlugin() - } else if (nonHtmlPropsHaveChanged(this.props, prevProps)) { - const options = { ...this.props, target: this.container } - delete options.uppy - this.plugin.setOptions(options) - } - } - - componentWillUnmount () { - this.uninstallPlugin() - } - - installPlugin () { - const { uppy } = this.props - const options = { - id: 'react:Dashboard', - ...this.props, - target: this.container, - } - delete options.uppy - uppy.use(DashboardPlugin, options) - - this.plugin = uppy.getPlugin(options.id) - } - - uninstallPlugin (props = this.props) { - const { uppy } = props - - uppy.removePlugin(this.plugin) - } - - render () { - return h('div', { - className: 'uppy-Container', - ref: (container) => { - this.container = container - }, - ...getHTMLProps(this.props), - }) - } -} - -Dashboard.propTypes = basePropTypes - -Dashboard.defaultProps = { - inline: true, -} - -export default Dashboard diff --git a/packages/@uppy/react/src/Dashboard.ts b/packages/@uppy/react/src/Dashboard.ts new file mode 100644 index 0000000000..40c707b0d8 --- /dev/null +++ b/packages/@uppy/react/src/Dashboard.ts @@ -0,0 +1,109 @@ +import { createElement as h, Component } from 'react' +import PropTypes from 'prop-types' +import type { UnknownPlugin, Uppy } from '@uppy/core' +import DashboardPlugin from '@uppy/dashboard' +import type { Body, Meta } from '@uppy/utils/lib/UppyFile' +import type { DashboardOptions } from '@uppy/dashboard' +import { + locale, + uppy as uppyPropType, + plugins, + metaFields, + cssSize, +} from './propTypes.ts' +import getHTMLProps from './getHTMLProps.ts' +import nonHtmlPropsHaveChanged from './nonHtmlPropsHaveChanged.ts' + +type DashboardInlineOptions = Omit< + DashboardOptions & { inline: true }, + 'inline' +> & + React.BaseHTMLAttributes + +export interface DashboardProps + extends DashboardInlineOptions { + uppy: Uppy +} + +/** + * 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 Component< + DashboardProps +> { + static propsTypes = { + uppy: uppyPropType, + disableInformer: PropTypes.bool, + disableStatusBar: PropTypes.bool, + disableThumbnailGenerator: PropTypes.bool, + height: cssSize, + hideProgressAfterFinish: PropTypes.bool, + hideUploadButton: PropTypes.bool, + locale, + metaFields, + note: PropTypes.string, + plugins, + proudlyDisplayPoweredByUppy: PropTypes.bool, + showProgressDetails: PropTypes.bool, + width: cssSize, + // pass-through to ThumbnailGenerator + thumbnailType: PropTypes.string, + thumbnailWidth: PropTypes.number, + } + + private container: HTMLElement + + private plugin: UnknownPlugin + + componentDidMount(): void { + this.installPlugin() + } + + componentDidUpdate(prevProps: Dashboard['props']): void { + // eslint-disable-next-line react/destructuring-assignment + if (prevProps.uppy !== this.props.uppy) { + this.uninstallPlugin(prevProps) + this.installPlugin() + } else if (nonHtmlPropsHaveChanged(this.props, prevProps)) { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { uppy, ...options } = { ...this.props, target: this.container } + this.plugin.setOptions(options) + } + } + + componentWillUnmount(): void { + this.uninstallPlugin() + } + + installPlugin(): void { + const { uppy, ...options } = { + id: 'react:Dashboard', + inline: true, + ...this.props, + target: this.container, + } + uppy.use(DashboardPlugin, options) + + this.plugin = uppy.getPlugin(options.id)! + } + + uninstallPlugin(props = this.props): void { + const { uppy } = props + + uppy.removePlugin(this.plugin) + } + + render(): JSX.Element { + return h('div', { + className: 'uppy-Container', + ref: (container: HTMLElement): void => { + this.container = container + }, + ...getHTMLProps(this.props), + }) + } +} + +export default Dashboard diff --git a/packages/@uppy/react/src/DashboardModal.js b/packages/@uppy/react/src/DashboardModal.js deleted file mode 100644 index d11cfbacfc..0000000000 --- a/packages/@uppy/react/src/DashboardModal.js +++ /dev/null @@ -1,157 +0,0 @@ -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 Component { - componentDidMount () { - this.installPlugin() - } - - componentDidUpdate (prevProps) { - const { uppy, open, onRequestClose } = this.props - if (prevProps.uppy !== uppy) { - this.uninstallPlugin(prevProps) - this.installPlugin() - } else if (nonHtmlPropsHaveChanged(this.props, prevProps)) { - const options = { ...this.props, onRequestCloseModal: onRequestClose } - delete options.uppy - this.plugin.setOptions(options) - } - if (prevProps.open && !open) { - this.plugin.closeModal() - } else if (!prevProps.open && open) { - this.plugin.openModal() - } - } - - componentWillUnmount () { - this.uninstallPlugin() - } - - installPlugin () { - const { id='react:DashboardModal', target=this.container, open, onRequestClose, uppy } = this.props - const options = { - ...this.props, - id, - target, - onRequestCloseModal: onRequestClose, - } - delete options.uppy - - uppy.use(DashboardPlugin, options) - - this.plugin = uppy.getPlugin(options.id) - if (open) { - this.plugin.openModal() - } - } - - uninstallPlugin (props = this.props) { - const { uppy } = props - - uppy.removePlugin(this.plugin) - } - - render () { - return h('div', { - className: 'uppy-Container', - ref: (container) => { - this.container = container - }, - ...getHTMLProps(this.props), - }) - } -} - -/* eslint-disable react/no-unused-prop-types */ -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, - inline: PropTypes.bool, - plugins, - width: cssSize, - height: cssSize, - showProgressDetails: PropTypes.bool, - note: PropTypes.string, - metaFields, - proudlyDisplayPoweredByUppy: PropTypes.bool, - autoOpen: PropTypes.oneOf(['imageEditor', 'metaEditor', null]), - 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.tsx. -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', - autoOpen: false, - disabled: false, - disableLocalFiles: false, - - // extra - open: undefined, - target: undefined, - locale: null, - onRequestClose: undefined, -} - -export default DashboardModal diff --git a/packages/@uppy/react/src/DashboardModal.ts b/packages/@uppy/react/src/DashboardModal.ts new file mode 100644 index 0000000000..e7f54d7246 --- /dev/null +++ b/packages/@uppy/react/src/DashboardModal.ts @@ -0,0 +1,196 @@ +import { createElement as h, Component } from 'react' +import PropTypes from 'prop-types' +import DashboardPlugin, { type DashboardOptions } from '@uppy/dashboard' +import type { Body, Meta } from '@uppy/utils/lib/UppyFile' +import type { Uppy } from '@uppy/core' +import { + cssSize, + locale, + metaFields, + plugins, + uppy as uppyPropType, +} from './propTypes.ts' +import getHTMLProps from './getHTMLProps.ts' +import nonHtmlPropsHaveChanged from './nonHtmlPropsHaveChanged.ts' + +type DashboardInlineOptions = Omit< + DashboardOptions & { inline: false }, + 'inline' | 'onRequestCloseModal' +> & + React.BaseHTMLAttributes + +export interface DashboardModalProps + extends DashboardInlineOptions { + uppy: Uppy + onRequestClose: () => void + open: boolean +} + +/** + * React Component that renders a Dashboard for an Uppy instance in a Modal + * dialog. Visibility of the Modal is toggled using the `open` prop. + */ + +class DashboardModal extends Component< + DashboardModalProps +> { + static 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, + 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. + static defaultProps = { + metaFields: [], + plugins: [], + 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, + } + + private container: HTMLElement + + private plugin: DashboardPlugin + + componentDidMount(): void { + this.installPlugin() + } + + componentDidUpdate(prevProps: DashboardModal['props']): void { + const { uppy, open, onRequestClose } = this.props + if (prevProps.uppy !== uppy) { + this.uninstallPlugin(prevProps) + this.installPlugin() + } else if (nonHtmlPropsHaveChanged(this.props, prevProps)) { + // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-shadow + const { uppy, ...options } = { + ...this.props, + inline: false, + onRequestCloseModal: onRequestClose, + } + this.plugin.setOptions(options) + } + if (prevProps.open && !open) { + this.plugin.closeModal() + } else if (!prevProps.open && open) { + this.plugin.openModal() + } + } + + componentWillUnmount(): void { + this.uninstallPlugin() + } + + installPlugin(): void { + const { + target = this.container, + open, + onRequestClose, + uppy, + ...rest + } = this.props + const options = { + ...rest, + id: 'react:DashboardModal', + inline: false, + target, + open, + onRequestCloseModal: onRequestClose, + } + + uppy.use(DashboardPlugin, options) + + this.plugin = uppy.getPlugin(options.id) as DashboardPlugin + if (open) { + this.plugin.openModal() + } + } + + uninstallPlugin(props = this.props): void { + const { uppy } = props + + uppy.removePlugin(this.plugin) + } + + render(): JSX.Element { + return h('div', { + className: 'uppy-Container', + ref: (container: HTMLElement) => { + this.container = container + }, + ...getHTMLProps(this.props), + }) + } +} + +export default DashboardModal diff --git a/packages/@uppy/react/src/DragDrop.js b/packages/@uppy/react/src/DragDrop.js deleted file mode 100644 index 581b84d8ea..0000000000 --- a/packages/@uppy/react/src/DragDrop.js +++ /dev/null @@ -1,93 +0,0 @@ -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 Component { - componentDidMount () { - this.installPlugin() - } - - componentDidUpdate (prevProps) { - // eslint-disable-next-line react/destructuring-assignment - if (prevProps.uppy !== this.props.uppy) { - this.uninstallPlugin(prevProps) - this.installPlugin() - } else if (nonHtmlPropsHaveChanged(this.props, prevProps)) { - const options = { ...this.props, target: this.container } - delete options.uppy - this.plugin.setOptions(options) - } - } - - componentWillUnmount () { - this.uninstallPlugin() - } - - installPlugin () { - const { - uppy, - locale, - inputName, - width, - height, - note, - } = this.props - const options = { - id: 'react:DragDrop', - locale, - inputName, - width, - height, - note, - target: this.container, - } - delete options.uppy - - uppy.use(DragDropPlugin, options) - - this.plugin = uppy.getPlugin(options.id) - } - - uninstallPlugin (props = this.props) { - const { uppy } = props - - uppy.removePlugin(this.plugin) - } - - render () { - return h('div', { - className: 'uppy-Container', - ref: (container) => { - this.container = container - }, - ...getHTMLProps(this.props), - }) - } -} - -DragDrop.propTypes = { - 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, -} - -export default DragDrop diff --git a/packages/@uppy/react/src/DragDrop.ts b/packages/@uppy/react/src/DragDrop.ts new file mode 100644 index 0000000000..387955ddc0 --- /dev/null +++ b/packages/@uppy/react/src/DragDrop.ts @@ -0,0 +1,99 @@ +import { createElement as h, Component } from 'react' +import PropTypes from 'prop-types' +import type { UnknownPlugin, Uppy } from '@uppy/core' +import DragDropPlugin, { type DragDropOptions } from '@uppy/drag-drop' +import type { Body, Meta } from '@uppy/utils/lib/UppyFile' +import * as propTypes from './propTypes.ts' +import getHTMLProps from './getHTMLProps.ts' +import nonHtmlPropsHaveChanged from './nonHtmlPropsHaveChanged.ts' + +interface DragDropProps + extends DragDropOptions { + uppy: Uppy +} + +/** + * React component that renders an area in which files can be dropped to be + * uploaded. + */ + +class DragDrop extends Component< + DragDropProps +> { + static propTypes = { + 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. + static defaultProps = { + locale: null, + inputName: 'files[]', + width: '100%', + height: '100%', + note: null, + } + + private container: HTMLElement + + private plugin: UnknownPlugin + + componentDidMount(): void { + this.installPlugin() + } + + componentDidUpdate(prevProps: DragDrop['props']): void { + // eslint-disable-next-line react/destructuring-assignment + if (prevProps.uppy !== this.props.uppy) { + this.uninstallPlugin(prevProps) + this.installPlugin() + } else if (nonHtmlPropsHaveChanged(this.props, prevProps)) { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { uppy, ...options } = { ...this.props, target: this.container } + this.plugin.setOptions(options) + } + } + + componentWillUnmount(): void { + this.uninstallPlugin() + } + + installPlugin(): void { + const { uppy, locale, inputName, width, height, note } = this.props + const options = { + id: 'react:DragDrop', + locale, + inputName, + width, + height, + note, + target: this.container, + } + + uppy.use(DragDropPlugin, options) + + this.plugin = uppy.getPlugin(options.id)! + } + + uninstallPlugin(props = this.props): void { + const { uppy } = props + + uppy.removePlugin(this.plugin) + } + + render(): JSX.Element { + return h('div', { + className: 'uppy-Container', + ref: (container: HTMLElement) => { + this.container = container + }, + ...getHTMLProps(this.props), + }) + } +} + +export default DragDrop diff --git a/packages/@uppy/react/src/FileInput.js b/packages/@uppy/react/src/FileInput.js deleted file mode 100644 index dd84137af2..0000000000 --- a/packages/@uppy/react/src/FileInput.js +++ /dev/null @@ -1,73 +0,0 @@ -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 Component { - componentDidMount () { - this.installPlugin() - } - - componentDidUpdate (prevProps) { - // eslint-disable-next-line react/destructuring-assignment - if (prevProps.uppy !== this.props.uppy) { - this.uninstallPlugin(prevProps) - this.installPlugin() - } - } - - componentWillUnmount () { - this.uninstallPlugin() - } - - installPlugin () { - const { uppy, locale, pretty, inputName } = this.props - const options = { - id: 'react:FileInput', - locale, - pretty, - inputName, - target: this.container, - } - delete options.uppy - - uppy.use(FileInputPlugin, options) - - this.plugin = uppy.getPlugin(options.id) - } - - uninstallPlugin (props = this.props) { - const { uppy } = props - - uppy.removePlugin(this.plugin) - } - - render () { - return h('div', { - className: 'uppy-Container', - ref: (container) => { - this.container = container - }, - }) - } -} - -FileInput.propTypes = { - 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[]', -} - -export default FileInput diff --git a/packages/@uppy/react/src/FileInput.ts b/packages/@uppy/react/src/FileInput.ts new file mode 100644 index 0000000000..5148084f5a --- /dev/null +++ b/packages/@uppy/react/src/FileInput.ts @@ -0,0 +1,89 @@ +import { createElement as h, Component } from 'react' +import PropTypes from 'prop-types' +import type { UnknownPlugin, Uppy } from '@uppy/core' +import FileInputPlugin from '@uppy/file-input' +import type { Body, Meta } from '@uppy/utils/lib/UppyFile' +import type { Locale } from '@uppy/utils/lib/Translator' +import * as propTypes from './propTypes.ts' + +interface FileInputProps { + uppy: Uppy + locale?: Locale + pretty?: boolean + inputName?: string +} + +/** + * React component that renders an area in which files can be dropped to be + * uploaded. + */ + +class FileInput extends Component< + FileInputProps +> { + static propTypes = { + 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 + static defaultProps = { + locale: undefined, + pretty: true, + inputName: 'files[]', + } + + private container: HTMLElement + + private plugin: UnknownPlugin + + componentDidMount(): void { + this.installPlugin() + } + + componentDidUpdate(prevProps: FileInputProps): void { + // eslint-disable-next-line react/destructuring-assignment + if (prevProps.uppy !== this.props.uppy) { + this.uninstallPlugin(prevProps) + this.installPlugin() + } + } + + componentWillUnmount(): void { + this.uninstallPlugin() + } + + installPlugin(): void { + const { uppy, locale, pretty, inputName } = this.props + const options = { + id: 'react:FileInput', + locale, + pretty, + inputName, + target: this.container, + } + + uppy.use(FileInputPlugin, options) + + this.plugin = uppy.getPlugin(options.id)! + } + + uninstallPlugin(props = this.props): void { + const { uppy } = props + + uppy.removePlugin(this.plugin) + } + + render(): JSX.Element { + return h('div', { + className: 'uppy-Container', + ref: (container: HTMLElement) => { + this.container = container + }, + }) + } +} + +export default FileInput diff --git a/packages/@uppy/react/src/ProgressBar.js b/packages/@uppy/react/src/ProgressBar.js deleted file mode 100644 index fefcd6db1f..0000000000 --- a/packages/@uppy/react/src/ProgressBar.js +++ /dev/null @@ -1,76 +0,0 @@ -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 Component { - componentDidMount () { - this.installPlugin() - } - - componentDidUpdate (prevProps) { - // eslint-disable-next-line react/destructuring-assignment - if (prevProps.uppy !== this.props.uppy) { - this.uninstallPlugin(prevProps) - this.installPlugin() - } else if (nonHtmlPropsHaveChanged(this.props, prevProps)) { - const options = { ...this.props, target: this.container } - delete options.uppy - this.plugin.setOptions(options) - } - } - - componentWillUnmount () { - this.uninstallPlugin() - } - - installPlugin () { - const { uppy, fixed, hideAfterFinish } = this.props - const options = { - id: 'react:ProgressBar', - fixed, - hideAfterFinish, - target: this.container, - } - delete options.uppy - - uppy.use(ProgressBarPlugin, options) - - this.plugin = uppy.getPlugin(options.id) - } - - uninstallPlugin (props = this.props) { - const { uppy } = props - - uppy.removePlugin(this.plugin) - } - - render () { - return h('div', { - className: 'uppy-Container', - ref: (container) => { - this.container = container - }, - ...getHTMLProps(this.props), - }) - } -} - -ProgressBar.propTypes = { - 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, -} - -export default ProgressBar diff --git a/packages/@uppy/react/src/ProgressBar.ts b/packages/@uppy/react/src/ProgressBar.ts new file mode 100644 index 0000000000..9879850cdb --- /dev/null +++ b/packages/@uppy/react/src/ProgressBar.ts @@ -0,0 +1,90 @@ +import { createElement as h, Component } from 'react' +import PropTypes from 'prop-types' +import type { UnknownPlugin, Uppy } from '@uppy/core' +import ProgressBarPlugin from '@uppy/progress-bar' +import type { Body, Meta } from '@uppy/utils/lib/UppyFile' +import { uppy as uppyPropType } from './propTypes.ts' +import getHTMLProps from './getHTMLProps.ts' +import nonHtmlPropsHaveChanged from './nonHtmlPropsHaveChanged.ts' + +interface ProgressBarProps { + uppy: Uppy + fixed?: boolean + hideAfterFinish?: boolean +} + +/** + * React component that renders a progress bar at the top of the page. + */ + +class ProgressBar extends Component< + ProgressBarProps +> { + static propTypes = { + uppy: uppyPropType.isRequired, + fixed: PropTypes.bool, + hideAfterFinish: PropTypes.bool, + } + + // Must be kept in sync with @uppy/progress-bar/src/ProgressBar.jsx + static defaultProps = { + fixed: false, + hideAfterFinish: true, + } + + private container: HTMLElement + + private plugin: UnknownPlugin + + componentDidMount(): void { + this.installPlugin() + } + + componentDidUpdate(prevProps: ProgressBar['props']): void { + // eslint-disable-next-line react/destructuring-assignment + if (prevProps.uppy !== this.props.uppy) { + this.uninstallPlugin(prevProps) + this.installPlugin() + } else if (nonHtmlPropsHaveChanged(this.props, prevProps)) { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { uppy, ...options } = { ...this.props, target: this.container } + this.plugin.setOptions(options) + } + } + + componentWillUnmount(): void { + this.uninstallPlugin() + } + + installPlugin(): void { + const { uppy, fixed, hideAfterFinish } = this.props + const options = { + id: 'react:ProgressBar', + fixed, + hideAfterFinish, + target: this.container, + } + + uppy.use(ProgressBarPlugin, options) + + this.plugin = uppy.getPlugin(options.id)! + } + + uninstallPlugin(props = this.props): void { + const { uppy } = props + + uppy.removePlugin(this.plugin) + } + + render(): JSX.Element { + return h('div', { + className: 'uppy-Container', + ref: (container: HTMLElement) => { + this.container = container + }, + ...getHTMLProps(this.props), + }) + } +} + +export default ProgressBar diff --git a/packages/@uppy/react/src/StatusBar.js b/packages/@uppy/react/src/StatusBar.js deleted file mode 100644 index 2e48587e8a..0000000000 --- a/packages/@uppy/react/src/StatusBar.js +++ /dev/null @@ -1,101 +0,0 @@ -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 Component { - componentDidMount () { - this.installPlugin() - } - - componentDidUpdate (prevProps) { - // eslint-disable-next-line react/destructuring-assignment - if (prevProps.uppy !== this.props.uppy) { - this.uninstallPlugin(prevProps) - this.installPlugin() - } else if (nonHtmlPropsHaveChanged(this.props, prevProps)) { - const options = { ...this.props, target: this.container } - delete options.uppy - this.plugin.setOptions(options) - } - } - - componentWillUnmount () { - this.uninstallPlugin() - } - - installPlugin () { - const { - uppy, - hideUploadButton, - hideRetryButton, - hidePauseResumeButton, - hideCancelButton, - showProgressDetails, - hideAfterFinish, - doneButtonHandler, - } = this.props - const options = { - id: 'react:StatusBar', - hideUploadButton, - hideRetryButton, - hidePauseResumeButton, - hideCancelButton, - showProgressDetails, - hideAfterFinish, - doneButtonHandler, - target: this.container, - } - delete options.uppy - - uppy.use(StatusBarPlugin, options) - - this.plugin = uppy.getPlugin(options.id) - } - - uninstallPlugin (props = this.props) { - const { uppy } = props - - uppy.removePlugin(this.plugin) - } - - render () { - return h('div', { - className: 'uppy-Container', - ref: (container) => { - this.container = container - }, - ...getHTMLProps(this.props), - }) - } -} - -StatusBar.propTypes = { - 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, -} - -export default StatusBar diff --git a/packages/@uppy/react/src/StatusBar.ts b/packages/@uppy/react/src/StatusBar.ts new file mode 100644 index 0000000000..0271773d2b --- /dev/null +++ b/packages/@uppy/react/src/StatusBar.ts @@ -0,0 +1,114 @@ +import { createElement as h, Component } from 'react' +import PropTypes from 'prop-types' +import type { UnknownPlugin, Uppy } from '@uppy/core' +import StatusBarPlugin, { type StatusBarOptions } from '@uppy/status-bar' +import type { Body, Meta } from '@uppy/utils/lib/UppyFile' +import { uppy as uppyPropType } from './propTypes.ts' +import getHTMLProps from './getHTMLProps.ts' +import nonHtmlPropsHaveChanged from './nonHtmlPropsHaveChanged.ts' + +interface StatusBarProps + extends StatusBarOptions { + uppy: Uppy +} + +/** + * React component that renders a status bar containing upload progress and speed, + * processing progress and pause/resume/cancel controls. + */ + +class StatusBar extends Component< + StatusBarProps +> { + static propTypes = { + 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. + static defaultProps = { + hideUploadButton: false, + hideRetryButton: false, + hidePauseResumeButton: false, + hideCancelButton: false, + showProgressDetails: false, + hideAfterFinish: true, + doneButtonHandler: null, + } + + private container: HTMLElement + + private plugin: UnknownPlugin + + componentDidMount(): void { + this.installPlugin() + } + + componentDidUpdate(prevProps: StatusBar['props']): void { + // eslint-disable-next-line react/destructuring-assignment + if (prevProps.uppy !== this.props.uppy) { + this.uninstallPlugin(prevProps) + this.installPlugin() + } else if (nonHtmlPropsHaveChanged(this.props, prevProps)) { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { uppy, ...options } = { ...this.props, target: this.container } + this.plugin.setOptions(options) + } + } + + componentWillUnmount(): void { + this.uninstallPlugin() + } + + installPlugin(): void { + const { + uppy, + hideUploadButton, + hideRetryButton, + hidePauseResumeButton, + hideCancelButton, + showProgressDetails, + hideAfterFinish, + doneButtonHandler, + } = this.props + const options = { + id: 'react:StatusBar', + hideUploadButton, + hideRetryButton, + hidePauseResumeButton, + hideCancelButton, + showProgressDetails, + hideAfterFinish, + doneButtonHandler, + target: this.container, + } + + uppy.use(StatusBarPlugin, options) + + this.plugin = uppy.getPlugin(options.id)! + } + + uninstallPlugin(props = this.props): void { + const { uppy } = props + + uppy.removePlugin(this.plugin) + } + + render(): JSX.Element { + return h('div', { + className: 'uppy-Container', + ref: (container: HTMLElement) => { + this.container = container + }, + ...getHTMLProps(this.props), + }) + } +} + +export default StatusBar diff --git a/packages/@uppy/react/src/Wrapper.js b/packages/@uppy/react/src/Wrapper.js deleted file mode 100644 index 438484a18d..0000000000 --- a/packages/@uppy/react/src/Wrapper.js +++ /dev/null @@ -1,57 +0,0 @@ -import { createElement as h, Component } from 'react' -import PropTypes from 'prop-types' -import { uppy as uppyPropType } from './propTypes.js' - -class UppyWrapper extends Component { - constructor (props) { - super(props) - - this.refContainer = this.refContainer.bind(this) - } - - componentDidMount () { - this.installPlugin() - } - - componentDidUpdate (prevProps) { - const { uppy } = this.props - if (prevProps.uppy !== uppy) { - this.uninstallPlugin(prevProps) - this.installPlugin() - } - } - - componentWillUnmount () { - this.uninstallPlugin() - } - - installPlugin () { - const { plugin, uppy } = this.props - const pluginObj = uppy - .getPlugin(plugin) - - pluginObj.mount(this.container, pluginObj) - } - - uninstallPlugin ({ uppy } = this.props) { - const { plugin } = this.props - uppy - .getPlugin(plugin) - .unmount() - } - - refContainer (container) { - this.container = container - } - - render () { - return h('div', { className: 'uppy-Container', ref: this.refContainer }) - } -} - -UppyWrapper.propTypes = { - uppy: uppyPropType.isRequired, - plugin: PropTypes.string.isRequired, -} - -export default UppyWrapper diff --git a/packages/@uppy/react/src/Wrapper.ts b/packages/@uppy/react/src/Wrapper.ts new file mode 100644 index 0000000000..a933ec0b17 --- /dev/null +++ b/packages/@uppy/react/src/Wrapper.ts @@ -0,0 +1,59 @@ +import { createElement as h, Component } from 'react' +import type { Body, Meta } from '@uppy/utils/lib/UppyFile' +import type { UIPlugin, Uppy } from '@uppy/core' +import PropTypes from 'prop-types' +import { uppy as uppyPropType } from './propTypes.ts' + +interface UppyWrapperProps { + uppy: Uppy + plugin: string +} + +class UppyWrapper extends Component< + UppyWrapperProps +> { + static propTypes = { + uppy: uppyPropType.isRequired, + plugin: PropTypes.string.isRequired, + } + + private container: HTMLDivElement + + componentDidMount(): void { + this.installPlugin() + } + + componentDidUpdate(prevProps: UppyWrapperProps): void { + const { uppy } = this.props + if (prevProps.uppy !== uppy) { + this.uninstallPlugin(prevProps) + this.installPlugin() + } + } + + componentWillUnmount(): void { + this.uninstallPlugin() + } + + private refContainer = (container: UppyWrapper['container']) => { + this.container = container + } + + installPlugin(): void { + const { plugin, uppy } = this.props + const pluginObj = uppy.getPlugin(plugin) as UIPlugin + + pluginObj.mount(this.container, pluginObj) + } + + uninstallPlugin({ uppy } = this.props): void { + const { plugin } = this.props + ;(uppy.getPlugin(plugin) as UIPlugin).unmount() + } + + render(): ReturnType { + return h('div', { className: 'uppy-Container', ref: this.refContainer }) + } +} + +export default UppyWrapper diff --git a/packages/@uppy/react/src/getHTMLProps.js b/packages/@uppy/react/src/getHTMLProps.ts similarity index 95% rename from packages/@uppy/react/src/getHTMLProps.js rename to packages/@uppy/react/src/getHTMLProps.ts index 8ea159fb72..54af2d7577 100644 --- a/packages/@uppy/react/src/getHTMLProps.js +++ b/packages/@uppy/react/src/getHTMLProps.ts @@ -253,11 +253,15 @@ const reactSupportedHtmlAttr = [ const validHTMLAttribute = /^(aria-|data-)/ -const getHTMLProps = (props) => { +const getHTMLProps = ( + props: Record, +): Record => { // Gets all the React props return Object.fromEntries( - Object.entries(props) - .filter(([key]) => validHTMLAttribute.test(key) || reactSupportedHtmlAttr.includes(key)), + Object.entries(props).filter( + ([key]) => + validHTMLAttribute.test(key) || reactSupportedHtmlAttr.includes(key), + ), ) } diff --git a/packages/@uppy/react/src/index.js b/packages/@uppy/react/src/index.js deleted file mode 100644 index f8c8213a20..0000000000 --- a/packages/@uppy/react/src/index.js +++ /dev/null @@ -1,7 +0,0 @@ -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' diff --git a/packages/@uppy/react/src/index.ts b/packages/@uppy/react/src/index.ts new file mode 100644 index 0000000000..f241b05d83 --- /dev/null +++ b/packages/@uppy/react/src/index.ts @@ -0,0 +1,7 @@ +export { default as Dashboard } from './Dashboard.ts' +export { default as DashboardModal } from './DashboardModal.ts' +export { default as DragDrop } from './DragDrop.ts' +export { default as ProgressBar } from './ProgressBar.ts' +export { default as StatusBar } from './StatusBar.ts' +export { default as FileInput } from './FileInput.ts' +export { default as useUppy } from './useUppy.ts' diff --git a/packages/@uppy/react/src/nonHtmlPropsHaveChanged.js b/packages/@uppy/react/src/nonHtmlPropsHaveChanged.js deleted file mode 100644 index 9aee5a556f..0000000000 --- a/packages/@uppy/react/src/nonHtmlPropsHaveChanged.js +++ /dev/null @@ -1,3 +0,0 @@ -export default function nonHtmlPropsHaveChanged (props, prevProps) { - return Object.keys(props).some(key => !Object.hasOwn(props, key) && props[key] !== prevProps[key]) -} diff --git a/packages/@uppy/react/src/nonHtmlPropsHaveChanged.ts b/packages/@uppy/react/src/nonHtmlPropsHaveChanged.ts new file mode 100644 index 0000000000..179c1625b8 --- /dev/null +++ b/packages/@uppy/react/src/nonHtmlPropsHaveChanged.ts @@ -0,0 +1,7 @@ +export default function nonHtmlPropsHaveChanged< + T extends Record, +>(props: T, prevProps: T): boolean { + return Object.keys(props).some( + (key) => !Object.hasOwn(props, key) && props[key] !== prevProps[key], + ) +} diff --git a/packages/@uppy/react/src/propTypes.js b/packages/@uppy/react/src/propTypes.ts similarity index 52% rename from packages/@uppy/react/src/propTypes.js rename to packages/@uppy/react/src/propTypes.ts index e744a3dd1d..1054423ab5 100644 --- a/packages/@uppy/react/src/propTypes.js +++ b/packages/@uppy/react/src/propTypes.ts @@ -25,37 +25,6 @@ const metaFields = PropTypes.oneOfType([ ]) // A size in pixels (number) or with some other unit (string). -const cssSize = PropTypes.oneOfType([ - PropTypes.string, - PropTypes.number, -]) - -// Common props for dashboardy components (Dashboard and DashboardModal). -const dashboard = { - uppy, - inline: PropTypes.bool, - plugins, - width: cssSize, - height: cssSize, - showProgressDetails: PropTypes.bool, - hideUploadButton: PropTypes.bool, - hideProgressAfterFinish: PropTypes.bool, - note: PropTypes.string, - metaFields, - proudlyDisplayPoweredByUppy: PropTypes.bool, - disableStatusBar: PropTypes.bool, - disableInformer: PropTypes.bool, - disableThumbnailGenerator: PropTypes.bool, - // pass-through to ThumbnailGenerator - thumbnailWidth: PropTypes.number, - locale, -} +const cssSize = PropTypes.oneOfType([PropTypes.string, PropTypes.number]) -export { - uppy, - locale, - dashboard, - plugins, - metaFields, - cssSize, -} +export { uppy, locale, plugins, metaFields, cssSize } diff --git a/packages/@uppy/react/src/useUppy.js b/packages/@uppy/react/src/useUppy.ts similarity index 50% rename from packages/@uppy/react/src/useUppy.js rename to packages/@uppy/react/src/useUppy.ts index 3913833b37..e549d82071 100644 --- a/packages/@uppy/react/src/useUppy.js +++ b/packages/@uppy/react/src/useUppy.ts @@ -1,20 +1,27 @@ import { useEffect, useRef } from 'react' import { Uppy as UppyCore } from '@uppy/core' +import type { Body, Meta } from '@uppy/utils/lib/UppyFile' /** * @deprecated Initialize Uppy outside of the component. */ -export default function useUppy (factory) { +export default function useUppy( + factory: () => UppyCore, +): UppyCore | undefined { if (typeof factory !== 'function') { - throw new TypeError('useUppy: expected a function that returns a new Uppy instance') + throw new TypeError( + 'useUppy: expected a function that returns a new Uppy instance', + ) } - const uppy = useRef(undefined) + const uppy = useRef | undefined>(undefined) if (uppy.current === undefined) { uppy.current = factory() if (!(uppy.current instanceof UppyCore)) { - throw new TypeError(`useUppy: factory function must return an Uppy instance, got ${typeof uppy.current}`) + throw new TypeError( + `useUppy: factory function must return an Uppy instance, got ${typeof uppy.current}`, + ) } } diff --git a/packages/@uppy/react/tsconfig.build.json b/packages/@uppy/react/tsconfig.build.json new file mode 100644 index 0000000000..151f7261b5 --- /dev/null +++ b/packages/@uppy/react/tsconfig.build.json @@ -0,0 +1,50 @@ +{ + "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/*"], + "@uppy/dashboard": ["../dashboard/src/index.js"], + "@uppy/dashboard/lib/*": ["../dashboard/src/*"], + "@uppy/drag-drop": ["../drag-drop/src/index.js"], + "@uppy/drag-drop/lib/*": ["../drag-drop/src/*"], + "@uppy/file-input": ["../file-input/src/index.js"], + "@uppy/file-input/lib/*": ["../file-input/src/*"], + "@uppy/progress-bar": ["../progress-bar/src/index.js"], + "@uppy/progress-bar/lib/*": ["../progress-bar/src/*"], + "@uppy/status-bar": ["../status-bar/src/index.js"], + "@uppy/status-bar/lib/*": ["../status-bar/src/*"] + }, + "resolveJsonModule": false, + "rootDir": "./src", + "skipLibCheck": true + }, + "include": ["./src/**/*.*"], + "exclude": ["./src/**/*.test.ts"], + "references": [ + { + "path": "../utils/tsconfig.build.json" + }, + { + "path": "../core/tsconfig.build.json" + }, + { + "path": "../dashboard/tsconfig.build.json" + }, + { + "path": "../drag-drop/tsconfig.build.json" + }, + { + "path": "../file-input/tsconfig.build.json" + }, + { + "path": "../progress-bar/tsconfig.build.json" + }, + { + "path": "../status-bar/tsconfig.build.json" + } + ] +} diff --git a/packages/@uppy/react/tsconfig.json b/packages/@uppy/react/tsconfig.json new file mode 100644 index 0000000000..aae4219b7c --- /dev/null +++ b/packages/@uppy/react/tsconfig.json @@ -0,0 +1,46 @@ +{ + "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/*"], + "@uppy/dashboard": ["../dashboard/src/index.js"], + "@uppy/dashboard/lib/*": ["../dashboard/src/*"], + "@uppy/drag-drop": ["../drag-drop/src/index.js"], + "@uppy/drag-drop/lib/*": ["../drag-drop/src/*"], + "@uppy/file-input": ["../file-input/src/index.js"], + "@uppy/file-input/lib/*": ["../file-input/src/*"], + "@uppy/progress-bar": ["../progress-bar/src/index.js"], + "@uppy/progress-bar/lib/*": ["../progress-bar/src/*"], + "@uppy/status-bar": ["../status-bar/src/index.js"], + "@uppy/status-bar/lib/*": ["../status-bar/src/*"], + }, + }, + "include": ["./package.json", "./src/**/*.*"], + "references": [ + { + "path": "../utils/tsconfig.build.json", + }, + { + "path": "../core/tsconfig.build.json", + }, + { + "path": "../dashboard/tsconfig.build.json", + }, + { + "path": "../drag-drop/tsconfig.build.json", + }, + { + "path": "../file-input/tsconfig.build.json", + }, + { + "path": "../progress-bar/tsconfig.build.json", + }, + { + "path": "../status-bar/tsconfig.build.json", + }, + ], +} diff --git a/packages/@uppy/react/src/CommonTypes.d.ts b/packages/@uppy/react/types/CommonTypes.d.ts similarity index 100% rename from packages/@uppy/react/src/CommonTypes.d.ts rename to packages/@uppy/react/types/CommonTypes.d.ts diff --git a/packages/@uppy/react/src/Dashboard.d.ts b/packages/@uppy/react/types/Dashboard.d.ts similarity index 100% rename from packages/@uppy/react/src/Dashboard.d.ts rename to packages/@uppy/react/types/Dashboard.d.ts diff --git a/packages/@uppy/react/src/DashboardModal.d.ts b/packages/@uppy/react/types/DashboardModal.d.ts similarity index 100% rename from packages/@uppy/react/src/DashboardModal.d.ts rename to packages/@uppy/react/types/DashboardModal.d.ts diff --git a/packages/@uppy/react/src/DragDrop.d.ts b/packages/@uppy/react/types/DragDrop.d.ts similarity index 100% rename from packages/@uppy/react/src/DragDrop.d.ts rename to packages/@uppy/react/types/DragDrop.d.ts diff --git a/packages/@uppy/react/src/FileInput.d.ts b/packages/@uppy/react/types/FileInput.d.ts similarity index 100% rename from packages/@uppy/react/src/FileInput.d.ts rename to packages/@uppy/react/types/FileInput.d.ts diff --git a/packages/@uppy/react/src/ProgressBar.d.ts b/packages/@uppy/react/types/ProgressBar.d.ts similarity index 100% rename from packages/@uppy/react/src/ProgressBar.d.ts rename to packages/@uppy/react/types/ProgressBar.d.ts diff --git a/packages/@uppy/react/src/StatusBar.d.ts b/packages/@uppy/react/types/StatusBar.d.ts similarity index 100% rename from packages/@uppy/react/src/StatusBar.d.ts rename to packages/@uppy/react/types/StatusBar.d.ts diff --git a/packages/@uppy/react/types/index.d.ts b/packages/@uppy/react/types/index.d.ts index d64be3577f..2fc2c265da 100644 --- a/packages/@uppy/react/types/index.d.ts +++ b/packages/@uppy/react/types/index.d.ts @@ -1,7 +1,7 @@ -export { default as Dashboard } from '../src/Dashboard' -export { default as DashboardModal } from '../src/DashboardModal' -export { default as DragDrop } from '../src/DragDrop' -export { default as ProgressBar } from '../src/ProgressBar' -export { default as StatusBar } from '../src/StatusBar' -export { default as FileInput } from '../src/FileInput' -export { default as useUppy } from '../src/useUppy' +export { default as Dashboard } from './Dashboard' +export { default as DashboardModal } from './DashboardModal' +export { default as DragDrop } from './DragDrop' +export { default as ProgressBar } from './ProgressBar' +export { default as StatusBar } from './StatusBar' +export { default as FileInput } from './FileInput' +export { default as useUppy } from './useUppy' diff --git a/packages/@uppy/react/src/useUppy.d.ts b/packages/@uppy/react/types/useUppy.d.ts similarity index 100% rename from packages/@uppy/react/src/useUppy.d.ts rename to packages/@uppy/react/types/useUppy.d.ts