mirror of
https://gitee.com/ant-design/ant-design.git
synced 2024-11-30 11:08:45 +08:00
merge master
This commit is contained in:
commit
867910e6f4
@ -9,8 +9,6 @@ import triggerEvent from '../triggerEvent';
|
||||
import Wave from '../wave';
|
||||
import TransButton from '../transButton';
|
||||
import openAnimation from '../openAnimation';
|
||||
import ResizeObserver from '../resizeObserver';
|
||||
import { spyElementPrototype } from '../../__tests__/util/domHook';
|
||||
|
||||
describe('Test utils function', () => {
|
||||
beforeAll(() => {
|
||||
@ -223,47 +221,4 @@ describe('Test utils function', () => {
|
||||
expect(done).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('ResizeObserver', () => {
|
||||
let domMock;
|
||||
|
||||
beforeAll(() => {
|
||||
domMock = spyElementPrototype(HTMLDivElement, 'getBoundingClientRect', () => {
|
||||
return {
|
||||
width: 1128 + Math.random(),
|
||||
height: 903 + Math.random(),
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
domMock.mockRestore();
|
||||
});
|
||||
|
||||
it('should not trigger `onResize` if size shaking', () => {
|
||||
const onResize = jest.fn();
|
||||
let divNode;
|
||||
|
||||
const wrapper = mount(
|
||||
<ResizeObserver onResize={onResize}>
|
||||
<div
|
||||
ref={node => {
|
||||
divNode = node;
|
||||
}}
|
||||
/>
|
||||
</ResizeObserver>,
|
||||
);
|
||||
|
||||
// First trigger
|
||||
wrapper.instance().onResize([{ target: divNode }]);
|
||||
onResize.mockReset();
|
||||
|
||||
// Repeat trigger should not trigger outer `onResize` with shaking
|
||||
for (let i = 0; i < 10; i += 1) {
|
||||
wrapper.instance().onResize([{ target: divNode }]);
|
||||
}
|
||||
|
||||
expect(onResize).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,91 +0,0 @@
|
||||
import * as React from 'react';
|
||||
import { findDOMNode } from 'react-dom';
|
||||
import ResizeObserver from 'resize-observer-polyfill';
|
||||
|
||||
type DomElement = Element | null;
|
||||
|
||||
interface ResizeObserverProps {
|
||||
children?: React.ReactNode;
|
||||
disabled?: boolean;
|
||||
onResize?: () => void;
|
||||
}
|
||||
|
||||
interface ResizeObserverState {
|
||||
height: number;
|
||||
width: number;
|
||||
}
|
||||
|
||||
class ReactResizeObserver extends React.Component<ResizeObserverProps, ResizeObserverState> {
|
||||
resizeObserver: ResizeObserver | null = null;
|
||||
|
||||
state = {
|
||||
width: 0,
|
||||
height: 0,
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this.onComponentUpdated();
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this.onComponentUpdated();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.destroyObserver();
|
||||
}
|
||||
|
||||
onComponentUpdated() {
|
||||
const { disabled } = this.props;
|
||||
const element = findDOMNode(this) as DomElement;
|
||||
if (!this.resizeObserver && !disabled && element) {
|
||||
// Add resize observer
|
||||
this.resizeObserver = new ResizeObserver(this.onResize);
|
||||
this.resizeObserver.observe(element);
|
||||
} else if (disabled) {
|
||||
// Remove resize observer
|
||||
this.destroyObserver();
|
||||
}
|
||||
}
|
||||
|
||||
onResize: ResizeObserverCallback = (entries: ResizeObserverEntry[]) => {
|
||||
const { onResize } = this.props;
|
||||
|
||||
const { target } = entries[0];
|
||||
|
||||
const { width, height } = target.getBoundingClientRect();
|
||||
|
||||
/**
|
||||
* Resize observer trigger when content size changed.
|
||||
* In most case we just care about element size,
|
||||
* let's use `boundary` instead of `contentRect` here to avoid shaking.
|
||||
*/
|
||||
const fixedWidth = Math.floor(width);
|
||||
const fixedHeight = Math.floor(height);
|
||||
|
||||
if (this.state.width !== fixedWidth || this.state.height !== fixedHeight) {
|
||||
this.setState({
|
||||
width: fixedWidth,
|
||||
height: fixedHeight,
|
||||
});
|
||||
|
||||
if (onResize) {
|
||||
onResize();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
destroyObserver() {
|
||||
if (this.resizeObserver) {
|
||||
this.resizeObserver.disconnect();
|
||||
this.resizeObserver = null;
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { children = null } = this.props;
|
||||
return children;
|
||||
}
|
||||
}
|
||||
|
||||
export default ReactResizeObserver;
|
@ -182,7 +182,7 @@ describe('Affix Render', () => {
|
||||
// Mock trigger resize
|
||||
updateCalled.mockReset();
|
||||
wrapper
|
||||
.find('ReactResizeObserver')
|
||||
.find('ResizeObserver')
|
||||
.at(index)
|
||||
.instance()
|
||||
.onResize([{ target: { getBoundingClientRect: () => ({ width: 99, height: 99 }) } }]);
|
||||
|
@ -2,9 +2,9 @@ import * as React from 'react';
|
||||
import { polyfill } from 'react-lifecycles-compat';
|
||||
import classNames from 'classnames';
|
||||
import omit from 'omit.js';
|
||||
import ResizeObserver from 'rc-resize-observer';
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
import { throttleByAnimationFrameDecorator } from '../_util/throttleByAnimationFrame';
|
||||
import ResizeObserver from '../_util/resizeObserver';
|
||||
|
||||
import warning from '../_util/warning';
|
||||
import {
|
||||
@ -35,6 +35,7 @@ export interface AffixProps {
|
||||
target?: () => Window | HTMLElement | null;
|
||||
prefixCls?: string;
|
||||
className?: string;
|
||||
children: React.ReactElement;
|
||||
}
|
||||
|
||||
enum AffixStatus {
|
||||
|
@ -2,9 +2,9 @@ import * as React from 'react';
|
||||
import omit from 'omit.js';
|
||||
import classNames from 'classnames';
|
||||
import { polyfill } from 'react-lifecycles-compat';
|
||||
import ResizeObserver from 'rc-resize-observer';
|
||||
import calculateNodeHeight from './calculateNodeHeight';
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
import ResizeObserver from '../_util/resizeObserver';
|
||||
import raf from '../_util/raf';
|
||||
|
||||
export interface AutoSizeType {
|
||||
|
@ -414,7 +414,7 @@ exports[`TextArea should support disabled 1`] = `
|
||||
<TextArea
|
||||
disabled={true}
|
||||
>
|
||||
<ReactResizeObserver
|
||||
<ResizeObserver
|
||||
disabled={true}
|
||||
onResize={[Function]}
|
||||
>
|
||||
@ -425,7 +425,7 @@ exports[`TextArea should support disabled 1`] = `
|
||||
onKeyDown={[Function]}
|
||||
style={Object {}}
|
||||
/>
|
||||
</ReactResizeObserver>
|
||||
</ResizeObserver>
|
||||
</TextArea>
|
||||
`;
|
||||
|
||||
@ -433,7 +433,7 @@ exports[`TextArea should support maxLength 1`] = `
|
||||
<TextArea
|
||||
maxLength={10}
|
||||
>
|
||||
<ReactResizeObserver
|
||||
<ResizeObserver
|
||||
disabled={true}
|
||||
onResize={[Function]}
|
||||
>
|
||||
@ -444,6 +444,6 @@ exports[`TextArea should support maxLength 1`] = `
|
||||
onKeyDown={[Function]}
|
||||
style={Object {}}
|
||||
/>
|
||||
</ReactResizeObserver>
|
||||
</ResizeObserver>
|
||||
</TextArea>
|
||||
`;
|
||||
|
@ -5,12 +5,11 @@ import toArray from 'rc-util/lib/Children/toArray';
|
||||
import copy from 'copy-to-clipboard';
|
||||
import omit from 'omit.js';
|
||||
import { Edit, Check, Copy } from '@ant-design/icons';
|
||||
|
||||
import ResizeObserver from 'rc-resize-observer';
|
||||
import { withConfigConsumer, ConfigConsumerProps, configConsumerProps } from '../config-provider';
|
||||
import LocaleReceiver from '../locale-provider/LocaleReceiver';
|
||||
import warning from '../_util/warning';
|
||||
import TransButton from '../_util/transButton';
|
||||
import ResizeObserver from '../_util/resizeObserver';
|
||||
import raf from '../_util/raf';
|
||||
import isStyleSupport from '../_util/styleChecker';
|
||||
import Tooltip from '../tooltip';
|
||||
|
@ -98,7 +98,7 @@ class Upload extends React.Component<UploadProps, UploadState> {
|
||||
fileList: nextFileList,
|
||||
});
|
||||
// fix ie progress
|
||||
if (!(window as any).FormData) {
|
||||
if (!(window as any).File || process.env.TEST_IE) {
|
||||
this.autoUpdateProgress(0, targetItem);
|
||||
}
|
||||
};
|
||||
|
@ -953,3 +953,99 @@ exports[`Upload List should non-image format file preview 1`] = `
|
||||
</div>
|
||||
</span>
|
||||
`;
|
||||
|
||||
exports[`Upload List should support showRemoveIcon and showPreviewIcon 1`] = `
|
||||
<span
|
||||
class=""
|
||||
>
|
||||
<div
|
||||
class="ant-upload ant-upload-select ant-upload-select-picture"
|
||||
>
|
||||
<span
|
||||
class="ant-upload"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<input
|
||||
accept=""
|
||||
style="display: none;"
|
||||
type="file"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
>
|
||||
upload
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-upload-list ant-upload-list-picture"
|
||||
>
|
||||
<div
|
||||
class="ant-upload-list-item ant-upload-list-item-uploading"
|
||||
>
|
||||
<div
|
||||
class="ant-upload-list-item-info"
|
||||
>
|
||||
<span>
|
||||
<a
|
||||
class="ant-upload-list-item-thumbnail"
|
||||
href="https://cdn.xxx.com/aaa"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
<img
|
||||
alt="image"
|
||||
class="ant-upload-list-item-image"
|
||||
src="https://cdn.xxx.com/aaa"
|
||||
/>
|
||||
</a>
|
||||
<a
|
||||
class="ant-upload-list-item-name"
|
||||
href="https://cdn.xxx.com/aaa"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
title="image"
|
||||
>
|
||||
image
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-upload-list-item-progress"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-upload-list-item ant-upload-list-item-done"
|
||||
>
|
||||
<div
|
||||
class="ant-upload-list-item-info"
|
||||
>
|
||||
<span>
|
||||
<a
|
||||
class="ant-upload-list-item-thumbnail"
|
||||
href="https://cdn.xxx.com/aaa"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
<img
|
||||
alt="image"
|
||||
class="ant-upload-list-item-image"
|
||||
src="https://cdn.xxx.com/aaa"
|
||||
/>
|
||||
</a>
|
||||
<a
|
||||
class="ant-upload-list-item-name"
|
||||
href="https://cdn.xxx.com/aaa"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
title="image"
|
||||
>
|
||||
image
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
`;
|
||||
|
28
components/upload/__tests__/dragger.test.js
Normal file
28
components/upload/__tests__/dragger.test.js
Normal file
@ -0,0 +1,28 @@
|
||||
/* eslint-disable react/no-string-refs, react/prefer-es6-class */
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import Upload from '..';
|
||||
import { setup, teardown } from './mock';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
|
||||
describe('Upload.Dragger', () => {
|
||||
mountTest(Upload.Dragger);
|
||||
|
||||
beforeEach(() => setup());
|
||||
afterEach(() => teardown());
|
||||
|
||||
it('support drag file with over style', () => {
|
||||
const wrapper = mount(
|
||||
<Upload.Dragger action="http://upload.com">
|
||||
<div />
|
||||
</Upload.Dragger>,
|
||||
);
|
||||
|
||||
wrapper.find('.ant-upload-drag-container').simulate('dragover', {
|
||||
target: {
|
||||
files: [{ file: 'foo.png' }],
|
||||
},
|
||||
});
|
||||
expect(wrapper.find('.ant-upload-drag').hasClass('ant-upload-drag-hover')).toBe(true);
|
||||
});
|
||||
});
|
@ -10,7 +10,6 @@ import mountTest from '../../../tests/shared/mountTest';
|
||||
|
||||
describe('Upload', () => {
|
||||
mountTest(Upload);
|
||||
mountTest(Upload.Dragger);
|
||||
|
||||
beforeEach(() => setup());
|
||||
afterEach(() => teardown());
|
||||
@ -62,6 +61,61 @@ describe('Upload', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should update progress in IE', done => {
|
||||
const originSetInterval = window.setInterval;
|
||||
process.env.TEST_IE = true;
|
||||
Object.defineProperty(window, 'setInterval', {
|
||||
value: fn => fn(),
|
||||
});
|
||||
const props = {
|
||||
action: 'http://upload.com',
|
||||
onChange: ({ file }) => {
|
||||
if (file.status !== 'uploading') {
|
||||
process.env.TEST_IE = undefined;
|
||||
Object.defineProperty(window, 'setInterval', {
|
||||
value: originSetInterval,
|
||||
});
|
||||
done();
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
const wrapper = mount(
|
||||
<Upload {...props}>
|
||||
<button type="button">upload</button>
|
||||
</Upload>,
|
||||
);
|
||||
wrapper.find('input').simulate('change', {
|
||||
target: {
|
||||
files: [{ file: 'foo.png' }],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('beforeUpload can be falsy', done => {
|
||||
const props = {
|
||||
action: 'http://upload.com',
|
||||
beforeUpload: false,
|
||||
onChange: ({ file }) => {
|
||||
if (file.status !== 'uploading') {
|
||||
done();
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
const wrapper = mount(
|
||||
<Upload {...props}>
|
||||
<button type="button">upload</button>
|
||||
</Upload>,
|
||||
);
|
||||
|
||||
wrapper.find('input').simulate('change', {
|
||||
target: {
|
||||
files: [{ file: 'foo.png' }],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('upload promise return file in beforeUpload', done => {
|
||||
const data = jest.fn();
|
||||
const props = {
|
||||
|
@ -366,6 +366,37 @@ describe('Upload List', () => {
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should support showRemoveIcon and showPreviewIcon', () => {
|
||||
const list = [
|
||||
{
|
||||
name: 'image',
|
||||
status: 'uploading',
|
||||
uid: '-4',
|
||||
url: 'https://cdn.xxx.com/aaa',
|
||||
},
|
||||
{
|
||||
name: 'image',
|
||||
status: 'done',
|
||||
uid: '-5',
|
||||
url: 'https://cdn.xxx.com/aaa',
|
||||
},
|
||||
];
|
||||
|
||||
const wrapper = mount(
|
||||
<Upload
|
||||
listType="picture"
|
||||
defaultFileList={list}
|
||||
showUploadList={{
|
||||
showRemoveIcon: false,
|
||||
showPreviewIcon: false,
|
||||
}}
|
||||
>
|
||||
<button type="button">upload</button>
|
||||
</Upload>,
|
||||
);
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/7762
|
||||
it('work with form validation', async () => {
|
||||
let formRef;
|
||||
|
@ -58,16 +58,15 @@ export function removeFileItem(file: UploadFile, fileList: UploadFile[]) {
|
||||
}
|
||||
|
||||
// ==================== Default Image Preview ====================
|
||||
const extname = (url: string) => {
|
||||
if (!url) {
|
||||
return '';
|
||||
}
|
||||
const extname = (url: string = '') => {
|
||||
const temp = url.split('/');
|
||||
const filename = temp[temp.length - 1];
|
||||
const filenameWithoutSuffix = filename.split(/#|\?/)[0];
|
||||
return (/\.[^./\\]*$/.exec(filenameWithoutSuffix) || [''])[0];
|
||||
};
|
||||
|
||||
const isImageFileType = (type: string): boolean => !!type && type.indexOf('image/') === 0;
|
||||
|
||||
export const isImageUrl = (file: UploadFile): boolean => {
|
||||
if (isImageFileType(file.type)) {
|
||||
return true;
|
||||
|
@ -122,6 +122,7 @@
|
||||
"rc-pagination": "~1.20.5",
|
||||
"rc-progress": "~2.5.0",
|
||||
"rc-rate": "~2.5.0",
|
||||
"rc-resize-observer": "^0.1.0",
|
||||
"rc-select": "~10.0.0-alpha.27",
|
||||
"rc-slider": "~8.6.11",
|
||||
"rc-steps": "~3.5.0",
|
||||
|
Loading…
Reference in New Issue
Block a user