From 8d04f746ffc32b2ef000bd8a76879fe3addb08c3 Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Sun, 10 Mar 2024 15:17:31 +0100 Subject: [PATCH 01/24] @uppy/dashboard: refactor to TypeScript --- packages/@uppy/dashboard/.npmignore | 1 + .../src/{Dashboard.jsx => Dashboard.tsx} | 382 ++++++++++++------ .../components/{AddFiles.jsx => AddFiles.tsx} | 10 +- .../{AddFilesPanel.jsx => AddFilesPanel.tsx} | 2 +- .../{Dashboard.jsx => Dashboard.tsx} | 16 +- .../{EditorPanel.jsx => EditorPanel.tsx} | 0 ...derMetaFields.jsx => RenderMetaFields.tsx} | 0 .../FileCard/{index.jsx => index.tsx} | 8 +- .../FileItem/Buttons/{index.jsx => index.tsx} | 2 +- .../FileInfo/{index.jsx => index.tsx} | 2 +- .../{index.jsx => index.tsx} | 6 +- .../FileProgress/{index.jsx => index.tsx} | 0 ...aErrorMessage.jsx => MetaErrorMessage.tsx} | 0 .../FileItem/{index.jsx => index.tsx} | 8 +- .../components/{FileList.jsx => FileList.tsx} | 2 +- .../{FilePreview.jsx => FilePreview.tsx} | 2 +- ...anelContent.jsx => PickerPanelContent.tsx} | 2 +- ...rPanelTopBar.jsx => PickerPanelTopBar.tsx} | 0 .../src/components/{Slide.jsx => Slide.tsx} | 0 packages/@uppy/dashboard/src/index.js | 1 - .../src/{index.test.js => index.test.ts} | 2 +- packages/@uppy/dashboard/src/index.ts | 1 + .../dashboard/src/{locale.js => locale.ts} | 0 ...pboard.test.js => copyToClipboard.test.ts} | 2 +- ...{copyToClipboard.js => copyToClipboard.ts} | 0 ...Focus.test.js => createSuperFocus.test.ts} | 2 +- ...reateSuperFocus.js => createSuperFocus.ts} | 2 +- ...tiveOverlayEl.js => getActiveOverlayEl.ts} | 0 ...etFileTypeIcon.jsx => getFileTypeIcon.tsx} | 0 .../utils/{ignoreEvent.js => ignoreEvent.ts} | 0 .../src/utils/{trapFocus.js => trapFocus.ts} | 2 +- packages/@uppy/dashboard/tsconfig.build.json | 98 +++++ packages/@uppy/dashboard/tsconfig.json | 93 +++++ 33 files changed, 477 insertions(+), 169 deletions(-) create mode 100644 packages/@uppy/dashboard/.npmignore rename packages/@uppy/dashboard/src/{Dashboard.jsx => Dashboard.tsx} (78%) rename packages/@uppy/dashboard/src/components/{AddFiles.jsx => AddFiles.tsx} (98%) rename packages/@uppy/dashboard/src/components/{AddFilesPanel.jsx => AddFilesPanel.tsx} (95%) rename packages/@uppy/dashboard/src/components/{Dashboard.jsx => Dashboard.tsx} (95%) rename packages/@uppy/dashboard/src/components/{EditorPanel.jsx => EditorPanel.tsx} (100%) rename packages/@uppy/dashboard/src/components/FileCard/{RenderMetaFields.jsx => RenderMetaFields.tsx} (100%) rename packages/@uppy/dashboard/src/components/FileCard/{index.jsx => index.tsx} (95%) rename packages/@uppy/dashboard/src/components/FileItem/Buttons/{index.jsx => index.tsx} (98%) rename packages/@uppy/dashboard/src/components/FileItem/FileInfo/{index.jsx => index.tsx} (98%) rename packages/@uppy/dashboard/src/components/FileItem/FilePreviewAndLink/{index.jsx => index.tsx} (85%) rename packages/@uppy/dashboard/src/components/FileItem/FileProgress/{index.jsx => index.tsx} (100%) rename packages/@uppy/dashboard/src/components/FileItem/{MetaErrorMessage.jsx => MetaErrorMessage.tsx} (100%) rename packages/@uppy/dashboard/src/components/FileItem/{index.jsx => index.tsx} (95%) rename packages/@uppy/dashboard/src/components/{FileList.jsx => FileList.tsx} (98%) rename packages/@uppy/dashboard/src/components/{FilePreview.jsx => FilePreview.tsx} (92%) rename packages/@uppy/dashboard/src/components/{PickerPanelContent.jsx => PickerPanelContent.tsx} (95%) rename packages/@uppy/dashboard/src/components/{PickerPanelTopBar.jsx => PickerPanelTopBar.tsx} (100%) rename packages/@uppy/dashboard/src/components/{Slide.jsx => Slide.tsx} (100%) delete mode 100644 packages/@uppy/dashboard/src/index.js rename packages/@uppy/dashboard/src/{index.test.js => index.test.ts} (98%) create mode 100644 packages/@uppy/dashboard/src/index.ts rename packages/@uppy/dashboard/src/{locale.js => locale.ts} (100%) rename packages/@uppy/dashboard/src/utils/{copyToClipboard.test.js => copyToClipboard.test.ts} (80%) rename packages/@uppy/dashboard/src/utils/{copyToClipboard.js => copyToClipboard.ts} (100%) rename packages/@uppy/dashboard/src/utils/{createSuperFocus.test.js => createSuperFocus.test.ts} (86%) rename packages/@uppy/dashboard/src/utils/{createSuperFocus.js => createSuperFocus.ts} (97%) rename packages/@uppy/dashboard/src/utils/{getActiveOverlayEl.js => getActiveOverlayEl.ts} (100%) rename packages/@uppy/dashboard/src/utils/{getFileTypeIcon.jsx => getFileTypeIcon.tsx} (100%) rename packages/@uppy/dashboard/src/utils/{ignoreEvent.js => ignoreEvent.ts} (100%) rename packages/@uppy/dashboard/src/utils/{trapFocus.js => trapFocus.ts} (98%) create mode 100644 packages/@uppy/dashboard/tsconfig.build.json create mode 100644 packages/@uppy/dashboard/tsconfig.json diff --git a/packages/@uppy/dashboard/.npmignore b/packages/@uppy/dashboard/.npmignore new file mode 100644 index 0000000000..6c816673f0 --- /dev/null +++ b/packages/@uppy/dashboard/.npmignore @@ -0,0 +1 @@ +tsconfig.* diff --git a/packages/@uppy/dashboard/src/Dashboard.jsx b/packages/@uppy/dashboard/src/Dashboard.tsx similarity index 78% rename from packages/@uppy/dashboard/src/Dashboard.jsx rename to packages/@uppy/dashboard/src/Dashboard.tsx index a3fe0cd4cb..87ed6afba3 100644 --- a/packages/@uppy/dashboard/src/Dashboard.jsx +++ b/packages/@uppy/dashboard/src/Dashboard.tsx @@ -1,4 +1,5 @@ -import { UIPlugin } from '@uppy/core' +import { UIPlugin, type UIPluginOptions, type UnknownPlugin, type Uppy } from '@uppy/core' +import type { DefinePluginOpts } from '@uppy/core/lib/BasePlugin.ts' import StatusBar from '@uppy/status-bar' import Informer from '@uppy/informer' import ThumbnailGenerator from '@uppy/thumbnail-generator' @@ -9,20 +10,23 @@ import { defaultPickerIcon } from '@uppy/provider-views' import { nanoid } from 'nanoid/non-secure' import memoizeOne from 'memoize-one' -import * as trapFocus from './utils/trapFocus.js' -import createSuperFocus from './utils/createSuperFocus.js' -import DashboardUI from './components/Dashboard.jsx' +import * as trapFocus from './utils/trapFocus.ts' +import createSuperFocus from './utils/createSuperFocus.ts' +import DashboardUI from './components/Dashboard.tsx' +// 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' +import type { Body, Meta, UppyFile } from '@uppy/utils/lib/UppyFile' const memoize = memoizeOne.default || memoizeOne const TAB_KEY = 9 const ESC_KEY = 27 -function createPromise () { - const o = {} +function createPromise(): ReturnType { + const o = {} as ReturnType o.promise = new Promise((resolve, reject) => { o.resolve = resolve o.reject = reject @@ -30,16 +34,115 @@ function createPromise () { return o } +interface MetaField { + id: string + name: string + placeholder?: string + render?: (field: FieldRenderOptions, h: PreactRender) => any +} + +interface DashboardOptions + extends UIPluginOptions { + animateOpenClose?: boolean + browserBackButtonClose?: boolean + closeAfterFinish?: boolean + singleFileFullScreen?: boolean + closeModalOnClickOutside?: boolean + disableInformer?: boolean + disablePageScrollWhenModalOpen?: boolean + disableStatusBar?: boolean + disableThumbnailGenerator?: boolean + height?: string | number + hideCancelButton?: boolean + hidePauseResumeButton?: boolean + hideProgressAfterFinish?: boolean + hideRetryButton?: boolean + hideUploadButton?: boolean + inline?: boolean + metaFields?: MetaField[] | ((file: UppyFile) => MetaField[]) + note?: string | null + plugins?: string[] + fileManagerSelectionType?: 'files' | 'folders' | 'both' + proudlyDisplayPoweredByUppy?: boolean + showLinkToFileUploadResult?: boolean + showProgressDetails?: boolean + showSelectedFiles?: boolean + showRemoveButtonAfterComplete?: boolean + showNativePhotoCameraButton?: boolean + showNativeVideoCameraButton?: boolean + theme?: 'auto' | 'dark' | 'light' + trigger?: string + width?: string | number + autoOpenFileEditor?: boolean + disabled?: boolean + disableLocalFiles?: boolean + onRequestCloseModal?: () => void + doneButtonHandler?: () => void + onDragOver?: (event: DragEvent) => void + onDragLeave?: (event: DragEvent) => void + onDrop?: (event: DragEvent) => void +} + +// set default options, must be kept in sync with packages/@uppy/react/src/DashboardModal.js +const defaultOptions = { + target: 'body', + metaFields: [], + trigger: null, + inline: false, + width: 750, + height: 550, + thumbnailWidth: 280, + thumbnailType: 'image/jpeg', + waitForThumbnailsBeforeUpload: false, + defaultPickerIcon, + showLinkToFileUploadResult: false, + showProgressDetails: false, + hideUploadButton: false, + hideCancelButton: false, + hideRetryButton: false, + hidePauseResumeButton: false, + hideProgressAfterFinish: false, + doneButtonHandler: () => { + this.uppy.clearUploadedFiles() + this.requestCloseModal() + }, + note: null, + closeModalOnClickOutside: false, + closeAfterFinish: false, + singleFileFullScreen: true, + disableStatusBar: false, + disableInformer: false, + disableThumbnailGenerator: false, + disablePageScrollWhenModalOpen: true, + animateOpenClose: true, + fileManagerSelectionType: 'files', + proudlyDisplayPoweredByUppy: true, + onRequestCloseModal: () => this.closeModal(), + showSelectedFiles: true, + showRemoveButtonAfterComplete: false, + browserBackButtonClose: false, + showNativePhotoCameraButton: false, + showNativeVideoCameraButton: false, + theme: 'light', + autoOpenFileEditor: false, + disabled: false, + disableLocalFiles: false, +} satisfies Partial> + /** * Dashboard UI with previews, metadata editing, tabs for various services and more */ -export default class Dashboard extends UIPlugin { +export default class Dashboard extends UIPlugin< + DefinePluginOpts, keyof typeof defaultOptions>, + M, + B +> { static VERSION = packageJson.version #disabledNodes = null - constructor (uppy, opts) { - super(uppy, opts) + constructor(uppy: Uppy, opts?: DashboardOptions) { + super(uppy, { ...defaultOptions, ...opts }) this.id = this.opts.id || 'Dashboard' this.title = 'Dashboard' this.type = 'orchestrator' @@ -47,55 +150,6 @@ export default class Dashboard extends UIPlugin { this.defaultLocale = locale - // set default options, must be kept in sync with packages/@uppy/react/src/DashboardModal.js - const defaultOptions = { - target: 'body', - metaFields: [], - trigger: null, - inline: false, - width: 750, - height: 550, - thumbnailWidth: 280, - thumbnailType: 'image/jpeg', - waitForThumbnailsBeforeUpload: false, - defaultPickerIcon, - showLinkToFileUploadResult: false, - showProgressDetails: false, - hideUploadButton: false, - hideCancelButton: false, - hideRetryButton: false, - hidePauseResumeButton: false, - hideProgressAfterFinish: false, - doneButtonHandler: () => { - this.uppy.clearUploadedFiles() - this.requestCloseModal() - }, - note: null, - closeModalOnClickOutside: false, - closeAfterFinish: false, - singleFileFullScreen: true, - disableStatusBar: false, - disableInformer: false, - disableThumbnailGenerator: false, - disablePageScrollWhenModalOpen: true, - animateOpenClose: true, - fileManagerSelectionType: 'files', - proudlyDisplayPoweredByUppy: true, - onRequestCloseModal: () => this.closeModal(), - showSelectedFiles: true, - showRemoveButtonAfterComplete: false, - browserBackButtonClose: false, - showNativePhotoCameraButton: false, - showNativeVideoCameraButton: false, - theme: 'light', - autoOpenFileEditor: false, - disabled: false, - disableLocalFiles: false, - } - - // merge default options with the ones set by user - this.opts = { ...defaultOptions, ...opts } - this.i18nInit() this.superFocus = createSuperFocus() @@ -106,25 +160,30 @@ export default class Dashboard extends UIPlugin { this.removeDragOverClassTimeout = null } - removeTarget = (plugin) => { + removeTarget = (plugin: UnknownPlugin): void => { const pluginState = this.getPluginState() // filter out the one we want to remove - const newTargets = pluginState.targets.filter(target => target.id !== plugin.id) + const newTargets = pluginState.targets.filter( + (target) => target.id !== plugin.id, + ) this.setPluginState({ targets: newTargets, }) } - addTarget = (plugin) => { + addTarget = (plugin: UnknownPlugin): HTMLElement|null => { const callerPluginId = plugin.id || plugin.constructor.name const callerPluginName = plugin.title || callerPluginId const callerPluginType = plugin.type - if (callerPluginType !== 'acquirer' - && callerPluginType !== 'progressindicator' - && callerPluginType !== 'editor') { - const msg = 'Dashboard: can only be targeted by plugins of types: acquirer, progressindicator, editor' + if ( + callerPluginType !== 'acquirer' && + callerPluginType !== 'progressindicator' && + callerPluginType !== 'editor' + ) { + const msg = + 'Dashboard: can only be targeted by plugins of types: acquirer, progressindicator, editor' this.uppy.log(msg, 'error') return undefined } @@ -146,7 +205,7 @@ export default class Dashboard extends UIPlugin { return this.el } - hideAllPanels = () => { + hideAllPanels = (): void => { const state = this.getPluginState() const update = { activePickerPanel: false, @@ -156,10 +215,12 @@ export default class Dashboard extends UIPlugin { showFileEditor: false, } - if (state.activePickerPanel === update.activePickerPanel - && state.showAddFilesPanel === update.showAddFilesPanel - && state.showFileEditor === update.showFileEditor - && state.activeOverlayType === update.activeOverlayType) { + if ( + state.activePickerPanel === update.activePickerPanel && + state.showAddFilesPanel === update.showAddFilesPanel && + state.showFileEditor === update.showFileEditor && + state.activeOverlayType === update.activeOverlayType + ) { // avoid doing a state update if nothing changed return } @@ -169,7 +230,7 @@ export default class Dashboard extends UIPlugin { this.uppy.emit('dashboard:close-panel', state.activePickerPanel.id) } - showPanel = (id) => { + showPanel = (id: string): void => { const { targets } = this.getPluginState() const activePickerPanel = targets.filter((target) => { @@ -184,16 +245,16 @@ export default class Dashboard extends UIPlugin { this.uppy.emit('dashboard:show-panel', id) } - canEditFile = (file) => { + canEditFile = (file): void => { const { targets } = this.getPluginState() const editors = this.#getEditors(targets) - return editors.some((target) => ( - this.uppy.getPlugin(target.id).canEditFile(file) - )) + return editors.some((target) => + this.uppy.getPlugin(target.id).canEditFile(file), + ) } - openFileEditor = (file) => { + openFileEditor = (file): void => { const { targets } = this.getPluginState() const editors = this.#getEditors(targets) @@ -208,25 +269,25 @@ export default class Dashboard extends UIPlugin { }) } - closeFileEditor = () => { + closeFileEditor = (): void => { const { metaFields } = this.getPluginState() const isMetaEditorEnabled = metaFields && metaFields.length > 0 if (isMetaEditorEnabled) { this.setPluginState({ showFileEditor: false, - activeOverlayType: 'FileCard' + activeOverlayType: 'FileCard', }) } else { this.setPluginState({ showFileEditor: false, fileCardFor: null, - activeOverlayType: 'AddFiles' + activeOverlayType: 'AddFiles', }) } } - saveFileEditor = () => { + saveFileEditor = (): void => { const { targets } = this.getPluginState() const editors = this.#getEditors(targets) @@ -237,7 +298,7 @@ export default class Dashboard extends UIPlugin { this.closeFileEditor() } - openModal = () => { + openModal = (): Promise => { const { promise, resolve } = createPromise() // save scroll position this.savedScrollPosition = window.pageYOffset @@ -276,7 +337,7 @@ export default class Dashboard extends UIPlugin { return promise } - closeModal = (opts = {}) => { + closeModal = (opts = {}): void|Promise => { const { // Whether the modal is being closed by the user (`true`) or by other means (e.g. browser back button) manualClose = true, @@ -342,18 +403,18 @@ export default class Dashboard extends UIPlugin { return promise } - isModalOpen = () => { + isModalOpen = (): boolean => { return !this.getPluginState().isHidden || false } - requestCloseModal = () => { + requestCloseModal = (): void|Promise => { if (this.opts.onRequestCloseModal) { return this.opts.onRequestCloseModal() } return this.closeModal() } - setDarkModeCapability = (isDarkModeOn) => { + setDarkModeCapability = (isDarkModeOn: boolean):void => { const { capabilities } = this.uppy.getState() this.uppy.setState({ capabilities: { @@ -436,14 +497,18 @@ export default class Dashboard extends UIPlugin { this.makeDashboardInsidesVisibleAnywayTimeout = setTimeout(() => { const pluginState = this.getPluginState() const isModalAndClosed = !this.opts.inline && pluginState.isHidden - if (// We might want to enable this in the future + if ( + // We might want to enable this in the future // if ResizeObserver hasn't yet fired, - !pluginState.areInsidesReadyToBeVisible + !pluginState.areInsidesReadyToBeVisible && // and it's not due to the modal being closed - && !isModalAndClosed + !isModalAndClosed ) { - this.uppy.log('[Dashboard] resize event didn’t fire on time: defaulted to mobile layout', 'warning') + this.uppy.log( + '[Dashboard] resize event didn’t fire on time: defaulted to mobile layout', + 'warning', + ) this.setPluginState({ areInsidesReadyToBeVisible: true, @@ -482,8 +547,11 @@ export default class Dashboard extends UIPlugin { '[role="button"]:not([disabled])', ] - const nodesToDisable = this.#disabledNodes ?? toArray(this.el.querySelectorAll(NODES_TO_DISABLE)) - .filter(node => !node.classList.contains('uppy-Dashboard-close')) + const nodesToDisable = + this.#disabledNodes ?? + toArray(this.el.querySelectorAll(NODES_TO_DISABLE)).filter( + (node) => !node.classList.contains('uppy-Dashboard-close'), + ) for (const node of nodesToDisable) { // Links can’t have `disabled` attr, so we use `aria-disabled` for a11y @@ -509,11 +577,14 @@ export default class Dashboard extends UIPlugin { if (!history.state?.[this.modalName]) { // Push to history so that the page is not lost on browser back button press // eslint-disable-next-line no-restricted-globals - history.pushState({ - // eslint-disable-next-line no-restricted-globals - ...history.state, - [this.modalName]: true, - }, '') + history.pushState( + { + // eslint-disable-next-line no-restricted-globals + ...history.state, + [this.modalName]: true, + }, + '', + ) } // Listen for back button presses @@ -542,7 +613,12 @@ export default class Dashboard extends UIPlugin { // close modal on esc key press if (event.keyCode === ESC_KEY) this.requestCloseModal(event) // trap focus on tab key press - if (event.keyCode === TAB_KEY) trapFocus.forModal(event, this.getPluginState().activeOverlayType, this.el) + if (event.keyCode === TAB_KEY) + trapFocus.forModal( + event, + this.getPluginState().activeOverlayType, + this.el, + ) } handleClickOutside = () => { @@ -594,7 +670,7 @@ export default class Dashboard extends UIPlugin { // Check if the "type" of the datatransfer object includes files const doesEventHaveFiles = () => { const { types } = event.dataTransfer - return types.some(type => type === 'Files') + return types.some((type) => type === 'Files') } // Deny drop, if no plugins can handle datatransfer, there are no files, @@ -602,12 +678,13 @@ export default class Dashboard extends UIPlugin { const somePluginCanHandleRootDrop = canSomePluginHandleRootDrop(event) const hasFiles = doesEventHaveFiles(event) if ( - (!somePluginCanHandleRootDrop && !hasFiles) - || this.opts.disabled + (!somePluginCanHandleRootDrop && !hasFiles) || + this.opts.disabled || // opts.disableLocalFiles should only be taken into account if no plugins // can handle the datatransfer - || (this.opts.disableLocalFiles && (hasFiles || !somePluginCanHandleRootDrop)) - || !this.uppy.getState().allowNewUpload + (this.opts.disableLocalFiles && + (hasFiles || !somePluginCanHandleRootDrop)) || + !this.uppy.getState().allowNewUpload ) { event.dataTransfer.dropEffect = 'none' // eslint-disable-line no-param-reassign clearTimeout(this.removeDragOverClassTimeout) @@ -698,7 +775,12 @@ export default class Dashboard extends UIPlugin { handleKeyDownInInline = (event) => { // Trap focus on tab key press. - if (event.keyCode === TAB_KEY) trapFocus.forInline(event, this.getPluginState().activeOverlayType, this.el) + if (event.keyCode === TAB_KEY) + trapFocus.forInline( + event, + this.getPluginState().activeOverlayType, + this.el, + ) } // ___Why do we listen to the 'paste' event on a document instead of onPaste={props.handlePaste} prop, @@ -737,11 +819,15 @@ export default class Dashboard extends UIPlugin { const files = this.uppy.getFiles() if (files.length === 1) { - const thumbnailGenerator = this.uppy.getPlugin(`${this.id}:ThumbnailGenerator`) + const thumbnailGenerator = this.uppy.getPlugin( + `${this.id}:ThumbnailGenerator`, + ) thumbnailGenerator?.setOptions({ thumbnailWidth: LARGE_THUMBNAIL }) const fileForThumbnail = { ...files[0], preview: undefined } thumbnailGenerator.requestThumbnail(fileForThumbnail).then(() => { - thumbnailGenerator?.setOptions({ thumbnailWidth: this.opts.thumbnailWidth }) + thumbnailGenerator?.setOptions({ + thumbnailWidth: this.opts.thumbnailWidth, + }) }) } } @@ -749,7 +835,7 @@ export default class Dashboard extends UIPlugin { #openFileEditorWhenFilesAdded = (files) => { const firstFile = files[0] - const {metaFields} = this.getPluginState() + const { metaFields } = this.getPluginState() const isMetaEditorEnabled = metaFields && metaFields.length > 0 const isFileEditorEnabled = this.canEditFile(firstFile) @@ -765,9 +851,14 @@ export default class Dashboard extends UIPlugin { if (this.opts.trigger && !this.opts.inline) { const showModalTrigger = findAllDOMElements(this.opts.trigger) if (showModalTrigger) { - showModalTrigger.forEach(trigger => trigger.addEventListener('click', this.openModal)) + showModalTrigger.forEach((trigger) => + trigger.addEventListener('click', this.openModal), + ) } else { - this.uppy.log('Dashboard modal trigger not found. Make sure `trigger` is set in Dashboard options, unless you are planning to call `dashboard.openModal()` method yourself', 'warning') + this.uppy.log( + 'Dashboard modal trigger not found. Make sure `trigger` is set in Dashboard options, unless you are planning to call `dashboard.openModal()` method yourself', + 'warning', + ) } } @@ -800,7 +891,9 @@ export default class Dashboard extends UIPlugin { removeEvents = () => { const showModalTrigger = findAllDOMElements(this.opts.trigger) if (!this.opts.inline && showModalTrigger) { - showModalTrigger.forEach(trigger => trigger.removeEventListener('click', this.openModal)) + showModalTrigger.forEach((trigger) => + trigger.removeEventListener('click', this.openModal), + ) } this.stopListeningToResize() @@ -831,19 +924,20 @@ export default class Dashboard extends UIPlugin { superFocusOnEachUpdate = () => { const isFocusInUppy = this.el.contains(document.activeElement) // When focus is lost on the page (== focus is on body for most browsers, or focus is null for IE11) - const isFocusNowhere = document.activeElement === document.body || document.activeElement === null + const isFocusNowhere = + document.activeElement === document.body || + document.activeElement === null const isInformerHidden = this.uppy.getState().info.length === 0 const isModal = !this.opts.inline if ( // If update is connected to showing the Informer - let the screen reader calmly read it. - isInformerHidden - && ( - // If we are in a modal - always superfocus without concern for other elements - // on the page (user is unlikely to want to interact with the rest of the page) - isModal + isInformerHidden && + // If we are in a modal - always superfocus without concern for other elements + // on the page (user is unlikely to want to interact with the rest of the page) + (isModal || // If we are already inside of Uppy, or - || isFocusInUppy + isFocusInUppy || // If we are not focused on anything BUT we have already, at least once, focused on uppy // 1. We focus when isFocusNowhere, because when the element we were focused // on disappears (e.g. an overlay), - focus gets lost. If user is typing @@ -853,8 +947,7 @@ export default class Dashboard extends UIPlugin { // [Practical check] Without '&& this.ifFocusedOnUppyRecently', in Safari, in inline mode, // when file is uploading, - navigate via tab to the checkbox, // try to press space multiple times. Focus will jump to Uppy. - || (isFocusNowhere && this.ifFocusedOnUppyRecently) - ) + (isFocusNowhere && this.ifFocusedOnUppyRecently)) ) { this.superFocus(this.el, this.getPluginState().activeOverlayType) } else { @@ -900,19 +993,22 @@ export default class Dashboard extends UIPlugin { #getAcquirers = memoize((targets) => { return targets - .filter(target => target.type === 'acquirer' && this.#isTargetSupported(target)) + .filter( + (target) => + target.type === 'acquirer' && this.#isTargetSupported(target), + ) .map(this.#attachRenderFunctionToTarget) }) #getProgressIndicators = memoize((targets) => { return targets - .filter(target => target.type === 'progressindicator') + .filter((target) => target.type === 'progressindicator') .map(this.#attachRenderFunctionToTarget) }) #getEditors = memoize((targets) => { return targets - .filter(target => target.type === 'editor') + .filter((target) => target.type === 'editor') .map(this.#attachRenderFunctionToTarget) }) @@ -945,10 +1041,15 @@ export default class Dashboard extends UIPlugin { theme = this.opts.theme } - if (['files', 'folders', 'both'].indexOf(this.opts.fileManagerSelectionType) < 0) { + if ( + ['files', 'folders', 'both'].indexOf(this.opts.fileManagerSelectionType) < + 0 + ) { this.opts.fileManagerSelectionType = 'files' // eslint-disable-next-line no-console - console.warn(`Unsupported option for "fileManagerSelectionType". Using default of "${this.opts.fileManagerSelectionType}".`) + console.warn( + `Unsupported option for "fileManagerSelectionType". Using default of "${this.opts.fileManagerSelectionType}".`, + ) } return DashboardUI({ @@ -1049,7 +1150,10 @@ export default class Dashboard extends UIPlugin { if (plugin) { plugin.mount(this, plugin) } else { - this.uppy.log(`[Uppy] Dashboard could not find plugin '${pluginID}', make sure to uppy.use() the plugins you are specifying`, 'warning') + this.uppy.log( + `[Uppy] Dashboard could not find plugin '${pluginID}', make sure to uppy.use() the plugins you are specifying`, + 'warning', + ) } }) } @@ -1064,7 +1168,7 @@ export default class Dashboard extends UIPlugin { const typesAllowed = ['acquirer', 'editor'] if (plugin && !plugin.opts?.target && typesAllowed.includes(plugin.type)) { const pluginAlreadyAdded = this.getPluginState().targets.some( - installedPlugin => plugin.id === installedPlugin.id, + (installedPlugin) => plugin.id === installedPlugin.id, ) if (!pluginAlreadyAdded) { plugin.mount(this, plugin) @@ -1090,12 +1194,20 @@ export default class Dashboard extends UIPlugin { const { inline, closeAfterFinish } = this.opts if (inline && closeAfterFinish) { - throw new Error('[Dashboard] `closeAfterFinish: true` cannot be used on an inline Dashboard, because an inline Dashboard cannot be closed at all. Either set `inline: false`, or disable the `closeAfterFinish` option.') + throw new Error( + '[Dashboard] `closeAfterFinish: true` cannot be used on an inline Dashboard, because an inline Dashboard cannot be closed at all. Either set `inline: false`, or disable the `closeAfterFinish` option.', + ) } const { allowMultipleUploads, allowMultipleUploadBatches } = this.uppy.opts - if ((allowMultipleUploads || allowMultipleUploadBatches) && closeAfterFinish) { - this.uppy.log('[Dashboard] When using `closeAfterFinish`, we recommended setting the `allowMultipleUploadBatches` option to `false` in the Uppy constructor. See https://uppy.io/docs/uppy/#allowMultipleUploads-true', 'warning') + if ( + (allowMultipleUploads || allowMultipleUploadBatches) && + closeAfterFinish + ) { + this.uppy.log( + '[Dashboard] When using `closeAfterFinish`, we recommended setting the `allowMultipleUploadBatches` option to `false` in the Uppy constructor. See https://uppy.io/docs/uppy/#allowMultipleUploads-true', + 'warning', + ) } const { target } = this.opts @@ -1139,12 +1251,16 @@ export default class Dashboard extends UIPlugin { } // Dark Mode / theme - this.darkModeMediaQuery = (typeof window !== 'undefined' && window.matchMedia) - ? window.matchMedia('(prefers-color-scheme: dark)') + this.darkModeMediaQuery = + typeof window !== 'undefined' && window.matchMedia ? + window.matchMedia('(prefers-color-scheme: dark)') : null - const isDarkModeOnFromTheStart = this.darkModeMediaQuery ? this.darkModeMediaQuery.matches : false - this.uppy.log(`[Dashboard] Dark mode is ${isDarkModeOnFromTheStart ? 'on' : 'off'}`) + const isDarkModeOnFromTheStart = + this.darkModeMediaQuery ? this.darkModeMediaQuery.matches : false + this.uppy.log( + `[Dashboard] Dark mode is ${isDarkModeOnFromTheStart ? 'on' : 'off'}`, + ) this.setDarkModeCapability(isDarkModeOnFromTheStart) if (this.opts.theme === 'auto') { diff --git a/packages/@uppy/dashboard/src/components/AddFiles.jsx b/packages/@uppy/dashboard/src/components/AddFiles.tsx similarity index 98% rename from packages/@uppy/dashboard/src/components/AddFiles.jsx rename to packages/@uppy/dashboard/src/components/AddFiles.tsx index c9a547a2dc..994898cd7e 100644 --- a/packages/@uppy/dashboard/src/components/AddFiles.jsx +++ b/packages/@uppy/dashboard/src/components/AddFiles.tsx @@ -1,23 +1,23 @@ import { h, Component, Fragment } from 'preact' class AddFiles extends Component { - triggerFileInputClick = () => { + private triggerFileInputClick = () => { this.fileInput.click() } - triggerFolderInputClick = () => { + private triggerFolderInputClick = () => { this.folderInput.click() } - triggerVideoCameraInputClick = () => { + private triggerVideoCameraInputClick = () => { this.mobileVideoFileInput.click() } - triggerPhotoCameraInputClick = () => { + private triggerPhotoCameraInputClick = () => { this.mobilePhotoFileInput.click() } - onFileInputChange = (event) => { + private onFileInputChange = (event) => { this.props.handleInputChange(event) // We clear the input after a file is selected, because otherwise diff --git a/packages/@uppy/dashboard/src/components/AddFilesPanel.jsx b/packages/@uppy/dashboard/src/components/AddFilesPanel.tsx similarity index 95% rename from packages/@uppy/dashboard/src/components/AddFilesPanel.jsx rename to packages/@uppy/dashboard/src/components/AddFilesPanel.tsx index 1dbf032754..42f4af4905 100644 --- a/packages/@uppy/dashboard/src/components/AddFilesPanel.jsx +++ b/packages/@uppy/dashboard/src/components/AddFilesPanel.tsx @@ -1,6 +1,6 @@ import { h } from 'preact' import classNames from 'classnames' -import AddFiles from './AddFiles.jsx' +import AddFiles from './AddFiles.tsx' const AddFilesPanel = (props) => { return ( diff --git a/packages/@uppy/dashboard/src/components/Dashboard.jsx b/packages/@uppy/dashboard/src/components/Dashboard.tsx similarity index 95% rename from packages/@uppy/dashboard/src/components/Dashboard.jsx rename to packages/@uppy/dashboard/src/components/Dashboard.tsx index 406d9fb475..18efed7ccd 100644 --- a/packages/@uppy/dashboard/src/components/Dashboard.jsx +++ b/packages/@uppy/dashboard/src/components/Dashboard.tsx @@ -1,14 +1,14 @@ import { h } from 'preact' import classNames from 'classnames' import isDragDropSupported from '@uppy/utils/lib/isDragDropSupported' -import FileList from './FileList.jsx' -import AddFiles from './AddFiles.jsx' -import AddFilesPanel from './AddFilesPanel.jsx' -import PickerPanelContent from './PickerPanelContent.jsx' -import EditorPanel from './EditorPanel.jsx' -import PanelTopBar from './PickerPanelTopBar.jsx' -import FileCard from './FileCard/index.jsx' -import Slide from './Slide.jsx' +import FileList from './FileList.tsx' +import AddFiles from './AddFiles.tsx' +import AddFilesPanel from './AddFilesPanel.tsx' +import PickerPanelContent from './PickerPanelContent.tsx' +import EditorPanel from './EditorPanel.tsx' +import PanelTopBar from './PickerPanelTopBar.tsx' +import FileCard from './FileCard/index.tsx' +import Slide from './Slide.tsx' // http://dev.edenspiekermann.com/2016/02/11/introducing-accessible-modal-dialog // https://github.com/ghosh/micromodal diff --git a/packages/@uppy/dashboard/src/components/EditorPanel.jsx b/packages/@uppy/dashboard/src/components/EditorPanel.tsx similarity index 100% rename from packages/@uppy/dashboard/src/components/EditorPanel.jsx rename to packages/@uppy/dashboard/src/components/EditorPanel.tsx diff --git a/packages/@uppy/dashboard/src/components/FileCard/RenderMetaFields.jsx b/packages/@uppy/dashboard/src/components/FileCard/RenderMetaFields.tsx similarity index 100% rename from packages/@uppy/dashboard/src/components/FileCard/RenderMetaFields.jsx rename to packages/@uppy/dashboard/src/components/FileCard/RenderMetaFields.tsx diff --git a/packages/@uppy/dashboard/src/components/FileCard/index.jsx b/packages/@uppy/dashboard/src/components/FileCard/index.tsx similarity index 95% rename from packages/@uppy/dashboard/src/components/FileCard/index.jsx rename to packages/@uppy/dashboard/src/components/FileCard/index.tsx index e334f50b41..9bb7848038 100644 --- a/packages/@uppy/dashboard/src/components/FileCard/index.jsx +++ b/packages/@uppy/dashboard/src/components/FileCard/index.tsx @@ -2,10 +2,10 @@ import { h } from 'preact' import { useEffect, useState, useCallback } from 'preact/hooks' import classNames from 'classnames' import { nanoid } from 'nanoid/non-secure' -import getFileTypeIcon from '../../utils/getFileTypeIcon.jsx' -import ignoreEvent from '../../utils/ignoreEvent.js' -import FilePreview from '../FilePreview.jsx' -import RenderMetaFields from './RenderMetaFields.jsx' +import getFileTypeIcon from '../../utils/getFileTypeIcon.tsx' +import ignoreEvent from '../../utils/ignoreEvent.ts' +import FilePreview from '../FilePreview.tsx' +import RenderMetaFields from './RenderMetaFields.tsx' export default function FileCard (props) { const { diff --git a/packages/@uppy/dashboard/src/components/FileItem/Buttons/index.jsx b/packages/@uppy/dashboard/src/components/FileItem/Buttons/index.tsx similarity index 98% rename from packages/@uppy/dashboard/src/components/FileItem/Buttons/index.jsx rename to packages/@uppy/dashboard/src/components/FileItem/Buttons/index.tsx index 0f23814d8e..4b954509b5 100644 --- a/packages/@uppy/dashboard/src/components/FileItem/Buttons/index.jsx +++ b/packages/@uppy/dashboard/src/components/FileItem/Buttons/index.tsx @@ -1,5 +1,5 @@ import { h } from 'preact' -import copyToClipboard from '../../../utils/copyToClipboard.js' +import copyToClipboard from '../../../utils/copyToClipboard.ts' function EditButton ({ file, diff --git a/packages/@uppy/dashboard/src/components/FileItem/FileInfo/index.jsx b/packages/@uppy/dashboard/src/components/FileItem/FileInfo/index.tsx similarity index 98% rename from packages/@uppy/dashboard/src/components/FileItem/FileInfo/index.jsx rename to packages/@uppy/dashboard/src/components/FileItem/FileInfo/index.tsx index 3d32b3c896..3e839a7c53 100644 --- a/packages/@uppy/dashboard/src/components/FileItem/FileInfo/index.jsx +++ b/packages/@uppy/dashboard/src/components/FileItem/FileInfo/index.tsx @@ -1,7 +1,7 @@ import { h, Fragment } from 'preact' import prettierBytes from '@transloadit/prettier-bytes' import truncateString from '@uppy/utils/lib/truncateString' -import MetaErrorMessage from '../MetaErrorMessage.jsx' +import MetaErrorMessage from '../MetaErrorMessage.tsx' const renderFileName = (props) => { const { author, name } = props.file.meta diff --git a/packages/@uppy/dashboard/src/components/FileItem/FilePreviewAndLink/index.jsx b/packages/@uppy/dashboard/src/components/FileItem/FilePreviewAndLink/index.tsx similarity index 85% rename from packages/@uppy/dashboard/src/components/FileItem/FilePreviewAndLink/index.jsx rename to packages/@uppy/dashboard/src/components/FileItem/FilePreviewAndLink/index.tsx index a8731a0456..4831131752 100644 --- a/packages/@uppy/dashboard/src/components/FileItem/FilePreviewAndLink/index.jsx +++ b/packages/@uppy/dashboard/src/components/FileItem/FilePreviewAndLink/index.tsx @@ -1,7 +1,7 @@ import { h } from 'preact' -import FilePreview from '../../FilePreview.jsx' -import MetaErrorMessage from '../MetaErrorMessage.jsx' -import getFileTypeIcon from '../../../utils/getFileTypeIcon.jsx' +import FilePreview from '../../FilePreview.tsx' +import MetaErrorMessage from '../MetaErrorMessage.tsx' +import getFileTypeIcon from '../../../utils/getFileTypeIcon.tsx' export default function FilePreviewAndLink (props) { const { file, i18n, toggleFileCard, metaFields, showLinkToFileUploadResult } = props diff --git a/packages/@uppy/dashboard/src/components/FileItem/FileProgress/index.jsx b/packages/@uppy/dashboard/src/components/FileItem/FileProgress/index.tsx similarity index 100% rename from packages/@uppy/dashboard/src/components/FileItem/FileProgress/index.jsx rename to packages/@uppy/dashboard/src/components/FileItem/FileProgress/index.tsx diff --git a/packages/@uppy/dashboard/src/components/FileItem/MetaErrorMessage.jsx b/packages/@uppy/dashboard/src/components/FileItem/MetaErrorMessage.tsx similarity index 100% rename from packages/@uppy/dashboard/src/components/FileItem/MetaErrorMessage.jsx rename to packages/@uppy/dashboard/src/components/FileItem/MetaErrorMessage.tsx diff --git a/packages/@uppy/dashboard/src/components/FileItem/index.jsx b/packages/@uppy/dashboard/src/components/FileItem/index.tsx similarity index 95% rename from packages/@uppy/dashboard/src/components/FileItem/index.jsx rename to packages/@uppy/dashboard/src/components/FileItem/index.tsx index 89ecaac6f8..5e6525cb07 100644 --- a/packages/@uppy/dashboard/src/components/FileItem/index.jsx +++ b/packages/@uppy/dashboard/src/components/FileItem/index.tsx @@ -1,10 +1,10 @@ import { h, Component } from 'preact' import classNames from 'classnames' import shallowEqual from 'is-shallow-equal' -import FilePreviewAndLink from './FilePreviewAndLink/index.jsx' -import FileProgress from './FileProgress/index.jsx' -import FileInfo from './FileInfo/index.jsx' -import Buttons from './Buttons/index.jsx' +import FilePreviewAndLink from './FilePreviewAndLink/index.tsx' +import FileProgress from './FileProgress/index.tsx' +import FileInfo from './FileInfo/index.tsx' +import Buttons from './Buttons/index.tsx' export default class FileItem extends Component { componentDidMount () { diff --git a/packages/@uppy/dashboard/src/components/FileList.jsx b/packages/@uppy/dashboard/src/components/FileList.tsx similarity index 98% rename from packages/@uppy/dashboard/src/components/FileList.jsx rename to packages/@uppy/dashboard/src/components/FileList.tsx index f8721f1c6c..b864d7d7d4 100644 --- a/packages/@uppy/dashboard/src/components/FileList.jsx +++ b/packages/@uppy/dashboard/src/components/FileList.tsx @@ -1,7 +1,7 @@ import { h } from 'preact' import { useMemo } from 'preact/hooks' import VirtualList from '@uppy/utils/lib/VirtualList' -import FileItem from './FileItem/index.jsx' +import FileItem from './FileItem/index.tsx' function chunks (list, size) { const chunked = [] diff --git a/packages/@uppy/dashboard/src/components/FilePreview.jsx b/packages/@uppy/dashboard/src/components/FilePreview.tsx similarity index 92% rename from packages/@uppy/dashboard/src/components/FilePreview.jsx rename to packages/@uppy/dashboard/src/components/FilePreview.tsx index aba76574c1..e3f5356551 100644 --- a/packages/@uppy/dashboard/src/components/FilePreview.jsx +++ b/packages/@uppy/dashboard/src/components/FilePreview.tsx @@ -1,5 +1,5 @@ import { h } from 'preact' -import getFileTypeIcon from '../utils/getFileTypeIcon.jsx' +import getFileTypeIcon from '../utils/getFileTypeIcon.tsx' export default function FilePreview (props) { const { file } = props diff --git a/packages/@uppy/dashboard/src/components/PickerPanelContent.jsx b/packages/@uppy/dashboard/src/components/PickerPanelContent.tsx similarity index 95% rename from packages/@uppy/dashboard/src/components/PickerPanelContent.jsx rename to packages/@uppy/dashboard/src/components/PickerPanelContent.tsx index 2bbd95fd23..947595ad78 100644 --- a/packages/@uppy/dashboard/src/components/PickerPanelContent.jsx +++ b/packages/@uppy/dashboard/src/components/PickerPanelContent.tsx @@ -1,6 +1,6 @@ import { h } from 'preact' import classNames from 'classnames' -import ignoreEvent from '../utils/ignoreEvent.js' +import ignoreEvent from '../utils/ignoreEvent.ts' function PickerPanelContent ({ activePickerPanel, className, hideAllPanels, i18n, state, uppy }) { return ( diff --git a/packages/@uppy/dashboard/src/components/PickerPanelTopBar.jsx b/packages/@uppy/dashboard/src/components/PickerPanelTopBar.tsx similarity index 100% rename from packages/@uppy/dashboard/src/components/PickerPanelTopBar.jsx rename to packages/@uppy/dashboard/src/components/PickerPanelTopBar.tsx diff --git a/packages/@uppy/dashboard/src/components/Slide.jsx b/packages/@uppy/dashboard/src/components/Slide.tsx similarity index 100% rename from packages/@uppy/dashboard/src/components/Slide.jsx rename to packages/@uppy/dashboard/src/components/Slide.tsx diff --git a/packages/@uppy/dashboard/src/index.js b/packages/@uppy/dashboard/src/index.js deleted file mode 100644 index 6c74a32596..0000000000 --- a/packages/@uppy/dashboard/src/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from './Dashboard.jsx' diff --git a/packages/@uppy/dashboard/src/index.test.js b/packages/@uppy/dashboard/src/index.test.ts similarity index 98% rename from packages/@uppy/dashboard/src/index.test.js rename to packages/@uppy/dashboard/src/index.test.ts index 862c3ab7db..c6da2daf7c 100644 --- a/packages/@uppy/dashboard/src/index.test.js +++ b/packages/@uppy/dashboard/src/index.test.ts @@ -7,7 +7,7 @@ import WebcamPlugin from '@uppy/webcam' import Url from '@uppy/url' import resizeObserverPolyfill from 'resize-observer-polyfill' -import DashboardPlugin from '../lib/index.js' +import DashboardPlugin from '../lib/index.ts' describe('Dashboard', () => { beforeAll(() => { diff --git a/packages/@uppy/dashboard/src/index.ts b/packages/@uppy/dashboard/src/index.ts new file mode 100644 index 0000000000..9355137dc9 --- /dev/null +++ b/packages/@uppy/dashboard/src/index.ts @@ -0,0 +1 @@ +export { default } from './Dashboard.tsx' diff --git a/packages/@uppy/dashboard/src/locale.js b/packages/@uppy/dashboard/src/locale.ts similarity index 100% rename from packages/@uppy/dashboard/src/locale.js rename to packages/@uppy/dashboard/src/locale.ts diff --git a/packages/@uppy/dashboard/src/utils/copyToClipboard.test.js b/packages/@uppy/dashboard/src/utils/copyToClipboard.test.ts similarity index 80% rename from packages/@uppy/dashboard/src/utils/copyToClipboard.test.js rename to packages/@uppy/dashboard/src/utils/copyToClipboard.test.ts index 328ee49588..df8e9d9a5e 100644 --- a/packages/@uppy/dashboard/src/utils/copyToClipboard.test.js +++ b/packages/@uppy/dashboard/src/utils/copyToClipboard.test.ts @@ -1,5 +1,5 @@ import { describe, it, expect } from 'vitest' -import copyToClipboard from './copyToClipboard.js' +import copyToClipboard from './copyToClipboard.ts' describe('copyToClipboard', () => { it.skip('should copy the specified text to the clipboard', () => { diff --git a/packages/@uppy/dashboard/src/utils/copyToClipboard.js b/packages/@uppy/dashboard/src/utils/copyToClipboard.ts similarity index 100% rename from packages/@uppy/dashboard/src/utils/copyToClipboard.js rename to packages/@uppy/dashboard/src/utils/copyToClipboard.ts diff --git a/packages/@uppy/dashboard/src/utils/createSuperFocus.test.js b/packages/@uppy/dashboard/src/utils/createSuperFocus.test.ts similarity index 86% rename from packages/@uppy/dashboard/src/utils/createSuperFocus.test.js rename to packages/@uppy/dashboard/src/utils/createSuperFocus.test.ts index f30f1bc22d..1230dbf471 100644 --- a/packages/@uppy/dashboard/src/utils/createSuperFocus.test.js +++ b/packages/@uppy/dashboard/src/utils/createSuperFocus.test.ts @@ -1,5 +1,5 @@ import { describe, it, expect } from 'vitest' -import createSuperFocus from './createSuperFocus.js' +import createSuperFocus from './createSuperFocus.ts' describe('createSuperFocus', () => { // superFocus.cancel() is used in dashboard diff --git a/packages/@uppy/dashboard/src/utils/createSuperFocus.js b/packages/@uppy/dashboard/src/utils/createSuperFocus.ts similarity index 97% rename from packages/@uppy/dashboard/src/utils/createSuperFocus.js rename to packages/@uppy/dashboard/src/utils/createSuperFocus.ts index 6c7d178134..a336147a81 100644 --- a/packages/@uppy/dashboard/src/utils/createSuperFocus.js +++ b/packages/@uppy/dashboard/src/utils/createSuperFocus.ts @@ -1,6 +1,6 @@ import debounce from 'lodash/debounce.js' import FOCUSABLE_ELEMENTS from '@uppy/utils/lib/FOCUSABLE_ELEMENTS' -import getActiveOverlayEl from './getActiveOverlayEl.js' +import getActiveOverlayEl from './getActiveOverlayEl.ts' /* Focuses on some element in the currently topmost overlay. diff --git a/packages/@uppy/dashboard/src/utils/getActiveOverlayEl.js b/packages/@uppy/dashboard/src/utils/getActiveOverlayEl.ts similarity index 100% rename from packages/@uppy/dashboard/src/utils/getActiveOverlayEl.js rename to packages/@uppy/dashboard/src/utils/getActiveOverlayEl.ts diff --git a/packages/@uppy/dashboard/src/utils/getFileTypeIcon.jsx b/packages/@uppy/dashboard/src/utils/getFileTypeIcon.tsx similarity index 100% rename from packages/@uppy/dashboard/src/utils/getFileTypeIcon.jsx rename to packages/@uppy/dashboard/src/utils/getFileTypeIcon.tsx diff --git a/packages/@uppy/dashboard/src/utils/ignoreEvent.js b/packages/@uppy/dashboard/src/utils/ignoreEvent.ts similarity index 100% rename from packages/@uppy/dashboard/src/utils/ignoreEvent.js rename to packages/@uppy/dashboard/src/utils/ignoreEvent.ts diff --git a/packages/@uppy/dashboard/src/utils/trapFocus.js b/packages/@uppy/dashboard/src/utils/trapFocus.ts similarity index 98% rename from packages/@uppy/dashboard/src/utils/trapFocus.js rename to packages/@uppy/dashboard/src/utils/trapFocus.ts index 66353c22cd..72fe00e33a 100644 --- a/packages/@uppy/dashboard/src/utils/trapFocus.js +++ b/packages/@uppy/dashboard/src/utils/trapFocus.ts @@ -1,6 +1,6 @@ import toArray from '@uppy/utils/lib/toArray' import FOCUSABLE_ELEMENTS from '@uppy/utils/lib/FOCUSABLE_ELEMENTS' -import getActiveOverlayEl from './getActiveOverlayEl.js' +import getActiveOverlayEl from './getActiveOverlayEl.ts' function focusOnFirstNode (event, nodes) { const node = nodes[0] diff --git a/packages/@uppy/dashboard/tsconfig.build.json b/packages/@uppy/dashboard/tsconfig.build.json new file mode 100644 index 0000000000..bd61fa8ed7 --- /dev/null +++ b/packages/@uppy/dashboard/tsconfig.build.json @@ -0,0 +1,98 @@ +{ + "extends": "../../../tsconfig.shared", + "compilerOptions": { + "noImplicitAny": false, + "outDir": "./lib", + "paths": { + "@uppy/informer": [ + "../informer/src/index.js" + ], + "@uppy/informer/lib/*": [ + "../informer/src/*" + ], + "@uppy/provider-views": [ + "../provider-views/src/index.js" + ], + "@uppy/provider-views/lib/*": [ + "../provider-views/src/*" + ], + "@uppy/status-bar": [ + "../status-bar/src/index.js" + ], + "@uppy/status-bar/lib/*": [ + "../status-bar/src/*" + ], + "@uppy/thumbnail-generator": [ + "../thumbnail-generator/src/index.js" + ], + "@uppy/thumbnail-generator/lib/*": [ + "../thumbnail-generator/src/*" + ], + "@uppy/utils/lib/*": [ + "../utils/src/*" + ], + "@uppy/core": [ + "../core/src/index.js" + ], + "@uppy/core/lib/*": [ + "../core/src/*" + ], + "@uppy/google-drive": [ + "../google-drive/src/index.js" + ], + "@uppy/google-drive/lib/*": [ + "../google-drive/src/*" + ], + "@uppy/url": [ + "../url/src/index.js" + ], + "@uppy/url/lib/*": [ + "../url/src/*" + ], + "@uppy/webcam": [ + "../webcam/src/index.js" + ], + "@uppy/webcam/lib/*": [ + "../webcam/src/*" + ] + }, + "resolveJsonModule": false, + "rootDir": "./src", + "skipLibCheck": true + }, + "include": [ + "./src/**/*.*" + ], + "exclude": [ + "./src/**/*.test.ts" + ], + "references": [ + { + "path": "../informer/tsconfig.build.json" + }, + { + "path": "../provider-views/tsconfig.build.json" + }, + { + "path": "../status-bar/tsconfig.build.json" + }, + { + "path": "../thumbnail-generator/tsconfig.build.json" + }, + { + "path": "../utils/tsconfig.build.json" + }, + { + "path": "../core/tsconfig.build.json" + }, + { + "path": "../google-drive/tsconfig.build.json" + }, + { + "path": "../url/tsconfig.build.json" + }, + { + "path": "../webcam/tsconfig.build.json" + } + ] +} diff --git a/packages/@uppy/dashboard/tsconfig.json b/packages/@uppy/dashboard/tsconfig.json new file mode 100644 index 0000000000..1e35f61656 --- /dev/null +++ b/packages/@uppy/dashboard/tsconfig.json @@ -0,0 +1,93 @@ +{ + "extends": "../../../tsconfig.shared", + "compilerOptions": { + "emitDeclarationOnly": false, + "noEmit": true, + "paths": { + "@uppy/informer": [ + "../informer/src/index.js" + ], + "@uppy/informer/lib/*": [ + "../informer/src/*" + ], + "@uppy/provider-views": [ + "../provider-views/src/index.js" + ], + "@uppy/provider-views/lib/*": [ + "../provider-views/src/*" + ], + "@uppy/status-bar": [ + "../status-bar/src/index.js" + ], + "@uppy/status-bar/lib/*": [ + "../status-bar/src/*" + ], + "@uppy/thumbnail-generator": [ + "../thumbnail-generator/src/index.js" + ], + "@uppy/thumbnail-generator/lib/*": [ + "../thumbnail-generator/src/*" + ], + "@uppy/utils/lib/*": [ + "../utils/src/*" + ], + "@uppy/core": [ + "../core/src/index.js" + ], + "@uppy/core/lib/*": [ + "../core/src/*" + ], + "@uppy/google-drive": [ + "../google-drive/src/index.js" + ], + "@uppy/google-drive/lib/*": [ + "../google-drive/src/*" + ], + "@uppy/url": [ + "../url/src/index.js" + ], + "@uppy/url/lib/*": [ + "../url/src/*" + ], + "@uppy/webcam": [ + "../webcam/src/index.js" + ], + "@uppy/webcam/lib/*": [ + "../webcam/src/*" + ] + } + }, + "include": [ + "./package.json", + "./src/**/*.*" + ], + "references": [ + { + "path": "../informer/tsconfig.build.json" + }, + { + "path": "../provider-views/tsconfig.build.json" + }, + { + "path": "../status-bar/tsconfig.build.json" + }, + { + "path": "../thumbnail-generator/tsconfig.build.json" + }, + { + "path": "../utils/tsconfig.build.json" + }, + { + "path": "../core/tsconfig.build.json" + }, + { + "path": "../google-drive/tsconfig.build.json" + }, + { + "path": "../url/tsconfig.build.json" + }, + { + "path": "../webcam/tsconfig.build.json" + } + ] +} From 6e72a6b745e10384b78166de0d7fc69799d20b20 Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Sun, 10 Mar 2024 15:30:46 +0100 Subject: [PATCH 02/24] TSFixMe --- packages/@uppy/dashboard/src/components/AddFiles.tsx | 2 ++ packages/@uppy/dashboard/src/components/AddFilesPanel.tsx | 2 ++ packages/@uppy/dashboard/src/components/EditorPanel.tsx | 2 ++ .../dashboard/src/components/FileCard/RenderMetaFields.tsx | 2 ++ packages/@uppy/dashboard/src/components/FileCard/index.tsx | 2 ++ .../@uppy/dashboard/src/components/FileItem/Buttons/index.tsx | 2 ++ .../@uppy/dashboard/src/components/FileItem/FileInfo/index.tsx | 2 ++ .../src/components/FileItem/FilePreviewAndLink/index.tsx | 2 ++ .../dashboard/src/components/FileItem/FileProgress/index.tsx | 2 ++ .../dashboard/src/components/FileItem/MetaErrorMessage.tsx | 2 ++ packages/@uppy/dashboard/src/components/FileItem/index.tsx | 2 ++ packages/@uppy/dashboard/src/components/FileList.tsx | 2 ++ packages/@uppy/dashboard/src/components/FilePreview.tsx | 2 ++ packages/@uppy/dashboard/src/components/PickerPanelContent.tsx | 2 ++ packages/@uppy/dashboard/src/components/PickerPanelTopBar.tsx | 2 ++ packages/@uppy/dashboard/src/components/Slide.tsx | 2 ++ 16 files changed, 32 insertions(+) diff --git a/packages/@uppy/dashboard/src/components/AddFiles.tsx b/packages/@uppy/dashboard/src/components/AddFiles.tsx index 994898cd7e..ab7b9924fc 100644 --- a/packages/@uppy/dashboard/src/components/AddFiles.tsx +++ b/packages/@uppy/dashboard/src/components/AddFiles.tsx @@ -1,5 +1,7 @@ import { h, Component, Fragment } from 'preact' +$TSFixMe + class AddFiles extends Component { private triggerFileInputClick = () => { this.fileInput.click() diff --git a/packages/@uppy/dashboard/src/components/AddFilesPanel.tsx b/packages/@uppy/dashboard/src/components/AddFilesPanel.tsx index 42f4af4905..5008c5ec3c 100644 --- a/packages/@uppy/dashboard/src/components/AddFilesPanel.tsx +++ b/packages/@uppy/dashboard/src/components/AddFilesPanel.tsx @@ -2,6 +2,8 @@ import { h } from 'preact' import classNames from 'classnames' import AddFiles from './AddFiles.tsx' +type $TSFixMe = any + const AddFilesPanel = (props) => { return (
{ const { author, name } = props.file.meta diff --git a/packages/@uppy/dashboard/src/components/FileItem/FilePreviewAndLink/index.tsx b/packages/@uppy/dashboard/src/components/FileItem/FilePreviewAndLink/index.tsx index 4831131752..104a813b04 100644 --- a/packages/@uppy/dashboard/src/components/FileItem/FilePreviewAndLink/index.tsx +++ b/packages/@uppy/dashboard/src/components/FileItem/FilePreviewAndLink/index.tsx @@ -3,6 +3,8 @@ import FilePreview from '../../FilePreview.tsx' import MetaErrorMessage from '../MetaErrorMessage.tsx' import getFileTypeIcon from '../../../utils/getFileTypeIcon.tsx' +type $TSFixMe = any + export default function FilePreviewAndLink (props) { const { file, i18n, toggleFileCard, metaFields, showLinkToFileUploadResult } = props const white = 'rgba(255, 255, 255, 0.5)' diff --git a/packages/@uppy/dashboard/src/components/FileItem/FileProgress/index.tsx b/packages/@uppy/dashboard/src/components/FileItem/FileProgress/index.tsx index 2bb3b6c8ba..7d0825caf0 100644 --- a/packages/@uppy/dashboard/src/components/FileItem/FileProgress/index.tsx +++ b/packages/@uppy/dashboard/src/components/FileItem/FileProgress/index.tsx @@ -1,5 +1,7 @@ import { h } from 'preact' +type $TSFixMe = any + function onPauseResumeCancelRetry (props) { if (props.isUploaded) return diff --git a/packages/@uppy/dashboard/src/components/FileItem/MetaErrorMessage.tsx b/packages/@uppy/dashboard/src/components/FileItem/MetaErrorMessage.tsx index 3fe13e7872..a02cb825d0 100644 --- a/packages/@uppy/dashboard/src/components/FileItem/MetaErrorMessage.tsx +++ b/packages/@uppy/dashboard/src/components/FileItem/MetaErrorMessage.tsx @@ -1,5 +1,7 @@ import { h } from 'preact' +type $TSFixMe = any + const metaFieldIdToName = (metaFieldId, metaFields) => { const fields = typeof metaFields === 'function' ? metaFields() : metaFields const field = fields.filter(f => f.id === metaFieldId) diff --git a/packages/@uppy/dashboard/src/components/FileItem/index.tsx b/packages/@uppy/dashboard/src/components/FileItem/index.tsx index 5e6525cb07..49a8c24b66 100644 --- a/packages/@uppy/dashboard/src/components/FileItem/index.tsx +++ b/packages/@uppy/dashboard/src/components/FileItem/index.tsx @@ -6,6 +6,8 @@ import FileProgress from './FileProgress/index.tsx' import FileInfo from './FileInfo/index.tsx' import Buttons from './Buttons/index.tsx' +type $TSFixMe = any + export default class FileItem extends Component { componentDidMount () { const { file } = this.props diff --git a/packages/@uppy/dashboard/src/components/FileList.tsx b/packages/@uppy/dashboard/src/components/FileList.tsx index b864d7d7d4..6338455f32 100644 --- a/packages/@uppy/dashboard/src/components/FileList.tsx +++ b/packages/@uppy/dashboard/src/components/FileList.tsx @@ -3,6 +3,8 @@ import { useMemo } from 'preact/hooks' import VirtualList from '@uppy/utils/lib/VirtualList' import FileItem from './FileItem/index.tsx' +type $TSFixMe = any + function chunks (list, size) { const chunked = [] let currentChunk = [] diff --git a/packages/@uppy/dashboard/src/components/FilePreview.tsx b/packages/@uppy/dashboard/src/components/FilePreview.tsx index e3f5356551..6e2e9d8a98 100644 --- a/packages/@uppy/dashboard/src/components/FilePreview.tsx +++ b/packages/@uppy/dashboard/src/components/FilePreview.tsx @@ -1,6 +1,8 @@ import { h } from 'preact' import getFileTypeIcon from '../utils/getFileTypeIcon.tsx' +type $TSFixMe = any + export default function FilePreview (props) { const { file } = props diff --git a/packages/@uppy/dashboard/src/components/PickerPanelContent.tsx b/packages/@uppy/dashboard/src/components/PickerPanelContent.tsx index 947595ad78..59bef8c56b 100644 --- a/packages/@uppy/dashboard/src/components/PickerPanelContent.tsx +++ b/packages/@uppy/dashboard/src/components/PickerPanelContent.tsx @@ -2,6 +2,8 @@ import { h } from 'preact' import classNames from 'classnames' import ignoreEvent from '../utils/ignoreEvent.ts' +type $TSFixMe = any + function PickerPanelContent ({ activePickerPanel, className, hideAllPanels, i18n, state, uppy }) { return (
Date: Sun, 10 Mar 2024 15:57:23 +0100 Subject: [PATCH 03/24] `TSFixMe` --- .../dashboard/src/components/AddFiles.tsx | 222 ++++++++++++++---- .../src/components/AddFilesPanel.tsx | 9 +- .../dashboard/src/components/EditorPanel.tsx | 19 +- .../components/FileCard/RenderMetaFields.tsx | 54 +++-- .../src/components/FileCard/index.tsx | 47 ++-- .../src/components/FileItem/Buttons/index.tsx | 81 +++++-- .../components/FileItem/FileInfo/index.tsx | 53 +++-- .../FileItem/FilePreviewAndLink/index.tsx | 35 ++- .../FileItem/FileProgress/index.tsx | 69 ++++-- .../components/FileItem/MetaErrorMessage.tsx | 21 +- .../src/components/FileItem/index.tsx | 32 ++- .../dashboard/src/components/FileList.tsx | 67 ++++-- .../dashboard/src/components/FilePreview.tsx | 17 +- .../src/components/PickerPanelContent.tsx | 17 +- .../src/components/PickerPanelTopBar.tsx | 75 ++++-- .../@uppy/dashboard/src/components/Slide.tsx | 21 +- .../dashboard/src/utils/copyToClipboard.ts | 8 +- .../dashboard/src/utils/createSuperFocus.ts | 10 +- .../dashboard/src/utils/getActiveOverlayEl.ts | 11 +- .../dashboard/src/utils/getFileTypeIcon.tsx | 133 +++++++++-- .../@uppy/dashboard/src/utils/ignoreEvent.ts | 7 +- .../@uppy/dashboard/src/utils/trapFocus.ts | 35 ++- 22 files changed, 733 insertions(+), 310 deletions(-) diff --git a/packages/@uppy/dashboard/src/components/AddFiles.tsx b/packages/@uppy/dashboard/src/components/AddFiles.tsx index ab7b9924fc..28e2253342 100644 --- a/packages/@uppy/dashboard/src/components/AddFiles.tsx +++ b/packages/@uppy/dashboard/src/components/AddFiles.tsx @@ -1,8 +1,17 @@ -import { h, Component, Fragment } from 'preact' +/* eslint-disable react/destructuring-assignment */ +import { h, Component, Fragment, type ComponentChild } from 'preact' -$TSFixMe +type $TSFixMe = any class AddFiles extends Component { + fileInput: $TSFixMe + + folderInput: $TSFixMe + + mobilePhotoFileInput: $TSFixMe + + mobileVideoFileInput: $TSFixMe + private triggerFileInputClick = () => { this.fileInput.click() } @@ -19,7 +28,7 @@ class AddFiles extends Component { this.mobilePhotoFileInput.click() } - private onFileInputChange = (event) => { + private onFileInputChange = (event: $TSFixMe) => { this.props.handleInputChange(event) // We clear the input after a file is selected, because otherwise @@ -31,7 +40,7 @@ class AddFiles extends Component { event.target.value = null // eslint-disable-line no-param-reassign } - renderHiddenInput = (isFolder, refCallback) => { + private renderHiddenInput = (isFolder: $TSFixMe, refCallback: $TSFixMe) => { return ( { + private renderHiddenCameraInput = ( + type: $TSFixMe, + nativeCameraFacingMode: $TSFixMe, + refCallback: $TSFixMe, + ) => { const typeToAccept = { photo: 'image/*', video: 'video/*' } const accept = typeToAccept[type] @@ -69,7 +82,7 @@ class AddFiles extends Component { ) } - renderMyDeviceAcquirer = () => { + private renderMyDeviceAcquirer = () => { return (
-
-
{this.props.i18n('myDevice')}
+
+ {this.props.i18n('myDevice')} +
) } - renderPhotoCamera = () => { + private renderPhotoCamera = () => { return (
-
-
{this.props.i18n('takePictureBtn')}
+
+ {this.props.i18n('takePictureBtn')} +
) } - renderVideoCamera = () => { + private renderVideoCamera = () => { return (
-
{this.props.i18n('recordVideoBtn')}
+
+ {this.props.i18n('recordVideoBtn')} +
) } - renderBrowseButton = (text, onClickFn) => { + private renderBrowseButton = (text: $TSFixMe, onClickFn: $TSFixMe) => { const numberOfAcquirers = this.props.acquirers.length return (
) } - renderAcquirers = (acquirers) => { + private renderAcquirers = (acquirers: $TSFixMe) => { // Group last two buttons, so we don’t end up with // just one button on a new line const acquirersWithoutLastTwo = [...acquirers] - const lastTwoAcquirers = acquirersWithoutLastTwo.splice(acquirers.length - 2, acquirers.length) + const lastTwoAcquirers = acquirersWithoutLastTwo.splice( + acquirers.length - 2, + acquirers.length, + ) return ( <> - {acquirersWithoutLastTwo.map((acquirer) => this.renderAcquirer(acquirer))} + {acquirersWithoutLastTwo.map((acquirer) => + this.renderAcquirer(acquirer), + )} {lastTwoAcquirers.map((acquirer) => this.renderAcquirer(acquirer))} @@ -236,17 +301,35 @@ class AddFiles extends Component { ) } - renderSourcesList = (acquirers, disableLocalFiles) => { - const { showNativePhotoCameraButton, showNativeVideoCameraButton } = this.props + private renderSourcesList = ( + acquirers: $TSFixMe, + disableLocalFiles: $TSFixMe, + ) => { + const { showNativePhotoCameraButton, showNativeVideoCameraButton } = + this.props let list = [] const myDeviceKey = 'myDevice' - if (!disableLocalFiles) list.push({ key: myDeviceKey, elements: this.renderMyDeviceAcquirer() }) - if (showNativePhotoCameraButton) list.push({ key: 'nativePhotoCameraButton', elements: this.renderPhotoCamera() }) - if (showNativeVideoCameraButton) list.push({ key: 'nativePhotoCameraButton', elements: this.renderVideoCamera() }) - list.push(...acquirers.map((acquirer) => ({ key: acquirer.id, elements: this.renderAcquirer(acquirer) }))) + if (!disableLocalFiles) + list.push({ key: myDeviceKey, elements: this.renderMyDeviceAcquirer() }) + if (showNativePhotoCameraButton) + list.push({ + key: 'nativePhotoCameraButton', + elements: this.renderPhotoCamera(), + }) + if (showNativeVideoCameraButton) + list.push({ + key: 'nativePhotoCameraButton', + elements: this.renderVideoCamera(), + }) + list.push( + ...acquirers.map((acquirer: $TSFixMe) => ({ + key: acquirer.id, + elements: this.renderAcquirer(acquirer), + })), + ) // doesn't make sense to show only a lonely "My Device" const hasOnlyMyDevice = list.length === 1 && list[0].key === myDeviceKey @@ -257,7 +340,10 @@ class AddFiles extends Component { const listWithoutLastTwo = [...list] const lastTwo = listWithoutLastTwo.splice(list.length - 2, list.length) - const renderList = (l) => l.map(({ key, elements }) => {elements}) + const renderList = (l: $TSFixMe) => + l.map(({ key, elements }: $TSFixMe) => ( + {elements} + )) return ( <> @@ -274,13 +360,23 @@ class AddFiles extends Component { ) } - renderPoweredByUppy () { + private renderPoweredByUppy() { const { i18nArray } = this.props const uppyBranding = ( - Uppy @@ -301,7 +397,7 @@ class AddFiles extends Component { ) } - render () { + render(): ComponentChild { const { showNativePhotoCameraButton, showNativeVideoCameraButton, @@ -310,14 +406,38 @@ class AddFiles extends Component { return (
- {this.renderHiddenInput(false, (ref) => { this.fileInput = ref })} - {this.renderHiddenInput(true, (ref) => { this.folderInput = ref })} - {showNativePhotoCameraButton && this.renderHiddenCameraInput('photo', nativeCameraFacingMode, (ref) => { this.mobilePhotoFileInput = ref })} - {showNativeVideoCameraButton && this.renderHiddenCameraInput('video', nativeCameraFacingMode, (ref) => { this.mobileVideoFileInput = ref })} - {this.renderSourcesList(this.props.acquirers, this.props.disableLocalFiles)} + {this.renderHiddenInput(false, (ref: $TSFixMe) => { + this.fileInput = ref + })} + {this.renderHiddenInput(true, (ref: $TSFixMe) => { + this.folderInput = ref + })} + {showNativePhotoCameraButton && + this.renderHiddenCameraInput( + 'photo', + nativeCameraFacingMode, + (ref: $TSFixMe) => { + this.mobilePhotoFileInput = ref + }, + )} + {showNativeVideoCameraButton && + this.renderHiddenCameraInput( + 'video', + nativeCameraFacingMode, + (ref: $TSFixMe) => { + this.mobileVideoFileInput = ref + }, + )} + {this.renderSourcesList( + this.props.acquirers, + this.props.disableLocalFiles, + )}
- {this.props.note &&
{this.props.note}
} - {this.props.proudlyDisplayPoweredByUppy && this.renderPoweredByUppy(this.props)} + {this.props.note && ( +
{this.props.note}
+ )} + {this.props.proudlyDisplayPoweredByUppy && + this.renderPoweredByUppy(this.props)}
) diff --git a/packages/@uppy/dashboard/src/components/AddFilesPanel.tsx b/packages/@uppy/dashboard/src/components/AddFilesPanel.tsx index 5008c5ec3c..f0faea74af 100644 --- a/packages/@uppy/dashboard/src/components/AddFilesPanel.tsx +++ b/packages/@uppy/dashboard/src/components/AddFilesPanel.tsx @@ -1,10 +1,11 @@ +/* eslint-disable react/destructuring-assignment */ import { h } from 'preact' import classNames from 'classnames' import AddFiles from './AddFiles.tsx' type $TSFixMe = any -const AddFilesPanel = (props) => { +const AddFilesPanel = (props: $TSFixMe): $TSFixMe => { return (
{ aria-hidden={!props.showAddFilesPanel} >
-
+
{props.i18n('addingMoreFiles')}
- {props.editors.map((target) => { + {props.editors.map((target: $TSFixMe) => { return props.uppy.getPlugin(target.id).render(props.state) })}
diff --git a/packages/@uppy/dashboard/src/components/FileCard/RenderMetaFields.tsx b/packages/@uppy/dashboard/src/components/FileCard/RenderMetaFields.tsx index 877e4f2d6b..e64447d167 100644 --- a/packages/@uppy/dashboard/src/components/FileCard/RenderMetaFields.tsx +++ b/packages/@uppy/dashboard/src/components/FileCard/RenderMetaFields.tsx @@ -1,8 +1,8 @@ -import { h } from 'preact' +import { h, type ComponentChild } from 'preact' type $TSFixMe = any -export default function RenderMetaFields (props) { +export default function RenderMetaFields(props: $TSFixMe): ComponentChild { const { computedMetaFields, requiredMetaFields, @@ -15,33 +15,37 @@ export default function RenderMetaFields (props) { text: 'uppy-u-reset uppy-c-textInput uppy-Dashboard-FileCard-input', } - return computedMetaFields.map((field) => { + return computedMetaFields.map((field: $TSFixMe) => { const id = `uppy-Dashboard-FileCard-input-${field.id}` const required = requiredMetaFields.includes(field.id) return (
- - {field.render !== undefined - ? field.render({ - value: formState[field.id], - onChange: (newVal) => updateMeta(newVal, field.id), - fieldCSSClasses, - required, - form: form.id, - }, h) - : ( - updateMeta(ev.target.value, field.id)} - data-uppy-super-focusable - /> - )} + + {field.render !== undefined ? + field.render( + { + value: formState[field.id], + onChange: (newVal: $TSFixMe) => updateMeta(newVal, field.id), + fieldCSSClasses, + required, + form: form.id, + }, + h, + ) + : updateMeta(ev.target.value, field.id)} + data-uppy-super-focusable + /> + }
) }) diff --git a/packages/@uppy/dashboard/src/components/FileCard/index.tsx b/packages/@uppy/dashboard/src/components/FileCard/index.tsx index 24e2c09cda..6cfbf5f606 100644 --- a/packages/@uppy/dashboard/src/components/FileCard/index.tsx +++ b/packages/@uppy/dashboard/src/components/FileCard/index.tsx @@ -1,4 +1,4 @@ -import { h } from 'preact' +import { h, type ComponentChild } from 'preact' import { useEffect, useState, useCallback } from 'preact/hooks' import classNames from 'classnames' import { nanoid } from 'nanoid/non-secure' @@ -9,7 +9,7 @@ import RenderMetaFields from './RenderMetaFields.tsx' type $TSFixMe = any -export default function FileCard (props) { +export default function FileCard(props: $TSFixMe): ComponentChild { const { files, fileCardFor, @@ -25,8 +25,8 @@ export default function FileCard (props) { } = props const getMetaFields = () => { - return typeof metaFields === 'function' - ? metaFields(files[fileCardFor]) + return typeof metaFields === 'function' ? + metaFields(files[fileCardFor]) : metaFields } @@ -35,18 +35,21 @@ export default function FileCard (props) { const showEditButton = canEditFile(file) const storedMetaData = {} - computedMetaFields.forEach((field) => { + computedMetaFields.forEach((field: $TSFixMe) => { storedMetaData[field.id] = file.meta[field.id] ?? '' }) const [formState, setFormState] = useState(storedMetaData) - const handleSave = useCallback((ev) => { - ev.preventDefault() - saveFileCard(formState, fileCardFor) - }, [saveFileCard, formState, fileCardFor]) + const handleSave = useCallback( + (ev: $TSFixMe) => { + ev.preventDefault() + saveFileCard(formState, fileCardFor) + }, + [saveFileCard, formState, fileCardFor], + ) - const updateMeta = (newVal, name) => { + const updateMeta = (newVal: $TSFixMe, name: $TSFixMe) => { setFormState({ ...formState, [name]: newVal, @@ -83,9 +86,17 @@ export default function FileCard (props) { onPaste={ignoreEvent} >
-
+
{i18nArray('editing', { - file: {file.meta ? file.meta.name : file.name}, + file: ( + + {file.meta ? file.meta.name : file.name} + + ), })}
- )} + )}
diff --git a/packages/@uppy/dashboard/src/components/FileItem/Buttons/index.tsx b/packages/@uppy/dashboard/src/components/FileItem/Buttons/index.tsx index ebd1f91599..8d6f288e6c 100644 --- a/packages/@uppy/dashboard/src/components/FileItem/Buttons/index.tsx +++ b/packages/@uppy/dashboard/src/components/FileItem/Buttons/index.tsx @@ -1,19 +1,19 @@ -import { h } from 'preact' +import { h, type ComponentChild } from 'preact' import copyToClipboard from '../../../utils/copyToClipboard.ts' type $TSFixMe = any -function EditButton ({ +function EditButton({ file, uploadInProgressOrComplete, metaFields, canEditFile, i18n, onClick, -}) { +}: $TSFixMe) { if ( - (!uploadInProgressOrComplete && metaFields && metaFields.length > 0) - || (!uploadInProgressOrComplete && canEditFile(file)) + (!uploadInProgressOrComplete && metaFields && metaFields.length > 0) || + (!uploadInProgressOrComplete && canEditFile(file)) ) { return ( @@ -36,7 +49,7 @@ function EditButton ({ return null } -function RemoveButton ({ i18n, onClick, file }) { +function RemoveButton({ i18n, onClick, file }: $TSFixMe) { return ( ) } -const copyLinkToClipboard = (event, props) => { - copyToClipboard(props.file.uploadURL, props.i18n('copyLinkToClipboardFallback')) +const copyLinkToClipboard = (event: $TSFixMe, props: $TSFixMe) => { + copyToClipboard( + props.file.uploadURL, + props.i18n('copyLinkToClipboardFallback'), + ) .then(() => { props.uppy.log('Link copied to clipboard.') props.uppy.info(props.i18n('copyLinkToClipboardSuccess'), 'info', 3000) @@ -64,7 +90,7 @@ const copyLinkToClipboard = (event, props) => { .then(() => event.target.focus({ preventScroll: true })) } -function CopyLinkButton (props) { +function CopyLinkButton(props: $TSFixMe) { const { i18n } = props return ( @@ -75,14 +101,21 @@ function CopyLinkButton (props) { title={i18n('copyLink')} onClick={(event) => copyLinkToClipboard(event, props)} > -
) } diff --git a/packages/@uppy/dashboard/src/components/FileItem/FileInfo/index.tsx b/packages/@uppy/dashboard/src/components/FileItem/FileInfo/index.tsx index 89634bde18..f721b59572 100644 --- a/packages/@uppy/dashboard/src/components/FileItem/FileInfo/index.tsx +++ b/packages/@uppy/dashboard/src/components/FileItem/FileInfo/index.tsx @@ -1,14 +1,15 @@ -import { h, Fragment } from 'preact' +/* eslint-disable react/destructuring-assignment */ +import { h, Fragment, type ComponentChild } from 'preact' import prettierBytes from '@transloadit/prettier-bytes' import truncateString from '@uppy/utils/lib/truncateString' import MetaErrorMessage from '../MetaErrorMessage.tsx' type $TSFixMe = any -const renderFileName = (props) => { +const renderFileName = (props: $TSFixMe) => { const { author, name } = props.file.meta - function getMaxNameLength () { + function getMaxNameLength() { if (props.isSingleFile && props.containerHeight >= 350) { return 90 } @@ -31,7 +32,7 @@ const renderFileName = (props) => { ) } -const renderAuthor = (props) => { +const renderAuthor = (props: $TSFixMe) => { const { author } = props.file.meta const providerName = props.file.remote?.providerName const dot = `\u00B7` @@ -49,37 +50,39 @@ const renderAuthor = (props) => { > {truncateString(author.name, 13)} - {providerName ? ( + {providerName ? <> {` ${dot} `} {providerName} {` ${dot} `} - ) : null} + : null}
) } -const renderFileSize = (props) => props.file.size && ( -
- {prettierBytes(props.file.size)} -
-) +const renderFileSize = (props: $TSFixMe) => + props.file.size && ( +
+ {prettierBytes(props.file.size)} +
+ ) -const ReSelectButton = (props) => props.file.isGhost && ( - - {' \u2022 '} - - -) +const ReSelectButton = (props: $TSFixMe) => + props.file.isGhost && ( + + {' \u2022 '} + + + ) -const ErrorButton = ({ file, onClick }) => { +const ErrorButton = ({ file, onClick }: $TSFixMe) => { if (file.error) { return (
@@ -127,7 +133,14 @@ export default function FileProgress (props) { return ( // eslint-disable-next-line react/jsx-props-no-spreading -
{i18n('missingRequiredMetaFields', { smart_count: missingRequiredMetaFields.length, fields: metaFieldsString, - })} - {' '} + })}{' '} - ) : ( -
- )} + :
} -
+
{/* eslint-disable-next-line react/jsx-props-no-spreading */}
- {allowNewUpload ? ( + {allowNewUpload ? - ) : ( -
- )} + :
}
) } diff --git a/packages/@uppy/dashboard/src/components/Slide.tsx b/packages/@uppy/dashboard/src/components/Slide.tsx index 410d9f726e..3ffd2474b7 100644 --- a/packages/@uppy/dashboard/src/components/Slide.tsx +++ b/packages/@uppy/dashboard/src/components/Slide.tsx @@ -1,4 +1,9 @@ -import { cloneElement, Component, toChildArray } from 'preact' +import { + cloneElement, + Component, + toChildArray, + type ComponentChild, +} from 'preact' import classNames from 'classnames' type $TSFixMe = any @@ -16,7 +21,15 @@ const duration = 250 * transition by setting the CSS name and duration as props. */ class Slide extends Component { - constructor (props) { + animationFrame: $TSFixMe + + enterTimeout: $TSFixMe + + leaveTimeout: $TSFixMe + + setState: $TSFixMe + + constructor(props: $TSFixMe) { super(props) this.state = { @@ -27,7 +40,7 @@ class Slide extends Component { // TODO: refactor to stable lifecycle method // eslint-disable-next-line - componentWillUpdate (nextProps) { + componentWillUpdate(nextProps: $TSFixMe) { const { cachedChildren } = this.state const child = toChildArray(nextProps.children)[0] @@ -85,7 +98,7 @@ class Slide extends Component { this.setState(patch) } - render () { + render(): ComponentChild { const { cachedChildren, className } = this.state if (!cachedChildren) { diff --git a/packages/@uppy/dashboard/src/utils/copyToClipboard.ts b/packages/@uppy/dashboard/src/utils/copyToClipboard.ts index 6f738730bc..b0ec7a98aa 100644 --- a/packages/@uppy/dashboard/src/utils/copyToClipboard.ts +++ b/packages/@uppy/dashboard/src/utils/copyToClipboard.ts @@ -8,7 +8,13 @@ * @param {string} fallbackString * @returns {Promise} */ -export default function copyToClipboard (textToCopy, fallbackString = 'Copy the URL below') { + +type $TSFixMe = any + +export default function copyToClipboard( + textToCopy: $TSFixMe, + fallbackString = 'Copy the URL below', +): $TSFixMe { return new Promise((resolve) => { const textArea = document.createElement('textarea') textArea.setAttribute('style', { diff --git a/packages/@uppy/dashboard/src/utils/createSuperFocus.ts b/packages/@uppy/dashboard/src/utils/createSuperFocus.ts index a336147a81..4acd1a8b3f 100644 --- a/packages/@uppy/dashboard/src/utils/createSuperFocus.ts +++ b/packages/@uppy/dashboard/src/utils/createSuperFocus.ts @@ -2,6 +2,8 @@ import debounce from 'lodash/debounce.js' import FOCUSABLE_ELEMENTS from '@uppy/utils/lib/FOCUSABLE_ELEMENTS' import getActiveOverlayEl from './getActiveOverlayEl.ts' +type $TSFixMe = any + /* Focuses on some element in the currently topmost overlay. @@ -12,10 +14,10 @@ import getActiveOverlayEl from './getActiveOverlayEl.ts' 2. If there are no [data-uppy-super-focusable] elements yet (or ever) - focuses on the first focusable element, but switches focus if superfocusable elements appear on next render. */ -export default function createSuperFocus () { +export default function createSuperFocus(): $TSFixMe { let lastFocusWasOnSuperFocusableEl = false - const superFocus = (dashboardEl, activeOverlayType) => { + const superFocus = (dashboardEl: $TSFixMe, activeOverlayType: $TSFixMe) => { const overlayEl = getActiveOverlayEl(dashboardEl, activeOverlayType) const isFocusInOverlay = overlayEl.contains(document.activeElement) @@ -24,7 +26,9 @@ export default function createSuperFocus () { // [Practical check] without this line, typing in the search input in googledrive overlay won't work. if (isFocusInOverlay && lastFocusWasOnSuperFocusableEl) return - const superFocusableEl = overlayEl.querySelector('[data-uppy-super-focusable]') + const superFocusableEl = overlayEl.querySelector( + '[data-uppy-super-focusable]', + ) // If we are already in the topmost overlay, AND there are no super focusable elements yet, - leave focus up to the user. // [Practical check] without this line, if you are in an empty folder in google drive, and something's uploading in the // bg, - focus will be jumping to Done all the time. diff --git a/packages/@uppy/dashboard/src/utils/getActiveOverlayEl.ts b/packages/@uppy/dashboard/src/utils/getActiveOverlayEl.ts index 7a73ee5b25..2adc29b95d 100644 --- a/packages/@uppy/dashboard/src/utils/getActiveOverlayEl.ts +++ b/packages/@uppy/dashboard/src/utils/getActiveOverlayEl.ts @@ -1,9 +1,16 @@ +type $TSFixMe = any + /** * @returns {HTMLElement} - either dashboard element, or the overlay that's most on top */ -export default function getActiveOverlayEl (dashboardEl, activeOverlayType) { +export default function getActiveOverlayEl( + dashboardEl: $TSFixMe, + activeOverlayType: $TSFixMe, +): $TSFixMe { if (activeOverlayType) { - const overlayEl = dashboardEl.querySelector(`[data-uppy-paneltype="${activeOverlayType}"]`) + const overlayEl = dashboardEl.querySelector( + `[data-uppy-paneltype="${activeOverlayType}"]`, + ) // if an overlay is already mounted if (overlayEl) return overlayEl } diff --git a/packages/@uppy/dashboard/src/utils/getFileTypeIcon.tsx b/packages/@uppy/dashboard/src/utils/getFileTypeIcon.tsx index ad5a9445c1..51ddd39d4c 100644 --- a/packages/@uppy/dashboard/src/utils/getFileTypeIcon.tsx +++ b/packages/@uppy/dashboard/src/utils/getFileTypeIcon.tsx @@ -1,52 +1,116 @@ import { h } from 'preact' -function iconImage () { +type $TSFixMe = any + +function iconImage() { return ( -