Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

@uppy/react: refactor to TS #5012

Merged
merged 16 commits into from
Mar 27, 2024
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
2 changes: 1 addition & 1 deletion packages/@uppy/core/src/Uppy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ type Processor = (
uploadID: string,
) => Promise<unknown> | void

type FileRemoveReason = 'user' | 'cancel-all'
type FileRemoveReason = 'user' | 'cancel-all' | 'unmount'

type LogLevel = 'info' | 'warning' | 'error' | 'success'

Expand Down
1 change: 1 addition & 0 deletions packages/@uppy/react/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
tsconfig.*
69 changes: 0 additions & 69 deletions packages/@uppy/react/src/Dashboard.js

This file was deleted.

109 changes: 109 additions & 0 deletions packages/@uppy/react/src/Dashboard.ts
Original file line number Diff line number Diff line change
@@ -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<M extends Meta, B extends Body> = Omit<
DashboardOptions<M, B> & { inline: true },
'inline'
> &
React.BaseHTMLAttributes<HTMLDivElement>
Comment on lines +17 to +21
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should have reviewed this in the other PR but didn't foresee how we'd use it, but I initially envisioned we'd import DashboardInlineOptions which does this trick inside @uppy/dashboard. Then we keep the conditions of the discriminated union in one place instead of repeating it everywhere.

What do you think? Doesn't need a separate PR.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if it's worth it, exporting a single type is less likely to confuse users. The fact that we need to remove the discriminated union here is probably more the exception than the rule.


export interface DashboardProps<M extends Meta, B extends Body>
extends DashboardInlineOptions<M, B> {
uppy: Uppy<M, B>
}

/**
* 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<M extends Meta, B extends Body> extends Component<
DashboardProps<M, B>
> {
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<M, B>

componentDidMount(): void {
this.installPlugin()
}

componentDidUpdate(prevProps: Dashboard<M, B>['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<M, B>, options)

this.plugin = uppy.getPlugin(options.id)!
}

uninstallPlugin(props = this.props): void {
const { uppy } = props

uppy.removePlugin(this.plugin)
}

render(): JSX.Element {
aduh95 marked this conversation as resolved.
Show resolved Hide resolved
return h('div', {
className: 'uppy-Container',
ref: (container: HTMLElement): void => {
this.container = container
},
...getHTMLProps(this.props),
})
}
}

export default Dashboard
157 changes: 0 additions & 157 deletions packages/@uppy/react/src/DashboardModal.js

This file was deleted.