Socket
Socket
Sign inDemoInstall

@uppy/dashboard

Package Overview
Dependencies
Maintainers
8
Versions
138
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@uppy/dashboard - npm Package Compare versions

Comparing version 2.2.0 to 2.3.0

lib/Dashboard.js

9

CHANGELOG.md
# @uppy/dashboard
## 2.3.0
Released: 2022-05-30
Included in: Uppy v2.11.0
- @uppy/angular,@uppy/audio,@uppy/aws-s3-multipart,@uppy/aws-s3,@uppy/box,@uppy/core,@uppy/dashboard,@uppy/drag-drop,@uppy/dropbox,@uppy/facebook,@uppy/file-input,@uppy/form,@uppy/golden-retriever,@uppy/google-drive,@uppy/image-editor,@uppy/informer,@uppy/instagram,@uppy/onedrive,@uppy/progress-bar,@uppy/react,@uppy/redux-dev-tools,@uppy/robodog,@uppy/screen-capture,@uppy/status-bar,@uppy/store-default,@uppy/store-redux,@uppy/thumbnail-generator,@uppy/transloadit,@uppy/tus,@uppy/unsplash,@uppy/url,@uppy/vue,@uppy/webcam,@uppy/xhr-upload,@uppy/zoom: doc: update bundler recommendation (Antoine du Hamel / #3763)
- @uppy/dashboard: refactor to ESM (Antoine du Hamel / #3701)
- @uppy/dashboard: use webkitRelativePath when querying a file's relative path (Eduard Müller / taktik / #3766)
## 2.1.4

@@ -4,0 +13,0 @@

57

lib/components/AddFiles.js

@@ -0,11 +1,10 @@

"use strict";
var _preact = require("preact");
let _Symbol$for;
const {
h,
Component
} = require('preact');
_Symbol$for = Symbol.for('uppy test: disable unused locale key warning');
class AddFiles extends Component {
class AddFiles extends _preact.Component {
constructor() {

@@ -30,7 +29,7 @@ super(...arguments);

event.target.value = null;
event.target.value = null; // eslint-disable-line no-param-reassign
};
this.renderHiddenInput = (isFolder, refCallback) => {
return h("input", {
return (0, _preact.h)("input", {
className: "uppy-Dashboard-input",

@@ -51,7 +50,7 @@ hidden: true,

this.renderMyDeviceAcquirer = () => {
return h("div", {
return (0, _preact.h)("div", {
className: "uppy-DashboardTab",
role: "presentation",
"data-uppy-acquirer-id": "MyDevice"
}, h("button", {
}, (0, _preact.h)("button", {
type: "button",

@@ -63,3 +62,3 @@ className: "uppy-u-reset uppy-c-btn uppy-DashboardTab-btn",

onClick: this.triggerFileInputClick
}, h("svg", {
}, (0, _preact.h)("svg", {
"aria-hidden": "true",

@@ -70,6 +69,6 @@ focusable: "false",

viewBox: "0 0 32 32"
}, h("g", {
}, (0, _preact.h)("g", {
fill: "none",
fillRule: "evenodd"
}, h("rect", {
}, (0, _preact.h)("rect", {
className: "uppy-ProviderIconBg",

@@ -80,6 +79,6 @@ width: "32",

fill: "#2275D7"
}), h("path", {
}), (0, _preact.h)("path", {
d: "M21.973 21.152H9.863l-1.108-5.087h14.464l-1.246 5.087zM9.935 11.37h3.958l.886 1.444a.673.673 0 0 0 .585.316h6.506v1.37H9.935v-3.13zm14.898 3.44a.793.793 0 0 0-.616-.31h-.978v-2.126c0-.379-.275-.613-.653-.613H15.75l-.886-1.445a.673.673 0 0 0-.585-.316H9.232c-.378 0-.667.209-.667.587V14.5h-.782a.793.793 0 0 0-.61.303.795.795 0 0 0-.155.663l1.45 6.633c.078.36.396.618.764.618h13.354c.36 0 .674-.246.76-.595l1.631-6.636a.795.795 0 0 0-.144-.675z",
fill: "#FFF"
}))), h("div", {
}))), (0, _preact.h)("div", {
className: "uppy-DashboardTab-name"

@@ -91,3 +90,3 @@ }, this.props.i18n('myDevice'))));

const numberOfAcquirers = this.props.acquirers.length;
return h("button", {
return (0, _preact.h)("button", {
type: "button",

@@ -108,3 +107,3 @@ className: "uppy-u-reset uppy-Dashboard-browse",

const camelFMSelectionType = lowerFMSelectionType.charAt(0).toUpperCase() + lowerFMSelectionType.slice(1);
return h("div", {
return (0, _preact.h)("div", {
class: "uppy-Dashboard-AddFiles-title"

@@ -124,7 +123,7 @@ }, // eslint-disable-next-line no-nested-ternary

this.renderAcquirer = acquirer => {
return h("div", {
return (0, _preact.h)("div", {
className: "uppy-DashboardTab",
role: "presentation",
"data-uppy-acquirer-id": acquirer.id
}, h("button", {
}, (0, _preact.h)("button", {
type: "button",

@@ -139,3 +138,3 @@ className: "uppy-u-reset uppy-c-btn uppy-DashboardTab-btn",

onClick: () => this.props.showPanel(acquirer.id)
}, acquirer.icon(), h("div", {
}, acquirer.icon(), (0, _preact.h)("div", {
className: "uppy-DashboardTab-name"

@@ -150,6 +149,6 @@ }, acquirer.name)));

const lastTwoAcquirers = acquirersWithoutLastTwo.splice(acquirers.length - 2, acquirers.length);
return h("div", {
return (0, _preact.h)("div", {
className: "uppy-Dashboard-AddFiles-list",
role: "tablist"
}, !disableLocalFiles && this.renderMyDeviceAcquirer(), acquirersWithoutLastTwo.map(acquirer => this.renderAcquirer(acquirer)), h("span", {
}, !disableLocalFiles && this.renderMyDeviceAcquirer(), acquirersWithoutLastTwo.map(acquirer => this.renderAcquirer(acquirer)), (0, _preact.h)("span", {
role: "presentation",

@@ -177,3 +176,3 @@ style: {

} = this.props;
const uppyBranding = h("span", null, h("svg", {
const uppyBranding = (0, _preact.h)("span", null, (0, _preact.h)("svg", {
"aria-hidden": "true",

@@ -185,6 +184,6 @@ focusable: "false",

viewBox: "0 0 11 11"
}, h("path", {
}, (0, _preact.h)("path", {
d: "M7.365 10.5l-.01-4.045h2.612L5.5.806l-4.467 5.65h2.604l.01 4.044h3.718z",
fillRule: "evenodd"
})), h("span", {
})), (0, _preact.h)("span", {
className: "uppy-Dashboard-poweredByUppy"

@@ -195,3 +194,3 @@ }, "Uppy"));

});
return h("a", {
return (0, _preact.h)("a", {
tabIndex: "-1",

@@ -206,3 +205,3 @@ href: "https://uppy.io",

render() {
return h("div", {
return (0, _preact.h)("div", {
className: "uppy-Dashboard-AddFiles"

@@ -213,5 +212,5 @@ }, this.renderHiddenInput(false, ref => {

this.folderInput = ref;
}), this.renderDropPasteBrowseTagline(), this.props.acquirers.length > 0 && this.renderAcquirers(this.props.acquirers, this.props.disableLocalFiles), h("div", {
}), this.renderDropPasteBrowseTagline(), this.props.acquirers.length > 0 && this.renderAcquirers(this.props.acquirers, this.props.disableLocalFiles), (0, _preact.h)("div", {
className: "uppy-Dashboard-AddFiles-info"
}, this.props.note && h("div", {
}, this.props.note && (0, _preact.h)("div", {
className: "uppy-Dashboard-note"

@@ -218,0 +217,0 @@ }, this.props.note), this.props.proudlyDisplayPoweredByUppy && this.renderPoweredByUppy(this.props)));

@@ -1,27 +0,27 @@

const {
h
} = require('preact');
"use strict";
const classNames = require('classnames');
var _preact = require("preact");
const AddFiles = require('./AddFiles');
const classNames = require("classnames");
const AddFiles = require("./AddFiles.js");
const AddFilesPanel = props => {
return h("div", {
return (0, _preact.h)("div", {
className: classNames('uppy-Dashboard-AddFilesPanel', props.className),
"data-uppy-panelType": "AddFiles",
"aria-hidden": props.showAddFilesPanel
}, h("div", {
}, (0, _preact.h)("div", {
className: "uppy-DashboardContent-bar"
}, h("div", {
}, (0, _preact.h)("div", {
className: "uppy-DashboardContent-title",
role: "heading",
"aria-level": "1"
}, props.i18n('addingMoreFiles')), h("button", {
}, props.i18n('addingMoreFiles')), (0, _preact.h)("button", {
className: "uppy-DashboardContent-back",
type: "button",
onClick: () => props.toggleAddFilesPanel(false)
}, props.i18n('back'))), h(AddFiles, props));
}, props.i18n('back'))), (0, _preact.h)(AddFiles, props));
};
module.exports = AddFilesPanel;

@@ -0,26 +1,26 @@

"use strict";
var _preact = require("preact");
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); }
const {
h
} = require('preact');
const classNames = require("classnames");
const classNames = require('classnames');
const isDragDropSupported = require("@uppy/utils/lib/isDragDropSupported");
const isDragDropSupported = require('@uppy/utils/lib/isDragDropSupported');
const FileList = require("./FileList.js");
const FileList = require('./FileList');
const AddFiles = require("./AddFiles.js");
const AddFiles = require('./AddFiles');
const AddFilesPanel = require("./AddFilesPanel.js");
const AddFilesPanel = require('./AddFilesPanel');
const PickerPanelContent = require("./PickerPanelContent.js");
const PickerPanelContent = require('./PickerPanelContent');
const EditorPanel = require("./EditorPanel.js");
const EditorPanel = require('./EditorPanel');
const PanelTopBar = require("./PickerPanelTopBar.js");
const PanelTopBar = require('./PickerPanelTopBar');
const FileCard = require("./FileCard/index.js");
const FileCard = require('./FileCard');
const Slide = require('./Slide'); // http://dev.edenspiekermann.com/2016/02/11/introducing-accessible-modal-dialog
const Slide = require("./Slide.js"); // http://dev.edenspiekermann.com/2016/02/11/introducing-accessible-modal-dialog
// https://github.com/ghosh/micromodal

@@ -34,3 +34,3 @@

module.exports = function Dashboard(props) {
function Dashboard(props) {
const noFiles = props.totalFileCount === 0;

@@ -77,3 +77,3 @@ const isSizeMD = props.containerWidth > WIDTH_MD;

const dashboard = h("div", {
const dashboard = (0, _preact.h)("div", {
className: dashboardClassName,

@@ -90,3 +90,3 @@ "data-uppy-theme": props.theme,

onDrop: props.handleDrop
}, h("div", {
}, (0, _preact.h)("div", {
"aria-hidden": "true",

@@ -96,3 +96,3 @@ className: "uppy-Dashboard-overlay",

onClick: props.handleClickOutside
}), h("div", {
}), (0, _preact.h)("div", {
className: "uppy-Dashboard-inner",

@@ -105,3 +105,3 @@ "aria-modal": !props.inline && 'true',

}
}, !props.inline ? h("button", {
}, !props.inline ? (0, _preact.h)("button", {
className: "uppy-u-reset uppy-Dashboard-close",

@@ -112,11 +112,11 @@ type: "button",

onClick: props.closeModal
}, h("span", {
}, (0, _preact.h)("span", {
"aria-hidden": "true"
}, "\xD7")) : null, h("div", {
}, "\xD7")) : null, (0, _preact.h)("div", {
className: "uppy-Dashboard-innerWrap"
}, h("div", {
}, (0, _preact.h)("div", {
className: "uppy-Dashboard-dropFilesHereHint"
}, props.i18n('dropHint')), showFileList && h(PanelTopBar, props), numberOfFilesForRecovery && h("div", {
}, props.i18n('dropHint')), showFileList && (0, _preact.h)(PanelTopBar, props), numberOfFilesForRecovery && (0, _preact.h)("div", {
className: "uppy-Dashboard-serviceMsg"
}, h("svg", {
}, (0, _preact.h)("svg", {
className: "uppy-Dashboard-serviceMsg-icon",

@@ -128,13 +128,13 @@ "aria-hidden": "true",

viewBox: "0 0 24 19"
}, h("g", {
}, (0, _preact.h)("g", {
transform: "translate(0 -1)",
fill: "none",
fillRule: "evenodd"
}, h("path", {
}, (0, _preact.h)("path", {
d: "M12.857 1.43l10.234 17.056A1 1 0 0122.234 20H1.766a1 1 0 01-.857-1.514L11.143 1.429a1 1 0 011.714 0z",
fill: "#FFD300"
}), h("path", {
}), (0, _preact.h)("path", {
fill: "#000",
d: "M11 6h2l-.3 8h-1.4z"
}), h("circle", {
}), (0, _preact.h)("circle", {
fill: "#000",

@@ -144,21 +144,23 @@ cx: "12",

r: "1"
}))), h("strong", {
}))), (0, _preact.h)("strong", {
className: "uppy-Dashboard-serviceMsg-title"
}, props.i18n('sessionRestored')), h("div", {
}, props.i18n('sessionRestored')), (0, _preact.h)("div", {
className: "uppy-Dashboard-serviceMsg-text"
}, renderRestoredText())), showFileList ? h(FileList, _extends({}, props, {
}, renderRestoredText())), showFileList ? (0, _preact.h)(FileList // eslint-disable-next-line react/jsx-props-no-spreading
, _extends({}, props, {
itemsPerRow: itemsPerRow
})) : h(AddFiles, _extends({}, props, {
})) : // eslint-disable-next-line react/jsx-props-no-spreading
(0, _preact.h)(AddFiles, _extends({}, props, {
isSizeMD: isSizeMD
})), h(Slide, null, props.showAddFilesPanel ? h(AddFilesPanel, _extends({
})), (0, _preact.h)(Slide, null, props.showAddFilesPanel ? (0, _preact.h)(AddFilesPanel, _extends({
key: "AddFiles"
}, props, {
isSizeMD: isSizeMD
})) : null), h(Slide, null, props.fileCardFor ? h(FileCard, _extends({
})) : null), (0, _preact.h)(Slide, null, props.fileCardFor ? (0, _preact.h)(FileCard, _extends({
key: "FileCard"
}, props)) : null), h(Slide, null, props.activePickerPanel ? h(PickerPanelContent, _extends({
}, props)) : null), (0, _preact.h)(Slide, null, props.activePickerPanel ? (0, _preact.h)(PickerPanelContent, _extends({
key: "Picker"
}, props)) : null), h(Slide, null, props.showFileEditor ? h(EditorPanel, _extends({
}, props)) : null), (0, _preact.h)(Slide, null, props.showFileEditor ? (0, _preact.h)(EditorPanel, _extends({
key: "Editor"
}, props)) : null), h("div", {
}, props)) : null), (0, _preact.h)("div", {
className: "uppy-Dashboard-progressindicators"

@@ -169,2 +171,4 @@ }, props.progressindicators.map(target => {

return dashboard;
};
}
module.exports = Dashboard;

@@ -1,10 +0,10 @@

const {
h
} = require('preact');
"use strict";
const classNames = require('classnames');
var _preact = require("preact");
const classNames = require("classnames");
function EditorPanel(props) {
const file = props.files[props.fileCardFor];
return h("div", {
return (0, _preact.h)("div", {
className: classNames('uppy-DashboardContent-panel', props.className),

@@ -14,5 +14,5 @@ role: "tabpanel",

id: "uppy-DashboardContent-panel--editor"
}, h("div", {
}, (0, _preact.h)("div", {
className: "uppy-DashboardContent-bar"
}, h("div", {
}, (0, _preact.h)("div", {
className: "uppy-DashboardContent-title",

@@ -22,14 +22,14 @@ role: "heading",

}, props.i18nArray('editing', {
file: h("span", {
file: (0, _preact.h)("span", {
className: "uppy-DashboardContent-titleFile"
}, file.meta ? file.meta.name : file.name)
})), h("button", {
})), (0, _preact.h)("button", {
className: "uppy-DashboardContent-back",
type: "button",
onClick: props.hideAllPanels
}, props.i18n('cancel')), h("button", {
}, props.i18n('cancel')), (0, _preact.h)("button", {
className: "uppy-DashboardContent-save",
type: "button",
onClick: props.saveFileEditor
}, props.i18n('save'))), h("div", {
}, props.i18n('save'))), (0, _preact.h)("div", {
className: "uppy-DashboardContent-panelBody"

@@ -36,0 +36,0 @@ }, props.editors.map(target => {

@@ -1,19 +0,16 @@

const {
h,
Component
} = require('preact');
"use strict";
const classNames = require('classnames');
var _preact = require("preact");
const {
nanoid
} = require('nanoid/non-secure');
var _nonSecure = require("nanoid/non-secure");
const getFileTypeIcon = require('../../utils/getFileTypeIcon');
const classNames = require("classnames");
const ignoreEvent = require('../../utils/ignoreEvent.js');
const getFileTypeIcon = require("../../utils/getFileTypeIcon.js");
const FilePreview = require('../FilePreview');
const ignoreEvent = require("../../utils/ignoreEvent.js");
class FileCard extends Component {
const FilePreview = require("../FilePreview.js");
class FileCard extends _preact.Component {
constructor(props) {

@@ -63,6 +60,6 @@ super(props);

const required = this.props.requiredMetaFields.includes(field.id);
return h("fieldset", {
return (0, _preact.h)("fieldset", {
key: field.id,
className: "uppy-Dashboard-FileCard-fieldset"
}, h("label", {
}, (0, _preact.h)("label", {
className: "uppy-Dashboard-FileCard-label",

@@ -76,3 +73,3 @@ htmlFor: id

form: this.form.id
}, h) : h("input", {
}, _preact.h) : (0, _preact.h)("input", {
className: fieldCSSClasses.text,

@@ -109,3 +106,3 @@ id: id,

};
this.form.id = nanoid();
this.form.id = (0, _nonSecure.nanoid)();
} // TODO(aduh95): move this to `UNSAFE_componentWillMount` when updating to Preact X+.

@@ -132,3 +129,3 @@

const showEditButton = this.props.canEditFile(file);
return h("div", {
return (0, _preact.h)("div", {
className: classNames('uppy-Dashboard-FileCard', this.props.className),

@@ -140,5 +137,5 @@ "data-uppy-panelType": "FileCard",

onPaste: ignoreEvent
}, h("div", {
}, (0, _preact.h)("div", {
className: "uppy-DashboardContent-bar"
}, h("div", {
}, (0, _preact.h)("div", {
className: "uppy-DashboardContent-title",

@@ -148,6 +145,6 @@ role: "heading",

}, this.props.i18nArray('editing', {
file: h("span", {
file: (0, _preact.h)("span", {
className: "uppy-DashboardContent-titleFile"
}, file.meta ? file.meta.name : file.name)
})), h("button", {
})), (0, _preact.h)("button", {
className: "uppy-DashboardContent-back",

@@ -158,5 +155,5 @@ type: "button",

onClick: this.handleCancel
}, this.props.i18n('cancel'))), h("div", {
}, this.props.i18n('cancel'))), (0, _preact.h)("div", {
className: "uppy-Dashboard-FileCard-inner"
}, h("div", {
}, (0, _preact.h)("div", {
className: "uppy-Dashboard-FileCard-preview",

@@ -166,5 +163,5 @@ style: {

}
}, h(FilePreview, {
}, (0, _preact.h)(FilePreview, {
file: file
}), showEditButton && h("button", {
}), showEditButton && (0, _preact.h)("button", {
type: "button",

@@ -181,7 +178,7 @@ className: "uppy-u-reset uppy-c-btn uppy-Dashboard-FileCard-edit",

form: this.form.id
}, this.props.i18n('editFile'))), h("div", {
}, this.props.i18n('editFile'))), (0, _preact.h)("div", {
className: "uppy-Dashboard-FileCard-info"
}, this.renderMetaFields()), h("div", {
}, this.renderMetaFields()), (0, _preact.h)("div", {
className: "uppy-Dashboard-FileCard-actions"
}, h("button", {
}, (0, _preact.h)("button", {
className: "uppy-u-reset uppy-c-btn uppy-c-btn-primary uppy-Dashboard-FileCard-actionsBtn" // If `form` attribute is supported, we want a submit button to trigger the form validation.

@@ -193,3 +190,3 @@ // Otherwise, fallback to a classic button with a onClick event handler.

form: this.form.id
}, this.props.i18n('saveChanges')), h("button", {
}, this.props.i18n('saveChanges')), (0, _preact.h)("button", {
className: "uppy-u-reset uppy-c-btn uppy-c-btn-link uppy-Dashboard-FileCard-actionsBtn",

@@ -196,0 +193,0 @@ type: "button",

@@ -1,7 +0,7 @@

const {
h
} = require('preact');
"use strict";
const copyToClipboard = require('../../../utils/copyToClipboard');
var _preact = require("preact");
const copyToClipboard = require("../../../utils/copyToClipboard.js");
function EditButton(_ref) {

@@ -18,3 +18,3 @@ let {

if (!uploadInProgressOrComplete && metaFields && metaFields.length > 0 || !uploadInProgressOrComplete && canEditFile(file)) {
return h("button", {
return (0, _preact.h)("button", {
className: "uppy-u-reset uppy-Dashboard-Item-action uppy-Dashboard-Item-action--edit",

@@ -29,3 +29,3 @@ type: "button",

onClick: () => onClick()
}, h("svg", {
}, (0, _preact.h)("svg", {
"aria-hidden": "true",

@@ -37,8 +37,8 @@ focusable: "false",

viewBox: "0 0 14 14"
}, h("g", {
}, (0, _preact.h)("g", {
fillRule: "evenodd"
}, h("path", {
}, (0, _preact.h)("path", {
d: "M1.5 10.793h2.793A1 1 0 0 0 5 10.5L11.5 4a1 1 0 0 0 0-1.414L9.707.793a1 1 0 0 0-1.414 0l-6.5 6.5A1 1 0 0 0 1.5 8v2.793zm1-1V8L9 1.5l1.793 1.793-6.5 6.5H2.5z",
fillRule: "nonzero"
}), h("rect", {
}), (0, _preact.h)("rect", {
x: "1",

@@ -49,3 +49,3 @@ y: "12.293",

rx: ".5"
}), h("path", {
}), (0, _preact.h)("path", {
fillRule: "nonzero",

@@ -65,3 +65,3 @@ d: "M6.793 2.5L9.5 5.207l.707-.707L7.5 1.793z"

} = _ref2;
return h("button", {
return (0, _preact.h)("button", {
className: "uppy-u-reset uppy-Dashboard-Item-action uppy-Dashboard-Item-action--remove",

@@ -76,3 +76,3 @@ type: "button",

onClick: () => onClick()
}, h("svg", {
}, (0, _preact.h)("svg", {
"aria-hidden": "true",

@@ -84,5 +84,5 @@ focusable: "false",

viewBox: "0 0 18 18"
}, h("path", {
}, (0, _preact.h)("path", {
d: "M9 0C4.034 0 0 4.034 0 9s4.034 9 9 9 9-4.034 9-9-4.034-9-9-9z"
}), h("path", {
}), (0, _preact.h)("path", {
fill: "#FFF",

@@ -107,3 +107,3 @@ d: "M13 12.222l-.778.778L9 9.778 5.778 13 5 12.222 8.222 9 5 5.778 5.778 5 9 8.222 12.222 5l.778.778L9.778 9z"

} = props;
return h("button", {
return (0, _preact.h)("button", {
className: "uppy-u-reset uppy-Dashboard-Item-action uppy-Dashboard-Item-action--copyLink",

@@ -114,3 +114,3 @@ type: "button",

onClick: event => copyLinkToClipboard(event, props)
}, h("svg", {
}, (0, _preact.h)("svg", {
"aria-hidden": "true",

@@ -122,3 +122,3 @@ focusable: "false",

viewBox: "0 0 14 12"
}, h("path", {
}, (0, _preact.h)("path", {
d: "M7.94 7.703a2.613 2.613 0 0 1-.626 2.681l-.852.851a2.597 2.597 0 0 1-1.849.766A2.616 2.616 0 0 1 2.764 7.54l.852-.852a2.596 2.596 0 0 1 2.69-.625L5.267 7.099a1.44 1.44 0 0 0-.833.407l-.852.851a1.458 1.458 0 0 0 1.03 2.486c.39 0 .755-.152 1.03-.426l.852-.852c.231-.231.363-.522.406-.824l1.04-1.038zm4.295-5.937A2.596 2.596 0 0 0 10.387 1c-.698 0-1.355.272-1.849.766l-.852.851a2.614 2.614 0 0 0-.624 2.688l1.036-1.036c.041-.304.173-.6.407-.833l.852-.852c.275-.275.64-.426 1.03-.426a1.458 1.458 0 0 1 1.03 2.486l-.852.851a1.442 1.442 0 0 1-.824.406l-1.04 1.04a2.596 2.596 0 0 0 2.683-.628l.851-.85a2.616 2.616 0 0 0 0-3.697zm-6.88 6.883a.577.577 0 0 0 .82 0l3.474-3.474a.579.579 0 1 0-.819-.82L5.355 7.83a.579.579 0 0 0 0 .819z"

@@ -128,3 +128,3 @@ })));

module.exports = function Buttons(props) {
function Buttons(props) {
const {

@@ -151,5 +151,5 @@ uppy,

return h("div", {
return (0, _preact.h)("div", {
className: "uppy-Dashboard-Item-actionWrapper"
}, h(EditButton, {
}, (0, _preact.h)(EditButton, {
i18n: i18n,

@@ -161,7 +161,7 @@ file: file,

onClick: editAction
}), showLinkToFileUploadResult && file.uploadURL ? h(CopyLinkButton, {
}), showLinkToFileUploadResult && file.uploadURL ? (0, _preact.h)(CopyLinkButton, {
file: file,
uppy: uppy,
i18n: i18n
}) : null, showRemoveButton ? h(RemoveButton, {
}) : null, showRemoveButton ? (0, _preact.h)(RemoveButton, {
i18n: i18n,

@@ -172,2 +172,4 @@ file: file,

}) : null);
};
}
module.exports = Buttons;

@@ -1,12 +0,11 @@

const {
h,
Fragment
} = require('preact');
"use strict";
const prettierBytes = require('@transloadit/prettier-bytes');
var _preact = require("preact");
const truncateString = require('@uppy/utils/lib/truncateString');
const prettierBytes = require("@transloadit/prettier-bytes");
const MetaErrorMessage = require('../MetaErrorMessage');
const truncateString = require("@uppy/utils/lib/truncateString");
const MetaErrorMessage = require("../MetaErrorMessage.js");
const renderFileName = props => {

@@ -33,3 +32,3 @@ const {

return h("div", {
return (0, _preact.h)("div", {
className: "uppy-Dashboard-Item-name",

@@ -53,16 +52,16 @@ title: name

return h("div", {
return (0, _preact.h)("div", {
className: "uppy-Dashboard-Item-author"
}, h("a", {
}, (0, _preact.h)("a", {
href: `${author.url}?utm_source=Companion&utm_medium=referral`,
target: "_blank",
rel: "noopener noreferrer"
}, truncateString(author.name, 13)), providerName ? h(Fragment, null, ` ${dot} `, providerName, ` ${dot} `) : null);
}, truncateString(author.name, 13)), providerName ? (0, _preact.h)(_preact.Fragment, null, ` ${dot} `, providerName, ` ${dot} `) : null);
};
const renderFileSize = props => props.file.size && h("div", {
const renderFileSize = props => props.file.size && (0, _preact.h)("div", {
className: "uppy-Dashboard-Item-statusSize"
}, prettierBytes(props.file.size));
const ReSelectButton = props => props.file.isGhost && h("span", null, ' \u2022 ', h("button", {
const ReSelectButton = props => props.file.isGhost && (0, _preact.h)("span", null, ' \u2022 ', (0, _preact.h)("button", {
className: "uppy-u-reset uppy-c-btn uppy-Dashboard-Item-reSelect",

@@ -80,3 +79,3 @@ type: "button",

if (file.error) {
return h("button", {
return (0, _preact.h)("button", {
className: "uppy-u-reset uppy-Dashboard-Item-errorDetails",

@@ -94,12 +93,12 @@ "aria-label": file.error,

module.exports = function FileInfo(props) {
function FileInfo(props) {
const {
file
} = props;
return h("div", {
return (0, _preact.h)("div", {
className: "uppy-Dashboard-Item-fileInfo",
"data-uppy-file-source": file.source
}, h("div", {
}, (0, _preact.h)("div", {
className: "uppy-Dashboard-Item-fileName"
}, renderFileName(props), h(ErrorButton, {
}, renderFileName(props), (0, _preact.h)(ErrorButton, {
file: props.file // eslint-disable-next-line no-alert

@@ -109,5 +108,5 @@ ,

})), h("div", {
})), (0, _preact.h)("div", {
className: "uppy-Dashboard-Item-status"
}, renderAuthor(props), renderFileSize(props), ReSelectButton(props)), h(MetaErrorMessage, {
}, renderAuthor(props), renderFileSize(props), ReSelectButton(props)), (0, _preact.h)(MetaErrorMessage, {
file: props.file,

@@ -118,2 +117,4 @@ i18n: props.i18n,

}));
};
}
module.exports = FileInfo;

@@ -1,13 +0,13 @@

const {
h
} = require('preact');
"use strict";
const FilePreview = require('../../FilePreview');
var _preact = require("preact");
const MetaErrorMessage = require('../MetaErrorMessage');
const FilePreview = require("../../FilePreview.js");
const getFileTypeIcon = require('../../../utils/getFileTypeIcon');
const MetaErrorMessage = require("../MetaErrorMessage.js");
module.exports = function FilePreviewAndLink(props) {
return h("div", {
const getFileTypeIcon = require("../../../utils/getFileTypeIcon.js");
function FilePreviewAndLink(props) {
return (0, _preact.h)("div", {
className: "uppy-Dashboard-Item-previewInnerWrap",

@@ -17,3 +17,3 @@ style: {

}
}, props.showLinkToFileUploadResult && props.file.uploadURL && h("a", {
}, props.showLinkToFileUploadResult && props.file.uploadURL && (0, _preact.h)("a", {
className: "uppy-Dashboard-Item-previewLink",

@@ -24,7 +24,7 @@ href: props.file.uploadURL,

"aria-label": props.file.meta.name
}, h("span", {
}, (0, _preact.h)("span", {
hidden: true
}, props.file.meta.name)), h(FilePreview, {
}, props.file.meta.name)), (0, _preact.h)(FilePreview, {
file: props.file
}), h(MetaErrorMessage, {
}), (0, _preact.h)(MetaErrorMessage, {
file: props.file,

@@ -35,2 +35,4 @@ i18n: props.i18n,

}));
};
}
module.exports = FilePreviewAndLink;

@@ -1,5 +0,5 @@

const {
h
} = require('preact');
"use strict";
var _preact = require("preact");
function onPauseResumeCancelRetry(props) {

@@ -45,5 +45,5 @@ if (props.isUploaded) return;

function ProgressIndicatorButton(props) {
return h("div", {
return (0, _preact.h)("div", {
className: "uppy-Dashboard-Item-progress"
}, h("button", {
}, (0, _preact.h)("button", {
className: "uppy-u-reset uppy-Dashboard-Item-progressIndicator",

@@ -61,3 +61,3 @@ type: "button",

} = _ref;
return h("svg", {
return (0, _preact.h)("svg", {
"aria-hidden": "true",

@@ -78,3 +78,3 @@ focusable: "false",

const circleLength = 2 * Math.PI * 15;
return h("g", null, h("circle", {
return (0, _preact.h)("g", null, (0, _preact.h)("circle", {
className: "uppy-Dashboard-Item-progressIcon--bg",

@@ -86,3 +86,3 @@ r: "15",

fill: "none"
}), h("circle", {
}), (0, _preact.h)("circle", {
className: "uppy-Dashboard-Item-progressIcon--progress",

@@ -100,3 +100,3 @@ r: "15",

module.exports = function FileProgress(props) {
function FileProgress(props) {
// Nothing if upload has not started

@@ -109,7 +109,7 @@ if (!props.file.progress.uploadStarted) {

if (props.isUploaded) {
return h("div", {
return (0, _preact.h)("div", {
className: "uppy-Dashboard-Item-progress"
}, h("div", {
}, (0, _preact.h)("div", {
className: "uppy-Dashboard-Item-progressIndicator"
}, h(ProgressCircleContainer, null, h("circle", {
}, (0, _preact.h)(ProgressCircleContainer, null, (0, _preact.h)("circle", {
r: "15",

@@ -119,3 +119,3 @@ cx: "18",

fill: "#1bb240"
}), h("polygon", {
}), (0, _preact.h)("polygon", {
className: "uppy-Dashboard-Item-progressIcon--check",

@@ -128,3 +128,3 @@ transform: "translate(2, 3)",

if (props.recoveredState) {
return;
return undefined;
} // Retry button for error

@@ -134,18 +134,20 @@

if (props.error && !props.hideRetryButton) {
return h(ProgressIndicatorButton, props, h("svg", {
"aria-hidden": "true",
focusable: "false",
className: "uppy-c-icon uppy-Dashboard-Item-progressIcon--retry",
width: "28",
height: "31",
viewBox: "0 0 16 19"
}, h("path", {
d: "M16 11a8 8 0 1 1-8-8v2a6 6 0 1 0 6 6h2z"
}), h("path", {
d: "M7.9 3H10v2H7.9z"
}), h("path", {
d: "M8.536.5l3.535 3.536-1.414 1.414L7.12 1.914z"
}), h("path", {
d: "M10.657 2.621l1.414 1.415L8.536 7.57 7.12 6.157z"
})));
return (// eslint-disable-next-line react/jsx-props-no-spreading
(0, _preact.h)(ProgressIndicatorButton, props, (0, _preact.h)("svg", {
"aria-hidden": "true",
focusable: "false",
className: "uppy-c-icon uppy-Dashboard-Item-progressIcon--retry",
width: "28",
height: "31",
viewBox: "0 0 16 19"
}, (0, _preact.h)("path", {
d: "M16 11a8 8 0 1 1-8-8v2a6 6 0 1 0 6 6h2z"
}), (0, _preact.h)("path", {
d: "M7.9 3H10v2H7.9z"
}), (0, _preact.h)("path", {
d: "M8.536.5l3.535 3.536-1.414 1.414L7.12 1.914z"
}), (0, _preact.h)("path", {
d: "M10.657 2.621l1.414 1.415L8.536 7.57 7.12 6.157z"
})))
);
} // Pause/resume button for resumable uploads

@@ -155,24 +157,26 @@

if (props.resumableUploads && !props.hidePauseResumeButton) {
return h(ProgressIndicatorButton, props, h(ProgressCircleContainer, null, h(ProgressCircle, {
progress: props.file.progress.percentage
}), props.file.isPaused ? h("polygon", {
className: "uppy-Dashboard-Item-progressIcon--play",
transform: "translate(3, 3)",
points: "12 20 12 10 20 15"
}) : h("g", {
className: "uppy-Dashboard-Item-progressIcon--pause",
transform: "translate(14.5, 13)"
}, h("rect", {
x: "0",
y: "0",
width: "2",
height: "10",
rx: "0"
}), h("rect", {
x: "5",
y: "0",
width: "2",
height: "10",
rx: "0"
}))));
return (// eslint-disable-next-line react/jsx-props-no-spreading
(0, _preact.h)(ProgressIndicatorButton, props, (0, _preact.h)(ProgressCircleContainer, null, (0, _preact.h)(ProgressCircle, {
progress: props.file.progress.percentage
}), props.file.isPaused ? (0, _preact.h)("polygon", {
className: "uppy-Dashboard-Item-progressIcon--play",
transform: "translate(3, 3)",
points: "12 20 12 10 20 15"
}) : (0, _preact.h)("g", {
className: "uppy-Dashboard-Item-progressIcon--pause",
transform: "translate(14.5, 13)"
}, (0, _preact.h)("rect", {
x: "0",
y: "0",
width: "2",
height: "10",
rx: "0"
}), (0, _preact.h)("rect", {
x: "5",
y: "0",
width: "2",
height: "10",
rx: "0"
}))))
);
} // Cancel button for non-resumable uploads if individualCancellation is supported (not bundled)

@@ -182,19 +186,23 @@

if (!props.resumableUploads && props.individualCancellation && !props.hideCancelButton) {
return h(ProgressIndicatorButton, props, h(ProgressCircleContainer, null, h(ProgressCircle, {
progress: props.file.progress.percentage
}), h("polygon", {
className: "cancel",
transform: "translate(2, 2)",
points: "19.8856516 11.0625 16 14.9481516 12.1019737 11.0625 11.0625 12.1143484 14.9481516 16 11.0625 19.8980263 12.1019737 20.9375 16 17.0518484 19.8856516 20.9375 20.9375 19.8980263 17.0518484 16 20.9375 12"
})));
return (// eslint-disable-next-line react/jsx-props-no-spreading
(0, _preact.h)(ProgressIndicatorButton, props, (0, _preact.h)(ProgressCircleContainer, null, (0, _preact.h)(ProgressCircle, {
progress: props.file.progress.percentage
}), (0, _preact.h)("polygon", {
className: "cancel",
transform: "translate(2, 2)",
points: "19.8856516 11.0625 16 14.9481516 12.1019737 11.0625 11.0625 12.1143484 14.9481516 16 11.0625 19.8980263 12.1019737 20.9375 16 17.0518484 19.8856516 20.9375 20.9375 19.8980263 17.0518484 16 20.9375 12"
})))
);
} // Just progress when buttons are disabled
return h("div", {
return (0, _preact.h)("div", {
className: "uppy-Dashboard-Item-progress"
}, h("div", {
}, (0, _preact.h)("div", {
className: "uppy-Dashboard-Item-progressIndicator"
}, h(ProgressCircleContainer, null, h(ProgressCircle, {
}, (0, _preact.h)(ProgressCircleContainer, null, (0, _preact.h)(ProgressCircle, {
progress: props.file.progress.percentage
}))));
};
}
module.exports = FileProgress;

@@ -1,19 +0,18 @@

const {
h,
Component
} = require('preact');
"use strict";
const classNames = require('classnames');
var _preact = require("preact");
const shallowEqual = require('is-shallow-equal');
const classNames = require("classnames");
const FilePreviewAndLink = require('./FilePreviewAndLink');
const shallowEqual = require("is-shallow-equal");
const FileProgress = require('./FileProgress');
const FilePreviewAndLink = require("./FilePreviewAndLink/index.js");
const FileInfo = require('./FileInfo');
const FileProgress = require("./FileProgress/index.js");
const Buttons = require('./Buttons');
const FileInfo = require("./FileInfo/index.js");
module.exports = class FileItem extends Component {
const Buttons = require("./Buttons/index.js");
class FileItem extends _preact.Component {
componentDidMount() {

@@ -85,9 +84,9 @@ const {

});
return h("div", {
return (0, _preact.h)("div", {
className: dashboardItemClass,
id: `uppy_${file.id}`,
role: this.props.role
}, h("div", {
}, (0, _preact.h)("div", {
className: "uppy-Dashboard-Item-preview"
}, h(FilePreviewAndLink, {
}, (0, _preact.h)(FilePreviewAndLink, {
file: file,

@@ -98,3 +97,3 @@ showLinkToFileUploadResult: this.props.showLinkToFileUploadResult,

metaFields: this.props.metaFields
}), h(FileProgress, {
}), (0, _preact.h)(FileProgress, {
uppy: this.props.uppy,

@@ -112,5 +111,5 @@ file: file,

i18n: this.props.i18n
})), h("div", {
})), (0, _preact.h)("div", {
className: "uppy-Dashboard-Item-fileInfoAndButtons"
}, h(FileInfo, {
}, (0, _preact.h)(FileInfo, {
file: file,

@@ -124,3 +123,3 @@ id: this.props.id,

metaFields: this.props.metaFields
}), h(Buttons, {
}), (0, _preact.h)(Buttons, {
file: file,

@@ -139,2 +138,4 @@ metaFields: this.props.metaFields,

};
}
module.exports = FileItem;

@@ -1,5 +0,5 @@

const {
h
} = require('preact');
"use strict";
var _preact = require("preact");
const metaFieldIdToName = (metaFieldId, metaFields) => {

@@ -10,3 +10,3 @@ const field = metaFields.filter(f => f.id === metaFieldId);

module.exports = function renderMissingMetaFieldsError(props) {
function renderMissingMetaFieldsError(props) {
const {

@@ -27,3 +27,3 @@ file,

const metaFieldsString = missingRequiredMetaFields.map(missingMetaField => metaFieldIdToName(missingMetaField, metaFields)).join(', ');
return h("div", {
return (0, _preact.h)("div", {
className: "uppy-Dashboard-Item-errorMessage"

@@ -33,3 +33,3 @@ }, i18n('missingRequiredMetaFields', {

fields: metaFieldsString
}), ' ', h("button", {
}), ' ', (0, _preact.h)("button", {
type: "button",

@@ -39,2 +39,4 @@ class: "uppy-u-reset uppy-Dashboard-Item-errorMessageBtn",

}, i18n('editFile')));
};
}
module.exports = renderMissingMetaFieldsError;

@@ -0,13 +1,13 @@

"use strict";
var _preact = require("preact");
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); }
const classNames = require('classnames');
const classNames = require("classnames");
const {
h
} = require('preact');
const FileItem = require("./FileItem/index.js");
const FileItem = require('./FileItem/index.js');
const VirtualList = require("./VirtualList.js");
const VirtualList = require('./VirtualList');
function chunks(list, size) {

@@ -76,9 +76,10 @@ const chunked = [];

// We use the first file ID as the key—this should not change across scroll rerenders
h("div", {
(0, _preact.h)("div", {
role: "presentation",
key: row[0]
}, row.map(fileID => h(FileItem, _extends({
}, row.map(fileID => (0, _preact.h)(FileItem, _extends({
key: fileID,
uppy: props.uppy
}, fileProps, {
// eslint-disable-line react/jsx-props-no-spreading
role: "listitem",

@@ -91,3 +92,3 @@ openFileEditor: props.openFileEditor,

return h(VirtualList, {
return (0, _preact.h)(VirtualList, {
class: dashboardFilesClass,

@@ -94,0 +95,0 @@ role: "list",

@@ -1,8 +0,8 @@

const {
h
} = require('preact');
"use strict";
const getFileTypeIcon = require('../utils/getFileTypeIcon');
var _preact = require("preact");
module.exports = function FilePreview(props) {
const getFileTypeIcon = require("../utils/getFileTypeIcon.js");
function FilePreview(props) {
const {

@@ -13,3 +13,3 @@ file

if (file.preview) {
return h("img", {
return (0, _preact.h)("img", {
className: "uppy-Dashboard-Item-previewImg",

@@ -25,5 +25,5 @@ alt: file.name,

} = getFileTypeIcon(file.type);
return h("div", {
return (0, _preact.h)("div", {
className: "uppy-Dashboard-Item-previewIconWrap"
}, h("span", {
}, (0, _preact.h)("span", {
className: "uppy-Dashboard-Item-previewIcon",

@@ -33,3 +33,3 @@ style: {

}
}, icon), h("svg", {
}, icon), (0, _preact.h)("svg", {
"aria-hidden": "true",

@@ -41,3 +41,3 @@ focusable: "false",

viewBox: "0 0 58 76"
}, h("rect", {
}, (0, _preact.h)("rect", {
fill: "#FFF",

@@ -49,2 +49,4 @@ width: "58",

})));
};
}
module.exports = FilePreview;

@@ -1,15 +0,23 @@

const {
h
} = require('preact');
"use strict";
const classNames = require('classnames');
var _preact = require("preact");
const ignoreEvent = require('../utils/ignoreEvent.js');
const classNames = require("classnames");
function PickerPanelContent(props) {
return h("div", {
className: classNames('uppy-DashboardContent-panel', props.className),
const ignoreEvent = require("../utils/ignoreEvent.js");
function PickerPanelContent(_ref) {
let {
activePickerPanel,
className,
hideAllPanels,
i18n,
state,
uppy
} = _ref;
return (0, _preact.h)("div", {
className: classNames('uppy-DashboardContent-panel', className),
role: "tabpanel",
"data-uppy-panelType": "PickerPanel",
id: `uppy-DashboardContent-panel--${props.activePickerPanel.id}`,
id: `uppy-DashboardContent-panel--${activePickerPanel.id}`,
onDragOver: ignoreEvent,

@@ -19,19 +27,19 @@ onDragLeave: ignoreEvent,

onPaste: ignoreEvent
}, h("div", {
}, (0, _preact.h)("div", {
className: "uppy-DashboardContent-bar"
}, h("div", {
}, (0, _preact.h)("div", {
className: "uppy-DashboardContent-title",
role: "heading",
"aria-level": "1"
}, props.i18n('importFrom', {
name: props.activePickerPanel.name
})), h("button", {
}, i18n('importFrom', {
name: activePickerPanel.name
})), (0, _preact.h)("button", {
className: "uppy-DashboardContent-back",
type: "button",
onClick: props.hideAllPanels
}, props.i18n('cancel'))), h("div", {
onClick: hideAllPanels
}, i18n('cancel'))), (0, _preact.h)("div", {
className: "uppy-DashboardContent-panelBody"
}, props.uppy.getPlugin(props.activePickerPanel.id).render(props.state)));
}, uppy.getPlugin(activePickerPanel.id).render(state)));
}
module.exports = PickerPanelContent;

@@ -1,5 +0,5 @@

const {
h
} = require('preact');
"use strict";
var _preact = require("preact");
const uploadStates = {

@@ -60,9 +60,19 @@ STATE_ERROR: 'error',

function UploadStatus(props) {
const uploadingState = getUploadingState(props.isAllErrored, props.isAllComplete, props.isAllPaused, props.files);
function UploadStatus(_ref) {
let {
files,
i18n,
isAllComplete,
isAllErrored,
isAllPaused,
inProgressNotPausedFiles,
newFiles,
processingFiles
} = _ref;
const uploadingState = getUploadingState(isAllErrored, isAllComplete, isAllPaused, files);
switch (uploadingState) {
case 'uploading':
return props.i18n('uploadingXFiles', {
smart_count: props.inProgressNotPausedFiles.length
return i18n('uploadingXFiles', {
smart_count: inProgressNotPausedFiles.length
});

@@ -72,16 +82,18 @@

case 'postprocessing':
return props.i18n('processingXFiles', {
smart_count: props.processingFiles.length
return i18n('processingXFiles', {
smart_count: processingFiles.length
});
case 'paused':
return props.i18n('uploadPaused');
return i18n('uploadPaused');
case 'waiting':
return props.i18n('xFilesSelected', {
smart_count: props.newFiles.length
return i18n('xFilesSelected', {
smart_count: newFiles.length
});
case 'complete':
return props.i18n('uploadComplete');
return i18n('uploadComplete');
default:
}

@@ -91,27 +103,36 @@ }

function PanelTopBar(props) {
const {
i18n,
isAllComplete,
hideCancelButton,
maxNumberOfFiles,
toggleAddFilesPanel,
uppy
} = props;
let {
allowNewUpload
} = props; // TODO maybe this should be done in ../index.js, then just pass that down as `allowNewUpload`
} = props; // TODO maybe this should be done in ../Dashboard.jsx, then just pass that down as `allowNewUpload`
if (allowNewUpload && props.maxNumberOfFiles) {
if (allowNewUpload && maxNumberOfFiles) {
// eslint-disable-next-line react/destructuring-assignment
allowNewUpload = props.totalFileCount < props.maxNumberOfFiles;
}
return h("div", {
return (0, _preact.h)("div", {
className: "uppy-DashboardContent-bar"
}, !props.isAllComplete && !props.hideCancelButton ? h("button", {
}, !isAllComplete && !hideCancelButton ? (0, _preact.h)("button", {
className: "uppy-DashboardContent-back",
type: "button",
onClick: () => props.uppy.cancelAll()
}, props.i18n('cancel')) : h("div", null), h("div", {
onClick: () => uppy.cancelAll()
}, i18n('cancel')) : (0, _preact.h)("div", null), (0, _preact.h)("div", {
className: "uppy-DashboardContent-title",
role: "heading",
"aria-level": "1"
}, h(UploadStatus, props)), allowNewUpload ? h("button", {
}, (0, _preact.h)(UploadStatus, props)), allowNewUpload ? (0, _preact.h)("button", {
className: "uppy-DashboardContent-addMore",
type: "button",
"aria-label": props.i18n('addMoreFiles'),
title: props.i18n('addMoreFiles'),
onClick: () => props.toggleAddFilesPanel(true)
}, h("svg", {
"aria-label": i18n('addMoreFiles'),
title: i18n('addMoreFiles'),
onClick: () => toggleAddFilesPanel(true)
}, (0, _preact.h)("svg", {
"aria-hidden": "true",

@@ -123,9 +144,9 @@ focusable: "false",

viewBox: "0 0 15 15"
}, h("path", {
}, (0, _preact.h)("path", {
d: "M8 6.5h6a.5.5 0 0 1 .5.5v.5a.5.5 0 0 1-.5.5H8v6a.5.5 0 0 1-.5.5H7a.5.5 0 0 1-.5-.5V8h-6a.5.5 0 0 1-.5-.5V7a.5.5 0 0 1 .5-.5h6v-6A.5.5 0 0 1 7 0h.5a.5.5 0 0 1 .5.5v6z"
})), h("span", {
})), (0, _preact.h)("span", {
className: "uppy-DashboardContent-addMoreCaption"
}, props.i18n('addMore'))) : h("div", null));
}, i18n('addMore'))) : (0, _preact.h)("div", null));
}
module.exports = PanelTopBar;

@@ -1,9 +0,7 @@

const {
cloneElement,
Component,
toChildArray
} = require('preact');
"use strict";
const classNames = require('classnames');
var _preact = require("preact");
const classNames = require("classnames");
const transitionName = 'uppy-transition-slideDownUp';

@@ -21,3 +19,3 @@ const duration = 250;

class Slide extends Component {
class Slide extends _preact.Component {
constructor(props) {

@@ -37,3 +35,3 @@ super(props);

} = this.state;
const child = toChildArray(nextProps.children)[0];
const child = (0, _preact.toChildArray)(nextProps.children)[0];
if (cachedChildren === child) return null;

@@ -97,3 +95,3 @@ const patch = {

return cloneElement(cachedChildren, {
return (0, _preact.cloneElement)(cachedChildren, {
className: classNames(className, cachedChildren.props.className)

@@ -100,0 +98,0 @@ });

@@ -0,35 +1,7 @@

"use strict";
var _preact = require("preact");
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); }
/**
* Adapted from preact-virtual-list: https://github.com/developit/preact-virtual-list
*
* © 2016 Jason Miller
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Adaptations:
* - Added role=presentation to helper elements
* - Tweaked styles for Uppy's Dashboard use case
*/
const {
h,
Component
} = require('preact');
const STYLE_INNER = {

@@ -57,3 +29,3 @@ position: 'relative',

class VirtualList extends Component {
class VirtualList extends _preact.Component {
constructor(props) {

@@ -154,11 +126,13 @@ super(props); // The currently focused node, used to retain focus when the visible rows change.

return h("div", _extends({
onScroll: this.handleScroll
}, props), h("div", {
role: "presentation",
style: styleInner
}, h("div", {
role: "presentation",
style: styleContent
}, selection.map(renderRow))));
return (// eslint-disable-next-line react/jsx-props-no-spreading
(0, _preact.h)("div", _extends({
onScroll: this.handleScroll
}, props), (0, _preact.h)("div", {
role: "presentation",
style: styleInner
}, (0, _preact.h)("div", {
role: "presentation",
style: styleContent
}, selection.map(renderRow))))
);
}

@@ -165,0 +139,0 @@

@@ -1,1164 +0,3 @@

var _class, _openFileEditorWhenFilesAdded, _attachRenderFunctionToTarget, _isTargetSupported, _getAcquirers, _getProgressIndicators, _getEditors, _temp;
"use strict";
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; }
const {
h
} = require('preact');
const {
UIPlugin
} = require('@uppy/core');
const StatusBar = require('@uppy/status-bar');
const Informer = require('@uppy/informer');
const ThumbnailGenerator = require('@uppy/thumbnail-generator');
const findAllDOMElements = require('@uppy/utils/lib/findAllDOMElements');
const toArray = require('@uppy/utils/lib/toArray');
const getDroppedFiles = require('@uppy/utils/lib/getDroppedFiles');
const {
nanoid
} = require('nanoid/non-secure');
const trapFocus = require('./utils/trapFocus');
const createSuperFocus = require('./utils/createSuperFocus');
const memoize = require('memoize-one').default || require('memoize-one');
const FOCUSABLE_ELEMENTS = require('@uppy/utils/lib/FOCUSABLE_ELEMENTS');
const DashboardUI = require('./components/Dashboard');
const locale = require('./locale');
const TAB_KEY = 9;
const ESC_KEY = 27;
function createPromise() {
const o = {};
o.promise = new Promise((resolve, reject) => {
o.resolve = resolve;
o.reject = reject;
});
return o;
}
function defaultPickerIcon() {
return h("svg", {
"aria-hidden": "true",
focusable: "false",
width: "30",
height: "30",
viewBox: "0 0 30 30"
}, h("path", {
d: "M15 30c8.284 0 15-6.716 15-15 0-8.284-6.716-15-15-15C6.716 0 0 6.716 0 15c0 8.284 6.716 15 15 15zm4.258-12.676v6.846h-8.426v-6.846H5.204l9.82-12.364 9.82 12.364H19.26z"
}));
}
/**
* Dashboard UI with previews, metadata editing, tabs for various services and more
*/
module.exports = (_temp = (_openFileEditorWhenFilesAdded = /*#__PURE__*/_classPrivateFieldLooseKey("openFileEditorWhenFilesAdded"), _attachRenderFunctionToTarget = /*#__PURE__*/_classPrivateFieldLooseKey("attachRenderFunctionToTarget"), _isTargetSupported = /*#__PURE__*/_classPrivateFieldLooseKey("isTargetSupported"), _getAcquirers = /*#__PURE__*/_classPrivateFieldLooseKey("getAcquirers"), _getProgressIndicators = /*#__PURE__*/_classPrivateFieldLooseKey("getProgressIndicators"), _getEditors = /*#__PURE__*/_classPrivateFieldLooseKey("getEditors"), _class = class Dashboard extends UIPlugin {
constructor(uppy, _opts) {
var _this;
super(uppy, _opts);
_this = this;
this.removeTarget = plugin => {
const pluginState = this.getPluginState(); // filter out the one we want to remove
const newTargets = pluginState.targets.filter(target => target.id !== plugin.id);
this.setPluginState({
targets: newTargets
});
};
this.addTarget = plugin => {
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';
this.uppy.log(msg, 'error');
return;
}
const target = {
id: callerPluginId,
name: callerPluginName,
type: callerPluginType
};
const state = this.getPluginState();
const newTargets = state.targets.slice();
newTargets.push(target);
this.setPluginState({
targets: newTargets
});
return this.el;
};
this.hideAllPanels = () => {
const state = this.getPluginState();
const update = {
activePickerPanel: false,
showAddFilesPanel: false,
activeOverlayType: null,
fileCardFor: null,
showFileEditor: false
};
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;
}
this.setPluginState(update);
};
this.showPanel = id => {
const {
targets
} = this.getPluginState();
const activePickerPanel = targets.filter(target => {
return target.type === 'acquirer' && target.id === id;
})[0];
this.setPluginState({
activePickerPanel,
activeOverlayType: 'PickerPanel'
});
};
this.canEditFile = file => {
const {
targets
} = this.getPluginState();
const editors = _classPrivateFieldLooseBase(this, _getEditors)[_getEditors](targets);
return editors.some(target => this.uppy.getPlugin(target.id).canEditFile(file));
};
this.openFileEditor = file => {
const {
targets
} = this.getPluginState();
const editors = _classPrivateFieldLooseBase(this, _getEditors)[_getEditors](targets);
this.setPluginState({
showFileEditor: true,
fileCardFor: file.id || null,
activeOverlayType: 'FileEditor'
});
editors.forEach(editor => {
this.uppy.getPlugin(editor.id).selectFile(file);
});
};
this.saveFileEditor = () => {
const {
targets
} = this.getPluginState();
const editors = _classPrivateFieldLooseBase(this, _getEditors)[_getEditors](targets);
editors.forEach(editor => {
this.uppy.getPlugin(editor.id).save();
});
this.hideAllPanels();
};
this.openModal = () => {
const {
promise,
resolve
} = createPromise(); // save scroll position
this.savedScrollPosition = window.pageYOffset; // save active element, so we can restore focus when modal is closed
this.savedActiveElement = document.activeElement;
if (this.opts.disablePageScrollWhenModalOpen) {
document.body.classList.add('uppy-Dashboard-isFixed');
}
if (this.opts.animateOpenClose && this.getPluginState().isClosing) {
const handler = () => {
this.setPluginState({
isHidden: false
});
this.el.removeEventListener('animationend', handler, false);
resolve();
};
this.el.addEventListener('animationend', handler, false);
} else {
this.setPluginState({
isHidden: false
});
resolve();
}
if (this.opts.browserBackButtonClose) {
this.updateBrowserHistory();
} // handle ESC and TAB keys in modal dialog
document.addEventListener('keydown', this.handleKeyDownInModal);
this.uppy.emit('dashboard:modal-open');
return promise;
};
this.closeModal = function (opts) {
if (opts === void 0) {
opts = {};
}
const {
// Whether the modal is being closed by the user (`true`) or by other means (e.g. browser back button)
manualClose = true
} = opts;
const {
isHidden,
isClosing
} = _this.getPluginState();
if (isHidden || isClosing) {
// short-circuit if animation is ongoing
return;
}
const {
promise,
resolve
} = createPromise();
if (_this.opts.disablePageScrollWhenModalOpen) {
document.body.classList.remove('uppy-Dashboard-isFixed');
}
if (_this.opts.animateOpenClose) {
_this.setPluginState({
isClosing: true
});
const handler = () => {
_this.setPluginState({
isHidden: true,
isClosing: false
});
_this.superFocus.cancel();
_this.savedActiveElement.focus();
_this.el.removeEventListener('animationend', handler, false);
resolve();
};
_this.el.addEventListener('animationend', handler, false);
} else {
_this.setPluginState({
isHidden: true
});
_this.superFocus.cancel();
_this.savedActiveElement.focus();
resolve();
} // handle ESC and TAB keys in modal dialog
document.removeEventListener('keydown', _this.handleKeyDownInModal);
if (manualClose) {
if (_this.opts.browserBackButtonClose) {
var _history$state;
// Make sure that the latest entry in the history state is our modal name
// eslint-disable-next-line no-restricted-globals
if ((_history$state = history.state) != null && _history$state[_this.modalName]) {
// Go back in history to clear out the entry we created (ultimately closing the modal)
// eslint-disable-next-line no-restricted-globals
history.back();
}
}
}
_this.uppy.emit('dashboard:modal-closed');
return promise;
};
this.isModalOpen = () => {
return !this.getPluginState().isHidden || false;
};
this.requestCloseModal = () => {
if (this.opts.onRequestCloseModal) {
return this.opts.onRequestCloseModal();
}
return this.closeModal();
};
this.setDarkModeCapability = isDarkModeOn => {
const {
capabilities
} = this.uppy.getState();
this.uppy.setState({
capabilities: { ...capabilities,
darkMode: isDarkModeOn
}
});
};
this.handleSystemDarkModeChange = event => {
const isDarkModeOnNow = event.matches;
this.uppy.log(`[Dashboard] Dark mode is ${isDarkModeOnNow ? 'on' : 'off'}`);
this.setDarkModeCapability(isDarkModeOnNow);
};
this.toggleFileCard = (show, fileID) => {
const file = this.uppy.getFile(fileID);
if (show) {
this.uppy.emit('dashboard:file-edit-start', file);
} else {
this.uppy.emit('dashboard:file-edit-complete', file);
}
this.setPluginState({
fileCardFor: show ? fileID : null,
activeOverlayType: show ? 'FileCard' : null
});
};
this.toggleAddFilesPanel = show => {
this.setPluginState({
showAddFilesPanel: show,
activeOverlayType: show ? 'AddFiles' : null
});
};
this.addFiles = files => {
const descriptors = files.map(file => ({
source: this.id,
name: file.name,
type: file.type,
data: file,
meta: {
// path of the file relative to the ancestor directory the user selected.
// e.g. 'docs/Old Prague/airbnb.pdf'
relativePath: file.relativePath || null
}
}));
try {
this.uppy.addFiles(descriptors);
} catch (err) {
this.uppy.log(err);
}
};
this.startListeningToResize = () => {
// Watch for Dashboard container (`.uppy-Dashboard-inner`) resize
// and update containerWidth/containerHeight in plugin state accordingly.
// Emits first event on initialization.
this.resizeObserver = new ResizeObserver(entries => {
const uppyDashboardInnerEl = entries[0];
const {
width,
height
} = uppyDashboardInnerEl.contentRect;
this.uppy.log(`[Dashboard] resized: ${width} / ${height}`, 'debug');
this.setPluginState({
containerWidth: width,
containerHeight: height,
areInsidesReadyToBeVisible: true
});
});
this.resizeObserver.observe(this.el.querySelector('.uppy-Dashboard-inner')); // If ResizeObserver fails to emit an event telling us what size to use - default to the mobile view
this.makeDashboardInsidesVisibleAnywayTimeout = setTimeout(() => {
const pluginState = this.getPluginState();
const isModalAndClosed = !this.opts.inline && pluginState.isHidden;
if ( // if ResizeObserver hasn't yet fired,
!pluginState.areInsidesReadyToBeVisible // and it's not due to the modal being closed
&& !isModalAndClosed) {
this.uppy.log("[Dashboard] resize event didn't fire on time: defaulted to mobile layout", 'debug');
this.setPluginState({
areInsidesReadyToBeVisible: true
});
}
}, 1000);
};
this.stopListeningToResize = () => {
this.resizeObserver.disconnect();
clearTimeout(this.makeDashboardInsidesVisibleAnywayTimeout);
};
this.recordIfFocusedOnUppyRecently = event => {
if (this.el.contains(event.target)) {
this.ifFocusedOnUppyRecently = true;
} else {
this.ifFocusedOnUppyRecently = false; // ___Why run this.superFocus.cancel here when it already runs in superFocusOnEachUpdate?
// Because superFocus is debounced, when we move from Uppy to some other element on the page,
// previously run superFocus sometimes hits and moves focus back to Uppy.
this.superFocus.cancel();
}
};
this.disableAllFocusableElements = disable => {
const focusableNodes = toArray(this.el.querySelectorAll(FOCUSABLE_ELEMENTS));
if (disable) {
focusableNodes.forEach(node => {
// save previous tabindex in a data-attribute, to restore when enabling
const currentTabIndex = node.getAttribute('tabindex');
if (currentTabIndex) {
node.dataset.inertTabindex = currentTabIndex;
}
node.setAttribute('tabindex', '-1');
});
} else {
focusableNodes.forEach(node => {
if ('inertTabindex' in node.dataset) {
node.setAttribute('tabindex', node.dataset.inertTabindex);
} else {
node.removeAttribute('tabindex');
}
});
}
this.dashboardIsDisabled = disable;
};
this.updateBrowserHistory = () => {
var _history$state2;
// Ensure history state does not already contain our modal name to avoid double-pushing
// eslint-disable-next-line no-restricted-globals
if (!((_history$state2 = history.state) != null && _history$state2[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
}, '');
} // Listen for back button presses
window.addEventListener('popstate', this.handlePopState, false);
};
this.handlePopState = event => {
var _event$state;
// Close the modal if the history state no longer contains our modal name
if (this.isModalOpen() && (!event.state || !event.state[this.modalName])) {
this.closeModal({
manualClose: false
});
} // When the browser back button is pressed and uppy is now the latest entry
// in the history but the modal is closed, fix the history by removing the
// uppy history entry.
// This occurs when another entry is added into the history state while the
// modal is open, and then the modal gets manually closed.
// Solves PR #575 (https://github.com/transloadit/uppy/pull/575)
if (!this.isModalOpen() && (_event$state = event.state) != null && _event$state[this.modalName]) {
// eslint-disable-next-line no-restricted-globals
history.back();
}
};
this.handleKeyDownInModal = event => {
// 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);
};
this.handleClickOutside = () => {
if (this.opts.closeModalOnClickOutside) this.requestCloseModal();
};
this.handlePaste = event => {
// Let any acquirer plugin (Url/Webcam/etc.) handle pastes to the root
this.uppy.iteratePlugins(plugin => {
if (plugin.type === 'acquirer') {
// Every Plugin with .type acquirer can define handleRootPaste(event)
plugin.handleRootPaste == null ? void 0 : plugin.handleRootPaste(event);
}
}); // Add all dropped files
const files = toArray(event.clipboardData.files);
if (files.length > 0) {
this.uppy.log('[Dashboard] Files pasted');
this.addFiles(files);
}
};
this.handleInputChange = event => {
event.preventDefault();
const files = toArray(event.target.files);
if (files.length > 0) {
this.uppy.log('[Dashboard] Files selected through input');
this.addFiles(files);
}
};
this.handleDragOver = event => {
var _this$opts$onDragOver, _this$opts;
event.preventDefault();
event.stopPropagation(); // Check if some plugin can handle the datatransfer without files —
// for instance, the Url plugin can import a url
const canSomePluginHandleRootDrop = () => {
let somePluginCanHandleRootDrop = true;
this.uppy.iteratePlugins(plugin => {
if (plugin.canHandleRootDrop != null && plugin.canHandleRootDrop(event)) {
somePluginCanHandleRootDrop = true;
}
});
return somePluginCanHandleRootDrop;
}; // Check if the "type" of the datatransfer object includes files
const doesEventHaveFiles = () => {
const {
types
} = event.dataTransfer;
return types.some(type => type === 'Files');
}; // Deny drop, if no plugins can handle datatransfer, there are no files,
// or when opts.disabled is set, or new uploads are not allowed
const somePluginCanHandleRootDrop = canSomePluginHandleRootDrop(event);
const hasFiles = doesEventHaveFiles(event);
if (!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) {
event.dataTransfer.dropEffect = 'none';
clearTimeout(this.removeDragOverClassTimeout);
return;
} // Add a small (+) icon on drop
// (and prevent browsers from interpreting this as files being _moved_ into the
// browser, https://github.com/transloadit/uppy/issues/1978).
event.dataTransfer.dropEffect = 'copy';
clearTimeout(this.removeDragOverClassTimeout);
this.setPluginState({
isDraggingOver: true
});
(_this$opts$onDragOver = (_this$opts = this.opts).onDragOver) == null ? void 0 : _this$opts$onDragOver.call(_this$opts, event);
};
this.handleDragLeave = event => {
var _this$opts$onDragLeav, _this$opts2;
event.preventDefault();
event.stopPropagation();
clearTimeout(this.removeDragOverClassTimeout); // Timeout against flickering, this solution is taken from drag-drop library.
// Solution with 'pointer-events: none' didn't work across browsers.
this.removeDragOverClassTimeout = setTimeout(() => {
this.setPluginState({
isDraggingOver: false
});
}, 50);
(_this$opts$onDragLeav = (_this$opts2 = this.opts).onDragLeave) == null ? void 0 : _this$opts$onDragLeav.call(_this$opts2, event);
};
this.handleDrop = async event => {
var _this$opts$onDrop, _this$opts3;
event.preventDefault();
event.stopPropagation();
clearTimeout(this.removeDragOverClassTimeout);
this.setPluginState({
isDraggingOver: false
}); // Let any acquirer plugin (Url/Webcam/etc.) handle drops to the root
this.uppy.iteratePlugins(plugin => {
if (plugin.type === 'acquirer') {
// Every Plugin with .type acquirer can define handleRootDrop(event)
plugin.handleRootDrop == null ? void 0 : plugin.handleRootDrop(event);
}
}); // Add all dropped files
let executedDropErrorOnce = false;
const logDropError = error => {
this.uppy.log(error, 'error'); // In practice all drop errors are most likely the same,
// so let's just show one to avoid overwhelming the user
if (!executedDropErrorOnce) {
this.uppy.info(error.message, 'error');
executedDropErrorOnce = true;
}
}; // Add all dropped files
const files = await getDroppedFiles(event.dataTransfer, {
logDropError
});
if (files.length > 0) {
this.uppy.log('[Dashboard] Files dropped');
this.addFiles(files);
}
(_this$opts$onDrop = (_this$opts3 = this.opts).onDrop) == null ? void 0 : _this$opts$onDrop.call(_this$opts3, event);
};
this.handleRequestThumbnail = file => {
if (!this.opts.waitForThumbnailsBeforeUpload) {
this.uppy.emit('thumbnail:request', file);
}
};
this.handleCancelThumbnail = file => {
if (!this.opts.waitForThumbnailsBeforeUpload) {
this.uppy.emit('thumbnail:cancel', file);
}
};
this.handleKeyDownInInline = event => {
// Trap focus on tab key press.
if (event.keyCode === TAB_KEY) trapFocus.forInline(event, this.getPluginState().activeOverlayType, this.el);
};
this.handlePasteOnBody = event => {
const isFocusInOverlay = this.el.contains(document.activeElement);
if (isFocusInOverlay) {
this.handlePaste(event);
}
};
this.handleComplete = _ref => {
let {
failed
} = _ref;
if (this.opts.closeAfterFinish && failed.length === 0) {
// All uploads are done
this.requestCloseModal();
}
};
this.handleCancelRestore = () => {
this.uppy.emit('restore-canceled');
};
Object.defineProperty(this, _openFileEditorWhenFilesAdded, {
writable: true,
value: files => {
const firstFile = files[0];
if (this.canEditFile(firstFile)) {
this.openFileEditor(firstFile);
}
}
});
this.initEvents = () => {
// Modal open button
if (this.opts.trigger && !this.opts.inline) {
const showModalTrigger = findAllDOMElements(this.opts.trigger);
if (showModalTrigger) {
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.startListeningToResize();
document.addEventListener('paste', this.handlePasteOnBody);
this.uppy.on('plugin-remove', this.removeTarget);
this.uppy.on('file-added', this.hideAllPanels);
this.uppy.on('dashboard:modal-closed', this.hideAllPanels);
this.uppy.on('file-editor:complete', this.hideAllPanels);
this.uppy.on('complete', this.handleComplete); // ___Why fire on capture?
// Because this.ifFocusedOnUppyRecently needs to change before onUpdate() fires.
document.addEventListener('focus', this.recordIfFocusedOnUppyRecently, true);
document.addEventListener('click', this.recordIfFocusedOnUppyRecently, true);
if (this.opts.inline) {
this.el.addEventListener('keydown', this.handleKeyDownInInline);
}
if (this.opts.autoOpenFileEditor) {
this.uppy.on('files-added', _classPrivateFieldLooseBase(this, _openFileEditorWhenFilesAdded)[_openFileEditorWhenFilesAdded]);
}
};
this.removeEvents = () => {
const showModalTrigger = findAllDOMElements(this.opts.trigger);
if (!this.opts.inline && showModalTrigger) {
showModalTrigger.forEach(trigger => trigger.removeEventListener('click', this.openModal));
}
this.stopListeningToResize();
document.removeEventListener('paste', this.handlePasteOnBody);
window.removeEventListener('popstate', this.handlePopState, false);
this.uppy.off('plugin-remove', this.removeTarget);
this.uppy.off('file-added', this.hideAllPanels);
this.uppy.off('dashboard:modal-closed', this.hideAllPanels);
this.uppy.off('file-editor:complete', this.hideAllPanels);
this.uppy.off('complete', this.handleComplete);
document.removeEventListener('focus', this.recordIfFocusedOnUppyRecently);
document.removeEventListener('click', this.recordIfFocusedOnUppyRecently);
if (this.opts.inline) {
this.el.removeEventListener('keydown', this.handleKeyDownInInline);
}
if (this.opts.autoOpenFileEditor) {
this.uppy.off('files-added', _classPrivateFieldLooseBase(this, _openFileEditorWhenFilesAdded)[_openFileEditorWhenFilesAdded]);
}
};
this.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 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 // If we are already inside of Uppy, or
|| 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
// something somewhere else on the page, - focus won't be 'nowhere'.
// 2. We only focus when focus is nowhere AND this.ifFocusedOnUppyRecently,
// to avoid focus jumps if we do something else on the page.
// [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)) {
this.superFocus(this.el, this.getPluginState().activeOverlayType);
} else {
this.superFocus.cancel();
}
};
this.afterUpdate = () => {
if (this.opts.disabled && !this.dashboardIsDisabled) {
this.disableAllFocusableElements(true);
return;
}
if (!this.opts.disabled && this.dashboardIsDisabled) {
this.disableAllFocusableElements(false);
}
this.superFocusOnEachUpdate();
};
this.saveFileCard = (meta, fileID) => {
this.uppy.setFileMeta(fileID, meta);
this.toggleFileCard(false, fileID);
};
Object.defineProperty(this, _attachRenderFunctionToTarget, {
writable: true,
value: target => {
const plugin = this.uppy.getPlugin(target.id);
return { ...target,
icon: plugin.icon || this.opts.defaultPickerIcon,
render: plugin.render
};
}
});
Object.defineProperty(this, _isTargetSupported, {
writable: true,
value: target => {
const plugin = this.uppy.getPlugin(target.id); // If the plugin does not provide a `supported` check, assume the plugin works everywhere.
if (typeof plugin.isSupported !== 'function') {
return true;
}
return plugin.isSupported();
}
});
Object.defineProperty(this, _getAcquirers, {
writable: true,
value: memoize(targets => {
return targets.filter(target => target.type === 'acquirer' && _classPrivateFieldLooseBase(this, _isTargetSupported)[_isTargetSupported](target)).map(_classPrivateFieldLooseBase(this, _attachRenderFunctionToTarget)[_attachRenderFunctionToTarget]);
})
});
Object.defineProperty(this, _getProgressIndicators, {
writable: true,
value: memoize(targets => {
return targets.filter(target => target.type === 'progressindicator').map(_classPrivateFieldLooseBase(this, _attachRenderFunctionToTarget)[_attachRenderFunctionToTarget]);
})
});
Object.defineProperty(this, _getEditors, {
writable: true,
value: memoize(targets => {
return targets.filter(target => target.type === 'editor').map(_classPrivateFieldLooseBase(this, _attachRenderFunctionToTarget)[_attachRenderFunctionToTarget]);
})
});
this.render = state => {
const pluginState = this.getPluginState();
const {
files,
capabilities,
allowNewUpload
} = state;
const {
newFiles,
uploadStartedFiles,
completeFiles,
erroredFiles,
inProgressFiles,
inProgressNotPausedFiles,
processingFiles,
isUploadStarted,
isAllComplete,
isAllErrored,
isAllPaused
} = this.uppy.getObjectOfFilesPerState();
const acquirers = _classPrivateFieldLooseBase(this, _getAcquirers)[_getAcquirers](pluginState.targets);
const progressindicators = _classPrivateFieldLooseBase(this, _getProgressIndicators)[_getProgressIndicators](pluginState.targets);
const editors = _classPrivateFieldLooseBase(this, _getEditors)[_getEditors](pluginState.targets);
let theme;
if (this.opts.theme === 'auto') {
theme = capabilities.darkMode ? 'dark' : 'light';
} else {
theme = this.opts.theme;
}
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}".`);
}
return DashboardUI({
state,
isHidden: pluginState.isHidden,
files,
newFiles,
uploadStartedFiles,
completeFiles,
erroredFiles,
inProgressFiles,
inProgressNotPausedFiles,
processingFiles,
isUploadStarted,
isAllComplete,
isAllErrored,
isAllPaused,
totalFileCount: Object.keys(files).length,
totalProgress: state.totalProgress,
allowNewUpload,
acquirers,
theme,
disabled: this.opts.disabled,
disableLocalFiles: this.opts.disableLocalFiles,
direction: this.opts.direction,
activePickerPanel: pluginState.activePickerPanel,
showFileEditor: pluginState.showFileEditor,
saveFileEditor: this.saveFileEditor,
disableAllFocusableElements: this.disableAllFocusableElements,
animateOpenClose: this.opts.animateOpenClose,
isClosing: pluginState.isClosing,
progressindicators,
editors,
autoProceed: this.uppy.opts.autoProceed,
id: this.id,
closeModal: this.requestCloseModal,
handleClickOutside: this.handleClickOutside,
handleInputChange: this.handleInputChange,
handlePaste: this.handlePaste,
inline: this.opts.inline,
showPanel: this.showPanel,
hideAllPanels: this.hideAllPanels,
i18n: this.i18n,
i18nArray: this.i18nArray,
uppy: this.uppy,
note: this.opts.note,
recoveredState: state.recoveredState,
metaFields: pluginState.metaFields,
resumableUploads: capabilities.resumableUploads || false,
individualCancellation: capabilities.individualCancellation,
isMobileDevice: capabilities.isMobileDevice,
fileCardFor: pluginState.fileCardFor,
toggleFileCard: this.toggleFileCard,
toggleAddFilesPanel: this.toggleAddFilesPanel,
showAddFilesPanel: pluginState.showAddFilesPanel,
saveFileCard: this.saveFileCard,
openFileEditor: this.openFileEditor,
canEditFile: this.canEditFile,
width: this.opts.width,
height: this.opts.height,
showLinkToFileUploadResult: this.opts.showLinkToFileUploadResult,
fileManagerSelectionType: this.opts.fileManagerSelectionType,
proudlyDisplayPoweredByUppy: this.opts.proudlyDisplayPoweredByUppy,
hideCancelButton: this.opts.hideCancelButton,
hideRetryButton: this.opts.hideRetryButton,
hidePauseResumeButton: this.opts.hidePauseResumeButton,
showRemoveButtonAfterComplete: this.opts.showRemoveButtonAfterComplete,
containerWidth: pluginState.containerWidth,
containerHeight: pluginState.containerHeight,
areInsidesReadyToBeVisible: pluginState.areInsidesReadyToBeVisible,
isTargetDOMEl: this.isTargetDOMEl,
parentElement: this.el,
allowedFileTypes: this.uppy.opts.restrictions.allowedFileTypes,
maxNumberOfFiles: this.uppy.opts.restrictions.maxNumberOfFiles,
requiredMetaFields: this.uppy.opts.restrictions.requiredMetaFields,
showSelectedFiles: this.opts.showSelectedFiles,
handleCancelRestore: this.handleCancelRestore,
handleRequestThumbnail: this.handleRequestThumbnail,
handleCancelThumbnail: this.handleCancelThumbnail,
// drag props
isDraggingOver: pluginState.isDraggingOver,
handleDragOver: this.handleDragOver,
handleDragLeave: this.handleDragLeave,
handleDrop: this.handleDrop
});
};
this.discoverProviderPlugins = () => {
this.uppy.iteratePlugins(plugin => {
if (plugin && !plugin.target && plugin.opts && plugin.opts.target === this.constructor) {
this.addTarget(plugin);
}
});
};
this.install = () => {
// Set default state for Dashboard
this.setPluginState({
isHidden: true,
fileCardFor: null,
activeOverlayType: null,
showAddFilesPanel: false,
activePickerPanel: false,
showFileEditor: false,
metaFields: this.opts.metaFields,
targets: [],
// We'll make them visible once .containerWidth is determined
areInsidesReadyToBeVisible: false,
isDraggingOver: false
});
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.');
}
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');
}
const {
target
} = this.opts;
if (target) {
this.mount(target, this);
}
const plugins = this.opts.plugins || [];
plugins.forEach(pluginID => {
const plugin = this.uppy.getPlugin(pluginID);
if (plugin) {
plugin.mount(this, plugin);
}
});
if (!this.opts.disableStatusBar) {
this.uppy.use(StatusBar, {
id: `${this.id}:StatusBar`,
target: this,
hideUploadButton: this.opts.hideUploadButton,
hideRetryButton: this.opts.hideRetryButton,
hidePauseResumeButton: this.opts.hidePauseResumeButton,
hideCancelButton: this.opts.hideCancelButton,
showProgressDetails: this.opts.showProgressDetails,
hideAfterFinish: this.opts.hideProgressAfterFinish,
locale: this.opts.locale,
doneButtonHandler: this.opts.doneButtonHandler
});
}
if (!this.opts.disableInformer) {
this.uppy.use(Informer, {
id: `${this.id}:Informer`,
target: this
});
}
if (!this.opts.disableThumbnailGenerator) {
this.uppy.use(ThumbnailGenerator, {
id: `${this.id}:ThumbnailGenerator`,
thumbnailWidth: this.opts.thumbnailWidth,
thumbnailHeight: this.opts.thumbnailHeight,
thumbnailType: this.opts.thumbnailType,
waitForThumbnailsBeforeUpload: this.opts.waitForThumbnailsBeforeUpload,
// If we don't block on thumbnails, we can lazily generate them
lazy: !this.opts.waitForThumbnailsBeforeUpload
});
} // Dark Mode / theme
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'}`);
this.setDarkModeCapability(isDarkModeOnFromTheStart);
if (this.opts.theme === 'auto') {
this.darkModeMediaQuery.addListener(this.handleSystemDarkModeChange);
}
this.discoverProviderPlugins();
this.initEvents();
};
this.uninstall = () => {
if (!this.opts.disableInformer) {
const informer = this.uppy.getPlugin(`${this.id}:Informer`); // Checking if this plugin exists, in case it was removed by uppy-core
// before the Dashboard was.
if (informer) this.uppy.removePlugin(informer);
}
if (!this.opts.disableStatusBar) {
const statusBar = this.uppy.getPlugin(`${this.id}:StatusBar`);
if (statusBar) this.uppy.removePlugin(statusBar);
}
if (!this.opts.disableThumbnailGenerator) {
const thumbnail = this.uppy.getPlugin(`${this.id}:ThumbnailGenerator`);
if (thumbnail) this.uppy.removePlugin(thumbnail);
}
const plugins = this.opts.plugins || [];
plugins.forEach(pluginID => {
const plugin = this.uppy.getPlugin(pluginID);
if (plugin) plugin.unmount();
});
if (this.opts.theme === 'auto') {
this.darkModeMediaQuery.removeListener(this.handleSystemDarkModeChange);
}
this.unmount();
this.removeEvents();
};
this.id = this.opts.id || 'Dashboard';
this.title = 'Dashboard';
this.type = 'orchestrator';
this.modalName = `uppy-Dashboard-${nanoid()}`;
this.defaultLocale = locale; // set default options
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.reset();
this.requestCloseModal();
},
note: null,
closeModalOnClickOutside: false,
closeAfterFinish: false,
disableStatusBar: false,
disableInformer: false,
disableThumbnailGenerator: false,
disablePageScrollWhenModalOpen: true,
animateOpenClose: true,
fileManagerSelectionType: 'files',
proudlyDisplayPoweredByUppy: true,
onRequestCloseModal: () => this.closeModal(),
showSelectedFiles: true,
showRemoveButtonAfterComplete: false,
browserBackButtonClose: 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();
this.ifFocusedOnUppyRecently = false; // Timeouts
this.makeDashboardInsidesVisibleAnywayTimeout = null;
this.removeDragOverClassTimeout = null;
}
}), _class.VERSION = "2.2.0", _temp);
module.exports = require("./Dashboard.js");

@@ -0,1 +1,3 @@

"use strict";
module.exports = {

@@ -2,0 +4,0 @@ strings: {

@@ -1,13 +0,7 @@

/**
* Copies text to clipboard by creating an almost invisible textarea,
* adding text there, then running execCommand('copy').
* Falls back to prompt() when the easy way fails (hello, Safari!)
* From http://stackoverflow.com/a/30810322
*
* @param {string} textToCopy
* @param {string} fallbackString
* @returns {Promise}
*/
module.exports = function copyToClipboard(textToCopy, fallbackString) {
fallbackString = fallbackString || 'Copy the URL below';
"use strict";
function copyToClipboard(textToCopy, fallbackString) {
// TODO: make `fallbackString` an optional parameter instead.
fallbackString || (fallbackString = 'Copy the URL below'); // eslint-disable-line no-param-reassign
return new Promise(resolve => {

@@ -52,2 +46,14 @@ const textArea = document.createElement('textarea');

});
};
}
/**
* Copies text to clipboard by creating an almost invisible textarea,
* adding text there, then running execCommand('copy').
* Falls back to prompt() when the easy way fails (hello, Safari!)
* From http://stackoverflow.com/a/30810322
*
* @param {string} textToCopy
* @param {string} fallbackString
* @returns {Promise}
*/
module.exports = copyToClipboard;

@@ -1,6 +0,8 @@

const debounce = require('lodash.debounce');
"use strict";
const FOCUSABLE_ELEMENTS = require('@uppy/utils/lib/FOCUSABLE_ELEMENTS');
const debounce = require("lodash.debounce");
const getActiveOverlayEl = require('./getActiveOverlayEl');
const FOCUSABLE_ELEMENTS = require("@uppy/utils/lib/FOCUSABLE_ELEMENTS");
const getActiveOverlayEl = require("./getActiveOverlayEl.js");
/*

@@ -18,3 +20,3 @@ Focuses on some element in the currently topmost overlay.

module.exports = function createSuperFocus() {
function createSuperFocus() {
let lastFocusWasOnSuperFocusableEl = false;

@@ -56,2 +58,4 @@

return debounce(superFocus, 260);
};
}
module.exports = createSuperFocus;

@@ -1,5 +0,4 @@

/**
* @returns {HTMLElement} - either dashboard element, or the overlay that's most on top
*/
module.exports = function getActiveOverlayEl(dashboardEl, activeOverlayType) {
"use strict";
function getActiveOverlayEl(dashboardEl, activeOverlayType) {
if (activeOverlayType) {

@@ -12,2 +11,7 @@ const overlayEl = dashboardEl.querySelector(`[data-uppy-paneltype="${activeOverlayType}"]`); // if an overlay is already mounted

return dashboardEl;
};
}
/**
* @returns {HTMLElement} - either dashboard element, or the overlay that's most on top
*/
module.exports = getActiveOverlayEl;

@@ -1,7 +0,7 @@

const {
h
} = require('preact');
"use strict";
var _preact = require("preact");
function iconImage() {
return h("svg", {
return (0, _preact.h)("svg", {
"aria-hidden": "true",

@@ -12,12 +12,12 @@ focusable: "false",

viewBox: "0 0 25 25"
}, h("g", {
}, (0, _preact.h)("g", {
fill: "#686DE0",
fillRule: "evenodd"
}, h("path", {
}, (0, _preact.h)("path", {
d: "M5 7v10h15V7H5zm0-1h15a1 1 0 0 1 1 1v10a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1z",
fillRule: "nonzero"
}), h("path", {
}), (0, _preact.h)("path", {
d: "M6.35 17.172l4.994-5.026a.5.5 0 0 1 .707 0l2.16 2.16 3.505-3.505a.5.5 0 0 1 .707 0l2.336 2.31-.707.72-1.983-1.97-3.505 3.505a.5.5 0 0 1-.707 0l-2.16-2.159-3.938 3.939-1.409.026z",
fillRule: "nonzero"
}), h("circle", {
}), (0, _preact.h)("circle", {
cx: "7.5",

@@ -30,3 +30,3 @@ cy: "9.5",

function iconAudio() {
return h("svg", {
return (0, _preact.h)("svg", {
"aria-hidden": "true",

@@ -38,3 +38,3 @@ focusable: "false",

viewBox: "0 0 25 25"
}, h("path", {
}, (0, _preact.h)("path", {
d: "M9.5 18.64c0 1.14-1.145 2-2.5 2s-2.5-.86-2.5-2c0-1.14 1.145-2 2.5-2 .557 0 1.079.145 1.5.396V7.25a.5.5 0 0 1 .379-.485l9-2.25A.5.5 0 0 1 18.5 5v11.64c0 1.14-1.145 2-2.5 2s-2.5-.86-2.5-2c0-1.14 1.145-2 2.5-2 .557 0 1.079.145 1.5.396V8.67l-8 2v7.97zm8-11v-2l-8 2v2l8-2zM7 19.64c.855 0 1.5-.484 1.5-1s-.645-1-1.5-1-1.5.484-1.5 1 .645 1 1.5 1zm9-2c.855 0 1.5-.484 1.5-1s-.645-1-1.5-1-1.5.484-1.5 1 .645 1 1.5 1z",

@@ -47,3 +47,3 @@ fill: "#049BCF",

function iconVideo() {
return h("svg", {
return (0, _preact.h)("svg", {
"aria-hidden": "true",

@@ -55,3 +55,3 @@ focusable: "false",

viewBox: "0 0 25 25"
}, h("path", {
}, (0, _preact.h)("path", {
d: "M16 11.834l4.486-2.691A1 1 0 0 1 22 10v6a1 1 0 0 1-1.514.857L16 14.167V17a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V9a1 1 0 0 1 1-1h10a1 1 0 0 1 1 1v2.834zM15 9H5v8h10V9zm1 4l5 3v-6l-5 3z",

@@ -64,3 +64,3 @@ fill: "#19AF67",

function iconPDF() {
return h("svg", {
return (0, _preact.h)("svg", {
"aria-hidden": "true",

@@ -72,3 +72,3 @@ focusable: "false",

viewBox: "0 0 25 25"
}, h("path", {
}, (0, _preact.h)("path", {
d: "M9.766 8.295c-.691-1.843-.539-3.401.747-3.726 1.643-.414 2.505.938 2.39 3.299-.039.79-.194 1.662-.537 3.148.324.49.66.967 1.055 1.51.17.231.382.488.629.757 1.866-.128 3.653.114 4.918.655 1.487.635 2.192 1.685 1.614 2.84-.566 1.133-1.839 1.084-3.416.249-1.141-.604-2.457-1.634-3.51-2.707a13.467 13.467 0 0 0-2.238.426c-1.392 4.051-4.534 6.453-5.707 4.572-.986-1.58 1.38-4.206 4.914-5.375.097-.322.185-.656.264-1.001.08-.353.306-1.31.407-1.737-.678-1.059-1.2-2.031-1.53-2.91zm2.098 4.87c-.033.144-.068.287-.104.427l.033-.01-.012.038a14.065 14.065 0 0 1 1.02-.197l-.032-.033.052-.004a7.902 7.902 0 0 1-.208-.271c-.197-.27-.38-.526-.555-.775l-.006.028-.002-.003c-.076.323-.148.632-.186.8zm5.77 2.978c1.143.605 1.832.632 2.054.187.26-.519-.087-1.034-1.113-1.473-.911-.39-2.175-.608-3.55-.608.845.766 1.787 1.459 2.609 1.894zM6.559 18.789c.14.223.693.16 1.425-.413.827-.648 1.61-1.747 2.208-3.206-2.563 1.064-4.102 2.867-3.633 3.62zm5.345-10.97c.088-1.793-.351-2.48-1.146-2.28-.473.119-.564 1.05-.056 2.405.213.566.52 1.188.908 1.859.18-.858.268-1.453.294-1.984z",

@@ -81,3 +81,3 @@ fill: "#E2514A",

function iconArchive() {
return h("svg", {
return (0, _preact.h)("svg", {
"aria-hidden": "true",

@@ -88,3 +88,3 @@ focusable: "false",

viewBox: "0 0 25 25"
}, h("path", {
}, (0, _preact.h)("path", {
d: "M10.45 2.05h1.05a.5.5 0 0 1 .5.5v.024a.5.5 0 0 1-.5.5h-1.05a.5.5 0 0 1-.5-.5V2.55a.5.5 0 0 1 .5-.5zm2.05 1.024h1.05a.5.5 0 0 1 .5.5V3.6a.5.5 0 0 1-.5.5H12.5a.5.5 0 0 1-.5-.5v-.025a.5.5 0 0 1 .5-.5v-.001zM10.45 0h1.05a.5.5 0 0 1 .5.5v.025a.5.5 0 0 1-.5.5h-1.05a.5.5 0 0 1-.5-.5V.5a.5.5 0 0 1 .5-.5zm2.05 1.025h1.05a.5.5 0 0 1 .5.5v.024a.5.5 0 0 1-.5.5H12.5a.5.5 0 0 1-.5-.5v-.024a.5.5 0 0 1 .5-.5zm-2.05 3.074h1.05a.5.5 0 0 1 .5.5v.025a.5.5 0 0 1-.5.5h-1.05a.5.5 0 0 1-.5-.5v-.025a.5.5 0 0 1 .5-.5zm2.05 1.025h1.05a.5.5 0 0 1 .5.5v.024a.5.5 0 0 1-.5.5H12.5a.5.5 0 0 1-.5-.5v-.024a.5.5 0 0 1 .5-.5zm-2.05 1.024h1.05a.5.5 0 0 1 .5.5v.025a.5.5 0 0 1-.5.5h-1.05a.5.5 0 0 1-.5-.5v-.025a.5.5 0 0 1 .5-.5zm2.05 1.025h1.05a.5.5 0 0 1 .5.5v.025a.5.5 0 0 1-.5.5H12.5a.5.5 0 0 1-.5-.5v-.025a.5.5 0 0 1 .5-.5zm-2.05 1.025h1.05a.5.5 0 0 1 .5.5v.025a.5.5 0 0 1-.5.5h-1.05a.5.5 0 0 1-.5-.5v-.025a.5.5 0 0 1 .5-.5zm2.05 1.025h1.05a.5.5 0 0 1 .5.5v.024a.5.5 0 0 1-.5.5H12.5a.5.5 0 0 1-.5-.5v-.024a.5.5 0 0 1 .5-.5zm-1.656 3.074l-.82 5.946c.52.302 1.174.458 1.976.458.803 0 1.455-.156 1.975-.458l-.82-5.946h-2.311zm0-1.025h2.312c.512 0 .946.378 1.015.885l.82 5.946c.056.412-.142.817-.501 1.026-.686.398-1.515.597-2.49.597-.974 0-1.804-.199-2.49-.597a1.025 1.025 0 0 1-.5-1.026l.819-5.946c.07-.507.503-.885 1.015-.885zm.545 6.6a.5.5 0 0 1-.397-.561l.143-.999a.5.5 0 0 1 .495-.429h.74a.5.5 0 0 1 .495.43l.143.998a.5.5 0 0 1-.397.561c-.404.08-.819.08-1.222 0z",

@@ -97,3 +97,3 @@ fill: "#00C469",

function iconFile() {
return h("svg", {
return (0, _preact.h)("svg", {
"aria-hidden": "true",

@@ -105,8 +105,8 @@ focusable: "false",

viewBox: "0 0 25 25"
}, h("g", {
}, (0, _preact.h)("g", {
fill: "#A7AFB7",
fillRule: "nonzero"
}, h("path", {
}, (0, _preact.h)("path", {
d: "M5.5 22a.5.5 0 0 1-.5-.5v-18a.5.5 0 0 1 .5-.5h10.719a.5.5 0 0 1 .367.16l3.281 3.556a.5.5 0 0 1 .133.339V21.5a.5.5 0 0 1-.5.5h-14zm.5-1h13V7.25L16 4H6v17z"
}), h("path", {
}), (0, _preact.h)("path", {
d: "M15 4v3a1 1 0 0 0 1 1h3V7h-3V4h-1z"

@@ -117,3 +117,3 @@ })));

function iconText() {
return h("svg", {
return (0, _preact.h)("svg", {
"aria-hidden": "true",

@@ -125,3 +125,3 @@ focusable: "false",

viewBox: "0 0 25 25"
}, h("path", {
}, (0, _preact.h)("path", {
d: "M4.5 7h13a.5.5 0 1 1 0 1h-13a.5.5 0 0 1 0-1zm0 3h15a.5.5 0 1 1 0 1h-15a.5.5 0 1 1 0-1zm0 3h15a.5.5 0 1 1 0 1h-15a.5.5 0 1 1 0-1zm0 3h10a.5.5 0 1 1 0 1h-10a.5.5 0 1 1 0-1z",

@@ -133,3 +133,3 @@ fill: "#5A5E69",

module.exports = function getIconByMime(fileType) {
function getIconByMime(fileType) {
const defaultChoice = {

@@ -193,2 +193,4 @@ color: '#838999',

return defaultChoice;
};
}
module.exports = getIconByMime;

@@ -0,1 +1,3 @@

"use strict";
// ignore drop/paste events if they are not in input or textarea —

@@ -2,0 +4,0 @@ // otherwise when Url plugin adds drop/paste listeners to this.el,

@@ -1,7 +0,15 @@

const toArray = require('@uppy/utils/lib/toArray');
"use strict";
const FOCUSABLE_ELEMENTS = require('@uppy/utils/lib/FOCUSABLE_ELEMENTS');
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.forInline = forInline;
exports.forModal = trapFocus;
const getActiveOverlayEl = require('./getActiveOverlayEl');
const toArray = require("@uppy/utils/lib/toArray");
const FOCUSABLE_ELEMENTS = require("@uppy/utils/lib/FOCUSABLE_ELEMENTS");
const getActiveOverlayEl = require("./getActiveOverlayEl.js");
function focusOnFirstNode(event, nodes) {

@@ -50,21 +58,16 @@ const node = nodes[0];

}
}
} // Traps focus inside of the currently open overlay (e.g. Dashboard, or e.g. Instagram),
// never lets focus disappear from the modal.
module.exports = {
// Traps focus inside of the currently open overlay (e.g. Dashboard, or e.g. Instagram),
// never lets focus disappear from the modal.
forModal: (event, activeOverlayType, dashboardEl) => {
// Traps focus inside of the currently open overlay, unless overlay is null - then let the user tab away.
function forInline(event, activeOverlayType, dashboardEl) {
// ___When we're in the bare 'Drop files here, paste, browse or import from' screen
if (activeOverlayType === null) {// Do nothing and let the browser handle it, user can tab away from Uppy to other elements on the page
// ___When there is some overlay with 'Done' button
} else {
// Trap the focus inside this overlay!
// User can close the overlay (click 'Done') if they want to travel away from Uppy.
trapFocus(event, activeOverlayType, dashboardEl);
},
// Traps focus inside of the currently open overlay, unless overlay is null - then let the user tab away.
forInline: (event, activeOverlayType, dashboardEl) => {
// ___When we're in the bare 'Drop files here, paste, browse or import from' screen
if (activeOverlayType === null) {// Do nothing and let the browser handle it, user can tab away from Uppy to other elements on the page
// ___When there is some overlay with 'Done' button
} else {
// Trap the focus inside this overlay!
// User can close the overlay (click 'Done') if they want to travel away from Uppy.
trapFocus(event, activeOverlayType, dashboardEl);
}
}
};
}
{
"name": "@uppy/dashboard",
"description": "Universal UI plugin for Uppy.",
"version": "2.2.0",
"version": "2.3.0",
"license": "MIT",

@@ -9,2 +9,3 @@ "main": "lib/index.js",

"types": "types/index.d.ts",
"type": "module",
"keywords": [

@@ -27,7 +28,7 @@ "file uploader",

"@transloadit/prettier-bytes": "0.0.7",
"@uppy/informer": "^2.0.5",
"@uppy/provider-views": "^2.1.0",
"@uppy/status-bar": "^2.2.0",
"@uppy/thumbnail-generator": "^2.1.1",
"@uppy/utils": "^4.0.7",
"@uppy/informer": "^2.1.0",
"@uppy/provider-views": "^2.1.1",
"@uppy/status-bar": "^2.2.1",
"@uppy/thumbnail-generator": "^2.2.0",
"@uppy/utils": "^4.1.0",
"classnames": "^2.2.6",

@@ -41,9 +42,10 @@ "is-shallow-equal": "^1.0.1",

"devDependencies": {
"@uppy/google-drive": "^2.1.0",
"@uppy/status-bar": "^2.2.0",
"@jest/globals": "^27.4.2",
"@uppy/google-drive": "^2.1.1",
"@uppy/status-bar": "^2.2.1",
"resize-observer-polyfill": "^1.5.0"
},
"peerDependencies": {
"@uppy/core": "^2.2.0"
"@uppy/core": "^2.3.0"
}
}

@@ -42,4 +42,2 @@ # @uppy/dashboard

We recommend installing from npm and then using a module bundler such as [Webpack](https://webpack.js.org/), [Browserify](http://browserify.org/) or [Rollup.js](http://rollupjs.org/).
Alternatively, you can also use this plugin in a pre-built bundle from Transloadit’s CDN: Edgly. In that case `Uppy` will attach itself to the global `window.Uppy` object. See the [main Uppy documentation](https://uppy.io/docs/#Installation) for instructions.

@@ -46,0 +44,0 @@

@@ -1,1109 +0,1 @@

const { h } = require('preact')
const { UIPlugin } = require('@uppy/core')
const StatusBar = require('@uppy/status-bar')
const Informer = require('@uppy/informer')
const ThumbnailGenerator = require('@uppy/thumbnail-generator')
const findAllDOMElements = require('@uppy/utils/lib/findAllDOMElements')
const toArray = require('@uppy/utils/lib/toArray')
const getDroppedFiles = require('@uppy/utils/lib/getDroppedFiles')
const { nanoid } = require('nanoid/non-secure')
const trapFocus = require('./utils/trapFocus')
const createSuperFocus = require('./utils/createSuperFocus')
const memoize = require('memoize-one').default || require('memoize-one')
const FOCUSABLE_ELEMENTS = require('@uppy/utils/lib/FOCUSABLE_ELEMENTS')
const DashboardUI = require('./components/Dashboard')
const locale = require('./locale')
const TAB_KEY = 9
const ESC_KEY = 27
function createPromise () {
const o = {}
o.promise = new Promise((resolve, reject) => {
o.resolve = resolve
o.reject = reject
})
return o
}
function defaultPickerIcon () {
return (
<svg aria-hidden="true" focusable="false" width="30" height="30" viewBox="0 0 30 30">
<path d="M15 30c8.284 0 15-6.716 15-15 0-8.284-6.716-15-15-15C6.716 0 0 6.716 0 15c0 8.284 6.716 15 15 15zm4.258-12.676v6.846h-8.426v-6.846H5.204l9.82-12.364 9.82 12.364H19.26z" />
</svg>
)
}
/**
* Dashboard UI with previews, metadata editing, tabs for various services and more
*/
module.exports = class Dashboard extends UIPlugin {
static VERSION = require('../package.json').version
constructor (uppy, opts) {
super(uppy, opts)
this.id = this.opts.id || 'Dashboard'
this.title = 'Dashboard'
this.type = 'orchestrator'
this.modalName = `uppy-Dashboard-${nanoid()}`
this.defaultLocale = locale
// set default options
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.reset()
this.requestCloseModal()
},
note: null,
closeModalOnClickOutside: false,
closeAfterFinish: false,
disableStatusBar: false,
disableInformer: false,
disableThumbnailGenerator: false,
disablePageScrollWhenModalOpen: true,
animateOpenClose: true,
fileManagerSelectionType: 'files',
proudlyDisplayPoweredByUppy: true,
onRequestCloseModal: () => this.closeModal(),
showSelectedFiles: true,
showRemoveButtonAfterComplete: false,
browserBackButtonClose: 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()
this.ifFocusedOnUppyRecently = false
// Timeouts
this.makeDashboardInsidesVisibleAnywayTimeout = null
this.removeDragOverClassTimeout = null
}
removeTarget = (plugin) => {
const pluginState = this.getPluginState()
// filter out the one we want to remove
const newTargets = pluginState.targets.filter(target => target.id !== plugin.id)
this.setPluginState({
targets: newTargets,
})
}
addTarget = (plugin) => {
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'
this.uppy.log(msg, 'error')
return
}
const target = {
id: callerPluginId,
name: callerPluginName,
type: callerPluginType,
}
const state = this.getPluginState()
const newTargets = state.targets.slice()
newTargets.push(target)
this.setPluginState({
targets: newTargets,
})
return this.el
}
hideAllPanels = () => {
const state = this.getPluginState()
const update = {
activePickerPanel: false,
showAddFilesPanel: false,
activeOverlayType: null,
fileCardFor: null,
showFileEditor: false,
}
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
}
this.setPluginState(update)
}
showPanel = (id) => {
const { targets } = this.getPluginState()
const activePickerPanel = targets.filter((target) => {
return target.type === 'acquirer' && target.id === id
})[0]
this.setPluginState({
activePickerPanel,
activeOverlayType: 'PickerPanel',
})
}
canEditFile = (file) => {
const { targets } = this.getPluginState()
const editors = this.#getEditors(targets)
return editors.some((target) => (
this.uppy.getPlugin(target.id).canEditFile(file)
))
}
openFileEditor = (file) => {
const { targets } = this.getPluginState()
const editors = this.#getEditors(targets)
this.setPluginState({
showFileEditor: true,
fileCardFor: file.id || null,
activeOverlayType: 'FileEditor',
})
editors.forEach((editor) => {
this.uppy.getPlugin(editor.id).selectFile(file)
})
}
saveFileEditor = () => {
const { targets } = this.getPluginState()
const editors = this.#getEditors(targets)
editors.forEach((editor) => {
this.uppy.getPlugin(editor.id).save()
})
this.hideAllPanels()
}
openModal = () => {
const { promise, resolve } = createPromise()
// save scroll position
this.savedScrollPosition = window.pageYOffset
// save active element, so we can restore focus when modal is closed
this.savedActiveElement = document.activeElement
if (this.opts.disablePageScrollWhenModalOpen) {
document.body.classList.add('uppy-Dashboard-isFixed')
}
if (this.opts.animateOpenClose && this.getPluginState().isClosing) {
const handler = () => {
this.setPluginState({
isHidden: false,
})
this.el.removeEventListener('animationend', handler, false)
resolve()
}
this.el.addEventListener('animationend', handler, false)
} else {
this.setPluginState({
isHidden: false,
})
resolve()
}
if (this.opts.browserBackButtonClose) {
this.updateBrowserHistory()
}
// handle ESC and TAB keys in modal dialog
document.addEventListener('keydown', this.handleKeyDownInModal)
this.uppy.emit('dashboard:modal-open')
return promise
}
closeModal = (opts = {}) => {
const {
// Whether the modal is being closed by the user (`true`) or by other means (e.g. browser back button)
manualClose = true,
} = opts
const { isHidden, isClosing } = this.getPluginState()
if (isHidden || isClosing) {
// short-circuit if animation is ongoing
return
}
const { promise, resolve } = createPromise()
if (this.opts.disablePageScrollWhenModalOpen) {
document.body.classList.remove('uppy-Dashboard-isFixed')
}
if (this.opts.animateOpenClose) {
this.setPluginState({
isClosing: true,
})
const handler = () => {
this.setPluginState({
isHidden: true,
isClosing: false,
})
this.superFocus.cancel()
this.savedActiveElement.focus()
this.el.removeEventListener('animationend', handler, false)
resolve()
}
this.el.addEventListener('animationend', handler, false)
} else {
this.setPluginState({
isHidden: true,
})
this.superFocus.cancel()
this.savedActiveElement.focus()
resolve()
}
// handle ESC and TAB keys in modal dialog
document.removeEventListener('keydown', this.handleKeyDownInModal)
if (manualClose) {
if (this.opts.browserBackButtonClose) {
// Make sure that the latest entry in the history state is our modal name
// eslint-disable-next-line no-restricted-globals
if (history.state?.[this.modalName]) {
// Go back in history to clear out the entry we created (ultimately closing the modal)
// eslint-disable-next-line no-restricted-globals
history.back()
}
}
}
this.uppy.emit('dashboard:modal-closed')
return promise
}
isModalOpen = () => {
return !this.getPluginState().isHidden || false
}
requestCloseModal = () => {
if (this.opts.onRequestCloseModal) {
return this.opts.onRequestCloseModal()
}
return this.closeModal()
}
setDarkModeCapability = (isDarkModeOn) => {
const { capabilities } = this.uppy.getState()
this.uppy.setState({
capabilities: {
...capabilities,
darkMode: isDarkModeOn,
},
})
}
handleSystemDarkModeChange = (event) => {
const isDarkModeOnNow = event.matches
this.uppy.log(`[Dashboard] Dark mode is ${isDarkModeOnNow ? 'on' : 'off'}`)
this.setDarkModeCapability(isDarkModeOnNow)
}
toggleFileCard = (show, fileID) => {
const file = this.uppy.getFile(fileID)
if (show) {
this.uppy.emit('dashboard:file-edit-start', file)
} else {
this.uppy.emit('dashboard:file-edit-complete', file)
}
this.setPluginState({
fileCardFor: show ? fileID : null,
activeOverlayType: show ? 'FileCard' : null,
})
}
toggleAddFilesPanel = (show) => {
this.setPluginState({
showAddFilesPanel: show,
activeOverlayType: show ? 'AddFiles' : null,
})
}
addFiles = (files) => {
const descriptors = files.map((file) => ({
source: this.id,
name: file.name,
type: file.type,
data: file,
meta: {
// path of the file relative to the ancestor directory the user selected.
// e.g. 'docs/Old Prague/airbnb.pdf'
relativePath: file.relativePath || null,
},
}))
try {
this.uppy.addFiles(descriptors)
} catch (err) {
this.uppy.log(err)
}
}
// ___Why make insides of Dashboard invisible until first ResizeObserver event is emitted?
// ResizeOberserver doesn't emit the first resize event fast enough, users can see the jump from one .uppy-size-- to
// another (e.g. in Safari)
// ___Why not apply visibility property to .uppy-Dashboard-inner?
// Because ideally, acc to specs, ResizeObserver should see invisible elements as of width 0. So even though applying
// invisibility to .uppy-Dashboard-inner works now, it may not work in the future.
startListeningToResize = () => {
// Watch for Dashboard container (`.uppy-Dashboard-inner`) resize
// and update containerWidth/containerHeight in plugin state accordingly.
// Emits first event on initialization.
this.resizeObserver = new ResizeObserver((entries) => {
const uppyDashboardInnerEl = entries[0]
const { width, height } = uppyDashboardInnerEl.contentRect
this.uppy.log(`[Dashboard] resized: ${width} / ${height}`, 'debug')
this.setPluginState({
containerWidth: width,
containerHeight: height,
areInsidesReadyToBeVisible: true,
})
})
this.resizeObserver.observe(this.el.querySelector('.uppy-Dashboard-inner'))
// If ResizeObserver fails to emit an event telling us what size to use - default to the mobile view
this.makeDashboardInsidesVisibleAnywayTimeout = setTimeout(() => {
const pluginState = this.getPluginState()
const isModalAndClosed = !this.opts.inline && pluginState.isHidden
if (
// if ResizeObserver hasn't yet fired,
!pluginState.areInsidesReadyToBeVisible
// and it's not due to the modal being closed
&& !isModalAndClosed
) {
this.uppy.log("[Dashboard] resize event didn't fire on time: defaulted to mobile layout", 'debug')
this.setPluginState({
areInsidesReadyToBeVisible: true,
})
}
}, 1000)
}
stopListeningToResize = () => {
this.resizeObserver.disconnect()
clearTimeout(this.makeDashboardInsidesVisibleAnywayTimeout)
}
// Records whether we have been interacting with uppy right now,
// which is then used to determine whether state updates should trigger a refocusing.
recordIfFocusedOnUppyRecently = (event) => {
if (this.el.contains(event.target)) {
this.ifFocusedOnUppyRecently = true
} else {
this.ifFocusedOnUppyRecently = false
// ___Why run this.superFocus.cancel here when it already runs in superFocusOnEachUpdate?
// Because superFocus is debounced, when we move from Uppy to some other element on the page,
// previously run superFocus sometimes hits and moves focus back to Uppy.
this.superFocus.cancel()
}
}
disableAllFocusableElements = (disable) => {
const focusableNodes = toArray(this.el.querySelectorAll(FOCUSABLE_ELEMENTS))
if (disable) {
focusableNodes.forEach((node) => {
// save previous tabindex in a data-attribute, to restore when enabling
const currentTabIndex = node.getAttribute('tabindex')
if (currentTabIndex) {
node.dataset.inertTabindex = currentTabIndex
}
node.setAttribute('tabindex', '-1')
})
} else {
focusableNodes.forEach((node) => {
if ('inertTabindex' in node.dataset) {
node.setAttribute('tabindex', node.dataset.inertTabindex)
} else {
node.removeAttribute('tabindex')
}
})
}
this.dashboardIsDisabled = disable
}
updateBrowserHistory = () => {
// Ensure history state does not already contain our modal name to avoid double-pushing
// eslint-disable-next-line no-restricted-globals
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,
}, '')
}
// Listen for back button presses
window.addEventListener('popstate', this.handlePopState, false)
}
handlePopState = (event) => {
// Close the modal if the history state no longer contains our modal name
if (this.isModalOpen() && (!event.state || !event.state[this.modalName])) {
this.closeModal({ manualClose: false })
}
// When the browser back button is pressed and uppy is now the latest entry
// in the history but the modal is closed, fix the history by removing the
// uppy history entry.
// This occurs when another entry is added into the history state while the
// modal is open, and then the modal gets manually closed.
// Solves PR #575 (https://github.com/transloadit/uppy/pull/575)
if (!this.isModalOpen() && event.state?.[this.modalName]) {
// eslint-disable-next-line no-restricted-globals
history.back()
}
}
handleKeyDownInModal = (event) => {
// 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)
}
handleClickOutside = () => {
if (this.opts.closeModalOnClickOutside) this.requestCloseModal()
}
handlePaste = (event) => {
// Let any acquirer plugin (Url/Webcam/etc.) handle pastes to the root
this.uppy.iteratePlugins((plugin) => {
if (plugin.type === 'acquirer') {
// Every Plugin with .type acquirer can define handleRootPaste(event)
plugin.handleRootPaste?.(event)
}
})
// Add all dropped files
const files = toArray(event.clipboardData.files)
if (files.length > 0) {
this.uppy.log('[Dashboard] Files pasted')
this.addFiles(files)
}
}
handleInputChange = (event) => {
event.preventDefault()
const files = toArray(event.target.files)
if (files.length > 0) {
this.uppy.log('[Dashboard] Files selected through input')
this.addFiles(files)
}
}
handleDragOver = (event) => {
event.preventDefault()
event.stopPropagation()
// Check if some plugin can handle the datatransfer without files —
// for instance, the Url plugin can import a url
const canSomePluginHandleRootDrop = () => {
let somePluginCanHandleRootDrop = true
this.uppy.iteratePlugins((plugin) => {
if (plugin.canHandleRootDrop?.(event)) {
somePluginCanHandleRootDrop = true
}
})
return somePluginCanHandleRootDrop
}
// Check if the "type" of the datatransfer object includes files
const doesEventHaveFiles = () => {
const { types } = event.dataTransfer
return types.some(type => type === 'Files')
}
// Deny drop, if no plugins can handle datatransfer, there are no files,
// or when opts.disabled is set, or new uploads are not allowed
const somePluginCanHandleRootDrop = canSomePluginHandleRootDrop(event)
const hasFiles = doesEventHaveFiles(event)
if (
(!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
) {
event.dataTransfer.dropEffect = 'none'
clearTimeout(this.removeDragOverClassTimeout)
return
}
// Add a small (+) icon on drop
// (and prevent browsers from interpreting this as files being _moved_ into the
// browser, https://github.com/transloadit/uppy/issues/1978).
event.dataTransfer.dropEffect = 'copy'
clearTimeout(this.removeDragOverClassTimeout)
this.setPluginState({ isDraggingOver: true })
this.opts.onDragOver?.(event)
}
handleDragLeave = (event) => {
event.preventDefault()
event.stopPropagation()
clearTimeout(this.removeDragOverClassTimeout)
// Timeout against flickering, this solution is taken from drag-drop library.
// Solution with 'pointer-events: none' didn't work across browsers.
this.removeDragOverClassTimeout = setTimeout(() => {
this.setPluginState({ isDraggingOver: false })
}, 50)
this.opts.onDragLeave?.(event)
}
handleDrop = async (event) => {
event.preventDefault()
event.stopPropagation()
clearTimeout(this.removeDragOverClassTimeout)
this.setPluginState({ isDraggingOver: false })
// Let any acquirer plugin (Url/Webcam/etc.) handle drops to the root
this.uppy.iteratePlugins((plugin) => {
if (plugin.type === 'acquirer') {
// Every Plugin with .type acquirer can define handleRootDrop(event)
plugin.handleRootDrop?.(event)
}
})
// Add all dropped files
let executedDropErrorOnce = false
const logDropError = (error) => {
this.uppy.log(error, 'error')
// In practice all drop errors are most likely the same,
// so let's just show one to avoid overwhelming the user
if (!executedDropErrorOnce) {
this.uppy.info(error.message, 'error')
executedDropErrorOnce = true
}
}
// Add all dropped files
const files = await getDroppedFiles(event.dataTransfer, { logDropError })
if (files.length > 0) {
this.uppy.log('[Dashboard] Files dropped')
this.addFiles(files)
}
this.opts.onDrop?.(event)
}
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) => {
// Trap focus on tab key press.
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,
// or this.el.addEventListener('paste')?
// Because (at least) Chrome doesn't handle paste if focus is on some button, e.g. 'My Device'.
// => Therefore, the best option is to listen to all 'paste' events, and only react to them when we are focused on our
// particular Uppy instance.
// ___Why do we still need onPaste={props.handlePaste} for the DashboardUi?
// Because if we click on the 'Drop files here' caption e.g., `document.activeElement` will be 'body'. Which means our
// standard determination of whether we're pasting into our Uppy instance won't work.
// => Therefore, we need a traditional onPaste={props.handlePaste} handler too.
handlePasteOnBody = (event) => {
const isFocusInOverlay = this.el.contains(document.activeElement)
if (isFocusInOverlay) {
this.handlePaste(event)
}
}
handleComplete = ({ failed }) => {
if (this.opts.closeAfterFinish && failed.length === 0) {
// All uploads are done
this.requestCloseModal()
}
}
handleCancelRestore = () => {
this.uppy.emit('restore-canceled')
}
#openFileEditorWhenFilesAdded = (files) => {
const firstFile = files[0]
if (this.canEditFile(firstFile)) {
this.openFileEditor(firstFile)
}
}
initEvents = () => {
// Modal open button
if (this.opts.trigger && !this.opts.inline) {
const showModalTrigger = findAllDOMElements(this.opts.trigger)
if (showModalTrigger) {
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.startListeningToResize()
document.addEventListener('paste', this.handlePasteOnBody)
this.uppy.on('plugin-remove', this.removeTarget)
this.uppy.on('file-added', this.hideAllPanels)
this.uppy.on('dashboard:modal-closed', this.hideAllPanels)
this.uppy.on('file-editor:complete', this.hideAllPanels)
this.uppy.on('complete', this.handleComplete)
// ___Why fire on capture?
// Because this.ifFocusedOnUppyRecently needs to change before onUpdate() fires.
document.addEventListener('focus', this.recordIfFocusedOnUppyRecently, true)
document.addEventListener('click', this.recordIfFocusedOnUppyRecently, true)
if (this.opts.inline) {
this.el.addEventListener('keydown', this.handleKeyDownInInline)
}
if (this.opts.autoOpenFileEditor) {
this.uppy.on('files-added', this.#openFileEditorWhenFilesAdded)
}
}
removeEvents = () => {
const showModalTrigger = findAllDOMElements(this.opts.trigger)
if (!this.opts.inline && showModalTrigger) {
showModalTrigger.forEach(trigger => trigger.removeEventListener('click', this.openModal))
}
this.stopListeningToResize()
document.removeEventListener('paste', this.handlePasteOnBody)
window.removeEventListener('popstate', this.handlePopState, false)
this.uppy.off('plugin-remove', this.removeTarget)
this.uppy.off('file-added', this.hideAllPanels)
this.uppy.off('dashboard:modal-closed', this.hideAllPanels)
this.uppy.off('file-editor:complete', this.hideAllPanels)
this.uppy.off('complete', this.handleComplete)
document.removeEventListener('focus', this.recordIfFocusedOnUppyRecently)
document.removeEventListener('click', this.recordIfFocusedOnUppyRecently)
if (this.opts.inline) {
this.el.removeEventListener('keydown', this.handleKeyDownInInline)
}
if (this.opts.autoOpenFileEditor) {
this.uppy.off('files-added', this.#openFileEditorWhenFilesAdded)
}
}
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 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
// If we are already inside of Uppy, or
|| 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
// something somewhere else on the page, - focus won't be 'nowhere'.
// 2. We only focus when focus is nowhere AND this.ifFocusedOnUppyRecently,
// to avoid focus jumps if we do something else on the page.
// [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)
)
) {
this.superFocus(this.el, this.getPluginState().activeOverlayType)
} else {
this.superFocus.cancel()
}
}
afterUpdate = () => {
if (this.opts.disabled && !this.dashboardIsDisabled) {
this.disableAllFocusableElements(true)
return
}
if (!this.opts.disabled && this.dashboardIsDisabled) {
this.disableAllFocusableElements(false)
}
this.superFocusOnEachUpdate()
}
saveFileCard = (meta, fileID) => {
this.uppy.setFileMeta(fileID, meta)
this.toggleFileCard(false, fileID)
}
#attachRenderFunctionToTarget = (target) => {
const plugin = this.uppy.getPlugin(target.id)
return {
...target,
icon: plugin.icon || this.opts.defaultPickerIcon,
render: plugin.render,
}
}
#isTargetSupported = (target) => {
const plugin = this.uppy.getPlugin(target.id)
// If the plugin does not provide a `supported` check, assume the plugin works everywhere.
if (typeof plugin.isSupported !== 'function') {
return true
}
return plugin.isSupported()
}
#getAcquirers = memoize((targets) => {
return targets
.filter(target => target.type === 'acquirer' && this.#isTargetSupported(target))
.map(this.#attachRenderFunctionToTarget)
})
#getProgressIndicators = memoize((targets) => {
return targets
.filter(target => target.type === 'progressindicator')
.map(this.#attachRenderFunctionToTarget)
})
#getEditors = memoize((targets) => {
return targets
.filter(target => target.type === 'editor')
.map(this.#attachRenderFunctionToTarget)
})
render = (state) => {
const pluginState = this.getPluginState()
const { files, capabilities, allowNewUpload } = state
const {
newFiles,
uploadStartedFiles,
completeFiles,
erroredFiles,
inProgressFiles,
inProgressNotPausedFiles,
processingFiles,
isUploadStarted,
isAllComplete,
isAllErrored,
isAllPaused,
} = this.uppy.getObjectOfFilesPerState()
const acquirers = this.#getAcquirers(pluginState.targets)
const progressindicators = this.#getProgressIndicators(pluginState.targets)
const editors = this.#getEditors(pluginState.targets)
let theme
if (this.opts.theme === 'auto') {
theme = capabilities.darkMode ? 'dark' : 'light'
} else {
theme = this.opts.theme
}
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}".`)
}
return DashboardUI({
state,
isHidden: pluginState.isHidden,
files,
newFiles,
uploadStartedFiles,
completeFiles,
erroredFiles,
inProgressFiles,
inProgressNotPausedFiles,
processingFiles,
isUploadStarted,
isAllComplete,
isAllErrored,
isAllPaused,
totalFileCount: Object.keys(files).length,
totalProgress: state.totalProgress,
allowNewUpload,
acquirers,
theme,
disabled: this.opts.disabled,
disableLocalFiles: this.opts.disableLocalFiles,
direction: this.opts.direction,
activePickerPanel: pluginState.activePickerPanel,
showFileEditor: pluginState.showFileEditor,
saveFileEditor: this.saveFileEditor,
disableAllFocusableElements: this.disableAllFocusableElements,
animateOpenClose: this.opts.animateOpenClose,
isClosing: pluginState.isClosing,
progressindicators,
editors,
autoProceed: this.uppy.opts.autoProceed,
id: this.id,
closeModal: this.requestCloseModal,
handleClickOutside: this.handleClickOutside,
handleInputChange: this.handleInputChange,
handlePaste: this.handlePaste,
inline: this.opts.inline,
showPanel: this.showPanel,
hideAllPanels: this.hideAllPanels,
i18n: this.i18n,
i18nArray: this.i18nArray,
uppy: this.uppy,
note: this.opts.note,
recoveredState: state.recoveredState,
metaFields: pluginState.metaFields,
resumableUploads: capabilities.resumableUploads || false,
individualCancellation: capabilities.individualCancellation,
isMobileDevice: capabilities.isMobileDevice,
fileCardFor: pluginState.fileCardFor,
toggleFileCard: this.toggleFileCard,
toggleAddFilesPanel: this.toggleAddFilesPanel,
showAddFilesPanel: pluginState.showAddFilesPanel,
saveFileCard: this.saveFileCard,
openFileEditor: this.openFileEditor,
canEditFile: this.canEditFile,
width: this.opts.width,
height: this.opts.height,
showLinkToFileUploadResult: this.opts.showLinkToFileUploadResult,
fileManagerSelectionType: this.opts.fileManagerSelectionType,
proudlyDisplayPoweredByUppy: this.opts.proudlyDisplayPoweredByUppy,
hideCancelButton: this.opts.hideCancelButton,
hideRetryButton: this.opts.hideRetryButton,
hidePauseResumeButton: this.opts.hidePauseResumeButton,
showRemoveButtonAfterComplete: this.opts.showRemoveButtonAfterComplete,
containerWidth: pluginState.containerWidth,
containerHeight: pluginState.containerHeight,
areInsidesReadyToBeVisible: pluginState.areInsidesReadyToBeVisible,
isTargetDOMEl: this.isTargetDOMEl,
parentElement: this.el,
allowedFileTypes: this.uppy.opts.restrictions.allowedFileTypes,
maxNumberOfFiles: this.uppy.opts.restrictions.maxNumberOfFiles,
requiredMetaFields: this.uppy.opts.restrictions.requiredMetaFields,
showSelectedFiles: this.opts.showSelectedFiles,
handleCancelRestore: this.handleCancelRestore,
handleRequestThumbnail: this.handleRequestThumbnail,
handleCancelThumbnail: this.handleCancelThumbnail,
// drag props
isDraggingOver: pluginState.isDraggingOver,
handleDragOver: this.handleDragOver,
handleDragLeave: this.handleDragLeave,
handleDrop: this.handleDrop,
})
}
discoverProviderPlugins = () => {
this.uppy.iteratePlugins((plugin) => {
if (plugin && !plugin.target && plugin.opts && plugin.opts.target === this.constructor) {
this.addTarget(plugin)
}
})
}
install = () => {
// Set default state for Dashboard
this.setPluginState({
isHidden: true,
fileCardFor: null,
activeOverlayType: null,
showAddFilesPanel: false,
activePickerPanel: false,
showFileEditor: false,
metaFields: this.opts.metaFields,
targets: [],
// We'll make them visible once .containerWidth is determined
areInsidesReadyToBeVisible: false,
isDraggingOver: false,
})
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.')
}
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')
}
const { target } = this.opts
if (target) {
this.mount(target, this)
}
const plugins = this.opts.plugins || []
plugins.forEach((pluginID) => {
const plugin = this.uppy.getPlugin(pluginID)
if (plugin) {
plugin.mount(this, plugin)
}
})
if (!this.opts.disableStatusBar) {
this.uppy.use(StatusBar, {
id: `${this.id}:StatusBar`,
target: this,
hideUploadButton: this.opts.hideUploadButton,
hideRetryButton: this.opts.hideRetryButton,
hidePauseResumeButton: this.opts.hidePauseResumeButton,
hideCancelButton: this.opts.hideCancelButton,
showProgressDetails: this.opts.showProgressDetails,
hideAfterFinish: this.opts.hideProgressAfterFinish,
locale: this.opts.locale,
doneButtonHandler: this.opts.doneButtonHandler,
})
}
if (!this.opts.disableInformer) {
this.uppy.use(Informer, {
id: `${this.id}:Informer`,
target: this,
})
}
if (!this.opts.disableThumbnailGenerator) {
this.uppy.use(ThumbnailGenerator, {
id: `${this.id}:ThumbnailGenerator`,
thumbnailWidth: this.opts.thumbnailWidth,
thumbnailHeight: this.opts.thumbnailHeight,
thumbnailType: this.opts.thumbnailType,
waitForThumbnailsBeforeUpload: this.opts.waitForThumbnailsBeforeUpload,
// If we don't block on thumbnails, we can lazily generate them
lazy: !this.opts.waitForThumbnailsBeforeUpload,
})
}
// Dark Mode / theme
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'}`)
this.setDarkModeCapability(isDarkModeOnFromTheStart)
if (this.opts.theme === 'auto') {
this.darkModeMediaQuery.addListener(this.handleSystemDarkModeChange)
}
this.discoverProviderPlugins()
this.initEvents()
}
uninstall = () => {
if (!this.opts.disableInformer) {
const informer = this.uppy.getPlugin(`${this.id}:Informer`)
// Checking if this plugin exists, in case it was removed by uppy-core
// before the Dashboard was.
if (informer) this.uppy.removePlugin(informer)
}
if (!this.opts.disableStatusBar) {
const statusBar = this.uppy.getPlugin(`${this.id}:StatusBar`)
if (statusBar) this.uppy.removePlugin(statusBar)
}
if (!this.opts.disableThumbnailGenerator) {
const thumbnail = this.uppy.getPlugin(`${this.id}:ThumbnailGenerator`)
if (thumbnail) this.uppy.removePlugin(thumbnail)
}
const plugins = this.opts.plugins || []
plugins.forEach((pluginID) => {
const plugin = this.uppy.getPlugin(pluginID)
if (plugin) plugin.unmount()
})
if (this.opts.theme === 'auto') {
this.darkModeMediaQuery.removeListener(this.handleSystemDarkModeChange)
}
this.unmount()
this.removeEvents()
}
}
export { default } from './Dashboard.jsx'

@@ -1,9 +0,12 @@

const Core = require('@uppy/core')
const StatusBarPlugin = require('@uppy/status-bar')
const GoogleDrivePlugin = require('@uppy/google-drive') // eslint-disable-line
const DashboardPlugin = require('./index')
import { afterAll, beforeAll, describe, it, expect } from '@jest/globals'
import Core from '@uppy/core'
import StatusBarPlugin from '@uppy/status-bar'
import GoogleDrivePlugin from '@uppy/google-drive'
import resizeObserverPolyfill from 'resize-observer-polyfill'
import DashboardPlugin from '../lib/index.js'
describe('Dashboard', () => {
beforeAll(() => {
globalThis.ResizeObserver = require('resize-observer-polyfill').default || require('resize-observer-polyfill')
globalThis.ResizeObserver = resizeObserverPolyfill.default || resizeObserverPolyfill
})

@@ -10,0 +13,0 @@ afterAll(() => {

@@ -1,2 +0,2 @@

module.exports = {
export default {
strings: {

@@ -3,0 +3,0 @@ // When `inline: false`, used as the screen reader label for the button that closes the modal.

@@ -11,4 +11,5 @@ /**

*/
module.exports = function copyToClipboard (textToCopy, fallbackString) {
fallbackString = fallbackString || 'Copy the URL below'
export default function copyToClipboard (textToCopy, fallbackString) {
// TODO: make `fallbackString` an optional parameter instead.
fallbackString ||= 'Copy the URL below' // eslint-disable-line no-param-reassign

@@ -15,0 +16,0 @@ return new Promise((resolve) => {

@@ -1,2 +0,3 @@

const copyToClipboard = require('./copyToClipboard')
import { describe, xit, expect } from '@jest/globals'
import copyToClipboard from './copyToClipboard.js'

@@ -3,0 +4,0 @@ describe('copyToClipboard', () => {

@@ -1,4 +0,4 @@

const debounce = require('lodash.debounce')
const FOCUSABLE_ELEMENTS = require('@uppy/utils/lib/FOCUSABLE_ELEMENTS')
const getActiveOverlayEl = require('./getActiveOverlayEl')
import debounce from 'lodash.debounce'
import FOCUSABLE_ELEMENTS from '@uppy/utils/lib/FOCUSABLE_ELEMENTS'
import getActiveOverlayEl from './getActiveOverlayEl.js'

@@ -15,3 +15,3 @@ /*

*/
module.exports = function createSuperFocus () {
export default function createSuperFocus () {
let lastFocusWasOnSuperFocusableEl = false

@@ -18,0 +18,0 @@

@@ -1,2 +0,3 @@

const createSuperFocus = require('./createSuperFocus')
import { describe, it, expect } from '@jest/globals'
import createSuperFocus from './createSuperFocus.js'

@@ -3,0 +4,0 @@ describe('createSuperFocus', () => {

/**
* @returns {HTMLElement} - either dashboard element, or the overlay that's most on top
*/
module.exports = function getActiveOverlayEl (dashboardEl, activeOverlayType) {
export default function getActiveOverlayEl (dashboardEl, activeOverlayType) {
if (activeOverlayType) {

@@ -6,0 +6,0 @@ const overlayEl = dashboardEl.querySelector(`[data-uppy-paneltype="${activeOverlayType}"]`)

@@ -17,2 +17,2 @@ // ignore drop/paste events if they are not in input or textarea —

module.exports = ignoreEvent
export default ignoreEvent

@@ -1,4 +0,4 @@

const toArray = require('@uppy/utils/lib/toArray')
const FOCUSABLE_ELEMENTS = require('@uppy/utils/lib/FOCUSABLE_ELEMENTS')
const getActiveOverlayEl = require('./getActiveOverlayEl')
import toArray from '@uppy/utils/lib/toArray'
import FOCUSABLE_ELEMENTS from '@uppy/utils/lib/FOCUSABLE_ELEMENTS'
import getActiveOverlayEl from './getActiveOverlayEl.js'

@@ -52,21 +52,17 @@ function focusOnFirstNode (event, nodes) {

module.exports = {
// Traps focus inside of the currently open overlay (e.g. Dashboard, or e.g. Instagram),
// never lets focus disappear from the modal.
forModal: (event, activeOverlayType, dashboardEl) => {
trapFocus(event, activeOverlayType, dashboardEl)
},
// Traps focus inside of the currently open overlay (e.g. Dashboard, or e.g. Instagram),
// never lets focus disappear from the modal.
export { trapFocus as forModal }
// Traps focus inside of the currently open overlay, unless overlay is null - then let the user tab away.
forInline: (event, activeOverlayType, dashboardEl) => {
// ___When we're in the bare 'Drop files here, paste, browse or import from' screen
if (activeOverlayType === null) {
// Do nothing and let the browser handle it, user can tab away from Uppy to other elements on the page
// Traps focus inside of the currently open overlay, unless overlay is null - then let the user tab away.
export function forInline (event, activeOverlayType, dashboardEl) {
// ___When we're in the bare 'Drop files here, paste, browse or import from' screen
if (activeOverlayType === null) {
// Do nothing and let the browser handle it, user can tab away from Uppy to other elements on the page
// ___When there is some overlay with 'Done' button
} else {
// Trap the focus inside this overlay!
// User can close the overlay (click 'Done') if they want to travel away from Uppy.
trapFocus(event, activeOverlayType, dashboardEl)
}
},
} else {
// Trap the focus inside this overlay!
// User can close the overlay (click 'Done') if they want to travel away from Uppy.
trapFocus(event, activeOverlayType, dashboardEl)
}
}

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

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

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

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

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc