UNPKG

25.6 kBJavaScriptView Raw
1'use strict';
2
3exports.__esModule = true;
4
5var _extends2 = require('babel-runtime/helpers/extends');
6
7var _extends3 = _interopRequireDefault(_extends2);
8
9var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
10
11var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
12
13var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
14
15var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
16
17var _inherits2 = require('babel-runtime/helpers/inherits');
18
19var _inherits3 = _interopRequireDefault(_inherits2);
20
21var _class, _temp2;
22
23var _react = require('react');
24
25var _react2 = _interopRequireDefault(_react);
26
27var _propTypes = require('prop-types');
28
29var _propTypes2 = _interopRequireDefault(_propTypes);
30
31var _classnames = require('classnames');
32
33var _classnames2 = _interopRequireDefault(_classnames);
34
35var _configProvider = require('../config-provider');
36
37var _configProvider2 = _interopRequireDefault(_configProvider);
38
39var _progress = require('../progress');
40
41var _progress2 = _interopRequireDefault(_progress);
42
43var _icon = require('../icon');
44
45var _icon2 = _interopRequireDefault(_icon);
46
47var _button = require('../button');
48
49var _button2 = _interopRequireDefault(_button);
50
51var _util = require('../util');
52
53var _zhCn = require('../locale/zh-cn.js');
54
55var _zhCn2 = _interopRequireDefault(_zhCn);
56
57var _util2 = require('./util');
58
59var _transform = require('./transform');
60
61var _transform2 = _interopRequireDefault(_transform);
62
63var _item = require('../menu/view/item');
64
65var _item2 = _interopRequireDefault(_item);
66
67var _selecter = require('./runtime/selecter');
68
69var _selecter2 = _interopRequireDefault(_selecter);
70
71function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
72
73var isIE9 = _util.env.ieVersion === 9;
74
75var List = (_temp2 = _class = function (_Component) {
76 (0, _inherits3.default)(List, _Component);
77
78 function List() {
79 var _temp, _this, _ret;
80
81 (0, _classCallCheck3.default)(this, List);
82
83 for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
84 args[_key] = arguments[_key];
85 }
86
87 return _ret = (_temp = (_this = (0, _possibleConstructorReturn3.default)(this, _Component.call.apply(_Component, [this].concat(args))), _this), _this.handleClose = function (file) {
88 var _this$props = _this.props,
89 onRemove = _this$props.onRemove,
90 uploader = _this$props.uploader;
91
92
93 var remove = onRemove(file);
94
95 _util.func.promiseCall(remove, function () {
96 uploader && uploader.removeFile(file);
97 });
98 }, _this.handleCancel = function (file) {
99 var _this$props2 = _this.props,
100 onCancel = _this$props2.onCancel,
101 uploader = _this$props2.uploader;
102
103 var cancel = onCancel(file);
104
105 _util.func.promiseCall(cancel, function () {
106 uploader && uploader.abort(file);
107 });
108 }, _this.onImageError = function (file, obj) {
109 obj.onerror = null;
110 _this.props.onImageError(obj, file);
111 }, _this.onSelect = function (oldfile, files) {
112 var uploader = _this.props.uploader;
113 uploader && files.length && uploader.replaceWithNewFile(oldfile, files[0]);
114 }, _temp), (0, _possibleConstructorReturn3.default)(_this, _ret);
115 }
116
117 List.prototype.componentDidUpdate = function componentDidUpdate() {
118 var _this2 = this;
119
120 var _props = this.props,
121 listType = _props.listType,
122 useDataURL = _props.useDataURL,
123 value = _props.value;
124
125 if (listType !== 'image' && listType !== 'card') {
126 return;
127 }
128
129 useDataURL && value.forEach(function (file) {
130 if (typeof document === 'undefined' || typeof window === 'undefined' || !window.FileReader || !window.File || !(file.originFileObj instanceof File) || file.imgURL !== undefined) {
131 return;
132 }
133 file.imgURL = '';
134 (0, _util2.previewFile)(file.originFileObj, function (previewDataUrl) {
135 file.imgURL = previewDataUrl;
136 _this2.forceUpdate();
137 });
138 });
139 };
140
141 List.prototype.onPreview = function onPreview(file, e) {
142 var onPreview = this.props.onPreview;
143
144
145 if (!onPreview) {
146 return;
147 }
148 // e.preventDefault();
149 return onPreview(file, e);
150 };
151
152 List.prototype.getInfo = function getInfo(file) {
153 var _classNames;
154
155 var prefixCls = this.props.prefix + 'upload';
156 var downloadURL = file.downloadURL || file.url;
157 var imgURL = file.imgURL || file.url;
158 var size = this.sizeCaculator(file.size);
159 var itemCls = (0, _classnames2.default)((_classNames = {}, _classNames[prefixCls + '-list-item'] = true, _classNames[prefixCls + '-list-item-' + file.state] = file.state, _classNames[prefixCls + '-list-item-error-with-msg'] = file.state === 'error' && file.errorMsg, _classNames));
160 var alt = file.name || file.alt;
161 return { prefixCls: prefixCls, downloadURL: downloadURL, imgURL: imgURL, size: size, itemCls: itemCls, alt: alt };
162 };
163 // transfer size from number to xx K/ XxxM / xxG
164
165
166 List.prototype.sizeCaculator = function sizeCaculator(size) {
167 var fileSize = parseFloat(size, 10);
168 // fileSize为浮点数 用 < 0.000001 替代 === 0
169 if (isNaN(fileSize) || fileSize < 0.0000001) {
170 return 0;
171 }
172 var SIZE_SUFFIX = ['B', 'K', 'M', 'G', 'T', 'P'];
173 var suffixIndex = 0;
174
175 // 在Mac上实验发现 取1024造成显示的大小和实际大小不一致
176 // 因为单位制不同 见 https://superuser.com/questions/938234/size-of-files-in-windows-os-its-kb-or-kb
177 var BIT_NUMBER_SYSTEM = 1024;
178 while (fileSize >= BIT_NUMBER_SYSTEM && suffixIndex < SIZE_SUFFIX.length) {
179 suffixIndex++;
180 fileSize /= BIT_NUMBER_SYSTEM;
181 }
182
183 var suffix = SIZE_SUFFIX[suffixIndex];
184 fileSize = fileSize.toFixed(2);
185
186 return '' + fileSize + suffix;
187 };
188
189 List.prototype.getTextList = function getTextList(file) {
190 var _this3 = this;
191
192 var _props2 = this.props,
193 locale = _props2.locale,
194 extraRender = _props2.extraRender,
195 actionRender = _props2.actionRender,
196 progressProps = _props2.progressProps,
197 rtl = _props2.rtl,
198 fileNameRender = _props2.fileNameRender,
199 previewOnFileName = _props2.previewOnFileName;
200
201 var _getInfo = this.getInfo(file),
202 prefixCls = _getInfo.prefixCls,
203 downloadURL = _getInfo.downloadURL,
204 size = _getInfo.size,
205 itemCls = _getInfo.itemCls;
206
207 var onClick = function onClick() {
208 return file.state === 'uploading' ? _this3.handleCancel(file) : _this3.handleClose(file);
209 };
210 var onKeyDown = function onKeyDown(e) {
211 if (e.keyCode === _util.KEYCODE.ENTER) {
212 onClick();
213 }
214 };
215 return _react2.default.createElement(
216 'div',
217 { className: itemCls, key: file.uid || file.name },
218 _react2.default.createElement(
219 'div',
220 { className: prefixCls + '-list-item-name-wrap' },
221 _react2.default.createElement(
222 'a',
223 {
224 onClick: previewOnFileName ? this.onPreview.bind(this, file) : _util.func.noop,
225 href: downloadURL,
226 target: '_blank',
227 style: { pointerEvents: downloadURL ? '' : 'none' },
228 className: prefixCls + '-list-item-name'
229 },
230 _react2.default.createElement(
231 'span',
232 null,
233 fileNameRender(file)
234 ),
235 !!size && _react2.default.createElement(
236 'span',
237 { className: prefixCls + '-list-item-size', dir: rtl ? 'rtl' : undefined },
238 '(',
239 size,
240 ')'
241 ),
242 _react2.default.createElement(
243 'span',
244 { className: prefixCls + '-extra' },
245 extraRender(file)
246 )
247 )
248 ),
249 file.state === 'uploading' ? _react2.default.createElement(
250 'div',
251 { className: prefixCls + '-list-item-progress' },
252 _react2.default.createElement(_progress2.default, (0, _extends3.default)({
253 size: 'medium',
254 percent: file.percent,
255 textRender: _util.func.noop,
256 rtl: rtl
257 }, progressProps))
258 ) : null,
259 file.state === 'error' && file.errorMsg ? _react2.default.createElement(
260 'div',
261 { className: prefixCls + '-list-item-error-msg' },
262 file.errorMsg
263 ) : null,
264 _react2.default.createElement(
265 'span',
266 { className: prefixCls + '-list-item-op' },
267 actionRender(file),
268 this.props.closable ? _react2.default.createElement(_icon2.default, {
269 type: 'close',
270 size: 'large',
271 role: 'button',
272 'aria-label': locale.upload.delete,
273 tabIndex: '0',
274 onClick: onClick,
275 onKeyDown: onKeyDown
276 }) : null
277 )
278 );
279 };
280
281 List.prototype.getImageList = function getImageList(file) {
282 var _this4 = this;
283
284 var _props3 = this.props,
285 extraRender = _props3.extraRender,
286 actionRender = _props3.actionRender,
287 progressProps = _props3.progressProps,
288 rtl = _props3.rtl,
289 fileNameRender = _props3.fileNameRender,
290 previewOnFileName = _props3.previewOnFileName;
291
292 var _getInfo2 = this.getInfo(file),
293 prefixCls = _getInfo2.prefixCls,
294 downloadURL = _getInfo2.downloadURL,
295 imgURL = _getInfo2.imgURL,
296 size = _getInfo2.size,
297 itemCls = _getInfo2.itemCls,
298 alt = _getInfo2.alt;
299
300 var img = null;
301
302 var onClick = function onClick() {
303 return file.state === 'uploading' ? _this4.handleCancel(file) : _this4.handleClose(file);
304 };
305 var onKeyDown = function onKeyDown(e) {
306 if (e.keyCode === _util.KEYCODE.ENTER) {
307 onClick();
308 }
309 };
310
311 if (file.state === 'uploading' || file.state === 'selected' && !imgURL) {
312 img = _react2.default.createElement(_icon2.default, { type: 'picture' });
313 } else if (file.state === 'error') {
314 img = _react2.default.createElement(_icon2.default, { type: 'cry' });
315 } else {
316 img = _react2.default.createElement('img', {
317 src: imgURL,
318 onError: this.onImageError.bind(this, file),
319 tabIndex: '0',
320 alt: alt,
321 onClick: this.onPreview.bind(this, file)
322 });
323 }
324
325 return _react2.default.createElement(
326 'div',
327 { className: itemCls, key: file.uid || file.name },
328 _react2.default.createElement(
329 'div',
330 { className: prefixCls + '-list-item-thumbnail' },
331 img
332 ),
333 _react2.default.createElement(
334 'span',
335 { className: prefixCls + '-list-item-op' },
336 actionRender(file),
337 this.props.closable ? _react2.default.createElement(_icon2.default, {
338 type: 'close',
339 size: 'large',
340 tabIndex: '0',
341 role: 'button',
342 onClick: onClick,
343 onKeyDown: onKeyDown
344 }) : null
345 ),
346 _react2.default.createElement(
347 'a',
348 {
349 onClick: previewOnFileName ? this.onPreview.bind(this, file) : _util.func.noop,
350 href: downloadURL,
351 target: '_blank',
352 style: { pointerEvents: downloadURL ? '' : 'none' },
353 className: prefixCls + '-list-item-name'
354 },
355 _react2.default.createElement(
356 'span',
357 null,
358 fileNameRender(file)
359 ),
360 !!size && _react2.default.createElement(
361 'span',
362 { className: prefixCls + '-list-item-size', dir: rtl ? 'rtl' : undefined },
363 '(',
364 size,
365 ')'
366 ),
367 _react2.default.createElement(
368 'span',
369 { className: prefixCls + '-extra' },
370 extraRender(file)
371 )
372 ),
373 file.state === 'uploading' ? _react2.default.createElement(
374 'div',
375 { className: prefixCls + '-list-item-progress' },
376 _react2.default.createElement(_progress2.default, (0, _extends3.default)({ size: 'medium', percent: file.percent, textRender: _util.func.noop }, progressProps))
377 ) : null,
378 file.state === 'error' && file.errorMsg ? _react2.default.createElement(
379 'div',
380 { className: prefixCls + '-list-item-error-msg' },
381 file.errorMsg
382 ) : null
383 );
384 };
385
386 List.prototype.getPictureCardList = function getPictureCardList(file, isPreview) {
387 var _this5 = this;
388
389 var _props4 = this.props,
390 locale = _props4.locale,
391 progressProps = _props4.progressProps,
392 fileNameRender = _props4.fileNameRender,
393 itemRender = _props4.itemRender,
394 showDownload = _props4.showDownload;
395
396 var _getInfo3 = this.getInfo(file),
397 prefixCls = _getInfo3.prefixCls,
398 downloadURL = _getInfo3.downloadURL,
399 imgURL = _getInfo3.imgURL,
400 itemCls = _getInfo3.itemCls,
401 alt = _getInfo3.alt;
402
403 var state = isPreview ? '' : file.state;
404
405 var img = null;
406
407 if (state === 'uploading' || state === 'selected' && !imgURL) {
408 img = _react2.default.createElement(
409 'div',
410 { className: prefixCls + '-list-item-handler' },
411 _react2.default.createElement(_icon2.default, { type: 'picture' }),
412 _react2.default.createElement(
413 _button2.default,
414 { text: true, onClick: function onClick() {
415 return _this5.handleCancel(file);
416 } },
417 locale.card.cancel
418 )
419 );
420 } else if (state === 'error') {
421 img = _react2.default.createElement(
422 'div',
423 { className: prefixCls + '-list-item-handler' },
424 _react2.default.createElement(_icon2.default, { type: 'cry' })
425 );
426 } else {
427 img = _react2.default.createElement('img', {
428 src: imgURL,
429 tabIndex: '0',
430 alt: alt,
431 onError: this.onImageError.bind(this, file),
432 onClick: this.onPreview.bind(this, file)
433 });
434 }
435
436 var onClose = function onClose() {
437 return _this5.handleClose(file);
438 };
439 var onKeyDownClose = function onKeyDownClose(e) {
440 if (e.keyCode === _util.KEYCODE.ENTER) {
441 onClose();
442 }
443 };
444
445 var item = null;
446 if (state === 'uploading') {
447 item = [_react2.default.createElement(
448 'div',
449 { className: prefixCls + '-list-item-thumbnail', key: 'img' },
450 img
451 ), _react2.default.createElement(
452 'div',
453 { className: prefixCls + '-list-item-progress', key: 'progress' },
454 _react2.default.createElement(_progress2.default, (0, _extends3.default)({ size: 'medium', percent: file.percent, textRender: _util.func.noop }, progressProps))
455 )];
456 } else {
457 /* eslint-disable no-lonely-if */
458 if (typeof itemRender === 'function') {
459 // 不处理上传态和选择态,太过复杂
460 item = itemRender(file, { remove: onClose });
461 } else {
462 var Uploader = this.props.uploader || { props: {} };
463 var UploaderProps = Uploader.props;
464
465 // TODO: 2.x 中逻辑会修改为,只要有showDownload,那就有下载按钮(不管有没有downloadURL)
466 item = [_react2.default.createElement(
467 'div',
468 { className: prefixCls + '-list-item-thumbnail', key: 'img' },
469 img
470 ), _react2.default.createElement(
471 'span',
472 { key: 'tool', className: prefixCls + '-tool' },
473 state !== 'error' && showDownload && downloadURL ? _react2.default.createElement(
474 'a',
475 {
476 href: downloadURL,
477 target: '_blank',
478 className: prefixCls + '-tool-item ' + prefixCls + '-tool-download-link'
479 },
480 _react2.default.createElement(_icon2.default, {
481 type: 'download',
482 'aria-label': locale.card.download,
483 className: prefixCls + '-tool-download-icon'
484 })
485 ) : null,
486 this.props.reUpload && !isPreview && !isIE9 ? _react2.default.createElement(
487 _selecter2.default,
488 {
489 className: prefixCls + '-tool-item ' + prefixCls + '-tool-reupload',
490 accept: UploaderProps.accept,
491 name: UploaderProps.fileKeyName,
492 onSelect: this.onSelect.bind(this, file)
493 },
494 _react2.default.createElement(_icon2.default, { type: 'edit', className: prefixCls + '-tool-reupload-icon' })
495 ) : null,
496 this.props.closable && !isPreview ? _react2.default.createElement(
497 'span',
498 { className: prefixCls + '-tool-item ' + prefixCls + '-tool-close' },
499 _react2.default.createElement(_icon2.default, {
500 type: 'ashbin',
501 'aria-label': locale.card.delete,
502 tabIndex: '0',
503 role: 'button',
504 onClick: onClose,
505 onKeyDown: onKeyDownClose
506 })
507 ) : null
508 )];
509 }
510 }
511
512 return _react2.default.createElement(
513 'div',
514 { className: itemCls, key: file.uid || file.name },
515 _react2.default.createElement(
516 'div',
517 { className: prefixCls + '-list-item-wrapper' },
518 item
519 ),
520 _react2.default.createElement(
521 'span',
522 { className: prefixCls + '-list-item-name' },
523 fileNameRender(file)
524 )
525 );
526 };
527
528 List.prototype.render = function render() {
529 var _this6 = this,
530 _classNames3;
531
532 var _props5 = this.props,
533 listType = _props5.listType,
534 children = _props5.children,
535 prefix = _props5.prefix,
536 rtl = _props5.rtl,
537 className = _props5.className,
538 isPreview = _props5.isPreview;
539
540 var prefixCls = prefix + 'upload';
541
542 var list = [];
543 if (isPreview) {
544 var _classNames2;
545
546 var previewCls = (0, _classnames2.default)((_classNames2 = {}, _classNames2[prefix + 'form-preview'] = true, _classNames2[className] = !!className, _classNames2));
547 list = this.props.value.map(function (file) {
548 if (!file) {
549 return null;
550 }
551
552 var downloadURL = file.downloadURL,
553 imgURL = file.imgURL,
554 name = file.name;
555
556 if (listType === 'text') {
557 return _react2.default.createElement(
558 'div',
559 { className: previewCls },
560 _react2.default.createElement(
561 'a',
562 { href: downloadURL, target: '_blank' },
563 name
564 )
565 );
566 } else if (listType === 'image' || listType === 'card') {
567 return _this6.getPictureCardList(file, true);
568 }
569 return null;
570 });
571 } else {
572 list = this.props.value.map(function (file) {
573 if (!file) {
574 return null;
575 }
576
577 if (listType === 'text') {
578 return _this6.getTextList(file);
579 } else if (listType === 'image') {
580 return _this6.getImageList(file);
581 } else if (listType === 'card') {
582 return _this6.getPictureCardList(file);
583 }
584 return null;
585 });
586 }
587
588 if (rtl && listType === 'card' && Array.isArray(list)) {
589 list = list.reverse();
590 }
591 var _listType = isPreview && listType === 'image' ? 'card' : this.props.listType;
592 var listclassNames = (0, _classnames2.default)((_classNames3 = {}, _classNames3[prefixCls + '-list'] = true, _classNames3[prefixCls + '-list-' + _listType] = true, _classNames3[prefixCls + '-ie9'] = isIE9, _classNames3), className);
593
594 var others = _util.obj.pickAttrsWith(this.props, 'data-');
595 return _react2.default.createElement(
596 'div',
597 (0, _extends3.default)({}, others, { className: listclassNames, dir: rtl ? 'rtl' : undefined }),
598 rtl ? children : list,
599 rtl ? list : children
600 );
601 };
602
603 return List;
604}(_react.Component), _class.propTypes = {
605 prefix: _propTypes2.default.string,
606 /**
607 * 多语言
608 */
609 locale: _propTypes2.default.object,
610 /**
611 * 文件列表,数据格式请参考 文件对象
612 */
613 listType: _propTypes2.default.oneOf(['text', 'image', 'card']),
614 /**
615 * 文件列表
616 */
617 value: _propTypes2.default.array,
618 closable: _propTypes2.default.bool,
619 /**
620 * 删除文件回调(支持Promise)
621 */
622 onRemove: _propTypes2.default.func,
623 /**
624 * 取消上传回调(支持Promise)
625 */
626 onCancel: _propTypes2.default.func,
627 /**
628 * 头像加载出错回调
629 */
630 onImageError: _propTypes2.default.func,
631 /**
632 * 点击图片回调
633 */
634 onPreview: _propTypes2.default.func,
635 /**
636 * 点击文件名时触发 onPreview
637 */
638 previewOnFileName: _propTypes2.default.bool,
639 /**
640 * 自定义额外渲染
641 */
642 extraRender: _propTypes2.default.func,
643 /**
644 * 自定义操作渲染
645 */
646 actionRender: _propTypes2.default.func,
647 /**
648 * 卡片自定义渲染(目前只支持 Card)
649 * @param {Object} file 文件对象
650 * @param {Object} {remove} remove:删除回调
651 * @retuns {ReactNode} React元素
652 */
653 itemRender: _propTypes2.default.func,
654 /**
655 * 透传给Progress props
656 */
657 progressProps: _propTypes2.default.object,
658 children: _propTypes2.default.node,
659 uploader: _propTypes2.default.any,
660 showDownload: _propTypes2.default.bool,
661 /**
662 * 可选参数,是否本地预览
663 */
664 useDataURL: _propTypes2.default.bool,
665 rtl: _propTypes2.default.bool,
666 isPreview: _propTypes2.default.bool,
667 fileNameRender: _propTypes2.default.func
668}, _class.defaultProps = {
669 prefix: 'next-',
670 listType: 'text',
671 value: [],
672 locale: _zhCn2.default.Upload,
673 closable: false,
674 showDownload: true,
675 onRemove: _util.func.noop,
676 onCancel: _util.func.noop,
677 extraRender: _util.func.noop,
678 actionRender: _util.func.noop,
679 onImageError: _util.func.noop,
680 progressProps: {},
681 fileNameRender: function fileNameRender(file) {
682 return file.name;
683 },
684 previewOnFileName: false
685}, _temp2);
686
687// Wrap <List> with <ConfigProvider> to avoid context missing if it is
688// referenced by other internal modules.
689// https://github.com/alibaba-fusion/next/blob/build/1.13.9/src/upload/upload.jsx#L521
690
691List.displayName = 'List';
692exports.default = _configProvider2.default.config(List, {
693 componentName: 'Upload',
694 transform: _transform2.default
695});
696module.exports = exports['default'];
\No newline at end of file