diff --git a/components/style.ts b/components/style.ts index d19d3c202..c377c48a6 100644 --- a/components/style.ts +++ b/components/style.ts @@ -4,8 +4,8 @@ import './radio/style'; // import './checkbox/style'; // import './grid/style'; // import './tag/style'; -import './rate/style'; -import './pagination/style'; +// import './rate/style'; +// import './pagination/style'; // import './avatar/style'; // import './badge/style'; import './tabs/style'; @@ -29,14 +29,14 @@ import './auto-complete/style'; // import './affix/style'; import './cascader/style'; // import './back-top/style'; -import './modal/style'; +// import './modal/style'; // import './alert/style'; import './time-picker/style'; import './steps/style'; // import './breadcrumb/style'; import './calendar/style'; -import './date-picker/style'; -import './slider/style'; +// import './date-picker/style'; +// import './slider/style'; import './table/style'; // import './progress/style'; import './timeline/style'; @@ -52,7 +52,7 @@ import './drawer/style'; // import './skeleton/style'; // import './comment/style'; // import './config-provider/style'; -import './empty/style'; +// import './empty/style'; // import './statistic/style'; // import './result/style'; // import './descriptions/style'; diff --git a/components/upload/Upload.tsx b/components/upload/Upload.tsx index c4aa8848a..8d5c83578 100644 --- a/components/upload/Upload.tsx +++ b/components/upload/Upload.tsx @@ -1,14 +1,7 @@ import type { UploadProps as RcUploadProps } from '../vc-upload'; import VcUpload from '../vc-upload'; import UploadList from './UploadList'; -import type { - UploadType, - UploadListType, - UploadFile, - UploadChangeParam, - ShowUploadListInterface, - FileType, -} from './interface'; +import type { UploadFile, UploadChangeParam, ShowUploadListInterface, FileType } from './interface'; import { uploadProps } from './interface'; import { file2Obj, getFileItem, removeFileItem, updateFileList } from './utils'; import { useLocaleReceiver } from '../locale-provider/LocaleReceiver'; @@ -25,6 +18,7 @@ import { useInjectFormItemContext } from '../form'; // CSSINJS import useStyle from './style'; +import { useInjectDisabled } from '../config-provider/DisabledContext'; export const LIST_IGNORE = `__LIST_IGNORE_${Date.now()}__`; @@ -33,18 +27,25 @@ export default defineComponent({ name: 'AUpload', inheritAttrs: false, props: initDefaultProps(uploadProps(), { - type: 'select' as UploadType, + type: 'select', multiple: false, action: '', data: {}, accept: '', showUploadList: true, - listType: 'text' as UploadListType, // or picture + listType: 'text', // or picture disabled: false, supportServerRender: true, }), setup(props, { slots, attrs, expose }) { const formItemContext = useInjectFormItemContext(); + const { prefixCls, direction, disabled } = useConfigInject('upload', props); + + // style + const [wrapSSR, hashId] = useStyle(prefixCls); + const disabledContext = useInjectDisabled(); + const mergedDisabled = computed(() => disabledContext.value ?? disabled.value); + const [mergedFileList, setMergedFileList] = useMergedState(props.defaultFileList || [], { value: toRef(props, 'fileList'), postState: list => { @@ -59,7 +60,7 @@ export default defineComponent({ }); const dragState = ref('drop'); - const upload = ref(); + const upload = ref(null); onMounted(() => { devWarning( props.fileList !== undefined || attrs.value === undefined, @@ -294,11 +295,6 @@ export default defineComponent({ upload, }); - const { prefixCls, direction } = useConfigInject('upload', props); - - // style - const [wrapSSR, hashId] = useStyle(prefixCls); - const [locale] = useLocaleReceiver( 'Upload', defaultLocale.Upload, @@ -312,7 +308,6 @@ export default defineComponent({ previewFile, onPreview, onDownload, - disabled, isImageUrl, progress, itemRender, @@ -330,7 +325,7 @@ export default defineComponent({ onPreview={onPreview} onDownload={onDownload} onRemove={handleRemove} - showRemoveIcon={!disabled && showRemoveIcon} + showRemoveIcon={!mergedDisabled.value && showRemoveIcon} showPreviewIcon={showPreviewIcon} showDownloadIcon={showDownloadIcon} removeIcon={removeIcon} @@ -350,7 +345,7 @@ export default defineComponent({ ); }; return () => { - const { listType, disabled, type } = props; + const { listType, type } = props; const { class: className, style: styleName, ...transAttrs } = attrs; const rcUploadProps = { onBatchStart, @@ -363,6 +358,7 @@ export default defineComponent({ prefixCls: prefixCls.value, beforeUpload: mergedBeforeUpload, onChange: undefined, + disabled: mergedDisabled.value, }; delete (rcUploadProps as any).remove; @@ -370,12 +366,12 @@ export default defineComponent({ // !children: https://github.com/ant-design/ant-design/issues/14298 // disabled: https://github.com/ant-design/ant-design/issues/16478 // https://github.com/ant-design/ant-design/issues/24197 - if (!slots.default || disabled) { + if (!slots.default || mergedDisabled.value) { delete rcUploadProps.id; } const rtlCls = { - [`${prefixCls}-rtl`]: direction.value === 'rtl', + [`${prefixCls.value}-rtl`]: direction.value === 'rtl', }; if (type === 'drag') { @@ -387,7 +383,7 @@ export default defineComponent({ file => file.status === 'uploading', ), [`${prefixCls.value}-drag-hover`]: dragState.value === 'dragover', - [`${prefixCls.value}-disabled`]: disabled, + [`${prefixCls.value}-disabled`]: mergedDisabled.value, [`${prefixCls.value}-rtl`]: direction.value === 'rtl', }, attrs.class, @@ -423,7 +419,7 @@ export default defineComponent({ const uploadButtonCls = classNames(prefixCls.value, { [`${prefixCls.value}-select`]: true, [`${prefixCls.value}-select-${listType}`]: true, - [`${prefixCls.value}-disabled`]: disabled, + [`${prefixCls.value}-disabled`]: mergedDisabled.value, [`${prefixCls.value}-rtl`]: direction.value === 'rtl', }); const children = flattenChildren(slots.default?.()); diff --git a/components/upload/UploadList/ListItem.tsx b/components/upload/UploadList/ListItem.tsx index e12ef14eb..560b929e0 100644 --- a/components/upload/UploadList/ListItem.tsx +++ b/components/upload/UploadList/ListItem.tsx @@ -1,4 +1,4 @@ -import { computed, defineComponent, onBeforeUnmount, onMounted, ref } from 'vue'; +import { computed, defineComponent, onBeforeUnmount, onMounted, ref, watch } from 'vue'; import type { ExtractPropTypes, CSSProperties } from 'vue'; import EyeOutlined from '@ant-design/icons-vue/EyeOutlined'; import DeleteOutlined from '@ant-design/icons-vue/DeleteOutlined'; @@ -69,6 +69,15 @@ export default defineComponent({ onBeforeUnmount(() => { clearTimeout(progressRafRef.value); }); + const mergedStatus = ref(props.file?.status); + watch( + () => props.file?.status, + status => { + if (status !== 'removed') { + mergedStatus.value = status; + } + }, + ); const { rootPrefixCls } = useConfigInject('upload', props); const transitionProps = computed(() => getTransitionProps(`${rootPrefixCls.value}-fade`)); return () => { @@ -100,10 +109,10 @@ export default defineComponent({ const iconNode = iconRender({ file }); let icon =
{iconNode}
; if (listType === 'picture' || listType === 'picture-card') { - if (file.status === 'uploading' || (!file.thumbUrl && !file.url)) { + if (mergedStatus.value === 'uploading' || (!file.thumbUrl && !file.url)) { const uploadingClassName = { [`${prefixCls}-list-item-thumbnail`]: true, - [`${prefixCls}-list-item-file`]: file.status !== 'uploading', + [`${prefixCls}-list-item-file`]: mergedStatus.value !== 'uploading', }; icon =
{iconNode}
; } else { @@ -137,8 +146,7 @@ export default defineComponent({ const infoUploadingClass = { [`${prefixCls}-list-item`]: true, - [`${prefixCls}-list-item-${file.status}`]: true, - [`${prefixCls}-list-item-list-type-${listType}`]: true, + [`${prefixCls}-list-item-${mergedStatus.value}`]: true, }; const linkProps = typeof file.linkProps === 'string' ? JSON.parse(file.linkProps) : file.linkProps; @@ -152,7 +160,7 @@ export default defineComponent({ }) : null; const downloadIcon = - showDownloadIcon && file.status === 'done' + showDownloadIcon && mergedStatus.value === 'done' ? actionIconRender({ customIcon: customDownloadIcon ? customDownloadIcon({ file }) : , callback: () => onDownload(file), @@ -175,7 +183,7 @@ export default defineComponent({ ); const listItemNameClass = `${prefixCls}-list-item-name`; - const preview = file.url + const fileName = file.url ? [ ) : null; - const actions = listType === 'picture-card' && file.status !== 'uploading' && ( - - {previewIcon} - {file.status === 'done' && downloadIcon} - {removeIcon} - - ); - - let message; - if (file.response && typeof file.response === 'string') { - message = file.response; - } else { - message = file.error?.statusText || file.error?.message || locale.uploadError; - } + const pictureCardActions = listType === 'picture-card' && + mergedStatus.value !== 'uploading' && ( + + {previewIcon} + {mergedStatus.value === 'done' && downloadIcon} + {removeIcon} + + ); const dom = (
{icon} - {preview} - {actions} + {fileName} + {pictureCardActions} {showProgress.value && ( -
+
{'percent' in file ? ( node.parentNode as HTMLElement}> {dom} diff --git a/components/upload/UploadList/index.tsx b/components/upload/UploadList/index.tsx index 0051015f7..c1f2bba06 100644 --- a/components/upload/UploadList/index.tsx +++ b/components/upload/UploadList/index.tsx @@ -2,7 +2,7 @@ import LoadingOutlined from '@ant-design/icons-vue/LoadingOutlined'; import PaperClipOutlined from '@ant-design/icons-vue/PaperClipOutlined'; import PictureTwoTone from '@ant-design/icons-vue/PictureTwoTone'; import FileTwoTone from '@ant-design/icons-vue/FileTwoTone'; -import type { UploadListType, InternalUploadFile, UploadFile } from '../interface'; +import type { InternalUploadFile, UploadFile } from '../interface'; import { uploadListProps } from '../interface'; import { previewImage, isImageUrl } from '../utils'; import type { ButtonProps } from '../../button'; @@ -24,7 +24,7 @@ export default defineComponent({ compatConfig: { MODE: 3 }, name: 'AUploadList', props: initDefaultProps(uploadListProps(), { - listType: 'text' as UploadListType, // or picture + listType: 'text', // or picture progress: { strokeWidth: 2, showInfo: false, @@ -138,23 +138,33 @@ export default defineComponent({ handleDownload: onInternalDownload, }); - const { prefixCls, direction } = useConfigInject('upload', props); + const { prefixCls, rootPrefixCls } = useConfigInject('upload', props); const listClassNames = computed(() => ({ [`${prefixCls.value}-list`]: true, [`${prefixCls.value}-list-${props.listType}`]: true, - [`${prefixCls.value}-list-rtl`]: direction.value === 'rtl', - })); - const transitionGroupProps = computed(() => ({ - ...collapseMotion( - `${prefixCls.value}-${props.listType === 'picture-card' ? 'animate-inline' : 'animate'}`, - ), - ...getTransitionGroupProps( - `${prefixCls.value}-${props.listType === 'picture-card' ? 'animate-inline' : 'animate'}`, - ), - class: listClassNames.value, - appear: motionAppear.value, })); + const transitionGroupProps = computed(() => { + const motion = { + ...collapseMotion(`${rootPrefixCls.value}-motion-collapse`), + }; + delete motion.onAfterAppear; + delete motion.onAfterEnter; + delete motion.onAfterLeave; + const motionConfig = { + ...getTransitionGroupProps( + `${prefixCls.value}-${props.listType === 'picture-card' ? 'animate-inline' : 'animate'}`, + ), + class: listClassNames.value, + appear: motionAppear.value, + }; + return props.listType !== 'picture-card' + ? { + ...motion, + ...motionConfig, + } + : motionConfig; + }); return () => { const { listType, diff --git a/components/upload/interface.tsx b/components/upload/interface.tsx index 836d0309e..f89857fad 100755 --- a/components/upload/interface.tsx +++ b/components/upload/interface.tsx @@ -111,10 +111,7 @@ function uploadProps() { >([Object, Function]), method: stringType<'POST' | 'PUT' | 'PATCH' | 'post' | 'put' | 'patch'>(), headers: objectType(), - showUploadList: someType( - [Boolean, Object], - undefined as boolean | ShowUploadListInterface, - ), + showUploadList: someType([Boolean, Object]), multiple: booleanType(), accept: String, beforeUpload: @@ -141,7 +138,7 @@ function uploadProps() { customRequest: functionType<(options: RcCustomRequestOptions) => void>(), withCredentials: booleanType(), openFileDialogOnClick: booleanType(), - locale: objectType(undefined as UploadLocale), + locale: objectType(), id: String, previewFile: functionType(), /** @deprecated Please use `beforeUpload` directly */ diff --git a/components/upload/utils.tsx b/components/upload/utils.tsx index 8e18d5f7a..ed4feeecf 100644 --- a/components/upload/utils.tsx +++ b/components/upload/utils.tsx @@ -110,6 +110,15 @@ export function previewImage(file: File | Blob): Promise { resolve(dataURL); }; - img.src = window.URL.createObjectURL(file); + img.crossOrigin = 'anonymous'; + if (file.type.startsWith('image/svg+xml')) { + const reader = new FileReader(); + reader.addEventListener('load', () => { + if (reader.result) img.src = reader.result as string; + }); + reader.readAsDataURL(file); + } else { + img.src = window.URL.createObjectURL(file); + } }); }