@uppy/status-bar
Advanced tools
Comparing version 3.1.2 to 3.2.0
# @uppy/status-bar | ||
## 3.2.0 | ||
Released: 2023-06-19 | ||
Included in: Uppy v3.10.0 | ||
- @uppy/companion,@uppy/core,@uppy/dashboard,@uppy/golden-retriever,@uppy/status-bar,@uppy/utils: Migrate all lodash' per-method-packages usage to lodash. (LinusMain / #4274) | ||
- @uppy/status-bar: Filtered ETA (stduhpf / #4458) | ||
## 3.0.1 | ||
@@ -4,0 +12,0 @@ |
@@ -5,3 +5,2 @@ export default function calculateProcessingProgress(files) { | ||
let message; | ||
for (const { | ||
@@ -13,5 +12,5 @@ progress | ||
postprocess | ||
} = progress; // In the future we should probably do this differently. For now we'll take the | ||
} = progress; | ||
// In the future we should probably do this differently. For now we'll take the | ||
// mode and message from the first file… | ||
if (message == null && (preprocess || postprocess)) { | ||
@@ -23,7 +22,5 @@ ({ | ||
} | ||
if ((preprocess == null ? void 0 : preprocess.mode) === 'determinate') values.push(preprocess.value); | ||
if ((postprocess == null ? void 0 : postprocess.mode) === 'determinate') values.push(postprocess.value); | ||
} | ||
const value = values.reduce((total, progressValue) => { | ||
@@ -30,0 +27,0 @@ return total + progressValue / values.length; |
import { h } from 'preact'; | ||
import classNames from 'classnames'; | ||
import throttle from 'lodash.throttle'; | ||
import throttle from 'lodash/throttle.js'; | ||
import prettierBytes from '@transloadit/prettier-bytes'; | ||
@@ -8,5 +8,3 @@ import prettyETA from '@uppy/utils/lib/prettyETA'; | ||
const DOT = `\u00B7`; | ||
const renderDot = () => ` ${DOT} `; | ||
function UploadBtn(props) { | ||
@@ -43,3 +41,2 @@ const { | ||
} | ||
function RetryBtn(props) { | ||
@@ -54,5 +51,3 @@ const { | ||
"aria-label": i18n('retryUpload'), | ||
onClick: () => uppy.retryAll().catch(() => { | ||
/* Error reported and handled via an event */ | ||
}), | ||
onClick: () => uppy.retryAll().catch(() => {/* Error reported and handled via an event */}), | ||
"data-uppy-super-focusable": true | ||
@@ -70,3 +65,2 @@ }, h("svg", { | ||
} | ||
function CancelBtn(props) { | ||
@@ -105,3 +99,2 @@ const { | ||
} | ||
function PauseResumeButton(props) { | ||
@@ -116,17 +109,12 @@ const { | ||
const title = isAllPaused ? i18n('resume') : i18n('pause'); | ||
function togglePauseResume() { | ||
if (isAllComplete) return null; | ||
if (!resumableUploads) { | ||
return uppy.cancelAll(); | ||
} | ||
if (isAllPaused) { | ||
return uppy.resumeAll(); | ||
} | ||
return uppy.pauseAll(); | ||
} | ||
return h("button", { | ||
@@ -159,3 +147,2 @@ title: title, | ||
} | ||
function DoneBtn(props) { | ||
@@ -173,3 +160,2 @@ const { | ||
} | ||
function LoadingSpinner() { | ||
@@ -187,3 +173,2 @@ return h("svg", { | ||
} | ||
function ProgressBarProcessing(props) { | ||
@@ -204,3 +189,2 @@ const { | ||
} | ||
function ProgressDetails(props) { | ||
@@ -230,3 +214,2 @@ const { | ||
} | ||
function FileUploadCount(props) { | ||
@@ -245,3 +228,2 @@ const { | ||
} | ||
function UploadNewlyAddedFiles(props) { | ||
@@ -269,3 +251,2 @@ const { | ||
} | ||
const ThrottledProgressDetails = throttle(ProgressDetails, 500, { | ||
@@ -275,3 +256,2 @@ leading: true, | ||
}); | ||
function ProgressBarUploading(props) { | ||
@@ -295,9 +275,6 @@ const { | ||
const showUploadNewlyAddedFiles = newFiles && isUploadStarted; | ||
if (!isUploadStarted || isAllComplete) { | ||
return null; | ||
} | ||
const title = isAllPaused ? i18n('paused') : i18n('uploading'); | ||
function renderProgressDetails() { | ||
@@ -315,3 +292,2 @@ if (!isAllPaused && !showUploadNewlyAddedFiles && showProgressDetails) { | ||
} | ||
return h(FileUploadCount, { | ||
@@ -323,6 +299,4 @@ i18n: i18n, | ||
} | ||
return null; | ||
} | ||
return h("div", { | ||
@@ -342,3 +316,2 @@ className: "uppy-StatusBar-content", | ||
} | ||
function ProgressBarComplete(props) { | ||
@@ -367,3 +340,2 @@ const { | ||
} | ||
function ProgressBarError(props) { | ||
@@ -376,6 +348,5 @@ const { | ||
} = props; | ||
function displayErrorAlert() { | ||
const errorMessage = `${i18n('uploadFailed')} \n\n ${error}`; // eslint-disable-next-line no-alert | ||
const errorMessage = `${i18n('uploadFailed')} \n\n ${error}`; | ||
// eslint-disable-next-line no-alert | ||
alert(errorMessage); // TODO: move to custom alert implementation | ||
@@ -413,3 +384,2 @@ } | ||
} | ||
export { UploadBtn, RetryBtn, CancelBtn, PauseResumeButton, DoneBtn, LoadingSpinner, ProgressDetails, ProgressBarProcessing, ProgressBarError, ProgressBarUploading, ProgressBarComplete }; |
@@ -0,4 +1,6 @@ | ||
function _classPrivateFieldLooseBase(receiver, privateKey) { if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) { throw new TypeError("attempted to use private field on non-instance"); } return receiver; } | ||
var id = 0; | ||
function _classPrivateFieldLooseKey(name) { return "__private_" + id++ + "_" + name; } | ||
import { UIPlugin } from '@uppy/core'; | ||
import getSpeed from '@uppy/utils/lib/getSpeed'; | ||
import getBytesRemaining from '@uppy/utils/lib/getBytesRemaining'; | ||
import emaFilter from '@uppy/utils/lib/emaFilter'; | ||
import getTextDirection from '@uppy/utils/lib/getTextDirection'; | ||
@@ -8,27 +10,7 @@ import statusBarStates from './StatusBarStates.js'; | ||
const packageJson = { | ||
"version": "3.1.2" | ||
"version": "3.2.0" | ||
}; | ||
import locale from './locale.js'; | ||
function getTotalSpeed(files) { | ||
let totalSpeed = 0; | ||
files.forEach(file => { | ||
totalSpeed += getSpeed(file.progress); | ||
}); | ||
return totalSpeed; | ||
} | ||
function getTotalETA(files) { | ||
const totalSpeed = getTotalSpeed(files); | ||
if (totalSpeed === 0) { | ||
return 0; | ||
} | ||
const totalBytesRemaining = files.reduce((total, file) => { | ||
return total + getBytesRemaining(file.progress); | ||
}, 0); | ||
return Math.round(totalBytesRemaining / totalSpeed * 10) / 10; | ||
} | ||
const speedFilterHalfLife = 2000; | ||
const ETAFilterHalfLife = 2000; | ||
function getUploadingState(error, isAllComplete, recoveredState, files) { | ||
@@ -38,31 +20,25 @@ if (error) { | ||
} | ||
if (isAllComplete) { | ||
return statusBarStates.STATE_COMPLETE; | ||
} | ||
if (recoveredState) { | ||
return statusBarStates.STATE_WAITING; | ||
} | ||
let state = statusBarStates.STATE_WAITING; | ||
const fileIDs = Object.keys(files); | ||
for (let i = 0; i < fileIDs.length; i++) { | ||
const { | ||
progress | ||
} = files[fileIDs[i]]; // If ANY files are being uploaded right now, show the uploading state. | ||
} = files[fileIDs[i]]; | ||
// If ANY files are being uploaded right now, show the uploading state. | ||
if (progress.uploadStarted && !progress.uploadComplete) { | ||
return statusBarStates.STATE_UPLOADING; | ||
} // If files are being preprocessed AND postprocessed at this time, we show the | ||
} | ||
// If files are being preprocessed AND postprocessed at this time, we show the | ||
// preprocess state. If any files are being uploaded we show uploading. | ||
if (progress.preprocess && state !== statusBarStates.STATE_UPLOADING) { | ||
state = statusBarStates.STATE_PREPROCESSING; | ||
} // If NO files are being preprocessed or uploaded right now, but some files are | ||
} | ||
// If NO files are being preprocessed or uploaded right now, but some files are | ||
// being postprocessed, show the postprocess state. | ||
if (progress.postprocess && state !== statusBarStates.STATE_UPLOADING && state !== statusBarStates.STATE_PREPROCESSING) { | ||
@@ -72,5 +48,5 @@ state = statusBarStates.STATE_POSTPROCESSING; | ||
} | ||
return state; | ||
} | ||
/** | ||
@@ -80,8 +56,29 @@ * StatusBar: renders a status bar with upload/pause/resume/cancel/retry buttons, | ||
*/ | ||
var _lastUpdateTime = /*#__PURE__*/_classPrivateFieldLooseKey("lastUpdateTime"); | ||
var _previousUploadedBytes = /*#__PURE__*/_classPrivateFieldLooseKey("previousUploadedBytes"); | ||
var _previousSpeed = /*#__PURE__*/_classPrivateFieldLooseKey("previousSpeed"); | ||
var _previousETA = /*#__PURE__*/_classPrivateFieldLooseKey("previousETA"); | ||
var _computeSmoothETA = /*#__PURE__*/_classPrivateFieldLooseKey("computeSmoothETA"); | ||
export default class StatusBar extends UIPlugin { | ||
constructor(uppy, opts) { | ||
super(uppy, opts); | ||
Object.defineProperty(this, _computeSmoothETA, { | ||
value: _computeSmoothETA2 | ||
}); | ||
Object.defineProperty(this, _lastUpdateTime, { | ||
writable: true, | ||
value: void 0 | ||
}); | ||
Object.defineProperty(this, _previousUploadedBytes, { | ||
writable: true, | ||
value: void 0 | ||
}); | ||
Object.defineProperty(this, _previousSpeed, { | ||
writable: true, | ||
value: void 0 | ||
}); | ||
Object.defineProperty(this, _previousETA, { | ||
writable: true, | ||
value: void 0 | ||
}); | ||
this.startUpload = () => { | ||
@@ -91,3 +88,2 @@ const { | ||
} = this.uppy.getState(); | ||
if (recoveredState) { | ||
@@ -97,12 +93,16 @@ this.uppy.emit('restore-confirmed'); | ||
} | ||
return this.uppy.upload().catch(() => {// Error logged in Core | ||
_classPrivateFieldLooseBase(this, _lastUpdateTime)[_lastUpdateTime] = performance.now(); | ||
_classPrivateFieldLooseBase(this, _previousUploadedBytes)[_previousUploadedBytes] = 0; | ||
_classPrivateFieldLooseBase(this, _previousSpeed)[_previousSpeed] = null; | ||
_classPrivateFieldLooseBase(this, _previousETA)[_previousETA] = null; | ||
return this.uppy.upload().catch(() => { | ||
// Error logged in Core | ||
}); | ||
}; | ||
this.id = this.opts.id || 'StatusBar'; | ||
this.title = 'StatusBar'; | ||
this.type = 'progressindicator'; | ||
this.defaultLocale = locale; // set default options, must be kept in sync with @uppy/react/src/StatusBar.js | ||
this.defaultLocale = locale; | ||
// set default options, must be kept in sync with @uppy/react/src/StatusBar.js | ||
const defaultOptions = { | ||
@@ -118,3 +118,4 @@ target: 'body', | ||
}; | ||
this.opts = { ...defaultOptions, | ||
this.opts = { | ||
...defaultOptions, | ||
...opts | ||
@@ -126,3 +127,2 @@ }; | ||
} | ||
render(state) { | ||
@@ -141,3 +141,2 @@ const { | ||
completeFiles, | ||
inProgressNotPausedFiles, | ||
isUploadStarted, | ||
@@ -149,8 +148,8 @@ isAllComplete, | ||
isSomeGhost | ||
} = this.uppy.getObjectOfFilesPerState(); // If some state was recovered, we want to show Upload button/counter | ||
} = this.uppy.getObjectOfFilesPerState(); | ||
// If some state was recovered, we want to show Upload button/counter | ||
// for all the files, because in this case it’s not an Upload button, | ||
// but “Confirm Restore Button” | ||
const newFilesOrRecovered = recoveredState ? Object.values(files) : newFiles; | ||
const totalETA = getTotalETA(inProgressNotPausedFiles); | ||
const resumableUploads = !!capabilities.resumableUploads; | ||
@@ -164,2 +163,7 @@ const supportsUploadProgress = capabilities.uploadProgress !== false; | ||
}); | ||
const totalETA = _classPrivateFieldLooseBase(this, _computeSmoothETA)[_computeSmoothETA]({ | ||
uploaded: totalUploadedSize, | ||
total: totalSize, | ||
remaining: totalSize - totalUploadedSize | ||
}); | ||
return StatusBarUI({ | ||
@@ -199,3 +203,2 @@ error, | ||
} | ||
onMount() { | ||
@@ -205,3 +208,2 @@ // Set the text direction if the page has not defined one. | ||
const direction = getTextDirection(element); | ||
if (!direction) { | ||
@@ -211,3 +213,2 @@ element.dir = 'ltr'; | ||
} | ||
install() { | ||
@@ -217,3 +218,2 @@ const { | ||
} = this.opts; | ||
if (target) { | ||
@@ -223,8 +223,34 @@ this.mount(target, this); | ||
} | ||
uninstall() { | ||
this.unmount(); | ||
} | ||
} | ||
function _computeSmoothETA2(totalBytes) { | ||
if (totalBytes.total === 0 || totalBytes.remaining === 0) { | ||
return 0; | ||
} | ||
const dt = performance.now() - _classPrivateFieldLooseBase(this, _lastUpdateTime)[_lastUpdateTime]; | ||
if (dt === 0) { | ||
var _classPrivateFieldLoo; | ||
return Math.round(((_classPrivateFieldLoo = _classPrivateFieldLooseBase(this, _previousETA)[_previousETA]) != null ? _classPrivateFieldLoo : 0) / 100) / 10; | ||
} | ||
const uploadedBytesSinceLastTick = totalBytes.uploaded - _classPrivateFieldLooseBase(this, _previousUploadedBytes)[_previousUploadedBytes]; | ||
_classPrivateFieldLooseBase(this, _previousUploadedBytes)[_previousUploadedBytes] = totalBytes.uploaded; | ||
// uploadedBytesSinceLastTick can be negative in some cases (packet loss?) | ||
// in which case, we wait for next tick to update ETA. | ||
if (uploadedBytesSinceLastTick <= 0) { | ||
var _classPrivateFieldLoo2; | ||
return Math.round(((_classPrivateFieldLoo2 = _classPrivateFieldLooseBase(this, _previousETA)[_previousETA]) != null ? _classPrivateFieldLoo2 : 0) / 100) / 10; | ||
} | ||
const currentSpeed = uploadedBytesSinceLastTick / dt; | ||
const filteredSpeed = _classPrivateFieldLooseBase(this, _previousSpeed)[_previousSpeed] == null ? currentSpeed : emaFilter(currentSpeed, _classPrivateFieldLooseBase(this, _previousSpeed)[_previousSpeed], speedFilterHalfLife, dt); | ||
_classPrivateFieldLooseBase(this, _previousSpeed)[_previousSpeed] = filteredSpeed; | ||
const instantETA = totalBytes.remaining / filteredSpeed; | ||
const updatedPreviousETA = Math.max(_classPrivateFieldLooseBase(this, _previousETA)[_previousETA] - dt, 0); | ||
const filteredETA = _classPrivateFieldLooseBase(this, _previousETA)[_previousETA] == null ? instantETA : emaFilter(instantETA, updatedPreviousETA, ETAFilterHalfLife, dt); | ||
_classPrivateFieldLooseBase(this, _previousETA)[_previousETA] = filteredETA; | ||
_classPrivateFieldLooseBase(this, _lastUpdateTime)[_lastUpdateTime] = performance.now(); | ||
return Math.round(filteredETA / 100) / 10; | ||
} | ||
StatusBar.VERSION = packageJson.version; |
@@ -13,4 +13,5 @@ import { h } from 'preact'; | ||
STATE_COMPLETE | ||
} = statusBarStates; // TODO: rename the function to StatusBarUI on the next major. | ||
} = statusBarStates; | ||
// TODO: rename the function to StatusBarUI on the next major. | ||
export default function StatusBar(props) { | ||
@@ -48,3 +49,2 @@ const { | ||
} = props; | ||
function getProgressValue() { | ||
@@ -56,10 +56,7 @@ switch (uploadState) { | ||
const progress = calculateProcessingProgress(files); | ||
if (progress.mode === 'determinate') { | ||
return progress.value * 100; | ||
} | ||
return totalProgress; | ||
} | ||
case STATE_ERROR: | ||
@@ -69,3 +66,2 @@ { | ||
} | ||
case STATE_UPLOADING: | ||
@@ -76,6 +72,4 @@ { | ||
} | ||
return totalProgress; | ||
} | ||
default: | ||
@@ -85,3 +79,2 @@ return totalProgress; | ||
} | ||
function getIsIndeterminate() { | ||
@@ -97,3 +90,2 @@ switch (uploadState) { | ||
} | ||
case STATE_UPLOADING: | ||
@@ -104,6 +96,4 @@ { | ||
} | ||
return false; | ||
} | ||
default: | ||
@@ -113,3 +103,2 @@ return false; | ||
} | ||
function getIsHidden() { | ||
@@ -119,10 +108,7 @@ if (recoveredState) { | ||
} | ||
switch (uploadState) { | ||
case STATE_WAITING: | ||
return hideUploadButton || newFiles === 0; | ||
case STATE_COMPLETE: | ||
return hideAfterFinish; | ||
default: | ||
@@ -132,3 +118,2 @@ return false; | ||
} | ||
const progressValue = getProgressValue(); | ||
@@ -169,3 +154,2 @@ const isHidden = getIsHidden(); | ||
}); | ||
case STATE_COMPLETE: | ||
@@ -175,3 +159,2 @@ return h(ProgressBarComplete, { | ||
}); | ||
case STATE_ERROR: | ||
@@ -184,3 +167,2 @@ return h(ProgressBarError, { | ||
}); | ||
case STATE_UPLOADING: | ||
@@ -203,3 +185,2 @@ return h(ProgressBarUploading, { | ||
}); | ||
default: | ||
@@ -206,0 +187,0 @@ return null; |
{ | ||
"name": "@uppy/status-bar", | ||
"description": "A progress bar for Uppy, with many bells and whistles.", | ||
"version": "3.1.2", | ||
"version": "3.2.0", | ||
"license": "MIT", | ||
@@ -31,10 +31,10 @@ "main": "lib/index.js", | ||
"@transloadit/prettier-bytes": "0.0.9", | ||
"@uppy/utils": "^5.3.0", | ||
"@uppy/utils": "^5.4.0", | ||
"classnames": "^2.2.6", | ||
"lodash.throttle": "^4.1.1", | ||
"lodash": "^4.17.21", | ||
"preact": "^10.5.13" | ||
}, | ||
"peerDependencies": { | ||
"@uppy/core": "^3.2.0" | ||
"@uppy/core": "^3.2.1" | ||
} | ||
} |
import { h } from 'preact' | ||
import classNames from 'classnames' | ||
import throttle from 'lodash.throttle' | ||
import throttle from 'lodash/throttle.js' | ||
import prettierBytes from '@transloadit/prettier-bytes' | ||
@@ -5,0 +5,0 @@ import prettyETA from '@uppy/utils/lib/prettyETA' |
import { UIPlugin } from '@uppy/core' | ||
import getSpeed from '@uppy/utils/lib/getSpeed' | ||
import getBytesRemaining from '@uppy/utils/lib/getBytesRemaining' | ||
import emaFilter from '@uppy/utils/lib/emaFilter' | ||
import getTextDirection from '@uppy/utils/lib/getTextDirection' | ||
@@ -11,23 +10,5 @@ import statusBarStates from './StatusBarStates.js' | ||
function getTotalSpeed (files) { | ||
let totalSpeed = 0 | ||
files.forEach((file) => { | ||
totalSpeed += getSpeed(file.progress) | ||
}) | ||
return totalSpeed | ||
} | ||
const speedFilterHalfLife = 2000 | ||
const ETAFilterHalfLife = 2000 | ||
function getTotalETA (files) { | ||
const totalSpeed = getTotalSpeed(files) | ||
if (totalSpeed === 0) { | ||
return 0 | ||
} | ||
const totalBytesRemaining = files.reduce((total, file) => { | ||
return total + getBytesRemaining(file.progress) | ||
}, 0) | ||
return Math.round((totalBytesRemaining / totalSpeed) * 10) / 10 | ||
} | ||
function getUploadingState (error, isAllComplete, recoveredState, files) { | ||
@@ -79,2 +60,10 @@ if (error) { | ||
#lastUpdateTime | ||
#previousUploadedBytes | ||
#previousSpeed | ||
#previousETA | ||
constructor (uppy, opts) { | ||
@@ -108,2 +97,37 @@ super(uppy, opts) | ||
#computeSmoothETA (totalBytes) { | ||
if (totalBytes.total === 0 || totalBytes.remaining === 0) { | ||
return 0 | ||
} | ||
const dt = performance.now() - this.#lastUpdateTime | ||
if (dt === 0) { | ||
return Math.round((this.#previousETA ?? 0) / 100) / 10 | ||
} | ||
const uploadedBytesSinceLastTick = totalBytes.uploaded - this.#previousUploadedBytes | ||
this.#previousUploadedBytes = totalBytes.uploaded | ||
// uploadedBytesSinceLastTick can be negative in some cases (packet loss?) | ||
// in which case, we wait for next tick to update ETA. | ||
if (uploadedBytesSinceLastTick <= 0) { | ||
return Math.round((this.#previousETA ?? 0) / 100) / 10 | ||
} | ||
const currentSpeed = uploadedBytesSinceLastTick / dt | ||
const filteredSpeed = this.#previousSpeed == null | ||
? currentSpeed | ||
: emaFilter(currentSpeed, this.#previousSpeed, speedFilterHalfLife, dt) | ||
this.#previousSpeed = filteredSpeed | ||
const instantETA = totalBytes.remaining / filteredSpeed | ||
const updatedPreviousETA = Math.max(this.#previousETA - dt, 0) | ||
const filteredETA = this.#previousETA == null | ||
? instantETA | ||
: emaFilter(instantETA, updatedPreviousETA, ETAFilterHalfLife, dt) | ||
this.#previousETA = filteredETA | ||
this.#lastUpdateTime = performance.now() | ||
return Math.round(filteredETA / 100) / 10 | ||
} | ||
startUpload = () => { | ||
@@ -116,3 +140,6 @@ const { recoveredState } = this.uppy.getState() | ||
} | ||
this.#lastUpdateTime = performance.now() | ||
this.#previousUploadedBytes = 0 | ||
this.#previousSpeed = null | ||
this.#previousETA = null | ||
return this.uppy.upload().catch(() => { | ||
@@ -137,3 +164,2 @@ // Error logged in Core | ||
completeFiles, | ||
inProgressNotPausedFiles, | ||
@@ -154,3 +180,2 @@ isUploadStarted, | ||
: newFiles | ||
const totalETA = getTotalETA(inProgressNotPausedFiles) | ||
const resumableUploads = !!capabilities.resumableUploads | ||
@@ -166,2 +191,7 @@ const supportsUploadProgress = capabilities.uploadProgress !== false | ||
}) | ||
const totalETA = this.#computeSmoothETA({ | ||
uploaded: totalUploadedSize, | ||
total: totalSize, | ||
remaining: totalSize - totalUploadedSize, | ||
}) | ||
@@ -168,0 +198,0 @@ return StatusBarUI({ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
163886
2560
+ Addedlodash@^4.17.21
- Removedlodash.throttle@^4.1.1
- Removedlodash.throttle@4.1.1(transitive)
Updated@uppy/utils@^5.4.0