UNPKG

choo-taro-ui-vue3

Version:

Taro UI Rewritten in Vue 3.0

306 lines (292 loc) 12.4 kB
import Taro from '@tarojs/taro'; import { defineComponent, computed, renderList, Fragment, openBlock, createElementBlock, resolveComponent, normalizeStyle, createVNode, mergeProps, withCtx, createBlock, toRef, createCommentVNode, toDisplayString, createTextVNode, normalizeClass } from 'vue'; import { pxTransform, uuid } from '../utils'; const AtLoading = defineComponent({ name: "AtLoading", props: { size: { type: [String, Number], default: 0 }, color: [String, Number] }, setup(props) { const loadingSize = computed(() => { return pxTransform(parseInt(`${props.size}`)); }); const sizeStyle = computed(() => ({ width: loadingSize.value, height: loadingSize.value })); const ringStyle = computed(() => ({ ...sizeStyle.value, border: props.color ? `1px solid ${props.color}` : "", "border-color": props.color ? `${props.color} transparent transparent transparent` : "" })); return { sizeStyle, ringStyle }; } }); // Binding optimization for webpack code-split const _renderList$1 = renderList, _Fragment$1 = Fragment, _openBlock$1 = openBlock, _createElementBlock$1 = createElementBlock, _resolveComponent$1 = resolveComponent, _normalizeStyle = normalizeStyle, _createVNode$1 = createVNode, _mergeProps$1 = mergeProps, _withCtx$1 = withCtx, _createBlock$1 = createBlock; function _sfc_render$1(_ctx, _cache, $props, $setup, $data, $options) { const _component_taro_view = process.env.TARO_ENV === "h5" ? _resolveComponent$1("taro-view") : "view"; return (_openBlock$1(), _createBlock$1(_component_taro_view, _mergeProps$1(_ctx.$attrs, { class: "at-loading", style: _ctx.sizeStyle }), { default: _withCtx$1(() => [ (_openBlock$1(), _createElementBlock$1(_Fragment$1, null, _renderList$1(3, (n) => { return _createVNode$1(_component_taro_view, { key: n, style: _normalizeStyle(_ctx.ringStyle), class: "at-loading__ring" }, null, 8 /* PROPS */, ["style"]) }), 64 /* STABLE_FRAGMENT */)) ]), _: 1 /* STABLE */ }, 16 /* FULL_PROPS */, ["style"])) } AtLoading.render = _sfc_render$1; const generateMatrix = (files, col, showAddBtn) => { const matrix = []; const length = showAddBtn ? files.length + 1 : files.length; const row = Math.ceil(length / col); for (let i = 0; i < row; i++) { if (i === row - 1) { const lastArr = files.slice(i * col); if (lastArr.length < col) { if (showAddBtn) { lastArr.push({ type: "btn", uuid: uuid() }); } for (let j = lastArr.length; j < col; j++) { lastArr.push({ type: "blank", uuid: uuid() }); } } matrix.push(lastArr); } else { matrix.push(files.slice(i * col, (i + 1) * col)); } } return matrix; }; const ENV = Taro.getEnv(); const modeOptions = [ "scaleToFill", "aspectFit", "aspectFill", "widthFix", "top", "bottom", "center", "left", "right", "top left", "top right", "bottom left", "bottom right" ]; const AtImagePicker = defineComponent({ name: "AtImagePicker", components: { AtLoading }, emits: { "change"(args) { return !!(args.files && Array.isArray(args.files) && args.operationType && ["add", "remove"].includes(args.operationType) && ["undefined", "number"].includes(typeof args.index)); }, "image-click"(index, file) { return !!(typeof index === "number" && file && typeof file === "object"); }, "fail"(message) { return !!(message && typeof message === "string"); } }, props: { files: { type: Array, default: () => [] }, mode: { type: String, default: "aspectFill", validator: (value) => modeOptions.includes(value) }, showAddBtn: { type: Boolean, default: true }, multiple: Boolean, length: { type: Number, default: 4 }, count: Number, sizeType: { type: Array, default: () => ["original", "compressed"] }, sourceType: { type: Array, default: () => ["album", "camera"] } }, setup(props, { emit }) { const rowLength = computed(() => props.length <= 0 ? 1 : props.length); const genKey = computed(() => (item, row, col) => { return item.url ? `preview-${row * props.length + col}` : `add-bar-${row * props.length + col}`; }); const matrix = computed(() => generateMatrix(props.files, rowLength.value, props.showAddBtn)); function chooseFile() { const params = {}; const filePathName = ENV === Taro.ENV_TYPE.ALIPAY ? "apFilePaths" : "tempFiles"; if (props.multiple) { params.count = 99; } if (props.count) { params.count = props.count; } if (props.sizeType) { params.sizeType = props.sizeType; } if (props.sourceType) { params.sourceType = props.sourceType; } Taro.chooseImage(params).then((res) => { const targetFiles = res.tempFilePaths.map((path, i) => ({ url: path, file: res[filePathName][i] })); const newFiles = props.files.concat(targetFiles); emit("change", { files: newFiles, operationType: "add" }); }).catch((err) => { emit("fail", err.errMsg); }); } function handleImageClick(idx) { emit("image-click", idx, props.files[idx]); } function handleRemoveImg(idx) { if (ENV === Taro.ENV_TYPE.WEB) { window.URL.revokeObjectURL(props.files[idx].url); } const newFiles = props.files.filter((_, i) => i !== idx); emit("change", { files: newFiles, operationType: "remove", index: idx }); } return { length: toRef(props, "length"), mode: toRef(props, "mode"), matrix, genKey, chooseFile, handleRemoveImg, handleImageClick }; } }); // Binding optimization for webpack code-split const _renderList = renderList, _Fragment = Fragment, _openBlock = openBlock, _createElementBlock = createElementBlock, _createCommentVNode = createCommentVNode, _resolveComponent = resolveComponent, _createVNode = createVNode, _createBlock = createBlock, _toDisplayString = toDisplayString, _createTextVNode = createTextVNode, _normalizeClass = normalizeClass, _withCtx = withCtx, _mergeProps = mergeProps; function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) { const _component_taro_view = process.env.TARO_ENV === "h5" ? _resolveComponent("taro-view") : "view"; const _component_taro_image = process.env.TARO_ENV === "h5" ? _resolveComponent("taro-image") : "image"; const _component_at_loading = _resolveComponent("at-loading"); return (_openBlock(), _createBlock(_component_taro_view, _mergeProps(_ctx.$attrs, { class: "at-image-picker" }), { default: _withCtx(() => [ (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.matrix, (row, i) => { return (_openBlock(), _createBlock(_component_taro_view, { key: i+1, class: "at-image-picker__flex-box" }, { default: _withCtx(() => [ (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(row, (item, j) => { return (_openBlock(), _createBlock(_component_taro_view, { key: _ctx.genKey(item, i, j), class: "at-image-picker__flex-item" }, { default: _withCtx(() => [ _createCommentVNode(" image thumb "), (item.url) ? (_openBlock(), _createBlock(_component_taro_view, { key: 0, class: "at-image-picker__item" }, { default: _withCtx(() => [ _createVNode(_component_taro_view, { class: "at-image-picker__remove-btn", onTap: $event => (_ctx.handleRemoveImg(i * _ctx.length + j)) }, null, 8 /* PROPS */, ["onTap"]), _createVNode(_component_taro_image, { class: "at-image-picker__preview-img", mode: _ctx.mode, src: item.url, onTap: $event => (_ctx.handleImageClick(i * _ctx.length + j)) }, null, 8 /* PROPS */, ["mode", "src", "onTap"]), _createCommentVNode(" upload status "), (item.status && item.status !== 'done') ? (_openBlock(), _createBlock(_component_taro_view, { key: 0, class: "at-image-picker__upload-status" }, { default: _withCtx(() => [ _createCommentVNode(" status icon "), (item.status === 'uploading') ? (_openBlock(), _createBlock(_component_at_loading, { key: 0, color: "#fff" })) : (_openBlock(), _createBlock(_component_taro_view, { key: 1, class: "at-image-picker__status-icon at-image-picker__status-icon--failed" })), _createCommentVNode(" status message "), (item.message) ? (_openBlock(), _createBlock(_component_taro_view, { key: 2, class: _normalizeClass(['at-image-picker__status-message', { 'at-image-picker__status-message--uploading': item.status === 'uploading', 'at-image-picker__status-message--failed': item.status !== 'uploading', }]) }, { default: _withCtx(() => [ _createTextVNode(_toDisplayString(item.message), 1 /* TEXT */) ]), _: 2 /* DYNAMIC */ }, 1032 /* PROPS, DYNAMIC_SLOTS */, ["class"])) : _createCommentVNode("v-if", true) ]), _: 2 /* DYNAMIC */ }, 1024 /* DYNAMIC_SLOTS */)) : _createCommentVNode("v-if", true) ]), _: 2 /* DYNAMIC */ }, 1024 /* DYNAMIC_SLOTS */)) : (item.type === 'btn') ? (_openBlock(), _createElementBlock(_Fragment, { key: 1 }, [ _createCommentVNode(" + add bar: choose button "), _createVNode(_component_taro_view, { class: "at-image-picker__item at-image-picker__choose-btn", onTap: _ctx.chooseFile }, { default: _withCtx(() => [ (_openBlock(), _createElementBlock(_Fragment, null, _renderList([0, 1], (i) => { return _createVNode(_component_taro_view, { key: i, class: "add-bar" }) }), 64 /* STABLE_FRAGMENT */)) ]), _: 2 /* DYNAMIC */ }, 1032 /* PROPS, DYNAMIC_SLOTS */, ["onTap"]) ], 2112 /* STABLE_FRAGMENT, DEV_ROOT_FRAGMENT */)) : _createCommentVNode("v-if", true) ]), _: 2 /* DYNAMIC */ }, 1024 /* DYNAMIC_SLOTS */)) }), 128 /* KEYED_FRAGMENT */)) ]), _: 2 /* DYNAMIC */ }, 1024 /* DYNAMIC_SLOTS */)) }), 128 /* KEYED_FRAGMENT */)) ]), _: 1 /* STABLE */ }, 16 /* FULL_PROPS */)) } AtImagePicker.render = _sfc_render; export default AtImagePicker;