mirror of
https://github.com/ant-design/ant-design.git
synced 2024-11-25 11:40:04 +08:00
785c132262
* use ul in list * update snapshot * update comment * feat: TreeSelect support `showSearch` in multiple mode (#15933) * update rc-tree-select * typo * update desc & snapshot * update desc & snapshot * check default showSearch * feat: table customizing variable (#15971) * feat: added table selected row color variable * fix: @table-selected-row-color default is inherit * feat: Upload support customize previewFile (#15984) * support preview file * use promise * dealy load * use canvas of render * use domHook of test * update demo * add snapshot * update types * update testcase * feat: form customizing variables (#15954) * fix: added styling form input background-color * feat: added '@form-warning-input-bg' variable * feat: added '@form-error-input-bg' variable * use li wrap with comment * feat: Support append theme less file with less-variable (#16118) * add override * add override support * update doc * feat: dropdown support set right icon * docs: update doc of dropdown component * style: format dropdown-button.md * test: update updateSnapshot * style: format dropdown-button.md * test: update updateSnapshot * test: update updateSnapshot * style: change style of dropdown-button demo * fix: fix document table order * feat: Support SkeletonAvatarProps.size accept number (#16078) (#16128) * chore:update style of demo * feat: Notification functions accept top, bottom and getContainer as arguments * drawer: add afterVisibleChange * rm onVisibleChange * update * feat: 🇭🇷 hr_HR locale (#16258) * Added Croatian locale * fixed lint error * ✅ Add test cases for hr_HR * 📝 update i18n documentation * feat: add `htmlFor` in Form.Item (#16278) * add htmlFor in Form.Item * update doc * feat: Button support `link` type (#16289) close #15892 * feat: Add Timeline.Item.position (#16148) (#16193) * fix: Timeline.pendingDot interface documentation there is a small problem (#16177) * feat: Add Timeline.Item.position (#16148) * doc: add version infomation for Timeline.Item.position * refactor: Update Tree & TreeSelect deps (#16330) * use CSSMotion * update snapshot * feat: Collapse support `expandIconPosition` (#16365) * update doc * support expandIconPosition * update snapshot * feat: Breadcrumb support DropDown (#16315) * breadcrumbs support drop down menu * update doc * add require less * fix test * fix md doc * less code * fix style warning * update snap * add children render test * feat: TreeNode support checkable * feat: add optional to support top and left slick dots (#16186) (#16225) * add optional to support top and left slick dots * update carousel snapshot * Update doc, add placement demo * update carousel placement demo snapshots * rename dots placement to position * update vertical as deprecated * rename dotsPosition to dotPosition * refine code * add warning testcase for vertical * remove unused warning * update expression * Additional test case for dotPosition * refactor: Upgrade `rc-tree-select` to support pure React motion (#16402) * upgrade `rc-tree-select` * update snapshot * 3.17.0 changelog * fix warning * fix review warning
227 lines
6.8 KiB
TypeScript
227 lines
6.8 KiB
TypeScript
import * as React from 'react';
|
|
import Animate from 'rc-animate';
|
|
import classNames from 'classnames';
|
|
import { UploadListProps, UploadFile, UploadListType } from './interface';
|
|
import { previewImage, isImageUrl } from './utils';
|
|
import Icon from '../icon';
|
|
import Tooltip from '../tooltip';
|
|
import Progress from '../progress';
|
|
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
|
|
|
export default class UploadList extends React.Component<UploadListProps, any> {
|
|
static defaultProps = {
|
|
listType: 'text' as UploadListType, // or picture
|
|
progressAttr: {
|
|
strokeWidth: 2,
|
|
showInfo: false,
|
|
},
|
|
showRemoveIcon: true,
|
|
showPreviewIcon: true,
|
|
previewFile: previewImage,
|
|
};
|
|
|
|
handleClose = (file: UploadFile) => {
|
|
const { onRemove } = this.props;
|
|
if (onRemove) {
|
|
onRemove(file);
|
|
}
|
|
};
|
|
|
|
handlePreview = (file: UploadFile, e: React.SyntheticEvent<HTMLElement>) => {
|
|
const { onPreview } = this.props;
|
|
if (!onPreview) {
|
|
return;
|
|
}
|
|
e.preventDefault();
|
|
return onPreview(file);
|
|
};
|
|
|
|
componentDidUpdate() {
|
|
const { listType, items, previewFile } = this.props;
|
|
if (listType !== 'picture' && listType !== 'picture-card') {
|
|
return;
|
|
}
|
|
(items || []).forEach(file => {
|
|
if (
|
|
typeof document === 'undefined' ||
|
|
typeof window === 'undefined' ||
|
|
!(window as any).FileReader ||
|
|
!(window as any).File ||
|
|
!(file.originFileObj instanceof File) ||
|
|
file.thumbUrl !== undefined
|
|
) {
|
|
return;
|
|
}
|
|
file.thumbUrl = '';
|
|
if (previewFile) {
|
|
previewFile(file.originFileObj).then((previewDataUrl: string) => {
|
|
// Need append '' to avoid dead loop
|
|
file.thumbUrl = previewDataUrl || '';
|
|
this.forceUpdate();
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
renderUploadList = ({ getPrefixCls }: ConfigConsumerProps) => {
|
|
const {
|
|
prefixCls: customizePrefixCls,
|
|
items = [],
|
|
listType,
|
|
showPreviewIcon,
|
|
showRemoveIcon,
|
|
locale,
|
|
} = this.props;
|
|
const prefixCls = getPrefixCls('upload', customizePrefixCls);
|
|
const list = items.map(file => {
|
|
let progress;
|
|
let icon = <Icon type={file.status === 'uploading' ? 'loading' : 'paper-clip'} />;
|
|
|
|
if (listType === 'picture' || listType === 'picture-card') {
|
|
if (listType === 'picture-card' && file.status === 'uploading') {
|
|
icon = <div className={`${prefixCls}-list-item-uploading-text`}>{locale.uploading}</div>;
|
|
} else if (!file.thumbUrl && !file.url) {
|
|
icon = (
|
|
<Icon className={`${prefixCls}-list-item-thumbnail`} type="picture" theme="twoTone" />
|
|
);
|
|
} else {
|
|
const thumbnail = isImageUrl(file) ? (
|
|
<img src={file.thumbUrl || file.url} alt={file.name} />
|
|
) : (
|
|
<Icon type="file" className={`${prefixCls}-list-item-icon`} theme="twoTone" />
|
|
);
|
|
icon = (
|
|
<a
|
|
className={`${prefixCls}-list-item-thumbnail`}
|
|
onClick={e => this.handlePreview(file, e)}
|
|
href={file.url || file.thumbUrl}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
>
|
|
{thumbnail}
|
|
</a>
|
|
);
|
|
}
|
|
}
|
|
|
|
if (file.status === 'uploading') {
|
|
// show loading icon if upload progress listener is disabled
|
|
const loadingProgress =
|
|
'percent' in file ? (
|
|
<Progress type="line" {...this.props.progressAttr} percent={file.percent} />
|
|
) : null;
|
|
|
|
progress = (
|
|
<div className={`${prefixCls}-list-item-progress`} key="progress">
|
|
{loadingProgress}
|
|
</div>
|
|
);
|
|
}
|
|
const infoUploadingClass = classNames({
|
|
[`${prefixCls}-list-item`]: true,
|
|
[`${prefixCls}-list-item-${file.status}`]: true,
|
|
});
|
|
const linkProps =
|
|
typeof file.linkProps === 'string' ? JSON.parse(file.linkProps) : file.linkProps;
|
|
const preview = file.url ? (
|
|
<a
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className={`${prefixCls}-list-item-name`}
|
|
title={file.name}
|
|
{...linkProps}
|
|
href={file.url}
|
|
onClick={e => this.handlePreview(file, e)}
|
|
>
|
|
{file.name}
|
|
</a>
|
|
) : (
|
|
<span
|
|
className={`${prefixCls}-list-item-name`}
|
|
onClick={e => this.handlePreview(file, e)}
|
|
title={file.name}
|
|
>
|
|
{file.name}
|
|
</span>
|
|
);
|
|
const style: React.CSSProperties = {
|
|
pointerEvents: 'none',
|
|
opacity: 0.5,
|
|
};
|
|
const previewIcon = showPreviewIcon ? (
|
|
<a
|
|
href={file.url || file.thumbUrl}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
style={file.url || file.thumbUrl ? undefined : style}
|
|
onClick={e => this.handlePreview(file, e)}
|
|
title={locale.previewFile}
|
|
>
|
|
<Icon type="eye-o" />
|
|
</a>
|
|
) : null;
|
|
const removeIcon = showRemoveIcon ? (
|
|
<Icon type="delete" title={locale.removeFile} onClick={() => this.handleClose(file)} />
|
|
) : null;
|
|
const removeIconClose = showRemoveIcon ? (
|
|
<Icon type="close" title={locale.removeFile} onClick={() => this.handleClose(file)} />
|
|
) : null;
|
|
const actions =
|
|
listType === 'picture-card' && file.status !== 'uploading' ? (
|
|
<span className={`${prefixCls}-list-item-actions`}>
|
|
{previewIcon}
|
|
{removeIcon}
|
|
</span>
|
|
) : (
|
|
removeIconClose
|
|
);
|
|
let message;
|
|
if (file.response && typeof file.response === 'string') {
|
|
message = file.response;
|
|
} else {
|
|
message = (file.error && file.error.statusText) || locale.uploadError;
|
|
}
|
|
const iconAndPreview =
|
|
file.status === 'error' ? (
|
|
<Tooltip title={message}>
|
|
{icon}
|
|
{preview}
|
|
</Tooltip>
|
|
) : (
|
|
<span>
|
|
{icon}
|
|
{preview}
|
|
</span>
|
|
);
|
|
|
|
return (
|
|
<div className={infoUploadingClass} key={file.uid}>
|
|
<div className={`${prefixCls}-list-item-info`}>{iconAndPreview}</div>
|
|
{actions}
|
|
<Animate transitionName="fade" component="">
|
|
{progress}
|
|
</Animate>
|
|
</div>
|
|
);
|
|
});
|
|
const listClassNames = classNames({
|
|
[`${prefixCls}-list`]: true,
|
|
[`${prefixCls}-list-${listType}`]: true,
|
|
});
|
|
const animationDirection = listType === 'picture-card' ? 'animate-inline' : 'animate';
|
|
return (
|
|
<Animate
|
|
transitionName={`${prefixCls}-${animationDirection}`}
|
|
component="div"
|
|
className={listClassNames}
|
|
>
|
|
{list}
|
|
</Animate>
|
|
);
|
|
};
|
|
|
|
render() {
|
|
return <ConfigConsumer>{this.renderUploadList}</ConfigConsumer>;
|
|
}
|
|
}
|