UNPKG

@nutui/nutui-react-taro

Version:

京东风格的轻量级移动端 React 组件库,支持一套代码生成 H5 和小程序

464 lines (463 loc) 20.4 kB
import { _ as _async_to_generator } from "@swc/helpers/_/_async_to_generator"; import { _ as _object_spread } from "@swc/helpers/_/_object_spread"; import { _ as _object_spread_props } from "@swc/helpers/_/_object_spread_props"; import { _ as _object_without_properties } from "@swc/helpers/_/_object_without_properties"; import { _ as _sliced_to_array } from "@swc/helpers/_/_sliced_to_array"; import { _ as _to_consumable_array } from "@swc/helpers/_/_to_consumable_array"; import { _ as _ts_generator } from "@swc/helpers/_/_ts_generator"; import React, { useEffect, useImperativeHandle, useRef, useState } from "react"; import classNames from "classnames"; import { chooseImage, chooseMedia, getEnv } from "@tarojs/taro"; import { Failure, Photograph } from "@nutui/icons-react-taro"; import { View } from "@tarojs/components"; import Button from "../button/index"; import { useConfig } from "../configprovider/index"; import { funcInterceptor } from "../../utils/interceptor"; import { ComponentDefaults } from "../../utils/typings"; import { usePropsValue } from "../../hooks/use-props-value"; import { Preview } from "./preview"; var defaultProps = _object_spread_props(_object_spread({}, ComponentDefaults), { maxCount: Number.MAX_VALUE, sizeType: [ 'original', 'compressed' ], sourceType: [ 'album', 'camera' ], mediaType: [ 'image', 'video' ], camera: 'back', uploadIcon: /*#__PURE__*/ React.createElement(Photograph, { size: "20px", color: "#808080" }), deleteIcon: /*#__PURE__*/ React.createElement(Failure, { color: "rgba(0,0,0,0.6)" }), uploadLabel: '', previewType: 'picture', fit: 'cover', name: 'file', accept: '*', disabled: false, autoUpload: true, multiple: false, maxFileSize: Number.MAX_VALUE, previewUrl: '', preview: true, deletable: true, maxDuration: 10, beforeDelete: function(file, files) { return true; } }); var InternalUploader = function(props, ref) { var locale = useConfig().locale; var _ref = _object_spread({}, defaultProps, props), children = _ref.children, uploadIcon = _ref.uploadIcon, deleteIcon = _ref.deleteIcon, uploadLabel = _ref.uploadLabel, listUploadRender = _ref.listUploadRender, accept = _ref.accept, name = _ref.name, camera = _ref.camera, defaultValue = _ref.defaultValue, value = _ref.value, previewType = _ref.previewType, fit = _ref.fit, disabled = _ref.disabled, multiple = _ref.multiple, previewUrl = _ref.previewUrl, preview = _ref.preview, deletable = _ref.deletable, maxCount = _ref.maxCount, maxFileSize = _ref.maxFileSize, mediaType = _ref.mediaType, className = _ref.className, autoUpload = _ref.autoUpload, sizeType = _ref.sizeType, sourceType = _ref.sourceType, maxDuration = _ref.maxDuration, onDelete = _ref.onDelete, onChange = _ref.onChange, onFileItemClick = _ref.onFileItemClick, onOversize = _ref.onOversize, onOverCount = _ref.onOverCount, beforeUpload = _ref.beforeUpload, upload = _ref.upload, beforeDelete = _ref.beforeDelete, onUploadQueueChange = _ref.onUploadQueueChange, restProps = _object_without_properties(_ref, [ "children", "uploadIcon", "deleteIcon", "uploadLabel", "listUploadRender", "accept", "name", "camera", "defaultValue", "value", "previewType", "fit", "disabled", "multiple", "previewUrl", "preview", "deletable", "maxCount", "maxFileSize", "mediaType", "className", "autoUpload", "sizeType", "sourceType", "maxDuration", "onDelete", "onChange", "onFileItemClick", "onOversize", "onOverCount", "beforeUpload", "upload", "beforeDelete", "onUploadQueueChange" ]); var _usePropsValue = _sliced_to_array(usePropsValue({ value: value, defaultValue: defaultValue, finalValue: [], onChange: function(v) { onChange === null || onChange === void 0 ? void 0 : onChange(v); } }), 2), fileList = _usePropsValue[0], setFileList = _usePropsValue[1]; var _useState = _sliced_to_array(useState([]), 2), uploadQueue = _useState[0], setUploadQueue = _useState[1]; var fileListRef = useRef([]); var classes = classNames(className, 'nut-uploader'); useImperativeHandle(ref, function() { return { submit: function() { return _async_to_generator(function() { return _ts_generator(this, function(_state) { switch(_state.label){ case 0: return [ 4, uploadAction(uploadQueue) ]; case 1: _state.sent(); return [ 2 ]; } }); })(); }, clear: function() { clearUploadQueue(); } }; }); useEffect(function() { fileListRef.current = fileList; }, [ fileList ]); useEffect(function() { onUploadQueueChange === null || onUploadQueueChange === void 0 ? void 0 : onUploadQueueChange(uploadQueue); }, [ uploadQueue ]); var clearUploadQueue = function() { var index = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : -1; if (index > -1) { uploadQueue.splice(index, 1); setUploadQueue(uploadQueue); } else { setUploadQueue([]); setFileList([]); } }; var _chooseImage = function() { if (disabled) { return; } var env = getEnv(); if (env === 'WEB') { var el = document.getElementById('taroChooseImage'); if (el) { el === null || el === void 0 ? void 0 : el.setAttribute('accept', accept); } else { var obj = document.createElement('input'); obj.setAttribute('type', 'file'); obj.setAttribute('id', 'taroChooseImage'); obj.setAttribute('accept', accept); obj.setAttribute('style', 'position: fixed; top: -4000px; left: -3000px; z-index: -300;'); document.body.appendChild(obj); } } if ([ 'WEAPP', 'JD', 'WEB', 'ASCF' ].includes(env) && chooseMedia) { chooseMedia({ count: multiple ? maxCount * 1 - fileList.length : 1, /** 文件类型 */ mediaType: mediaType, /** 图片和视频选择的来源 */ sourceType: sourceType, /** 拍摄视频最长拍摄时间,单位秒。时间范围为 3s 至 30s 之间 */ maxDuration: maxDuration, /** 仅对 mediaType 为 image 时有效,是否压缩所选文件 */ sizeType: sizeType, /** 仅在 sourceType 为 camera 时生效,使用前置或后置摄像头 */ camera: camera, success: onChangeMedia }); } else { chooseImage({ count: multiple ? maxCount * 1 - fileList.length : 1, // 可以指定是原图还是压缩图,默认二者都有 sizeType: sizeType, sourceType: sourceType, success: onChangeImage }); } }; var uploadAction = function(tasks) { return _async_to_generator(function() { var taskIds, list; return _ts_generator(this, function(_state) { switch(_state.label){ case 0: taskIds = tasks.map(function(task) { return task.uid; }); list = fileListRef.current.map(function(file) { if (taskIds.includes(file.uid)) { return _object_spread_props(_object_spread({}, file), { status: 'uploading', message: locale.uploader.uploading }); } return file; }); setFileList(list); return [ 4, Promise.all(tasks.map(function(currentTask, index) { return _async_to_generator(function() { var result, list, e, list1; return _ts_generator(this, function(_state) { switch(_state.label){ case 0: _state.trys.push([ 0, 2, , 3 ]); return [ 4, upload(currentTask.file) ]; case 1: result = _state.sent(); list = fileListRef.current.map(function(item) { if (item.uid === currentTask.uid) { item.status = 'success'; item.message = locale.uploader.success; item.url = result.url; } return item; }); setFileList(list); return [ 3, 3 ]; case 2: e = _state.sent(); list1 = fileListRef.current.map(function(item) { if (item.uid === currentTask.uid) { item.status = 'error'; item.message = locale.uploader.error; } return item; }); setFileList(list1); throw e; case 3: return [ 2 ]; } }); })(); })).catch(function(errs) { return console.error(errs); }) ]; case 1: _state.sent(); return [ 2 ]; } }); })(); }; var idCountRef = useRef(0); var readFile = function(files) { return _async_to_generator(function() { var tasks; return _ts_generator(this, function(_state) { switch(_state.label){ case 0: tasks = files.map(function(file) { var _file_originalFileObj, _file_originalFileObj1; var fileType = file.type; var filepath = file.tempFilePath || file.path; if (file.fileType) { fileType = file.fileType; } else { var imgReg = /\.(png|jpeg|jpg|webp|gif)$/i; if (!fileType && (imgReg.test(filepath) || filepath.includes('data:image'))) { fileType = 'image'; } } var info = { uid: idCountRef.current++, status: autoUpload ? 'uploading' : 'ready', file: file, message: autoUpload ? locale.uploader.uploading : locale.uploader.waitingUpload, name: getEnv() === 'WEB' ? (_file_originalFileObj = file.originalFileObj) === null || _file_originalFileObj === void 0 ? void 0 : _file_originalFileObj.name : filepath, path: filepath, type: getEnv() === 'WEB' ? (_file_originalFileObj1 = file.originalFileObj) === null || _file_originalFileObj1 === void 0 ? void 0 : _file_originalFileObj1.type : fileType }; if (preview) { info.url = fileType === 'video' ? file.thumbTempFilePath : filepath; } fileListRef.current = _to_consumable_array(fileListRef.current).concat([ info ]); setFileList(fileListRef.current); return info; }); if (!!autoUpload) return [ 3, 1 ]; setUploadQueue(tasks); return [ 3, 3 ]; case 1: return [ 4, uploadAction(tasks) ]; case 2: _state.sent(); _state.label = 3; case 3: return [ 2 ]; } }); })(); }; var filterFiles = function(files) { var maximum = maxCount * 1; var maximize = maxFileSize * 1; var oversizes = new Array(); var filterFile = files.filter(function(file) { if (file.size > maximize) { oversizes.push(file); return false; } return true; }); oversizes.length && (onOversize === null || onOversize === void 0 ? void 0 : onOversize(files)); var currentFileLength = filterFile.length + fileList.length; if (currentFileLength > maximum) { onOverCount === null || onOverCount === void 0 ? void 0 : onOverCount(filterFile.length); filterFile.splice(filterFile.length - (currentFileLength - maximum)); } return filterFile; }; var deleted = function(file, index) { var deletedFileList = fileList.filter(function(file, idx) { return idx !== index; }); onDelete === null || onDelete === void 0 ? void 0 : onDelete(file, deletedFileList); setFileList(deletedFileList); }; var onDeleteItem = function(file, index) { clearUploadQueue(index); funcInterceptor(beforeDelete, { args: [ file, fileList ], done: function() { return deleted(file, index); } }); }; var onChangeMedia = function(res) { return _async_to_generator(function() { var tempFiles, _files; return _ts_generator(this, function(_state) { // 返回选定照片的本地文件路径列表,tempFilePath可以作为img标签的src属性显示图片 tempFiles = res.tempFiles; _files = filterFiles(tempFiles); if (beforeUpload) { beforeUpload(new Array().slice.call(_files)).then(function(f) { var _files = filterFiles(new Array().slice.call(f)); if (!_files.length) res.tempFiles = []; readFile(_files); }); } else { readFile(_files); } return [ 2 ]; }); })(); }; var onChangeImage = function(res) { return _async_to_generator(function() { var tempFiles, _files; return _ts_generator(this, function(_state) { tempFiles = res.tempFiles; _files = filterFiles(tempFiles); if (beforeUpload) { beforeUpload(new Array().slice.call(_files)).then(function(f) { var _files = filterFiles(new Array().slice.call(f)); if (!_files.length) res.tempFiles = []; readFile(_files); }); } else { readFile(_files); } return [ 2 ]; }); })(); }; var handleItemClick = function(file, index) { onFileItemClick === null || onFileItemClick === void 0 ? void 0 : onFileItemClick(file, index); }; var renderListUploader = function() { if (previewType !== 'list') return null; return /*#__PURE__*/ React.createElement(View, { className: "nut-uploader-slot" }, listUploadRender || /*#__PURE__*/ React.createElement(React.Fragment, null, /*#__PURE__*/ React.createElement(Button, { size: "small", type: "primary" }, locale.uploader.list), Number(maxCount) > fileList.length && /*#__PURE__*/ React.createElement(Button, { className: "nut-uploader-input", onClick: _chooseImage }))); }; var renderImageUploader = function() { var shouldShow = Number(maxCount) > fileList.length && previewType === 'picture'; return shouldShow && /*#__PURE__*/ React.createElement(View, { className: "nut-uploader-upload ".concat(previewType, " ").concat(disabled ? 'nut-uploader-upload-disabled' : '') }, /*#__PURE__*/ React.createElement(View, { className: "nut-uploader-icon" }, uploadIcon, /*#__PURE__*/ React.createElement("span", { className: "nut-uploader-icon-tip" }, uploadLabel)), /*#__PURE__*/ React.createElement(Button, { className: "nut-uploader-input", onClick: _chooseImage })); }; return /*#__PURE__*/ React.createElement(View, _object_spread({ className: classes }, restProps), renderListUploader(), /*#__PURE__*/ React.createElement(Preview, { fileList: fileList, previewType: previewType, deletable: deletable, onDeleteItem: onDeleteItem, handleItemClick: handleItemClick, previewUrl: previewUrl, deleteIcon: deleteIcon, children: children }), renderImageUploader()); }; export var Uploader = /*#__PURE__*/ React.forwardRef(InternalUploader); Uploader.displayName = 'NutUploader';