@uppy/dashboard
Advanced tools
Comparing version 1.8.5 to 1.9.0
@@ -55,3 +55,14 @@ function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } | ||
'uppy-Dashboard--isInnerWrapVisible': props.areInsidesReadyToBeVisible | ||
}); | ||
}); // Important: keep these in sync with the percent width values in `src/components/FileItem/index.scss`. | ||
var itemsPerRow = 1; // mobile | ||
if (props.containerWidth > WIDTH_XL) { | ||
itemsPerRow = 5; | ||
} else if (props.containerWidth > WIDTH_LG) { | ||
itemsPerRow = 4; | ||
} else if (props.containerWidth > WIDTH_MD) { | ||
itemsPerRow = 3; | ||
} | ||
var showFileList = props.showSelectedFiles && !noFiles; | ||
@@ -93,3 +104,5 @@ return h("div", { | ||
class: "uppy-Dashboard-dropFilesHereHint" | ||
}, props.i18n('dropHint')), showFileList && h(PanelTopBar, props), showFileList ? h(FileList, props) : h(AddFiles, _extends({}, props, { | ||
}, props.i18n('dropHint')), showFileList && h(PanelTopBar, props), showFileList ? h(FileList, _extends({}, props, { | ||
itemsPerRow: itemsPerRow | ||
})) : h(AddFiles, _extends({}, props, { | ||
isSizeMD: isSizeMD | ||
@@ -96,0 +109,0 @@ })), h(TransitionWrapper, null, props.showAddFilesPanel ? h(AddFilesPanel, _extends({ |
@@ -11,28 +11,40 @@ var _require = require('preact'), | ||
var renderEditButton = function renderEditButton(props) { | ||
return !props.uploadInProgressOrComplete && props.metaFields && props.metaFields.length > 0 && h("button", { | ||
class: "uppy-u-reset uppy-DashboardItem-action uppy-DashboardItem-action--edit", | ||
type: "button", | ||
"aria-label": props.i18n('editFile') + ' ' + props.file.meta.name, | ||
title: props.i18n('editFile'), | ||
onclick: function onclick(e) { | ||
return props.toggleFileCard(props.file.id); | ||
} | ||
}, iconPencil()); | ||
}; | ||
function EditButton(_ref) { | ||
var file = _ref.file, | ||
uploadInProgressOrComplete = _ref.uploadInProgressOrComplete, | ||
metaFields = _ref.metaFields, | ||
i18n = _ref.i18n, | ||
onClick = _ref.onClick; | ||
var renderRemoveButton = function renderRemoveButton(props) { | ||
return props.showRemoveButton && h("button", { | ||
if (!uploadInProgressOrComplete && metaFields && metaFields.length > 0) { | ||
return h("button", { | ||
class: "uppy-u-reset uppy-DashboardItem-action uppy-DashboardItem-action--edit", | ||
type: "button", | ||
"aria-label": i18n('editFile') + ' ' + file.meta.name, | ||
title: i18n('editFile'), | ||
onclick: function onclick() { | ||
return onClick(); | ||
} | ||
}, iconPencil()); | ||
} | ||
return null; | ||
} | ||
function RemoveButton(_ref2) { | ||
var i18n = _ref2.i18n, | ||
onClick = _ref2.onClick; | ||
return h("button", { | ||
class: "uppy-u-reset uppy-DashboardItem-action uppy-DashboardItem-action--remove", | ||
type: "button", | ||
"aria-label": props.i18n('removeFile'), | ||
title: props.i18n('removeFile'), | ||
"aria-label": i18n('removeFile'), | ||
title: i18n('removeFile'), | ||
onclick: function onclick() { | ||
return props.removeFile(props.file.id); | ||
return onClick(); | ||
} | ||
}, iconCross()); | ||
}; | ||
} | ||
var copyLinkToClipboard = function copyLinkToClipboard(event, props) { | ||
return copyToClipboard(props.file.uploadURL, props.i18n('copyLinkToClipboardFallback')).then(function () { | ||
copyToClipboard(props.file.uploadURL, props.i18n('copyLinkToClipboardFallback')).then(function () { | ||
props.log('Link copied to clipboard.'); | ||
@@ -48,4 +60,4 @@ props.info(props.i18n('copyLinkToClipboardSuccess'), 'info', 3000); | ||
var renderCopyLinkButton = function renderCopyLinkButton(props) { | ||
return props.showLinkToFileUploadResult && props.file.uploadURL && h("button", { | ||
function CopyLinkButton(props) { | ||
return h("button", { | ||
class: "uppy-u-reset uppy-DashboardItem-action uppy-DashboardItem-action--copyLink", | ||
@@ -59,8 +71,61 @@ type: "button", | ||
}, iconCopyLink()); | ||
}; | ||
} | ||
function ErrorButton(_ref3) { | ||
var file = _ref3.file, | ||
onClick = _ref3.onClick; | ||
if (file.error) { | ||
return h("span", { | ||
class: "uppy-DashboardItem-errorDetails", | ||
"aria-label": file.error, | ||
"data-microtip-position": "bottom-left", | ||
"data-microtip-size": "medium", | ||
role: "tooltip", | ||
onclick: onClick | ||
}, "?"); | ||
} | ||
return null; | ||
} | ||
module.exports = function Buttons(props) { | ||
var file = props.file, | ||
uploadInProgressOrComplete = props.uploadInProgressOrComplete, | ||
metaFields = props.metaFields, | ||
showLinkToFileUploadResult = props.showLinkToFileUploadResult, | ||
showRemoveButton = props.showRemoveButton, | ||
i18n = props.i18n, | ||
removeFile = props.removeFile, | ||
toggleFileCard = props.toggleFileCard, | ||
log = props.log, | ||
info = props.info; | ||
return h("div", { | ||
className: "uppy-DashboardItem-actionWrapper" | ||
}, renderEditButton(props), renderCopyLinkButton(props), renderRemoveButton(props)); | ||
}, h(ErrorButton, { | ||
file: file, | ||
onClick: function onClick() { | ||
alert(file.error); | ||
} | ||
}), h(EditButton, { | ||
i18n: i18n, | ||
file: file, | ||
uploadInProgressOrComplete: uploadInProgressOrComplete, | ||
metaFields: metaFields, | ||
onClick: function onClick() { | ||
return toggleFileCard(file.id); | ||
} | ||
}), showLinkToFileUploadResult && file.uploadURL ? h(CopyLinkButton, { | ||
file: file, | ||
i18n: i18n, | ||
info: info, | ||
log: log | ||
}) : null, showRemoveButton ? h(RemoveButton, { | ||
i18n: i18n, | ||
info: props.info, | ||
log: props.log, | ||
onClick: function onClick() { | ||
return removeFile(file.id); | ||
} | ||
}) : null); | ||
}; |
var _require = require('preact'), | ||
h = _require.h; | ||
var prettyBytes = require('@uppy/utils/lib/prettyBytes'); | ||
var prettierBytes = require('@transloadit/prettier-bytes'); | ||
@@ -47,3 +47,3 @@ var truncateString = require('../../../utils/truncateString'); | ||
class: "uppy-DashboardItem-statusSize" | ||
}, prettyBytes(props.file.data.size)); | ||
}, prettierBytes(props.file.data.size)); | ||
}; | ||
@@ -50,0 +50,0 @@ |
@@ -51,3 +51,3 @@ var _require = require('preact'), | ||
module.exports = function FileProgress(props) { | ||
if (props.hideRetryButton && props.error) { | ||
if (props.hideRetryButton && props.error || props.isUploaded && props.showRemoveButtonAfterComplete) { | ||
return h("div", { | ||
@@ -54,0 +54,0 @@ class: "uppy-DashboardItem-progress" |
@@ -1,3 +0,1 @@ | ||
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } | ||
function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } | ||
@@ -34,2 +32,18 @@ | ||
_proto.componentDidMount = function componentDidMount() { | ||
var file = this.props.file; | ||
if (!file.preview) { | ||
this.props.handleRequestThumbnail(file); | ||
} | ||
}; | ||
_proto.componentWillUnmount = function componentWillUnmount() { | ||
var file = this.props.file; | ||
if (!file.preview) { | ||
this.props.handleCancelThumbnail(file); | ||
} | ||
}; | ||
_proto.render = function render() { | ||
@@ -44,2 +58,7 @@ var file = this.props.file; | ||
var showRemoveButton = this.props.individualCancellation ? !isUploaded : !uploadInProgress && !isUploaded; | ||
if (isUploaded && this.props.showRemoveButtonAfterComplete) { | ||
showRemoveButton = true; | ||
} | ||
var dashboardItemClass = classNames({ | ||
@@ -56,5 +75,6 @@ 'uppy-u-reset': true, | ||
}); | ||
return h("li", { | ||
return h("div", { | ||
class: dashboardItemClass, | ||
id: "uppy_" + file.id | ||
id: "uppy_" + file.id, | ||
role: this.props.role | ||
}, h("div", { | ||
@@ -65,7 +85,16 @@ class: "uppy-DashboardItem-preview" | ||
showLinkToFileUploadResult: this.props.showLinkToFileUploadResult | ||
}), h(FileProgress, _extends({}, this.props, { | ||
}), h(FileProgress, { | ||
file: file, | ||
error: error, | ||
isUploaded: isUploaded | ||
}))), h("div", { | ||
isUploaded: isUploaded, | ||
hideRetryButton: this.props.hideRetryButton, | ||
hidePauseResumeCancelButtons: this.props.hidePauseResumeCancelButtons, | ||
showRemoveButtonAfterComplete: this.props.showRemoveButtonAfterComplete, | ||
resumableUploads: this.props.resumableUploads, | ||
individualCancellation: this.props.individualCancellation, | ||
pauseUpload: this.props.pauseUpload, | ||
cancelUpload: this.props.cancelUpload, | ||
retryUpload: this.props.retryUpload, | ||
i18n: this.props.i18n | ||
})), h("div", { | ||
class: "uppy-DashboardItem-fileInfoAndButtons" | ||
@@ -72,0 +101,0 @@ }, h(FileInfo, { |
@@ -5,2 +5,4 @@ function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } | ||
var VirtualList = require('./VirtualList'); | ||
var classNames = require('classnames'); | ||
@@ -11,7 +13,27 @@ | ||
function chunks(list, size) { | ||
var chunked = []; | ||
var currentChunk = []; | ||
list.forEach(function (item, i) { | ||
if (currentChunk.length < size) { | ||
currentChunk.push(item); | ||
} else { | ||
chunked.push(currentChunk); | ||
currentChunk = [item]; | ||
} | ||
}); | ||
if (currentChunk.length) chunked.push(currentChunk); | ||
return chunked; | ||
} | ||
module.exports = function (props) { | ||
var dashboardFilesClass = classNames({ | ||
'uppy-Dashboard-files': true, | ||
'uppy-Dashboard-files--noFiles': props.totalFileCount === 0 | ||
}); | ||
var noFiles = props.totalFileCount === 0; | ||
var dashboardFilesClass = classNames('uppy-Dashboard-files', { | ||
'uppy-Dashboard-files--noFiles': noFiles | ||
}); // It's not great that this is hardcoded! | ||
// It's ESPECIALLY not great that this is checking against `itemsPerRow`! | ||
var rowHeight = props.itemsPerRow === 1 // Mobile | ||
? 71 // 190px height + 2 * 5px margin | ||
: 200; | ||
var fileProps = { | ||
@@ -33,2 +55,3 @@ // FIXME This is confusing, it's actually the Dashboard's plugin ID | ||
showLinkToFileUploadResult: props.showLinkToFileUploadResult, | ||
showRemoveButtonAfterComplete: props.showRemoveButtonAfterComplete, | ||
isWide: props.isWide, | ||
@@ -42,16 +65,31 @@ metaFields: props.metaFields, | ||
removeFile: props.removeFile, | ||
handleRequestThumbnail: props.handleRequestThumbnail | ||
handleRequestThumbnail: props.handleRequestThumbnail, | ||
handleCancelThumbnail: props.handleCancelThumbnail | ||
}; | ||
var rows = chunks(Object.keys(props.files), props.itemsPerRow); | ||
function renderItem(fileID) { | ||
return h(FileItem, _extends({ | ||
key: fileID | ||
}, fileProps, { | ||
file: props.files[fileID] | ||
})); | ||
function renderRow(row) { | ||
return (// The `role="presentation` attribute ensures that the list items are properly associated with the `VirtualList` element | ||
// We use the first file ID as the key—this should not change across scroll rerenders | ||
h("div", { | ||
role: "presentation", | ||
key: row[0] | ||
}, row.map(function (fileID) { | ||
return h(FileItem, _extends({ | ||
key: fileID | ||
}, fileProps, { | ||
role: "listitem", | ||
file: props.files[fileID] | ||
})); | ||
})) | ||
); | ||
} | ||
return h("ul", { | ||
class: dashboardFilesClass | ||
}, Object.keys(props.files).map(renderItem)); | ||
return h(VirtualList, { | ||
class: dashboardFilesClass, | ||
role: "list", | ||
data: rows, | ||
renderRow: renderRow, | ||
rowHeight: rowHeight | ||
}); | ||
}; |
@@ -537,2 +537,14 @@ var _class, _temp; | ||
_this.handleRequestThumbnail = function (file) { | ||
if (!_this.opts.waitForThumbnailsBeforeUpload) { | ||
_this.uppy.emit('thumbnail:request', file); | ||
} | ||
}; | ||
_this.handleCancelThumbnail = function (file) { | ||
if (!_this.opts.waitForThumbnailsBeforeUpload) { | ||
_this.uppy.emit('thumbnail:cancel', file); | ||
} | ||
}; | ||
_this.handleKeyDownInInline = function (event) { | ||
@@ -803,2 +815,3 @@ // Trap focus on tab key press. | ||
hideCancelButton: _this.opts.hideCancelButton, | ||
showRemoveButtonAfterComplete: _this.opts.showRemoveButtonAfterComplete, | ||
containerWidth: pluginState.containerWidth, | ||
@@ -812,2 +825,4 @@ containerHeight: pluginState.containerHeight, | ||
showSelectedFiles: _this.opts.showSelectedFiles, | ||
handleRequestThumbnail: _this.handleRequestThumbnail, | ||
handleCancelThumbnail: _this.handleCancelThumbnail, | ||
// drag props | ||
@@ -898,3 +913,5 @@ isDraggingOver: pluginState.isDraggingOver, | ||
thumbnailWidth: _this.opts.thumbnailWidth, | ||
waitForThumbnailsBeforeUpload: _this.opts.waitForThumbnailsBeforeUpload | ||
waitForThumbnailsBeforeUpload: _this.opts.waitForThumbnailsBeforeUpload, | ||
// If we don't block on thumbnails, we can lazily generate them | ||
lazy: !_this.opts.waitForThumbnailsBeforeUpload | ||
}); | ||
@@ -1044,2 +1061,3 @@ } // Dark Mode / theme | ||
showSelectedFiles: true, | ||
showRemoveButtonAfterComplete: false, | ||
browserBackButtonClose: false, | ||
@@ -1062,2 +1080,2 @@ theme: 'light' | ||
return Dashboard; | ||
}(Plugin), _class.VERSION = "1.8.5", _temp); | ||
}(Plugin), _class.VERSION = "1.9.0", _temp); |
{ | ||
"name": "@uppy/dashboard", | ||
"description": "Universal UI plugin for Uppy.", | ||
"version": "1.8.5", | ||
"version": "1.9.0", | ||
"license": "MIT", | ||
@@ -25,7 +25,8 @@ "main": "lib/index.js", | ||
"dependencies": { | ||
"@uppy/informer": "^1.5.5", | ||
"@uppy/provider-views": "^1.6.5", | ||
"@uppy/status-bar": "^1.6.5", | ||
"@uppy/thumbnail-generator": "^1.5.12", | ||
"@uppy/utils": "^2.4.4", | ||
"@transloadit/prettier-bytes": "0.0.7", | ||
"@uppy/informer": "^1.5.6", | ||
"@uppy/provider-views": "^1.6.6", | ||
"@uppy/status-bar": "^1.6.6", | ||
"@uppy/thumbnail-generator": "^1.6.0", | ||
"@uppy/utils": "^3.0.0", | ||
"classnames": "^2.2.6", | ||
@@ -44,3 +45,3 @@ "cuid": "^2.1.1", | ||
}, | ||
"gitHead": "5528c6f6eae8873a363be5a45862459f168a7c90" | ||
"gitHead": "6a0152327386cb6dd1ae8aada13f13062d326b61" | ||
} |
@@ -51,2 +51,12 @@ const FileList = require('./FileList') | ||
// Important: keep these in sync with the percent width values in `src/components/FileItem/index.scss`. | ||
let itemsPerRow = 1 // mobile | ||
if (props.containerWidth > WIDTH_XL) { | ||
itemsPerRow = 5 | ||
} else if (props.containerWidth > WIDTH_LG) { | ||
itemsPerRow = 4 | ||
} else if (props.containerWidth > WIDTH_MD) { | ||
itemsPerRow = 3 | ||
} | ||
const showFileList = props.showSelectedFiles && !noFiles | ||
@@ -103,3 +113,6 @@ | ||
{showFileList ? ( | ||
<FileList {...props} /> | ||
<FileList | ||
{...props} | ||
itemsPerRow={itemsPerRow} | ||
/> | ||
) : ( | ||
@@ -106,0 +119,0 @@ <AddFiles {...props} isSizeMD={isSizeMD} /> |
@@ -6,31 +6,42 @@ const { h } = require('preact') | ||
const renderEditButton = (props) => ( | ||
!props.uploadInProgressOrComplete && | ||
props.metaFields && | ||
props.metaFields.length > 0 && | ||
<button | ||
class="uppy-u-reset uppy-DashboardItem-action uppy-DashboardItem-action--edit" | ||
type="button" | ||
aria-label={props.i18n('editFile') + ' ' + props.file.meta.name} | ||
title={props.i18n('editFile')} | ||
onclick={(e) => props.toggleFileCard(props.file.id)} | ||
> | ||
{iconPencil()} | ||
</button> | ||
) | ||
function EditButton ({ | ||
file, | ||
uploadInProgressOrComplete, | ||
metaFields, | ||
i18n, | ||
onClick | ||
}) { | ||
if (!uploadInProgressOrComplete && | ||
metaFields && | ||
metaFields.length > 0) { | ||
return ( | ||
<button | ||
class="uppy-u-reset uppy-DashboardItem-action uppy-DashboardItem-action--edit" | ||
type="button" | ||
aria-label={i18n('editFile') + ' ' + file.meta.name} | ||
title={i18n('editFile')} | ||
onclick={() => onClick()} | ||
> | ||
{iconPencil()} | ||
</button> | ||
) | ||
} | ||
return null | ||
} | ||
const renderRemoveButton = (props) => ( | ||
props.showRemoveButton && | ||
function RemoveButton ({ i18n, onClick }) { | ||
return ( | ||
<button | ||
class="uppy-u-reset uppy-DashboardItem-action uppy-DashboardItem-action--remove" | ||
type="button" | ||
aria-label={props.i18n('removeFile')} | ||
title={props.i18n('removeFile')} | ||
onclick={() => props.removeFile(props.file.id)} | ||
aria-label={i18n('removeFile')} | ||
title={i18n('removeFile')} | ||
onclick={() => onClick()} | ||
> | ||
{iconCross()} | ||
</button> | ||
) | ||
) | ||
} | ||
const copyLinkToClipboard = (event, props) => | ||
const copyLinkToClipboard = (event, props) => { | ||
copyToClipboard(props.file.uploadURL, props.i18n('copyLinkToClipboardFallback')) | ||
@@ -44,6 +55,6 @@ .then(() => { | ||
.then(() => event.target.focus({ preventScroll: true })) | ||
} | ||
const renderCopyLinkButton = (props) => ( | ||
props.showLinkToFileUploadResult && | ||
props.file.uploadURL && | ||
function CopyLinkButton (props) { | ||
return ( | ||
<button | ||
@@ -58,12 +69,70 @@ class="uppy-u-reset uppy-DashboardItem-action uppy-DashboardItem-action--copyLink" | ||
</button> | ||
) | ||
) | ||
} | ||
function ErrorButton ({ file, onClick }) { | ||
if (file.error) { | ||
return ( | ||
<span | ||
class="uppy-DashboardItem-errorDetails" | ||
aria-label={file.error} | ||
data-microtip-position="bottom-left" | ||
data-microtip-size="medium" | ||
role="tooltip" | ||
onclick={onClick} | ||
> | ||
? | ||
</span> | ||
) | ||
} | ||
return null | ||
} | ||
module.exports = function Buttons (props) { | ||
const { | ||
file, | ||
uploadInProgressOrComplete, | ||
metaFields, | ||
showLinkToFileUploadResult, | ||
showRemoveButton, | ||
i18n, | ||
removeFile, | ||
toggleFileCard, | ||
log, | ||
info | ||
} = props | ||
return ( | ||
<div className="uppy-DashboardItem-actionWrapper"> | ||
{renderEditButton(props)} | ||
{renderCopyLinkButton(props)} | ||
{renderRemoveButton(props)} | ||
<ErrorButton | ||
file={file} | ||
onClick={() => { | ||
alert(file.error) | ||
}} | ||
/> | ||
<EditButton | ||
i18n={i18n} | ||
file={file} | ||
uploadInProgressOrComplete={uploadInProgressOrComplete} | ||
metaFields={metaFields} | ||
onClick={() => toggleFileCard(file.id)} | ||
/> | ||
{showLinkToFileUploadResult && file.uploadURL ? ( | ||
<CopyLinkButton | ||
file={file} | ||
i18n={i18n} | ||
info={info} | ||
log={log} | ||
/> | ||
) : null} | ||
{showRemoveButton ? ( | ||
<RemoveButton | ||
i18n={i18n} | ||
info={props.info} | ||
log={props.log} | ||
onClick={() => removeFile(file.id)} | ||
/> | ||
) : null} | ||
</div> | ||
) | ||
} |
const { h } = require('preact') | ||
const prettyBytes = require('@uppy/utils/lib/prettyBytes') | ||
const prettierBytes = require('@transloadit/prettier-bytes') | ||
const truncateString = require('../../../utils/truncateString') | ||
@@ -46,3 +46,3 @@ | ||
<div class="uppy-DashboardItem-statusSize"> | ||
{prettyBytes(props.file.data.size)} | ||
{prettierBytes(props.file.data.size)} | ||
</div> | ||
@@ -49,0 +49,0 @@ ) |
@@ -46,3 +46,4 @@ const { h } = require('preact') | ||
module.exports = function FileProgress (props) { | ||
if (props.hideRetryButton && props.error) { | ||
if ((props.hideRetryButton && props.error) || | ||
(props.isUploaded && props.showRemoveButtonAfterComplete)) { | ||
return <div class="uppy-DashboardItem-progress" /> | ||
@@ -49,0 +50,0 @@ } else if ( |
@@ -14,2 +14,16 @@ const { h, Component } = require('preact') | ||
componentDidMount () { | ||
const file = this.props.file | ||
if (!file.preview) { | ||
this.props.handleRequestThumbnail(file) | ||
} | ||
} | ||
componentWillUnmount () { | ||
const file = this.props.file | ||
if (!file.preview) { | ||
this.props.handleCancelThumbnail(file) | ||
} | ||
} | ||
render () { | ||
@@ -25,6 +39,10 @@ const file = this.props.file | ||
const showRemoveButton = this.props.individualCancellation | ||
let showRemoveButton = this.props.individualCancellation | ||
? !isUploaded | ||
: !uploadInProgress && !isUploaded | ||
if (isUploaded && this.props.showRemoveButtonAfterComplete) { | ||
showRemoveButton = true | ||
} | ||
const dashboardItemClass = classNames({ | ||
@@ -43,3 +61,7 @@ 'uppy-u-reset': true, | ||
return ( | ||
<li class={dashboardItemClass} id={`uppy_${file.id}`}> | ||
<div | ||
class={dashboardItemClass} | ||
id={`uppy_${file.id}`} | ||
role={this.props.role} | ||
> | ||
<div class="uppy-DashboardItem-preview"> | ||
@@ -51,6 +73,17 @@ <FilePreviewAndLink | ||
<FileProgress | ||
{...this.props} | ||
file={file} | ||
error={error} | ||
isUploaded={isUploaded} | ||
hideRetryButton={this.props.hideRetryButton} | ||
hidePauseResumeCancelButtons={this.props.hidePauseResumeCancelButtons} | ||
showRemoveButtonAfterComplete={this.props.showRemoveButtonAfterComplete} | ||
resumableUploads={this.props.resumableUploads} | ||
individualCancellation={this.props.individualCancellation} | ||
pauseUpload={this.props.pauseUpload} | ||
cancelUpload={this.props.cancelUpload} | ||
retryUpload={this.props.retryUpload} | ||
i18n={this.props.i18n} | ||
/> | ||
@@ -83,5 +116,5 @@ </div> | ||
</div> | ||
</li> | ||
</div> | ||
) | ||
} | ||
} |
const FileItem = require('./FileItem/index.js') | ||
const VirtualList = require('./VirtualList') | ||
const classNames = require('classnames') | ||
const { h } = require('preact') | ||
module.exports = (props) => { | ||
const dashboardFilesClass = classNames({ | ||
'uppy-Dashboard-files': true, | ||
'uppy-Dashboard-files--noFiles': props.totalFileCount === 0 | ||
function chunks (list, size) { | ||
const chunked = [] | ||
let currentChunk = [] | ||
list.forEach((item, i) => { | ||
if (currentChunk.length < size) { | ||
currentChunk.push(item) | ||
} else { | ||
chunked.push(currentChunk) | ||
currentChunk = [item] | ||
} | ||
}) | ||
if (currentChunk.length) chunked.push(currentChunk) | ||
return chunked | ||
} | ||
module.exports = (props) => { | ||
const noFiles = props.totalFileCount === 0 | ||
const dashboardFilesClass = classNames( | ||
'uppy-Dashboard-files', | ||
{ 'uppy-Dashboard-files--noFiles': noFiles } | ||
) | ||
// It's not great that this is hardcoded! | ||
// It's ESPECIALLY not great that this is checking against `itemsPerRow`! | ||
const rowHeight = props.itemsPerRow === 1 | ||
// Mobile | ||
? 71 | ||
// 190px height + 2 * 5px margin | ||
: 200 | ||
const fileProps = { | ||
@@ -27,2 +52,3 @@ // FIXME This is confusing, it's actually the Dashboard's plugin ID | ||
showLinkToFileUploadResult: props.showLinkToFileUploadResult, | ||
showRemoveButtonAfterComplete: props.showRemoveButtonAfterComplete, | ||
isWide: props.isWide, | ||
@@ -36,12 +62,22 @@ metaFields: props.metaFields, | ||
removeFile: props.removeFile, | ||
handleRequestThumbnail: props.handleRequestThumbnail | ||
handleRequestThumbnail: props.handleRequestThumbnail, | ||
handleCancelThumbnail: props.handleCancelThumbnail | ||
} | ||
function renderItem (fileID) { | ||
const rows = chunks(Object.keys(props.files), props.itemsPerRow) | ||
function renderRow (row) { | ||
return ( | ||
<FileItem | ||
key={fileID} | ||
{...fileProps} | ||
file={props.files[fileID]} | ||
/> | ||
// The `role="presentation` attribute ensures that the list items are properly associated with the `VirtualList` element | ||
// We use the first file ID as the key—this should not change across scroll rerenders | ||
<div role="presentation" key={row[0]}> | ||
{row.map((fileID) => ( | ||
<FileItem | ||
key={fileID} | ||
{...fileProps} | ||
role="listitem" | ||
file={props.files[fileID]} | ||
/> | ||
))} | ||
</div> | ||
) | ||
@@ -51,6 +87,10 @@ } | ||
return ( | ||
<ul class={dashboardFilesClass}> | ||
{Object.keys(props.files).map(renderItem)} | ||
</ul> | ||
<VirtualList | ||
class={dashboardFilesClass} | ||
role="list" | ||
data={rows} | ||
renderRow={renderRow} | ||
rowHeight={rowHeight} | ||
/> | ||
) | ||
} |
@@ -124,2 +124,3 @@ const { Plugin } = require('@uppy/core') | ||
showSelectedFiles: true, | ||
showRemoveButtonAfterComplete: false, | ||
browserBackButtonClose: false, | ||
@@ -574,2 +575,17 @@ theme: 'light' | ||
handleRequestThumbnail = (file) => { | ||
if (!this.opts.waitForThumbnailsBeforeUpload) { | ||
this.uppy.emit('thumbnail:request', file) | ||
} | ||
} | ||
/** | ||
* We cancel thumbnail requests when a file item component unmounts to avoid clogging up the queue when the user scrolls past many elements. | ||
*/ | ||
handleCancelThumbnail = (file) => { | ||
if (!this.opts.waitForThumbnailsBeforeUpload) { | ||
this.uppy.emit('thumbnail:cancel', file) | ||
} | ||
} | ||
handleKeyDownInInline = (event) => { | ||
@@ -842,2 +858,3 @@ // Trap focus on tab key press. | ||
hideCancelButton: this.opts.hideCancelButton, | ||
showRemoveButtonAfterComplete: this.opts.showRemoveButtonAfterComplete, | ||
containerWidth: pluginState.containerWidth, | ||
@@ -851,2 +868,4 @@ containerHeight: pluginState.containerHeight, | ||
showSelectedFiles: this.opts.showSelectedFiles, | ||
handleRequestThumbnail: this.handleRequestThumbnail, | ||
handleCancelThumbnail: this.handleCancelThumbnail, | ||
// drag props | ||
@@ -931,3 +950,5 @@ isDraggingOver: pluginState.isDraggingOver, | ||
thumbnailWidth: this.opts.thumbnailWidth, | ||
waitForThumbnailsBeforeUpload: this.opts.waitForThumbnailsBeforeUpload | ||
waitForThumbnailsBeforeUpload: this.opts.waitForThumbnailsBeforeUpload, | ||
// If we don't block on thumbnails, we can lazily generate them | ||
lazy: !this.opts.waitForThumbnailsBeforeUpload | ||
}) | ||
@@ -934,0 +955,0 @@ } |
@@ -45,2 +45,3 @@ import Uppy = require('@uppy/core') | ||
showSelectedFiles?: boolean | ||
showRemoveButtonAfterComplete?: boolean | ||
replaceTargetContent?: boolean | ||
@@ -47,0 +48,0 @@ target?: Uppy.PluginTarget |
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
366963
91
7513
16
- Removed@uppy/utils@2.4.4(transitive)
Updated@uppy/informer@^1.5.6
Updated@uppy/provider-views@^1.6.6
Updated@uppy/status-bar@^1.6.6
Updated@uppy/utils@^3.0.0