shineout
Version:
Shein 前端组件库
764 lines (636 loc) • 26 kB
JavaScript
"use strict";
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
exports.__esModule = true;
exports.default = void 0;
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread"));
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
var _inheritsLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/inheritsLoose"));
var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _react = _interopRequireDefault(require("react"));
var _classnames = _interopRequireDefault(require("classnames"));
var _immer = _interopRequireDefault(require("immer"));
var _Gap = _interopRequireDefault(require("../Gap"));
var _component = require("../component");
var _uid = require("../utils/uid");
var _errors = require("../utils/errors");
var _styles = require("./styles");
var _request = _interopRequireWildcard(require("./request"));
var _FileInput = _interopRequireDefault(require("./FileInput"));
var _File = _interopRequireDefault(require("./File"));
var _ImageFile = _interopRequireDefault(require("./ImageFile"));
var _Result = _interopRequireDefault(require("./Result"));
var _ImageResult = _interopRequireDefault(require("./ImageResult"));
var _context4 = require("./context");
var _Drop = _interopRequireDefault(require("./Drop"));
var _accept = _interopRequireDefault(require("../utils/accept"));
var _is = require("../utils/is");
var _locale = require("../locale");
var _accept2 = _interopRequireDefault(require("./accept"));
var _getDataset = _interopRequireDefault(require("../utils/dom/getDataset"));
var _config = require("../config");
var VALIDATORITEMS = [{
key: 'size',
param: function param(blob) {
return blob.size;
}
}, {
key: 'ext',
param: function param(blob) {
var exts = blob.name.split('.');
return exts[exts.length - 1];
}
}, {
key: 'customValidator',
param: function param(blob) {
return blob;
}
}];
var promised = function promised(action) {
for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
args[_key - 1] = arguments[_key];
}
var res = action.apply(void 0, args);
if (res && typeof res.then === 'function') return res;
return new Promise(function (resolve, reject) {
if (res instanceof Error) reject(res);
resolve(true);
});
};
var DefaultProps = {
cors: false,
limit: 100,
recoverAble: false,
validator: {},
value: [],
withCredentials: false,
showUploadList: true,
validatorHandle: true,
canDelete: true,
GapProps: {
column: 12,
row: 12
}
};
var Upload =
/*#__PURE__*/
function (_PureComponent) {
(0, _inheritsLoose2.default)(Upload, _PureComponent);
function Upload(props) {
var _this;
_this = _PureComponent.call(this, props) || this;
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)), "input", void 0);
_this.state = {
files: {},
recycle: []
};
_this.addFile = _this.addFile.bind((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)));
_this.bindElement = _this.bindElement.bind((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)));
_this.handleAddClick = _this.handleAddClick.bind((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)));
_this.removeFile = _this.removeFile.bind((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)));
_this.removeValue = _this.removeValue.bind((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)));
_this.recoverValue = _this.recoverValue.bind((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)));
_this.validatorHandle = _this.validatorHandle.bind((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)));
_this.useValidator = _this.useValidator.bind((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)));
_this.handleFileDrop = _this.handleFileDrop.bind((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)));
_this.handleReplace = _this.handleReplace.bind((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)));
props.validateHook(_this.validate.bind((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this))));
return _this;
}
var _proto = Upload.prototype;
_proto.getCanDelete = function getCanDelete(item, index) {
var canDelete = this.props.canDelete;
if ((0, _is.isFunc)(canDelete)) {
return canDelete(item, index);
}
return canDelete;
};
_proto.getAction = function getAction(file) {
var action = this.props.action;
if (typeof action === 'string') return action;
if (typeof action === 'function') return action(file);
return '';
};
_proto.validatorHandle = function validatorHandle(error, file) {
var vth = this.props.validatorHandle;
if (typeof vth === 'function') return vth(error, file);
return !!vth;
};
_proto.bindElement = function bindElement(input) {
this.input = input;
};
_proto.handleAddClick = function handleAddClick() {
var disabled = this.props.disabled;
if (disabled) return;
this.input.click();
};
_proto.validate = function validate() {
var files = this.state.files;
return new Promise(function (resolve, reject) {
if (Object.keys(files).length > 0) reject(new _errors.FormError(''));
resolve(true);
});
};
_proto.removeFile = function removeFile(id) {
var _this$props = this.props,
beforeCancel = _this$props.beforeCancel,
onErrorRemove = _this$props.onErrorRemove;
var file = this.state.files[id];
if (beforeCancel && (0, _is.isFunc)(beforeCancel)) beforeCancel(file);
if (file) {
if (file.xhr && file.xhr.abort) file.xhr.abort();
this.setState((0, _immer.default)(function (draft) {
delete draft.files[id];
}), function () {
if (file.status === _request.ERROR && onErrorRemove) {
onErrorRemove(file.xhr, file.blob, file);
}
});
}
};
_proto.removeValue = function removeValue(index) {
var _this2 = this;
var _this$props2 = this.props,
recoverAble = _this$props2.recoverAble,
disabled = _this$props2.disabled,
beforeRemove = _this$props2.beforeRemove;
if (disabled) return;
var current = this.props.value[index];
var startRemove = typeof beforeRemove === 'function' ? beforeRemove(current) : Promise.resolve();
startRemove.then(function () {
_this2.setState((0, _immer.default)(function (draft) {
draft.recycle.push(_this2.props.value[index]);
if (typeof recoverAble === 'number' && draft.recycle.length > recoverAble) {
draft.recycle.shift();
}
}));
var value = (0, _immer.default)(_this2.props.value, function (draft) {
draft.splice(index, 1);
});
_this2.props.onChange(value);
}).catch(function () {});
};
_proto.recoverValue = function recoverValue(index, value) {
var disabled = this.props.disabled;
if (disabled) return;
this.props.onChange((0, _immer.default)(this.props.value, function (draft) {
draft.push(value);
}));
this.setState((0, _immer.default)(function (draft) {
draft.recycle.splice(index, 1);
}));
};
_proto.useValidator =
/*#__PURE__*/
function () {
var _useValidator = (0, _asyncToGenerator2.default)(
/*#__PURE__*/
_regenerator.default.mark(function _callee(blob) {
var _this$props3, validator, accept, forceAccept, forceAcceptErrorMsg, files, error, i, acceptRes, item;
return _regenerator.default.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
_this$props3 = this.props, validator = _this$props3.validator, accept = _this$props3.accept, forceAccept = _this$props3.forceAccept, forceAcceptErrorMsg = _this$props3.forceAcceptErrorMsg;
files = this.state.files;
error = null;
i = 0;
if (!forceAccept) {
_context.next = 8;
break;
}
acceptRes = (0, _accept.default)(blob, accept);
if (acceptRes) {
_context.next = 8;
break;
}
return _context.abrupt("return", new Error(forceAcceptErrorMsg || (0, _locale.getLocale)('invalidAccept')));
case 8:
if (!VALIDATORITEMS[i]) {
_context.next = 24;
break;
}
item = VALIDATORITEMS[i];
if (!(validator && typeof validator[item.key] === 'function')) {
_context.next = 21;
break;
}
_context.prev = 11;
_context.next = 14;
return promised(validator[item.key], item.param(blob), files);
case 14:
_context.next = 19;
break;
case 16:
_context.prev = 16;
_context.t0 = _context["catch"](11);
error = _context.t0 instanceof Error ? _context.t0 : new Error(_context.t0);
case 19:
if (!(error instanceof Error)) {
_context.next = 21;
break;
}
return _context.abrupt("return", error);
case 21:
i += 1;
_context.next = 8;
break;
case 24:
return _context.abrupt("return", null);
case 25:
case "end":
return _context.stop();
}
}
}, _callee, this, [[11, 16]]);
}));
function useValidator(_x) {
return _useValidator.apply(this, arguments);
}
return useValidator;
}();
_proto.addFile =
/*#__PURE__*/
function () {
var _addFile = (0, _asyncToGenerator2.default)(
/*#__PURE__*/
_regenerator.default.mark(function _callee2(e) {
var _this3 = this;
var _this$props4, beforeUpload, value, _this$props4$limit, limit, filesFilter, files, finishedCode, fileList, addLength, list, _loop, i, _ret;
return _regenerator.default.wrap(function _callee2$(_context3) {
while (1) {
switch (_context3.prev = _context3.next) {
case 0:
_this$props4 = this.props, beforeUpload = _this$props4.beforeUpload, value = _this$props4.value, _this$props4$limit = _this$props4.limit, limit = _this$props4$limit === void 0 ? DefaultProps.limit : _this$props4$limit, filesFilter = _this$props4.filesFilter; // eslint-disable-next-line
files = (0, _objectSpread2.default)({}, this.state.files);
finishedCode = false;
fileList = (e.fromDragger && e.files ? e.files : e.target && e.target.files) || [];
if (filesFilter) fileList = filesFilter(Array.from(fileList)) || [];
addLength = limit - value.length - Object.keys(this.state.files).length;
if (!(addLength <= 0)) {
_context3.next = 8;
break;
}
return _context3.abrupt("return");
case 8:
list = Array.from({
length: Math.min(fileList.length, addLength)
});
_loop =
/*#__PURE__*/
_regenerator.default.mark(function _loop(i) {
var blob, id, file, error;
return _regenerator.default.wrap(function _loop$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
blob = fileList[i];
id = (0, _uid.getUidStr)();
file = {
name: blob.name,
process: -1,
status: _request.UPLOADING,
blob: blob
};
files[id] = file; // eslint-disable-next-line no-await-in-loop
_context2.next = 6;
return _this3.useValidator(blob);
case 6:
error = _context2.sent;
if (!(error instanceof Error)) {
_context2.next = 15;
break;
}
if (_this3.validatorHandle(error, file.blob)) {
_context2.next = 11;
break;
}
delete files[id];
return _context2.abrupt("return", "continue");
case 11:
file.message = error.message;
file.status = _request.ERROR;
if (beforeUpload) {
beforeUpload(blob, _this3.validatorHandle) // eslint-disable-next-line no-loop-func
.then(function (args) {
if (finishedCode) {
_this3.setState((0, _immer.default)(function (draft) {
draft.files[id] = Object.assign({}, draft.files[id], args);
}));
} else {
files[id] = Object.assign({}, files[id], args);
}
}).catch(function () {
return true;
});
}
return _context2.abrupt("return", "continue");
case 15:
if (beforeUpload) {
beforeUpload(blob, _this3.validatorHandle) // eslint-disable-next-line no-loop-func
.then(function (args) {
if (args.status !== _request.ERROR) files[id].xhr = _this3.uploadFile(id, blob, args.data);
if (finishedCode) {
_this3.setState((0, _immer.default)(function (draft) {
draft.files[id] = Object.assign({}, draft.files[id], args);
}));
} else {
files[id] = Object.assign({}, files[id], args);
}
}) // eslint-disable-next-line no-loop-func
.catch(function () {
if (finishedCode) {
_this3.setState((0, _immer.default)(function (draft) {
delete draft.files[id];
}));
} else {
delete files[id];
}
});
} else {
files[id].xhr = _this3.uploadFile(id, blob);
}
case 16:
case "end":
return _context2.stop();
}
}
}, _loop, this);
});
i = 0;
case 11:
if (!(i < list.length)) {
_context3.next = 19;
break;
}
return _context3.delegateYield(_loop(i), "t0", 13);
case 13:
_ret = _context3.t0;
if (!(_ret === "continue")) {
_context3.next = 16;
break;
}
return _context3.abrupt("continue", 16);
case 16:
i++;
_context3.next = 11;
break;
case 19:
finishedCode = true;
this.setState({
files: files
});
case 21:
case "end":
return _context3.stop();
}
}
}, _callee2, this);
}));
function addFile(_x2) {
return _addFile.apply(this, arguments);
}
return addFile;
}();
_proto.uploadFile = function uploadFile(id, file, data) {
var _this4 = this;
var _this$props5 = this.props,
onSuccess = _this$props5.onSuccess,
name = _this$props5.name,
htmlName = _this$props5.htmlName,
cors = _this$props5.cors,
params = _this$props5.params,
withCredentials = _this$props5.withCredentials,
headers = _this$props5.headers,
request = _this$props5.request,
_onProgress = _this$props5.onProgress,
onStart = _this$props5.onStart,
responseType = _this$props5.responseType;
var req = request || _request.default;
var throttle = false;
var options = {
url: this.getAction(file),
name: htmlName || name,
cors: cors,
params: params,
withCredentials: withCredentials,
file: file,
headers: headers,
responseType: responseType,
onStart: onStart,
onProgress: function onProgress(e, msg) {
var percent = typeof e.percent === 'number' ? e.percent : e.loaded / e.total * 100;
if (throttle) return;
throttle = true;
setTimeout(function () {
throttle = false;
}, 16);
if (_this4.state.files[id]) {
_this4.setState((0, _immer.default)(function (draft) {
draft.files[id].process = percent;
if (msg) draft.files[id].message = msg;
}), // expose the file progress to Upload.Button
function () {
if (typeof _onProgress === 'function') {
_onProgress(_this4.state.files[id]);
}
});
}
},
onSuccess: onSuccess,
onLoad: function onLoad(xhr) {
if (!/^2|1223/.test("" + xhr.status)) {
_this4.handleError(id, xhr, file);
return;
}
var value;
if (xhr.responseType === 'text' || !xhr.responseType) value = xhr.responseText;
if (!value) value = xhr.response;
if (onSuccess) {
value = onSuccess(value, file, data, xhr);
}
if (value instanceof Error) {
_this4.setState((0, _immer.default)(function (draft) {
draft.files[id].status = _request.ERROR;
draft.files[id].name = file.name;
draft.files[id].message = value.message;
}));
} else {
_this4.setState((0, _immer.default)(function (draft) {
delete draft.files[id];
})); // add value
var values = (0, _immer.default)(_this4.props.value, function (draft) {
draft.push(value);
});
_this4.props.onChange(values);
}
},
onError: function onError(xhr) {
return _this4.handleError(id, xhr, file);
}
};
if (_onProgress === false || _onProgress === null) {
options.onProgress = function () {};
}
return req(options);
};
_proto.handleFileDrop = function handleFileDrop(files) {
this.addFile({
files: files,
fromDragger: true
});
};
_proto.handleReplace = function handleReplace(files, index) {
var _this5 = this;
this.removeValue(index);
setTimeout(function () {
_this5.addFile({
files: files,
fromDragger: true
});
});
};
_proto.handleError = function handleError(id, xhr, file) {
var _this$props6 = this.props,
onError = _this$props6.onError,
onHttpError = _this$props6.onHttpError;
var message = xhr.statusText;
if (onError) message = onError(xhr, file);
if (onHttpError) message = onHttpError(xhr, file) || message;
this.setState((0, _immer.default)(function (draft) {
if (!draft.files[id]) return;
draft.files[id].status = _request.ERROR;
draft.files[id].message = message;
}));
};
_proto.renderHandle = function renderHandle() {
var _this$props7 = this.props,
_this$props7$limit = _this$props7.limit,
limit = _this$props7$limit === void 0 ? DefaultProps.limit : _this$props7$limit,
value = _this$props7.value,
children = _this$props7.children,
accept = _this$props7.accept,
multiple = _this$props7.multiple,
disabled = _this$props7.disabled,
webkitdirectory = _this$props7.webkitdirectory,
drop = _this$props7.drop;
var count = value.length + Object.keys(this.state.files).length;
if (limit > 0 && limit <= count) return null;
var dragProps = {
multiple: multiple,
addFile: this.addFile,
accept: accept,
disabled: disabled,
limit: limit
};
return _react.default.createElement(_Drop.default, {
drop: drop,
accept: accept,
disabled: disabled,
onDrop: this.handleFileDrop,
multiple: !!multiple || limit > 1
}, _react.default.createElement("span", {
className: (0, _styles.uploadClass)('handle', disabled && 'disabled'),
onClick: this.handleAddClick
}, _react.default.createElement(_context4.Provider, {
value: dragProps
}, children), _react.default.createElement(_FileInput.default, {
webkitdirectory: webkitdirectory,
accept: accept,
ref: this.bindElement,
multiple: multiple,
onChange: this.addFile
})));
};
_proto.render = function render() {
var _this6 = this;
var _this$props8 = this.props,
_this$props8$limit = _this$props8.limit,
limit = _this$props8$limit === void 0 ? DefaultProps.limit : _this$props8$limit,
value = _this$props8.value,
renderResult = _this$props8.renderResult,
style = _this$props8.style,
imageStyle = _this$props8.imageStyle,
recoverAble = _this$props8.recoverAble,
showUploadList = _this$props8.showUploadList,
CustomResult = _this$props8.customResult,
disabled = _this$props8.disabled,
renderContent = _this$props8.renderContent,
accept = _this$props8.accept,
drop = _this$props8.drop,
leftHandler = _this$props8.leftHandler,
onPreview = _this$props8.onPreview,
removeConfirm = _this$props8.removeConfirm,
gapProps = _this$props8.gapProps;
var _this$state = this.state,
files = _this$state.files,
recycle = _this$state.recycle;
var fileDrop = drop && !imageStyle;
var className = (0, _classnames.default)((0, _styles.uploadClass)('_', (0, _config.isRTL)() && 'rtl', disabled && 'disabled', showUploadList === false && 'hide-list', fileDrop && 'file-drop'), this.props.className);
var FileComponent = imageStyle ? _ImageFile.default : _File.default;
var ResultComponent = imageStyle ? _ImageResult.default : _Result.default;
if (CustomResult) {
return _react.default.createElement("div", {
className: className,
style: style
}, this.renderHandle(), _react.default.createElement(CustomResult, {
value: value,
files: files,
onValueRemove: this.removeValue,
onFileRemove: this.removeFile
}));
}
var Wrapper = imageStyle ? _Gap.default : _react.default.Fragment;
return _react.default.createElement("div", (0, _extends2.default)({
className: className,
style: style
}, (0, _getDataset.default)(this.props)), _react.default.createElement(Wrapper, imageStyle ? gapProps : null, !imageStyle && this.renderHandle(), imageStyle && leftHandler && this.renderHandle(), showUploadList && value.map(function (v, i) {
return _react.default.createElement(_Drop.default, {
drop: drop,
multiple: false,
key: i,
accept: accept,
dropData: i,
disabled: disabled,
onDrop: _this6.handleReplace
}, _react.default.createElement(ResultComponent, {
renderContent: renderContent,
value: v,
values: value,
index: i,
style: imageStyle,
renderResult: renderResult,
onRemove: _this6.getCanDelete(v, i) ? _this6.removeValue : undefined,
removeConfirm: removeConfirm,
onPreview: onPreview
}));
}), showUploadList && Object.keys(files).map(function (id) {
return _react.default.createElement(FileComponent, (0, _extends2.default)({}, files[id], {
key: id,
id: id,
style: imageStyle,
onRemove: _this6.removeFile
}));
}), imageStyle && !leftHandler && this.renderHandle(), recoverAble && recycle.map(function (v, i) {
return _react.default.createElement(ResultComponent, {
renderContent: renderContent,
key: i,
value: v,
values: recycle,
index: i,
renderResult: renderResult,
recoverAble: !!recoverAble,
showRecover: recoverAble && limit > value.length,
onRecover: _this6.recoverValue,
style: imageStyle
});
})));
};
return Upload;
}(_component.PureComponent);
(0, _defineProperty2.default)(Upload, "defaultProps", DefaultProps);
var _default = (0, _accept2.default)(Upload);
exports.default = _default;