Browse Source

refactor: 📦 smaller bundlesize limit (#20356)

* 📦 samller bundlesize limit

* 🗑️ remove React static PropTypes

* 🗑️ remove react-lifecycles-compat

* 🗑️ remove matchMedia polyfill

* 🗑️ remove Transfer buggy lazy prop

* 🗑️ remove enquire.js dep

* 🗑️ remove Transfer lazy related code and fix ci

* 🗑️ remove used dom-closest

*  replace dom-scroll-into-view to scroll-into-view for bundle size

*  fix eslint

* 🆙 upgrade browserslist

*  fix test cases

* 🗑️ remove @ant-design/create-react-context

* 🆙 upgrade @ant-design/bisheng-plugin

* 🆙 upgrade rc-slider

*  fix ci

* 🆙 upgrade rc-tabs and rc-mentions

* 📦 scroll-into-view -> scroll-into-view-if-needed

* remove unused devDep

* docs: 📝 update instruction about IE9/10

* 📦 reduce css bundle size by drop IE9/10 support

* 🆙 upgrade rc-upload

* 🗑️ drop unused swing motion css

*  update upload snapshots

* 📦 lift css bundlesize limit to 55kb
pull/20400/head
偏右 5 years ago
committed by 二货机器人
parent
commit
8501b708ea
  1. 4
      README-zh_CN.md
  2. 2
      README.md
  3. 66
      components/_util/responsiveObserve.ts
  4. 3
      components/affix/index.tsx
  5. 3
      components/anchor/AnchorLink.tsx
  6. 3
      components/badge/ScrollNumber.tsx
  7. 8
      components/badge/index.tsx
  8. 7
      components/breadcrumb/Breadcrumb.tsx
  9. 7
      components/breadcrumb/BreadcrumbItem.tsx
  10. 17
      components/button/button.tsx
  11. 15
      components/carousel/index.tsx
  12. 3
      components/cascader/index.tsx
  13. 3
      components/checkbox/Checkbox.tsx
  14. 3
      components/checkbox/Group.tsx
  15. 45
      components/config-provider/__tests__/__snapshots__/components.test.js.snap
  16. 1
      components/config-provider/__tests__/components.test.js
  17. 34
      components/descriptions/__tests__/index.test.js
  18. 3
      components/drawer/index.tsx
  19. 96
      components/form/__tests__/__snapshots__/demo.test.js.snap
  20. 4
      components/form/__tests__/index.test.js
  21. 27
      components/form/util.ts
  22. 2
      components/grid/RowContext.tsx
  23. 36
      components/grid/__tests__/index.test.js
  24. 7
      components/input/ClearableLabeledInput.tsx
  25. 27
      components/input/Input.tsx
  26. 3
      components/input/ResizableTextArea.tsx
  27. 3
      components/input/TextArea.tsx
  28. 23
      components/layout/Sider.tsx
  29. 10
      components/layout/__tests__/index.test.js
  30. 3
      components/layout/layout.tsx
  31. 4
      components/locale-provider/index.tsx
  32. 3
      components/mentions/index.tsx
  33. 2
      components/menu/MenuContext.tsx
  34. 7
      components/menu/__tests__/index.test.js
  35. 3
      components/menu/index.tsx
  36. 4
      components/menu/style/index.less
  37. 17
      components/modal/Modal.tsx
  38. 3
      components/popconfirm/index.tsx
  39. 15
      components/progress/progress.tsx
  40. 2
      components/radio/group.tsx
  41. 6
      components/rate/index.tsx
  42. 10
      components/spin/index.tsx
  43. 3
      components/statistic/Countdown.tsx
  44. 7
      components/steps/index.tsx
  45. 1
      components/style/core/motion.less
  46. 34
      components/style/core/motion/swing.less
  47. 11
      components/style/mixins/compatibility.less
  48. 9
      components/style/mixins/iconfont.less
  49. 11
      components/switch/index.tsx
  50. 3
      components/tag/index.tsx
  51. 3
      components/tooltip/index.tsx
  52. 27
      components/transfer/ListItem.tsx
  53. 587
      components/transfer/__tests__/__snapshots__/demo.test.js.snap
  54. 129
      components/transfer/__tests__/__snapshots__/index.test.js.snap
  55. 3
      components/transfer/__tests__/index.test.js
  56. 11
      components/transfer/__tests__/list.test.js
  57. 2
      components/transfer/__tests__/search.test.js
  58. 1
      components/transfer/index.en-US.md
  59. 38
      components/transfer/index.tsx
  60. 1
      components/transfer/index.zh-CN.md
  61. 18
      components/transfer/list.tsx
  62. 53
      components/transfer/renderListBody.tsx
  63. 3
      components/tree/DirectoryTree.tsx
  64. 3
      components/typography/Base.tsx
  65. 3
      components/typography/Editable.tsx
  66. 3
      components/upload/Upload.tsx
  67. 566
      components/upload/__tests__/__snapshots__/demo.test.js.snap
  68. 12
      docs/react/getting-started.en-US.md
  69. 12
      docs/react/getting-started.zh-CN.md
  70. 2
      docs/react/introduce.en-US.md
  71. 2
      docs/react/introduce.zh-CN.md
  72. 28
      package.json
  73. 2
      site/theme/index.js
  74. 5
      site/theme/static/template.html
  75. 3
      tests/__mocks__/create-react-context.js
  76. 10
      tests/setup.js
  77. 11
      typings/custom-typings.d.ts

4
README-zh_CN.md

@ -31,13 +31,13 @@
## 🖥 支持环境
- 现代浏览器和 IE9 及以上。
- 现代浏览器和 IE11 及以上。
- 支持服务端渲染。
- [Electron](http://electron.atom.io/)
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/opera/opera_48x48.png" alt="Opera" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Opera | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/electron/electron_48x48.png" alt="Electron" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Electron |
| --- | --- | --- | --- | --- | --- |
| IE9, IE10, IE11, Edge | last 2 versions | last 2 versions | last 2 versions | last 2 versions | last 2 versions |
| IE11, Edge | last 2 versions | last 2 versions | last 2 versions | last 2 versions | last 2 versions |
## 📦 安装

2
README.md

@ -37,7 +37,7 @@ English | [简体中文](./README-zh_CN.md)
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/opera/opera_48x48.png" alt="Opera" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Opera | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/electron/electron_48x48.png" alt="Electron" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Electron |
| --- | --- | --- | --- | --- | --- |
| IE9, IE10, IE11, Edge | last 2 versions | last 2 versions | last 2 versions | last 2 versions | last 2 versions |
| IE11, Edge | last 2 versions | last 2 versions | last 2 versions | last 2 versions | last 2 versions |
## 📦 Install

66
components/_util/responsiveObserve.ts

@ -1,23 +1,3 @@
// matchMedia polyfill for
// https://github.com/WickyNilliams/enquire.js/issues/82
let enquire: any;
// TODO: Will be removed in antd 4.0 because we will no longer support ie9
if (typeof window !== 'undefined') {
const matchMediaPolyfill = (mediaQuery: string) => {
return {
media: mediaQuery,
matches: false,
addListener() {},
removeListener() {},
};
};
// ref: https://github.com/ant-design/ant-design/issues/18774
if (!window.matchMedia) window.matchMedia = matchMediaPolyfill as any;
// eslint-disable-next-line global-require
enquire = require('enquire.js');
}
export type Breakpoint = 'xxl' | 'xl' | 'lg' | 'md' | 'sm' | 'xs';
export type BreakpointMap = Partial<Record<Breakpoint, string>>;
@ -42,6 +22,7 @@ let subUid = -1;
let screens = {};
const responsiveObserve = {
matchHandlers: {},
dispatch(pointMap: BreakpointMap) {
screens = pointMap;
if (subscribers.length < 1) {
@ -73,31 +54,30 @@ const responsiveObserve = {
}
},
unregister() {
Object.keys(responsiveMap).map((screen: Breakpoint) =>
enquire.unregister(responsiveMap[screen]),
);
Object.keys(responsiveMap).forEach((screen: Breakpoint) => {
const matchMediaQuery = responsiveMap[screen]!;
const handler = this.matchHandlers[matchMediaQuery];
if (handler && handler.mql && handler.listener) {
handler.mql.removeListener(handler.listener);
}
});
},
register() {
Object.keys(responsiveMap).map((screen: Breakpoint) =>
enquire.register(responsiveMap[screen], {
match: () => {
const pointMap = {
...screens,
[screen]: true,
};
this.dispatch(pointMap);
},
unmatch: () => {
const pointMap = {
...screens,
[screen]: false,
};
this.dispatch(pointMap);
},
// Keep a empty destory to avoid triggering unmatch when unregister
destroy() {},
}),
);
Object.keys(responsiveMap).forEach((screen: Breakpoint) => {
const matchMediaQuery = responsiveMap[screen]!;
const listener = ({ matches }: { matches: boolean }) => {
this.dispatch({
...screens,
[screen]: matches,
});
};
const mql = window.matchMedia(matchMediaQuery);
mql.addListener(listener);
this.matchHandlers[matchMediaQuery] = {
mql,
listener,
};
});
},
};

3
components/affix/index.tsx

@ -1,5 +1,4 @@
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';
@ -299,6 +298,4 @@ class Affix extends React.Component<AffixProps, AffixState> {
}
}
polyfill(Affix);
export default Affix;

3
components/anchor/AnchorLink.tsx

@ -1,6 +1,5 @@
import * as React from 'react';
import * as PropTypes from 'prop-types';
import { polyfill } from 'react-lifecycles-compat';
import classNames from 'classnames';
import { AntAnchor } from './Anchor';
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
@ -83,6 +82,4 @@ class AnchorLink extends React.Component<AnchorLinkProps, any> {
}
}
polyfill(AnchorLink);
export default AnchorLink;

3
components/badge/ScrollNumber.tsx

@ -1,7 +1,6 @@
import * as React from 'react';
import omit from 'omit.js';
import classNames from 'classnames';
import { polyfill } from 'react-lifecycles-compat';
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
function getNumberArray(num: string | number | undefined | null) {
@ -208,6 +207,4 @@ class ScrollNumber extends React.Component<ScrollNumberProps, ScrollNumberState>
}
}
polyfill(ScrollNumber);
export default ScrollNumber;

8
components/badge/index.tsx

@ -1,5 +1,4 @@
import * as React from 'react';
import * as PropTypes from 'prop-types';
import Animate from 'rc-animate';
import omit from 'omit.js';
import classNames from 'classnames';
@ -40,13 +39,6 @@ export default class Badge extends React.Component<BadgeProps, any> {
overflowCount: 99,
};
static propTypes = {
count: PropTypes.node,
showZero: PropTypes.bool,
dot: PropTypes.bool,
overflowCount: PropTypes.number,
};
getNumberedDispayCount() {
const { count, overflowCount } = this.props;
const displayCount =

7
components/breadcrumb/Breadcrumb.tsx

@ -1,5 +1,4 @@
import * as React from 'react';
import * as PropTypes from 'prop-types';
import classNames from 'classnames';
import toArray from 'rc-util/lib/Children/toArray';
import omit from 'omit.js';
@ -68,12 +67,6 @@ export default class Breadcrumb extends React.Component<BreadcrumbProps, any> {
separator: '/',
};
static propTypes = {
prefixCls: PropTypes.string,
separator: PropTypes.node,
routes: PropTypes.array,
};
getPath = (path: string, params: any) => {
path = (path || '').replace(/^\//, '');
Object.keys(params).forEach(key => {

7
components/breadcrumb/BreadcrumbItem.tsx

@ -1,5 +1,4 @@
import * as React from 'react';
import * as PropTypes from 'prop-types';
import { DownOutlined } from '@ant-design/icons';
import omit from 'omit.js';
@ -21,12 +20,6 @@ export default class BreadcrumbItem extends React.Component<BreadcrumbItemProps,
separator: '/',
};
static propTypes = {
prefixCls: PropTypes.string,
separator: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
href: PropTypes.string,
};
renderBreadcrumbItem = ({ getPrefixCls }: ConfigConsumerProps) => {
const { prefixCls: customizePrefixCls, separator, children, ...restProps } = this.props;
const prefixCls = getPrefixCls('breadcrumb', customizePrefixCls);

17
components/button/button.tsx

@ -1,9 +1,7 @@
/* eslint-disable react/button-has-type */
import * as React from 'react';
import * as PropTypes from 'prop-types';
import classNames from 'classnames';
import { LoadingOutlined } from '@ant-design/icons';
import { polyfill } from 'react-lifecycles-compat';
import omit from 'omit.js';
import Group from './button-group';
@ -124,19 +122,6 @@ class Button extends React.Component<ButtonProps, ButtonState> {
htmlType: 'button',
};
static propTypes = {
type: PropTypes.string,
shape: PropTypes.oneOf(ButtonShapes),
size: PropTypes.oneOf(ButtonSizes),
htmlType: PropTypes.oneOf(ButtonHTMLTypes),
onClick: PropTypes.func,
loading: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]),
className: PropTypes.string,
icon: PropTypes.node,
block: PropTypes.bool,
title: PropTypes.string,
};
private delayTimeout: number;
private buttonNode: HTMLElement | null;
@ -318,6 +303,4 @@ class Button extends React.Component<ButtonProps, ButtonState> {
}
}
polyfill(Button);
export default Button;

15
components/carousel/index.tsx

@ -4,21 +4,6 @@ import { Settings } from 'react-slick';
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
import warning from '../_util/warning';
// matchMedia polyfill for
// https://github.com/WickyNilliams/enquire.js/issues/82
// TODO: Will be removed in antd 4.0 because we will no longer support ie9
if (typeof window !== 'undefined') {
const matchMediaPolyfill = (mediaQuery: string) => {
return {
media: mediaQuery,
matches: false,
addListener() {},
removeListener() {},
};
};
// ref: https://github.com/ant-design/ant-design/issues/18774
if (!window.matchMedia) window.matchMedia = matchMediaPolyfill as any;
}
// Use require over import (will be lifted up)
// make sure matchMedia polyfill run before require('react-slick')
// Fix https://github.com/ant-design/ant-design/issues/6560

3
components/cascader/index.tsx

@ -4,7 +4,6 @@ import arrayTreeFilter from 'array-tree-filter';
import classNames from 'classnames';
import omit from 'omit.js';
import KeyCode from 'rc-util/lib/KeyCode';
import { polyfill } from 'react-lifecycles-compat';
import { CloseCircleFilled, DownOutlined, RightOutlined, RedoOutlined } from '@ant-design/icons';
import Input from '../input';
@ -601,6 +600,4 @@ class Cascader extends React.Component<CascaderProps, CascaderState> {
}
}
polyfill(Cascader);
export default Cascader;

3
components/checkbox/Checkbox.tsx

@ -1,6 +1,5 @@
import * as React from 'react';
import * as PropTypes from 'prop-types';
import { polyfill } from 'react-lifecycles-compat';
import classNames from 'classnames';
import RcCheckbox from 'rc-checkbox';
import shallowEqual from 'shallowequal';
@ -174,6 +173,4 @@ class Checkbox extends React.Component<CheckboxProps, {}> {
}
}
polyfill(Checkbox);
export default Checkbox;

3
components/checkbox/Group.tsx

@ -1,6 +1,5 @@
import * as React from 'react';
import * as PropTypes from 'prop-types';
import { polyfill } from 'react-lifecycles-compat';
import classNames from 'classnames';
import shallowEqual from 'shallowequal';
import omit from 'omit.js';
@ -187,6 +186,4 @@ class CheckboxGroup extends React.Component<CheckboxGroupProps, CheckboxGroupSta
}
}
polyfill(CheckboxGroup);
export default CheckboxGroup;

45
components/config-provider/__tests__/__snapshots__/components.test.js.snap

@ -18444,7 +18444,20 @@ exports[`ConfigProvider components Upload configProvider 1`] = `
>
<div
class="config-upload config-upload-select config-upload-select-text"
/>
>
<span
class="config-upload"
role="button"
tabindex="0"
>
<input
accept=""
style="display:none"
type="file"
/>
<span />
</span>
</div>
<div
class="config-upload-list config-upload-list-text"
>
@ -18556,7 +18569,20 @@ exports[`ConfigProvider components Upload normal 1`] = `
>
<div
class="ant-upload ant-upload-select ant-upload-select-text"
/>
>
<span
class="ant-upload"
role="button"
tabindex="0"
>
<input
accept=""
style="display:none"
type="file"
/>
<span />
</span>
</div>
<div
class="ant-upload-list ant-upload-list-text"
>
@ -18668,7 +18694,20 @@ exports[`ConfigProvider components Upload prefixCls 1`] = `
>
<div
class="prefix-Upload prefix-Upload-select prefix-Upload-select-text"
/>
>
<span
class="prefix-Upload"
role="button"
tabindex="0"
>
<input
accept=""
style="display:none"
type="file"
/>
<span />
</span>
</div>
<div
class="ant-upload-list ant-upload-list-text"
>

1
components/config-provider/__tests__/components.test.js

@ -54,7 +54,6 @@ import Tree from '../../tree';
import TreeSelect from '../../tree-select';
import Upload from '../../upload';
jest.mock('draft-js/lib/generateRandomKey', () => () => '123');
jest.mock('rc-util/lib/Portal');
describe('ConfigProvider', () => {

34
components/descriptions/__tests__/index.test.js

@ -5,29 +5,20 @@ import Descriptions from '..';
import mountTest from '../../../tests/shared/mountTest';
import { resetWarned } from '../../_util/warning';
jest.mock('enquire.js', () => {
let that;
let unmatchFun;
return {
unregister: jest.fn(),
register: (media, options) => {
if (media === '(max-width: 575px)') {
that = this;
options.match.call(that);
unmatchFun = options.unmatch;
}
},
callunmatch() {
unmatchFun.call(that);
},
};
});
describe('Descriptions', () => {
mountTest(Descriptions);
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
jest.spyOn(window, 'matchMedia').mockImplementationOnce(query => ({
addListener: (listener) => {
if (query === '(max-width: 575px)') {
listener({ matches: true });
}
},
removeListener: jest.fn(),
}));
afterEach(() => {
MockDate.reset();
errorSpy.mockReset();
@ -38,8 +29,6 @@ describe('Descriptions', () => {
});
it('when max-width: 575px,column=1', () => {
// eslint-disable-next-line global-require
const enquire = require('enquire.js');
const wrapper = mount(
<Descriptions>
<Descriptions.Item label="Product">Cloud Database</Descriptions.Item>
@ -51,14 +40,11 @@ describe('Descriptions', () => {
);
expect(wrapper.find('tr')).toHaveLength(5);
expect(wrapper.find('.ant-descriptions-item-no-label')).toHaveLength(1);
enquire.callunmatch();
wrapper.unmount();
});
it('when max-width: 575px,column=2', () => {
// eslint-disable-next-line global-require
const enquire = require('enquire.js');
const wrapper = mount(
<Descriptions column={{ xs: 2 }}>
<Descriptions.Item label="Product">Cloud Database</Descriptions.Item>
@ -68,8 +54,6 @@ describe('Descriptions', () => {
</Descriptions>,
);
expect(wrapper.find('tr')).toHaveLength(2);
enquire.callunmatch();
wrapper.unmount();
});

3
components/drawer/index.tsx

@ -1,6 +1,5 @@
import * as React from 'react';
import RcDrawer from 'rc-drawer';
import createReactContext from '@ant-design/create-react-context';
import { CloseOutlined } from '@ant-design/icons';
import classNames from 'classnames';
import omit from 'omit.js';
@ -10,7 +9,7 @@ import { ConfigConsumerProps } from '../config-provider';
import { withConfigConsumer } from '../config-provider/context';
import { tuple } from '../_util/type';
const DrawerContext = createReactContext<Drawer | null>(null);
const DrawerContext = React.createContext<Drawer | null>(null);
type EventType =
| React.KeyboardEvent<HTMLDivElement>

96
components/form/__tests__/__snapshots__/demo.test.js.snap

@ -4038,7 +4038,48 @@ exports[`renders ./components/form/demo/validate-other.md correctly 1`] = `
>
<div
class="ant-upload ant-upload-select ant-upload-select-picture"
/>
>
<span
class="ant-upload"
role="button"
tabindex="0"
>
<input
accept=""
id="validate_other_upload"
style="display:none"
type="file"
/>
<button
class="ant-btn"
type="button"
>
<span
aria-label="upload"
class="anticon anticon-upload"
role="img"
>
<svg
aria-hidden="true"
class=""
data-icon="upload"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M400 317.7h73.9V656c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V317.7H624c6.7 0 10.4-7.7 6.3-12.9L518.3 163a8 8 0 00-12.6 0l-112 141.7c-4.1 5.3-.4 13 6.3 13zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"
/>
</svg>
</span>
<span>
Click to upload
</span>
</button>
</span>
</div>
<div
class="ant-upload-list ant-upload-list-picture"
/>
@ -4073,7 +4114,58 @@ exports[`renders ./components/form/demo/validate-other.md correctly 1`] = `
<span>
<div
class="ant-upload ant-upload-drag"
/>
>
<span
class="ant-upload ant-upload-btn"
role="button"
tabindex="0"
>
<input
accept=""
id="validate_other_dragger"
style="display:none"
type="file"
/>
<div
class="ant-upload-drag-container"
>
<p
class="ant-upload-drag-icon"
>
<span
aria-label="inbox"
class="anticon anticon-inbox"
role="img"
>
<svg
aria-hidden="true"
class=""
data-icon="inbox"
fill="currentColor"
focusable="false"
height="1em"
viewBox="0 0 1024 1024"
width="1em"
>
<path
d="M885.2 446.3l-.2-.8-112.2-285.1c-5-16.1-19.9-27.2-36.8-27.2H281.2c-17 0-32.1 11.3-36.9 27.6L139.4 443l-.3.7-.2.8c-1.3 4.9-1.7 9.9-1 14.8-.1 1.6-.2 3.2-.2 4.8V830a60.9 60.9 0 0060.8 60.8h627.2c33.5 0 60.8-27.3 60.9-60.8V464.1c0-1.3 0-2.6-.1-3.7.4-4.9 0-9.6-1.3-14.1zm-295.8-43l-.3 15.7c-.8 44.9-31.8 75.1-77.1 75.1-22.1 0-41.1-7.1-54.8-20.6S436 441.2 435.6 419l-.3-15.7H229.5L309 210h399.2l81.7 193.3H589.4zm-375 76.8h157.3c24.3 57.1 76 90.8 140.4 90.8 33.7 0 65-9.4 90.3-27.2 22.2-15.6 39.5-37.4 50.7-63.6h156.5V814H214.4V480.1z"
/>
</svg>
</span>
</p>
<p
class="ant-upload-text"
>
Click or drag file to this area to upload
</p>
<p
class="ant-upload-hint"
>
Support for a single or bulk upload.
</p>
</div>
</span>
</div>
<div
class="ant-upload-list ant-upload-list-text"
/>

4
components/form/__tests__/index.test.js

@ -1,12 +1,12 @@
import React from 'react';
import { mount } from 'enzyme';
import scrollIntoView from 'dom-scroll-into-view';
import scrollIntoView from 'scroll-into-view-if-needed';
import Form from '..';
import Input from '../../input';
import Button from '../../button';
import mountTest from '../../../tests/shared/mountTest';
jest.mock('dom-scroll-into-view');
jest.mock('scroll-into-view-if-needed');
const delay = () =>
new Promise(resolve => {

27
components/form/util.ts

@ -1,6 +1,6 @@
import * as React from 'react';
import { useForm as useRcForm, FormInstance as RcFormInstance } from 'rc-field-form';
import scrollIntoView from 'dom-scroll-into-view';
import scrollIntoView from 'scroll-into-view-if-needed';
type InternalNamePath = (string | number)[];
@ -70,26 +70,6 @@ export function getFieldId(namePath: InternalNamePath, formName?: string): strin
return formName ? `${formName}_${mergedId}` : mergedId;
}
// Source: https://github.com/react-component/form/blob/master/src/createDOMForm.js
function getScrollableContainer(current: HTMLElement) {
let node: HTMLElement | null = current;
let nodeName;
/* eslint no-cond-assign:0 */
while (node && (nodeName = node.nodeName.toLowerCase()) !== 'body') {
const { overflowY } = getComputedStyle(node);
// https://stackoverflow.com/a/36900407/3040605
if (
node !== current &&
(overflowY === 'auto' || overflowY === 'scroll') &&
node.scrollHeight > node.clientHeight
) {
return node;
}
node = node.parentElement;
}
return nodeName === 'body' ? node!.ownerDocument : node;
}
export interface FormInstance extends RcFormInstance {
scrollToField: (name: string | number | InternalNamePath) => void;
__INTERNAL__: {
@ -107,8 +87,9 @@ export function useForm(form?: FormInstance): [FormInstance] {
const node: HTMLElement | null = fieldId ? document.getElementById(fieldId) : null;
if (node) {
scrollIntoView(node, getScrollableContainer(node), {
onlyScrollIfNeeded: true,
scrollIntoView(node, {
scrollMode: 'if-needed',
block: 'nearest',
});
}
},

2
components/grid/RowContext.tsx

@ -1,4 +1,4 @@
import createContext, { Context } from '@ant-design/create-react-context';
import { createContext, Context } from 'react';
export interface RowContextState {
gutter?: [number, number];

36
components/grid/__tests__/index.test.js

@ -3,23 +3,14 @@ import { render, mount } from 'enzyme';
import { Col, Row } from '..';
import mountTest from '../../../tests/shared/mountTest';
jest.mock('enquire.js', () => {
let that;
let unmatchFun;
return {
unregister: jest.fn(),
register: (media, options) => {
if (media === '(max-width: 575px)') {
that = this;
options.match.call(that);
unmatchFun = options.unmatch;
}
},
callunmatch() {
unmatchFun.call(that);
},
};
});
jest.spyOn(window, 'matchMedia').mockImplementationOnce(query => ({
addListener: (listener) => {
if (query === '(max-width: 575px)') {
listener({ matches: true });
}
},
removeListener: jest.fn(),
}));
describe('Grid', () => {
mountTest(Row);
@ -88,22 +79,11 @@ describe('Grid', () => {
});
it('should work correct when gutter is object', () => {
// eslint-disable-next-line global-require
const enquire = require('enquire.js');
const wrapper = mount(<Row gutter={{ xs: 20 }} />);
expect(wrapper.find('div').prop('style')).toEqual({
marginLeft: -10,
marginRight: -10,
});
enquire.callunmatch();
expect(
wrapper
.update()
.find('div')
.prop('style'),
).toEqual({});
wrapper.unmount();
expect(enquire.unregister).toHaveBeenCalled();
});
it('should work currect when gutter is array', () => {

7
components/input/ClearableLabeledInput.tsx

@ -1,5 +1,4 @@
import * as React from 'react';
import { polyfill } from 'react-lifecycles-compat';
import classNames from 'classnames';
import { CloseCircleFilled } from '@ant-design/icons';
import { tuple } from '../_util/type';
@ -16,7 +15,7 @@ export function hasPrefixSuffix(props: InputProps | ClearableInputProps) {
*/
interface BasicProps {
prefixCls: string;
inputType: (typeof ClearableInputType)[number];
inputType: typeof ClearableInputType[number];
value?: any;
defaultValue?: any;
allowClear?: boolean;
@ -31,7 +30,7 @@ interface BasicProps {
* This props only for input.
*/
interface ClearableInputProps extends BasicProps {
size?: (typeof InputSizes)[number];
size?: typeof InputSizes[number];
suffix?: React.ReactNode;
prefix?: React.ReactNode;
addonBefore?: React.ReactNode;
@ -168,6 +167,4 @@ class ClearableLabeledInput extends React.Component<ClearableInputProps> {
}
}
polyfill(ClearableLabeledInput);
export default ClearableLabeledInput;

27
components/input/Input.tsx

@ -1,5 +1,4 @@
import * as React from 'react';
import * as PropTypes from 'prop-types';
import classNames from 'classnames';
import omit from 'omit.js';
import Group from './Group';
@ -16,7 +15,7 @@ export const InputSizes = tuple('small', 'default', 'large');
export interface InputProps
extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size' | 'prefix'> {
prefixCls?: string;
size?: (typeof InputSizes)[number];
size?: typeof InputSizes[number];
onPressEnter?: React.KeyboardEventHandler<HTMLInputElement>;
addonBefore?: React.ReactNode;
addonAfter?: React.ReactNode;
@ -60,7 +59,7 @@ export function resolveOnChange(
export function getInputClassName(
prefixCls: string,
size?: (typeof InputSizes)[number],
size?: typeof InputSizes[number],
disabled?: boolean,
) {
return classNames(prefixCls, {
@ -87,28 +86,6 @@ class Input extends React.Component<InputProps, InputState> {
type: 'text',
};
static propTypes = {
type: PropTypes.string,
id: PropTypes.string,
size: PropTypes.oneOf(InputSizes),
maxLength: PropTypes.number,
disabled: PropTypes.bool,
value: PropTypes.any,
defaultValue: PropTypes.any,
className: PropTypes.string,
addonBefore: PropTypes.node,
addonAfter: PropTypes.node,
prefixCls: PropTypes.string,
onPressEnter: PropTypes.func,
onKeyDown: PropTypes.func,
onKeyUp: PropTypes.func,
onFocus: PropTypes.func,
onBlur: PropTypes.func,
prefix: PropTypes.node,
suffix: PropTypes.node,
allowClear: PropTypes.bool,
};
input: HTMLInputElement;
clearableInput: ClearableLabeledInput;

3
components/input/ResizableTextArea.tsx

@ -1,5 +1,4 @@
import * as React from 'react';
import { polyfill } from 'react-lifecycles-compat';
import ResizeObserver from 'rc-resize-observer';
import omit from 'omit.js';
import classNames from 'classnames';
@ -115,6 +114,4 @@ class ResizableTextArea extends React.Component<TextAreaProps, TextAreaState> {
}
}
polyfill(ResizableTextArea);
export default ResizableTextArea;

3
components/input/TextArea.tsx

@ -1,5 +1,4 @@
import * as React from 'react';
import { polyfill } from 'react-lifecycles-compat';
import ClearableLabeledInput from './ClearableLabeledInput';
import ResizableTextArea, { AutoSizeType } from './ResizableTextArea';
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
@ -123,6 +122,4 @@ class TextArea extends React.Component<TextAreaProps, TextAreaState> {
}
}
polyfill(TextArea);
export default TextArea;

23
components/layout/Sider.tsx

@ -1,7 +1,4 @@
import createContext, { Context } from '@ant-design/create-react-context';
import * as React from 'react';
import { polyfill } from 'react-lifecycles-compat';
import classNames from 'classnames';
import omit from 'omit.js';
import { BarsOutlined, RightOutlined, LeftOutlined } from '@ant-design/icons';
@ -10,22 +7,6 @@ import { LayoutContext, LayoutContextProps } from './layout';
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
import isNumeric from '../_util/isNumeric';
// matchMedia polyfill for
// https://github.com/WickyNilliams/enquire.js/issues/82
// TODO: Will be removed in antd 4.0 because we will no longer support ie9
if (typeof window !== 'undefined') {
const matchMediaPolyfill = (mediaQuery: string) => {
return {
media: mediaQuery,
matches: false,
addListener() {},
removeListener() {},
};
};
// ref: https://github.com/ant-design/ant-design/issues/18774
if (!window.matchMedia) window.matchMedia = matchMediaPolyfill as any;
}
const dimensionMaxMap = {
xs: '479.98px',
sm: '575.98px',
@ -40,7 +21,7 @@ export interface SiderContextProps {
collapsedWidth?: string | number;
}
export const SiderContext: Context<SiderContextProps> = createContext({});
export const SiderContext: React.Context<SiderContextProps> = React.createContext({});
export type CollapseType = 'clickTrigger' | 'responsive';
@ -272,8 +253,6 @@ class InternalSider extends React.Component<InternalSideProps, SiderState> {
}
}
polyfill(InternalSider);
// eslint-disable-next-line react/prefer-stateless-function
export default class Sider extends React.Component {
render() {

10
components/layout/__tests__/index.test.js

@ -154,16 +154,6 @@ describe('Sider', () => {
errorSpy.mockRestore();
});
beforeAll(() => {
Object.defineProperty(window, 'matchMedia', {
value: jest.fn(() => ({
matches: true,
addListener: () => {},
removeListener: () => {},
})),
});
});
it('should trigger onBreakpoint', async () => {
const onBreakpoint = jest.fn();

3
components/layout/layout.tsx

@ -1,6 +1,5 @@
import * as React from 'react';
import classNames from 'classnames';
import createContext from '@ant-design/create-react-context';
import { SiderProps } from './Sider';
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
@ -19,7 +18,7 @@ export interface LayoutContextProps {
removeSider: (id: string) => void;
};
}
export const LayoutContext = createContext<LayoutContextProps>({
export const LayoutContext = React.createContext<LayoutContextProps>({
siderHook: {
addSider: () => null,
removeSider: () => null,

4
components/locale-provider/index.tsx

@ -36,10 +36,6 @@ function setMomentLocale(locale: Locale) {
}
export default class LocaleProvider extends React.Component<LocaleProviderProps, any> {
static propTypes = {
locale: PropTypes.object,
};
static defaultProps = {
locale: {},
};

3
components/mentions/index.tsx

@ -1,7 +1,6 @@
import classNames from 'classnames';
import omit from 'omit.js';
import * as React from 'react';
import { polyfill } from 'react-lifecycles-compat';
import RcMentions from 'rc-mentions';
import { MentionsProps as RcMentionsProps } from 'rc-mentions/lib/Mentions';
import Spin from '../spin';
@ -172,6 +171,4 @@ class Mentions extends React.Component<MentionProps, MentionState> {
}
}
polyfill(Mentions);
export default Mentions;

2
components/menu/MenuContext.tsx

@ -1,4 +1,4 @@
import createContext from '@ant-design/create-react-context';
import { createContext } from 'react';
export type MenuTheme = 'light' | 'dark';

7
components/menu/__tests__/index.test.js

@ -6,13 +6,6 @@ import Layout from '../../layout';
import mountTest from '../../../tests/shared/mountTest';
import { resetWarned } from '../../_util/warning';
jest.mock('mutationobserver-shim', () => {
global.MutationObserver = function MutationObserver() {
this.observe = () => {};
this.disconnect = () => {};
};
});
const { SubMenu } = Menu;
describe('Menu', () => {

3
components/menu/index.tsx

@ -2,7 +2,6 @@ import * as React from 'react';
import RcMenu, { Divider, ItemGroup } from 'rc-menu';
import classNames from 'classnames';
import omit from 'omit.js';
import { polyfill } from 'react-lifecycles-compat';
import SubMenu from './SubMenu';
import Item from './MenuItem';
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
@ -334,8 +333,6 @@ class InternalMenu extends React.Component<InternalMenuProps, MenuState> {
}
}
polyfill(InternalMenu);
// We should keep this as ref-able
export default class Menu extends React.Component<MenuProps, {}> {
static Divider = Divider;

4
components/menu/style/index.less

@ -232,12 +232,8 @@
width: 6px;
height: 1.5px;
// background + background-image to makes before & after cross have same color.
// Since `linear-gradient` not work on IE9, we should hack it.
// ref: https://github.com/ant-design/ant-design/issues/15910
background: @menu-bg;
background: ~'@{menu-item-color} \9';
background-image: linear-gradient(to right, @menu-item-color, @menu-item-color);
background-image: ~'none \9';
border-radius: 2px;
transition: background 0.3s @ease-in-out, transform 0.3s @ease-in-out,
top 0.3s @ease-in-out;

17
components/modal/Modal.tsx

@ -1,6 +1,5 @@
import * as React from 'react';
import Dialog from 'rc-dialog';
import * as PropTypes from 'prop-types';
import classNames from 'classnames';
import addEventListener from 'rc-util/lib/Dom/addEventListener';
import { CloseOutlined } from '@ant-design/icons';
@ -151,22 +150,6 @@ export default class Modal extends React.Component<ModalProps, {}> {
okType: 'primary' as ButtonType,
};
static propTypes = {
prefixCls: PropTypes.string,
onOk: PropTypes.func,
onCancel: PropTypes.func,
okText: PropTypes.node,
cancelText: PropTypes.node,
centered: PropTypes.bool,
width: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
confirmLoading: PropTypes.bool,
visible: PropTypes.bool,
footer: PropTypes.node,
title: PropTypes.node,
closable: PropTypes.bool,
closeIcon: PropTypes.node,
};
handleCancel = (e: React.MouseEvent<HTMLButtonElement>) => {
const { onCancel } = this.props;
if (onCancel) {

3
components/popconfirm/index.tsx

@ -1,5 +1,4 @@
import * as React from 'react';
import { polyfill } from 'react-lifecycles-compat';
import { ExclamationCircleFilled } from '@ant-design/icons';
import Tooltip, { AbstractTooltipProps } from '../tooltip';
@ -166,6 +165,4 @@ class Popconfirm extends React.Component<PopconfirmProps, PopconfirmState> {
}
}
polyfill(Popconfirm);
export default Popconfirm;

15
components/progress/progress.tsx

@ -1,4 +1,3 @@
import * as PropTypes from 'prop-types';
import * as React from 'react';
import classNames from 'classnames';
import omit from 'omit.js';
@ -56,20 +55,6 @@ export default class Progress extends React.Component<ProgressProps> {
strokeLinecap: 'round',
};
static propTypes = {
status: PropTypes.oneOf(ProgressStatuses),
type: PropTypes.oneOf(ProgressTypes),
showInfo: PropTypes.bool,
percent: PropTypes.number,
width: PropTypes.number,
strokeWidth: PropTypes.number,
strokeLinecap: PropTypes.oneOf(['round', 'square']),
strokeColor: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
trailColor: PropTypes.string,
format: PropTypes.func,
gapDegree: PropTypes.number,
};
getPercentNumber() {
const { successPercent, percent = 0 } = this.props;
return parseInt(

2
components/radio/group.tsx

@ -2,7 +2,6 @@ import * as React from 'react';
import * as PropTypes from 'prop-types';
import classNames from 'classnames';
import shallowEqual from 'shallowequal';
import { polyfill } from 'react-lifecycles-compat';
import Radio from './radio';
import {
RadioGroupProps,
@ -161,5 +160,4 @@ class RadioGroup extends React.Component<RadioGroupProps, RadioGroupState> {
}
}
polyfill(RadioGroup);
export default RadioGroup;

6
components/rate/index.tsx

@ -1,5 +1,4 @@
import * as React from 'react';
import * as PropTypes from 'prop-types';
import RcRate from 'rc-rate';
import omit from 'omit.js';
import { StarFilled } from '@ant-design/icons';
@ -28,11 +27,6 @@ interface RateNodeProps {
}
export default class Rate extends React.Component<RateProps, any> {
static propTypes = {
prefixCls: PropTypes.string,
character: PropTypes.node,
};
static defaultProps = {
character: <StarFilled />,
};

10
components/spin/index.tsx

@ -1,5 +1,4 @@
import * as React from 'react';
import * as PropTypes from 'prop-types';
import classNames from 'classnames';
import omit from 'omit.js';
import debounce from 'lodash/debounce';
@ -72,15 +71,6 @@ class Spin extends React.Component<SpinProps, SpinState> {
wrapperClassName: '',
};
static propTypes = {
prefixCls: PropTypes.string,
className: PropTypes.string,
spinning: PropTypes.bool,
size: PropTypes.oneOf(SpinSizes),
wrapperClassName: PropTypes.string,
indicator: PropTypes.element,
};
static setDefaultIndicator(indicator: React.ReactNode) {
defaultIndicator = indicator;
}

3
components/statistic/Countdown.tsx

@ -1,5 +1,4 @@
import * as React from 'react';
import { polyfill } from 'react-lifecycles-compat';
import * as moment from 'moment';
import interopDefault from '../_util/interopDefault';
import Statistic, { StatisticProps } from './Statistic';
@ -86,6 +85,4 @@ class Countdown extends React.Component<CountdownProps, {}> {
}
}
polyfill(Countdown);
export default Countdown;

7
components/steps/index.tsx

@ -1,5 +1,4 @@
import * as React from 'react';
import * as PropTypes from 'prop-types';
import RcSteps from 'rc-steps';
import { CheckOutlined, CloseOutlined } from '@ant-design/icons';
@ -40,12 +39,6 @@ export default class Steps extends React.Component<StepsProps, any> {
current: 0,
};
static propTypes = {
prefixCls: PropTypes.string,
iconPrefix: PropTypes.string,
current: PropTypes.number,
};
renderSteps = ({ getPrefixCls }: ConfigConsumerProps) => {
const prefixCls = getPrefixCls('steps', this.props.prefixCls);
const iconPrefix = getPrefixCls('', this.props.iconPrefix);

1
components/style/core/motion.less

@ -3,7 +3,6 @@
@import 'motion/move';
@import 'motion/other';
@import 'motion/slide';
@import 'motion/swing';
@import 'motion/zoom';
// For common/openAnimation

34
components/style/core/motion/swing.less

@ -1,34 +0,0 @@
.swing-motion(@className, @keyframeName) {
.@{className}-enter,
.@{className}-appear {
.motion-common();
animation-play-state: paused;
}
.@{className}-enter.@{className}-enter-active,
.@{className}-appear.@{className}-appear-active {
animation-name: ~'@{keyframeName}In';
animation-play-state: running;
}
}
.swing-motion(swing, antSwing);
@keyframes antSwingIn {
0%,
100% {
transform: translateX(0);
}
20% {
transform: translateX(-10px);
}
40% {
transform: translateX(10px);
}
60% {
transform: translateX(-5px);
}
80% {
transform: translateX(5px);
}
}

11
components/style/mixins/compatibility.less

@ -3,16 +3,7 @@
// Placeholder text
.placeholder(@color: @input-placeholder-color) {
// Firefox
&::-moz-placeholder {
color: @color;
opacity: 1; // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526
}
// Internet Explorer 10+
&:-ms-input-placeholder {
color: @color;
}
// Safari and Chrome
&::-webkit-input-placeholder {
&::placeholder {
color: @color;
}

9
components/style/mixins/iconfont.less

@ -28,16 +28,9 @@
}
// for iconfont font size
// fix chrome 12px bug, support ie
// fix chrome 12px bug
.iconfont-size-under-12px(@size, @rotate: 0deg) {
display: inline-block;
@font-scale: unit(@size / 12px);
font-size: 12px;
// IE9
font-size: ~'@{size} \9';
transform: scale(@font-scale) rotate(@rotate);
:root & {
font-size: @font-size-sm; // reset IE9 and above
}
}

11
components/switch/index.tsx

@ -1,5 +1,4 @@
import * as React from 'react';
import * as PropTypes from 'prop-types';
import RcSwitch from 'rc-switch';
import classNames from 'classnames';
import omit from 'omit.js';
@ -33,16 +32,6 @@ export interface SwitchProps {
export default class Switch extends React.Component<SwitchProps, {}> {
static __ANT_SWITCH = true;
static propTypes = {
prefixCls: PropTypes.string,
// HACK: https://github.com/ant-design/ant-design/issues/5368
// size=default and size=large are the same
size: PropTypes.oneOf(['small', 'default', 'large']) as PropTypes.Requireable<
SwitchProps['size']
>,
className: PropTypes.string,
};
private rcSwitch: typeof RcSwitch;
constructor(props: SwitchProps) {

3
components/tag/index.tsx

@ -1,7 +1,6 @@
import * as React from 'react';
import classNames from 'classnames';
import omit from 'omit.js';
import { polyfill } from 'react-lifecycles-compat';
import { CloseOutlined } from '@ant-design/icons';
import CheckableTag from './CheckableTag';
@ -133,6 +132,4 @@ class Tag extends React.Component<TagProps, TagState> {
}
}
polyfill(Tag);
export default Tag;

3
components/tooltip/index.tsx

@ -1,5 +1,4 @@
import * as React from 'react';
import { polyfill } from 'react-lifecycles-compat';
import RcTooltip from 'rc-tooltip';
import classNames from 'classnames';
import { AlignType, ActionType, BuildInPlacements } from 'rc-trigger/lib/interface';
@ -280,6 +279,4 @@ class Tooltip extends React.Component<TooltipProps, any> {
}
}
polyfill(Tooltip);
export default Tooltip;

27
components/transfer/ListItem.tsx

@ -1,7 +1,6 @@
import * as React from 'react';
import classNames from 'classnames';
import PureRenderMixin from 'rc-util/lib/PureRenderMixin';
import Lazyload from 'react-lazy-load';
import Checkbox from '../checkbox';
export default class ListItem extends React.Component<any, any> {
@ -10,16 +9,7 @@ export default class ListItem extends React.Component<any, any> {
}
render() {
const {
renderedText,
renderedEl,
item,
lazy,
checked,
disabled,
prefixCls,
onClick,
} = this.props;
const { renderedText, renderedEl, item, checked, disabled, prefixCls, onClick } = this.props;
const className = classNames({
[`${prefixCls}-content-item`]: true,
@ -42,20 +32,7 @@ export default class ListItem extends React.Component<any, any> {
<span className={`${prefixCls}-content-item-text`}>{renderedEl}</span>
</li>
);
let children: JSX.Element | null = null;
if (lazy) {
const lazyProps = {
height: 32,
offset: 500,
throttle: 0,
debounce: false,
...lazy,
};
children = <Lazyload {...lazyProps}>{listItem}</Lazyload>;
} else {
children = listItem;
}
return children;
return listItem;
}
}

587
components/transfer/__tests__/__snapshots__/demo.test.js.snap

@ -388,62 +388,363 @@ exports[`renders ./components/transfer/demo/basic.md correctly 1`] = `
<ul
class="ant-transfer-list-content"
>
<div
class="LazyLoad"
style="height:32px"
/>
<div
class="LazyLoad"
style="height:32px"
/>
<div
class="LazyLoad"
style="height:32px"
/>
<div
class="LazyLoad"
style="height:32px"
/>
<div
class="LazyLoad"
style="height:32px"
/>
<div
class="LazyLoad"
style="height:32px"
/>
<div
class="LazyLoad"
style="height:32px"
/>
<div
class="LazyLoad"
style="height:32px"
/>
<div
class="LazyLoad"
style="height:32px"
/>
<div
class="LazyLoad"
style="height:32px"
/>
<div
class="LazyLoad"
style="height:32px"
/>
<div
class="LazyLoad"
style="height:32px"
/>
<div
class="LazyLoad"
style="height:32px"
/>
<div
class="LazyLoad"
style="height:32px"
/>
<li
class="ant-transfer-list-content-item ant-transfer-list-content-item-disabled"
title="content1"
>
<label
class="ant-checkbox-wrapper ant-checkbox-wrapper-disabled"
>
<span
class="ant-checkbox ant-checkbox-disabled"
>
<input
class="ant-checkbox-input"
disabled=""
type="checkbox"
/>
<span
class="ant-checkbox-inner"
/>
</span>
</label>
<span
class="ant-transfer-list-content-item-text"
>
content1
</span>
</li>
<li
class="ant-transfer-list-content-item"
title="content2"
>
<label
class="ant-checkbox-wrapper"
>
<span
class="ant-checkbox"
>
<input
class="ant-checkbox-input"
type="checkbox"
/>
<span
class="ant-checkbox-inner"
/>
</span>
</label>
<span
class="ant-transfer-list-content-item-text"
>
content2
</span>
</li>
<li
class="ant-transfer-list-content-item ant-transfer-list-content-item-disabled"
title="content4"
>
<label
class="ant-checkbox-wrapper ant-checkbox-wrapper-disabled"
>
<span
class="ant-checkbox ant-checkbox-disabled"
>
<input
class="ant-checkbox-input"
disabled=""
type="checkbox"
/>
<span
class="ant-checkbox-inner"
/>
</span>
</label>
<span
class="ant-transfer-list-content-item-text"
>
content4
</span>
</li>
<li
class="ant-transfer-list-content-item"
title="content5"
>
<label
class="ant-checkbox-wrapper"
>
<span
class="ant-checkbox"
>
<input
class="ant-checkbox-input"
type="checkbox"
/>
<span
class="ant-checkbox-inner"
/>
</span>
</label>
<span
class="ant-transfer-list-content-item-text"
>
content5
</span>
</li>
<li
class="ant-transfer-list-content-item ant-transfer-list-content-item-disabled"
title="content7"
>
<label
class="ant-checkbox-wrapper ant-checkbox-wrapper-disabled"
>
<span
class="ant-checkbox ant-checkbox-disabled"
>
<input
class="ant-checkbox-input"
disabled=""
type="checkbox"
/>
<span
class="ant-checkbox-inner"
/>
</span>
</label>
<span
class="ant-transfer-list-content-item-text"
>
content7
</span>
</li>
<li
class="ant-transfer-list-content-item"
title="content8"
>
<label
class="ant-checkbox-wrapper"
>
<span
class="ant-checkbox"
>
<input
class="ant-checkbox-input"
type="checkbox"
/>
<span
class="ant-checkbox-inner"
/>
</span>
</label>
<span
class="ant-transfer-list-content-item-text"
>
content8
</span>
</li>
<li
class="ant-transfer-list-content-item ant-transfer-list-content-item-disabled"
title="content10"
>
<label
class="ant-checkbox-wrapper ant-checkbox-wrapper-disabled"
>
<span
class="ant-checkbox ant-checkbox-disabled"
>
<input
class="ant-checkbox-input"
disabled=""
type="checkbox"
/>
<span
class="ant-checkbox-inner"
/>
</span>
</label>
<span
class="ant-transfer-list-content-item-text"
>
content10
</span>
</li>
<li
class="ant-transfer-list-content-item"
title="content11"
>
<label
class="ant-checkbox-wrapper"
>
<span
class="ant-checkbox"
>
<input
class="ant-checkbox-input"
type="checkbox"
/>
<span
class="ant-checkbox-inner"
/>
</span>
</label>
<span
class="ant-transfer-list-content-item-text"
>
content11
</span>
</li>
<li
class="ant-transfer-list-content-item ant-transfer-list-content-item-disabled"
title="content13"
>
<label
class="ant-checkbox-wrapper ant-checkbox-wrapper-disabled"
>
<span
class="ant-checkbox ant-checkbox-disabled"
>
<input
class="ant-checkbox-input"
disabled=""
type="checkbox"
/>
<span
class="ant-checkbox-inner"
/>
</span>
</label>
<span
class="ant-transfer-list-content-item-text"
>
content13
</span>
</li>
<li
class="ant-transfer-list-content-item"
title="content14"
>
<label
class="ant-checkbox-wrapper"
>
<span
class="ant-checkbox"
>
<input
class="ant-checkbox-input"
type="checkbox"
/>
<span
class="ant-checkbox-inner"
/>
</span>
</label>
<span
class="ant-transfer-list-content-item-text"
>
content14
</span>
</li>
<li
class="ant-transfer-list-content-item ant-transfer-list-content-item-disabled"
title="content16"
>
<label
class="ant-checkbox-wrapper ant-checkbox-wrapper-disabled"
>
<span
class="ant-checkbox ant-checkbox-disabled"
>
<input
class="ant-checkbox-input"
disabled=""
type="checkbox"
/>
<span
class="ant-checkbox-inner"
/>
</span>
</label>
<span
class="ant-transfer-list-content-item-text"
>
content16
</span>
</li>
<li
class="ant-transfer-list-content-item"
title="content17"
>
<label
class="ant-checkbox-wrapper"
>
<span
class="ant-checkbox"
>
<input
class="ant-checkbox-input"
type="checkbox"
/>
<span
class="ant-checkbox-inner"
/>
</span>
</label>
<span
class="ant-transfer-list-content-item-text"
>
content17
</span>
</li>
<li
class="ant-transfer-list-content-item ant-transfer-list-content-item-disabled"
title="content19"
>
<label
class="ant-checkbox-wrapper ant-checkbox-wrapper-disabled"
>
<span
class="ant-checkbox ant-checkbox-disabled"
>
<input
class="ant-checkbox-input"
disabled=""
type="checkbox"
/>
<span
class="ant-checkbox-inner"
/>
</span>
</label>
<span
class="ant-transfer-list-content-item-text"
>
content19
</span>
</li>
<li
class="ant-transfer-list-content-item"
title="content20"
>
<label
class="ant-checkbox-wrapper"
>
<span
class="ant-checkbox"
>
<input
class="ant-checkbox-input"
type="checkbox"
/>
<span
class="ant-checkbox-inner"
/>
</span>
</label>
<span
class="ant-transfer-list-content-item-text"
>
content20
</span>
</li>
</ul>
</div>
</div>
@ -543,30 +844,156 @@ exports[`renders ./components/transfer/demo/basic.md correctly 1`] = `
<ul
class="ant-transfer-list-content"
>
<div
class="LazyLoad"
style="height:32px"
/>
<div
class="LazyLoad"
style="height:32px"
/>
<div
class="LazyLoad"
style="height:32px"
/>
<div
class="LazyLoad"
style="height:32px"
/>
<div
class="LazyLoad"
style="height:32px"
/>
<div
class="LazyLoad"
style="height:32px"
/>
<li
class="ant-transfer-list-content-item"
title="content3"
>
<label
class="ant-checkbox-wrapper"
>
<span
class="ant-checkbox"
>
<input
class="ant-checkbox-input"
type="checkbox"
/>
<span
class="ant-checkbox-inner"
/>
</span>
</label>
<span
class="ant-transfer-list-content-item-text"
>
content3
</span>
</li>
<li
class="ant-transfer-list-content-item"
title="content6"
>
<label
class="ant-checkbox-wrapper"
>
<span
class="ant-checkbox"
>
<input
class="ant-checkbox-input"
type="checkbox"
/>
<span
class="ant-checkbox-inner"
/>
</span>
</label>
<span
class="ant-transfer-list-content-item-text"
>
content6
</span>
</li>
<li
class="ant-transfer-list-content-item"
title="content9"
>
<label
class="ant-checkbox-wrapper"
>
<span
class="ant-checkbox"
>
<input
class="ant-checkbox-input"
type="checkbox"
/>
<span
class="ant-checkbox-inner"
/>
</span>
</label>
<span
class="ant-transfer-list-content-item-text"
>
content9
</span>
</li>
<li
class="ant-transfer-list-content-item"
title="content12"
>
<label
class="ant-checkbox-wrapper"
>
<span
class="ant-checkbox"
>
<input
class="ant-checkbox-input"
type="checkbox"
/>
<span
class="ant-checkbox-inner"
/>
</span>
</label>
<span
class="ant-transfer-list-content-item-text"
>
content12
</span>
</li>
<li
class="ant-transfer-list-content-item"
title="content15"
>
<label
class="ant-checkbox-wrapper"
>
<span
class="ant-checkbox"
>
<input
class="ant-checkbox-input"
type="checkbox"
/>
<span
class="ant-checkbox-inner"
/>
</span>
</label>
<span
class="ant-transfer-list-content-item-text"
>
content15
</span>
</li>
<li
class="ant-transfer-list-content-item"
title="content18"
>
<label
class="ant-checkbox-wrapper"
>
<span
class="ant-checkbox"
>
<input
class="ant-checkbox-input"
type="checkbox"
/>
<span
class="ant-checkbox-inner"
/>
</span>
</label>
<span
class="ant-transfer-list-content-item-text"
>
content18
</span>
</li>
</ul>
</div>
</div>

129
components/transfer/__tests__/__snapshots__/index.test.js.snap

@ -480,7 +480,6 @@ exports[`Transfer should support render value and label in item 1`] = `
handleFilter={[Function]}
itemUnit="item"
itemsUnit="items"
lazy={Object {}}
notFoundContent={
<Context.Consumer>
[Function]
@ -593,7 +592,6 @@ exports[`Transfer should support render value and label in item 1`] = `
}
itemUnit="item"
itemsUnit="items"
lazy={Object {}}
notFoundContent={
<Context.Consumer>
[Function]
@ -615,78 +613,74 @@ exports[`Transfer should support render value and label in item 1`] = `
]
}
>
<Animate
animation={Object {}}
<ul
className="ant-transfer-list-content"
component="ul"
componentProps={
Object {
"onScroll": [Function],
}
}
onAppear={[Function]}
onEnd={[Function]}
onEnter={[Function]}
onLeave={[Function]}
transitionAppear={false}
transitionEnter={true}
transitionLeave={false}
transitionName=""
onScroll={[Function]}
>
<ul
className="ant-transfer-list-content"
onScroll={[Function]}
<ListItem
checked={false}
item={
Object {
"key": "a",
"title": "title",
}
}
key="a"
onClick={[Function]}
prefixCls="ant-transfer-list"
renderedEl="label"
renderedText="title value"
>
<AnimateChild
animation={Object {}}
key="a"
transitionAppear={false}
transitionEnter={true}
transitionLeave={false}
transitionName=""
<li
className="ant-transfer-list-content-item"
onClick={[Function]}
title="title value"
>
<ListItem
<Checkbox
checked={false}
item={
Object {
"key": "a",
"title": "title",
}
}
key="a"
lazy={Object {}}
onClick={[Function]}
prefixCls="ant-transfer-list"
renderedEl="label"
renderedText="title value"
indeterminate={false}
>
<LazyLoad
debounce={false}
elementType="div"
height={32}
offset={500}
offsetBottom={0}
offsetHorizontal={0}
offsetLeft={0}
offsetRight={0}
offsetTop={0}
offsetVertical={0}
throttle={0}
<label
className="ant-checkbox-wrapper"
>
<div
className="LazyLoad"
style={
Object {
"height": 32,
"width": undefined,
}
}
/>
</LazyLoad>
</ListItem>
</AnimateChild>
</ul>
</Animate>
<Checkbox
checked={false}
className=""
defaultChecked={false}
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
prefixCls="ant-checkbox"
style={Object {}}
type="checkbox"
>
<span
className="ant-checkbox"
style={Object {}}
>
<input
checked={false}
className="ant-checkbox-input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
type="checkbox"
/>
<span
className="ant-checkbox-inner"
/>
</span>
</Checkbox>
</label>
</Checkbox>
<span
className="ant-transfer-list-content-item-text"
>
label
</span>
</li>
</ListItem>
</ul>
</ListBody>
</div>
</div>
@ -899,7 +893,6 @@ exports[`Transfer should support render value and label in item 1`] = `
handleFilter={[Function]}
itemUnit="item"
itemsUnit="items"
lazy={Object {}}
notFoundContent={
<Context.Consumer>
[Function]

3
components/transfer/__tests__/index.test.js

@ -30,7 +30,6 @@ const listCommonProps = {
],
selectedKeys: ['a'],
targetKeys: ['b'],
lazy: false,
};
const listDisabledProps = {
@ -47,7 +46,6 @@ const listDisabledProps = {
],
selectedKeys: ['a', 'b'],
targetKeys: [],
lazy: false,
};
const searchTransferProps = {
@ -91,7 +89,6 @@ const searchTransferProps = {
],
selectedKeys: [],
targetKeys: ['3', '4'],
lazy: false,
};
describe('Transfer', () => {

11
components/transfer/__tests__/list.test.js

@ -22,23 +22,12 @@ const listCommonProps = {
],
checkedKeys: ['a'],
notFoundContent: 'Not Found',
lazy: false,
};
describe('Transfer.List', () => {
beforeAll(() => {
jest.useFakeTimers();
});
afterAll(() => {
jest.useRealTimers();
});
it('should render correctly', () => {
const wrapper = mount(<List {...listCommonProps} />);
jest.runAllTimers();
wrapper.update();
expect(wrapper.find('ListBody').state().mounted).toBeTruthy();
expect(wrapper.render()).toMatchSnapshot();
});

2
components/transfer/__tests__/search.test.js

@ -60,7 +60,6 @@ describe('Transfer.Search', () => {
.find('.ant-input')
.at(0)
.simulate('change', { target: { value: 'a' } });
jest.runAllTimers();
expect(onSearch).toHaveBeenCalledWith('left', 'a');
onSearch.mockReset();
@ -84,7 +83,6 @@ describe('Transfer.Search', () => {
.find('.ant-input')
.at(0)
.simulate('change', { target: { value: 'a' } });
jest.runAllTimers();
expect(errorSpy.mock.calls.length).toBe(0);
expect(onSearchChange).not.toHaveBeenCalled();

1
components/transfer/index.en-US.md

@ -25,7 +25,6 @@ One or more elements can be selected from either column, one click on the proper
| disabled | Whether disabled transfer | boolean | false | |
| filterOption | A function to determine whether an item should show in search result list | (inputValue, option): boolean | | |
| footer | A function used for rendering the footer. | (props) => ReactNode | | |
| lazy | property of [react-lazy-load](https://github.com/loktar00/react-lazy-load) for lazy rendering items. Turn off it by set to `false`. | object\|boolean | `{ height: 32, offset: 32 }` | |
| listStyle | A custom CSS style used for rendering the transfer columns. | object\|({direction: 'left'\|'right'}) => object | | |
| locale | i18n text including filter, empty text, item unit, etc | { itemUnit: string; itemsUnit: string; searchPlaceholder: string; notFoundContent: ReactNode; } | `{ itemUnit: 'item', itemsUnit: 'items', notFoundContent: 'The list is empty', searchPlaceholder: 'Search here' }` | |
| operations | A set of operations that are sorted from top to bottom. | string\[] | \['>', '<'] | |

38
components/transfer/index.tsx

@ -1,7 +1,5 @@
import * as React from 'react';
import * as PropTypes from 'prop-types';
import classNames from 'classnames';
import { polyfill } from 'react-lifecycles-compat';
import List, { TransferListProps } from './list';
import Operation from './operation';
import Search from './search';
@ -58,8 +56,7 @@ export interface TransferProps {
footer?: (props: TransferListProps) => React.ReactNode;
rowKey?: (record: TransferItem) => string;
onSearch?: (direction: TransferDirection, value: string) => void;
lazy?: {} | boolean;
onScroll?: (direction: TransferDirection, e: React.SyntheticEvent<HTMLDivElement>) => void;
onScroll?: (direction: TransferDirection, e: React.SyntheticEvent<HTMLUListElement>) => void;
children?: (props: TransferListBodyProps) => React.ReactNode;
showSelectAll?: boolean;
}
@ -87,28 +84,6 @@ class Transfer extends React.Component<TransferProps, any> {
listStyle: () => {},
};
static propTypes = {
prefixCls: PropTypes.string,
disabled: PropTypes.bool,
dataSource: PropTypes.array as PropTypes.Validator<TransferItem[]>,
render: PropTypes.func,
targetKeys: PropTypes.array,
onChange: PropTypes.func,
height: PropTypes.number,
style: PropTypes.object,
listStyle: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
operationStyle: PropTypes.object,
className: PropTypes.string,
titles: PropTypes.array,
operations: PropTypes.array,
showSearch: PropTypes.bool,
filterOption: PropTypes.func,
locale: PropTypes.object,
footer: PropTypes.func,
rowKey: PropTypes.func,
lazy: PropTypes.oneOfType([PropTypes.object, PropTypes.bool]),
};
static getDerivedStateFromProps(nextProps: TransferProps) {
if (nextProps.selectedKeys) {
const targetKeys = nextProps.targetKeys || [];
@ -259,16 +234,16 @@ class Transfer extends React.Component<TransferProps, any> {
onRightItemSelect = (selectedKey: string, checked: boolean) =>
this.onItemSelect('right', selectedKey, checked);
handleScroll = (direction: TransferDirection, e: React.SyntheticEvent<HTMLDivElement>) => {
handleScroll = (direction: TransferDirection, e: React.SyntheticEvent<HTMLUListElement>) => {
const { onScroll } = this.props;
if (onScroll) {
onScroll(direction, e);
}
};
handleLeftScroll = (e: React.SyntheticEvent<HTMLDivElement>) => this.handleScroll('left', e);
handleLeftScroll = (e: React.SyntheticEvent<HTMLUListElement>) => this.handleScroll('left', e);
handleRightScroll = (e: React.SyntheticEvent<HTMLDivElement>) => this.handleScroll('right', e);
handleRightScroll = (e: React.SyntheticEvent<HTMLUListElement>) => this.handleScroll('right', e);
handleSelectChange(direction: TransferDirection, holder: string[]) {
const { sourceSelectedKeys, targetSelectedKeys } = this.state;
@ -335,7 +310,6 @@ class Transfer extends React.Component<TransferProps, any> {
operationStyle,
filterOption,
render,
lazy,
children,
showSelectAll,
} = this.props;
@ -374,7 +348,6 @@ class Transfer extends React.Component<TransferProps, any> {
showSearch={showSearch}
renderList={children}
footer={footer}
lazy={lazy}
onScroll={this.handleLeftScroll}
disabled={disabled}
direction="left"
@ -407,7 +380,6 @@ class Transfer extends React.Component<TransferProps, any> {
showSearch={showSearch}
renderList={children}
footer={footer}
lazy={lazy}
onScroll={this.handleRightScroll}
disabled={disabled}
direction="right"
@ -429,6 +401,4 @@ class Transfer extends React.Component<TransferProps, any> {
}
}
polyfill(Transfer);
export default Transfer;

1
components/transfer/index.zh-CN.md

@ -28,7 +28,6 @@ title: Transfer
| disabled | 是否禁用 | boolean | false | |
| filterOption | 接收 `inputValue` `option` 两个参数,当 `option` 符合筛选条件时,应返回 `true`,反之则返回 `false`。 | | (inputValue, option): boolean | | |
| footer | 底部渲染函数 | (props) => ReactNode | | |
| lazy | Transfer 使用了 [react-lazy-load](https://github.com/loktar00/react-lazy-load) 优化性能,这里可以设置相关参数。设为 `false` 可以关闭懒加载。 | object\|boolean | `{ height: 32, offset: 32 }` | |
| listStyle | 两个穿梭框的自定义样式 | object\|({direction: 'left'\|'right'}) => object | | |
| locale | 各种语言 | { itemUnit: string; itemsUnit: string; searchPlaceholder: string; notFoundContent: ReactNode; } | `{ itemUnit: '项', itemsUnit: '项', searchPlaceholder: '请输入搜索内容' }` | |
| operations | 操作文案集合,顺序从上至下 | string\[] | \['>', '<'] | |

18
components/transfer/list.tsx

@ -1,5 +1,4 @@
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import omit from 'omit.js';
import classNames from 'classnames';
import PureRenderMixin from 'rc-util/lib/PureRenderMixin';
@ -7,7 +6,6 @@ import Checkbox from '../checkbox';
import { TransferItem, TransferDirection, RenderResult, RenderResultObject } from './index';
import Search from './search';
import defaultRenderList, { TransferListBodyProps, OmitProps } from './renderListBody';
import triggerEvent from '../_util/triggerEvent';
const defaultRender = () => null;
@ -46,8 +44,7 @@ export interface TransferListProps {
itemsUnit: string;
renderList?: RenderListFunction;
footer?: (props: TransferListProps) => React.ReactNode;
lazy?: boolean | {};
onScroll: Function;
onScroll: (e: React.UIEvent<HTMLUListElement>) => void;
disabled?: boolean;
direction: TransferDirection;
showSelectAll?: boolean;
@ -75,7 +72,6 @@ export default class TransferList extends React.Component<TransferListProps, Tra
dataSource: [],
titleText: '',
showSearch: false,
lazy: {},
};
timer: number;
@ -220,18 +216,6 @@ export default class TransferList extends React.Component<TransferListProps, Tra
} = e;
this.setState({ filterValue });
handleFilter(e);
if (!filterValue) {
return;
}
// Manually trigger scroll event for lazy search bug
// https://github.com/ant-design/ant-design/issues/5631
this.triggerScrollTimer = window.setTimeout(() => {
const transferNode = ReactDOM.findDOMNode(this) as Element;
const listNode = transferNode.querySelectorAll('.ant-transfer-list-content')[0];
if (listNode) {
triggerEvent(listNode, 'scroll');
}
}, 0);
};
handleClear = () => {

53
components/transfer/renderListBody.tsx

@ -1,14 +1,11 @@
import * as React from 'react';
import { findDOMNode } from 'react-dom';
import Animate from 'rc-animate';
import raf from '../_util/raf';
import { Omit, tuple } from '../_util/type';
import { TransferItem } from '.';
import { TransferListProps, RenderedItem } from './list';
import ListItem from './ListItem';
export const OmitProps = tuple('handleFilter', 'handleClear', 'checkedKeys');
export type OmitProp = (typeof OmitProps)[number];
export type OmitProp = typeof OmitProps[number];
type PartialTransferListProps = Omit<TransferListProps, OmitProp>;
export interface TransferListBodyProps extends PartialTransferListProps {
@ -18,41 +15,6 @@ export interface TransferListBodyProps extends PartialTransferListProps {
}
class ListBody extends React.Component<TransferListBodyProps> {
state = {
mounted: false,
};
private mountId: number;
private lazyId: number;
componentDidMount() {
this.mountId = raf(() => {
this.setState({ mounted: true });
});
}
componentDidUpdate(prevProps: TransferListBodyProps) {
const { filteredRenderItems, lazy } = this.props;
if (prevProps.filteredRenderItems.length !== filteredRenderItems.length && lazy !== false) {
// TODO: Replace this with ref when react 15 support removed.
const container = findDOMNode(this);
raf.cancel(this.lazyId);
this.lazyId = raf(() => {
if (container) {
const scrollEvent = new Event('scroll', { bubbles: true });
container.dispatchEvent(scrollEvent);
}
});
}
}
componentWillUnmount() {
raf.cancel(this.mountId);
raf.cancel(this.lazyId);
}
onItemSelect = (item: TransferItem) => {
const { onItemSelect, selectedKeys } = this.props;
const checked = selectedKeys.indexOf(item.key) >= 0;
@ -60,24 +22,16 @@ class ListBody extends React.Component<TransferListBodyProps> {
};
render() {
const { mounted } = this.state;
const {
prefixCls,
onScroll,
filteredRenderItems,
lazy,
selectedKeys,
disabled: globalDisabled,
} = this.props;
return (
<Animate
component="ul"
componentProps={{ onScroll }}
className={`${prefixCls}-content`}
transitionName={mounted ? `${prefixCls}-content-item-highlight` : ''}
transitionLeave={false}
>
<ul className={`${prefixCls}-content`} onScroll={onScroll}>
{filteredRenderItems.map(({ renderedEl, renderedText, item }: RenderedItem) => {
const { disabled } = item;
const checked = selectedKeys.indexOf(item.key) >= 0;
@ -87,7 +41,6 @@ class ListBody extends React.Component<TransferListBodyProps> {
disabled={globalDisabled || disabled}
key={item.key}
item={item}
lazy={lazy}
renderedText={renderedText}
renderedEl={renderedEl}
checked={checked}
@ -96,7 +49,7 @@ class ListBody extends React.Component<TransferListBodyProps> {
/>
);
})}
</Animate>
</ul>
);
}
}

3
components/tree/DirectoryTree.tsx

@ -4,7 +4,6 @@ import omit from 'omit.js';
import debounce from 'lodash/debounce';
import { conductExpandParent } from 'rc-tree/lib/util';
import { convertDataToEntities, convertTreeToData } from 'rc-tree/lib/utils/treeUtil';
import { polyfill } from 'react-lifecycles-compat';
import { FileOutlined, FolderOpenOutlined, FolderOutlined } from '@ant-design/icons';
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
@ -243,6 +242,4 @@ class DirectoryTree extends React.Component<DirectoryTreeProps, DirectoryTreeSta
}
}
polyfill(DirectoryTree);
export default DirectoryTree;

3
components/typography/Base.tsx

@ -1,6 +1,5 @@
import * as React from 'react';
import classNames from 'classnames';
import { polyfill } from 'react-lifecycles-compat';
import toArray from 'rc-util/lib/Children/toArray';
import findDOMNode from 'rc-util/lib/Dom/findDOMNode';
import copy from 'copy-to-clipboard';
@ -485,8 +484,6 @@ class Base extends React.Component<InternalBlockProps & ConfigConsumerProps, Bas
}
}
polyfill(Base);
export default withConfigConsumer<InternalBlockProps>({
prefixCls: 'typography',
})(Base);

3
components/typography/Editable.tsx

@ -1,6 +1,5 @@
import * as React from 'react';
import KeyCode from 'rc-util/lib/KeyCode';
import { polyfill } from 'react-lifecycles-compat';
import { EnterOutlined } from '@ant-design/icons';
import TextArea from '../input/TextArea';
@ -134,6 +133,4 @@ class Editable extends React.Component<EditableProps, EditableState> {
}
}
polyfill(Editable);
export default Editable;

3
components/upload/Upload.tsx

@ -1,5 +1,4 @@
import * as React from 'react';
import { polyfill } from 'react-lifecycles-compat';
import RcUpload from 'rc-upload';
import classNames from 'classnames';
import uniqBy from 'lodash/uniqBy';
@ -377,6 +376,4 @@ class Upload extends React.Component<UploadProps, UploadState> {
}
}
polyfill(Upload);
export default Upload;

566
components/upload/__tests__/__snapshots__/demo.test.js.snap

@ -6,7 +6,50 @@ exports[`renders ./components/upload/demo/avatar.md correctly 1`] = `
>
<div
class="ant-upload ant-upload-select ant-upload-select-picture-card"
/>
>
<span
class="ant-upload"
role="button"
tabindex="0"
>
<input
accept=""
style="display:none"
type="file"
/>
<div>
<span
aria-label="plus"
class="anticon anticon-plus"
role="img"
>
<svg
aria-hidden="true"
class=""
data-icon="plus"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<defs />
<path
d="M482 152h60q8 0 8 8v704q0 8-8 8h-60q-8 0-8-8V160q0-8 8-8z"
/>
<path
d="M176 474h672q8 0 8 8v60q0 8-8 8H176q-8 0-8-8v-60q0-8 8-8z"
/>
</svg>
</span>
<div
class="ant-upload-text"
>
Upload
</div>
</div>
</span>
</div>
</span>
`;
@ -16,7 +59,47 @@ exports[`renders ./components/upload/demo/basic.md correctly 1`] = `
>
<div
class="ant-upload ant-upload-select ant-upload-select-text"
/>
>
<span
class="ant-upload"
role="button"
tabindex="0"
>
<input
accept=""
style="display:none"
type="file"
/>
<button
class="ant-btn"
type="button"
>
<span
aria-label="upload"
class="anticon anticon-upload"
role="img"
>
<svg
aria-hidden="true"
class=""
data-icon="upload"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M400 317.7h73.9V656c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V317.7H624c6.7 0 10.4-7.7 6.3-12.9L518.3 163a8 8 0 00-12.6 0l-112 141.7c-4.1 5.3-.4 13 6.3 13zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"
/>
</svg>
</span>
<span>
Click to Upload
</span>
</button>
</span>
</div>
<div
class="ant-upload-list ant-upload-list-text"
/>
@ -29,7 +112,47 @@ exports[`renders ./components/upload/demo/defaultFileList.md correctly 1`] = `
>
<div
class="ant-upload ant-upload-select ant-upload-select-text"
/>
>
<span
class="ant-upload"
role="button"
tabindex="0"
>
<input
accept=""
style="display:none"
type="file"
/>
<button
class="ant-btn"
type="button"
>
<span
aria-label="upload"
class="anticon anticon-upload"
role="img"
>
<svg
aria-hidden="true"
class=""
data-icon="upload"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M400 317.7h73.9V656c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V317.7H624c6.7 0 10.4-7.7 6.3-12.9L518.3 163a8 8 0 00-12.6 0l-112 141.7c-4.1 5.3-.4 13 6.3 13zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"
/>
</svg>
</span>
<span>
Upload
</span>
</button>
</span>
</div>
<div
class="ant-upload-list ant-upload-list-text"
>
@ -318,7 +441,49 @@ exports[`renders ./components/upload/demo/directory.md correctly 1`] = `
>
<div
class="ant-upload ant-upload-select ant-upload-select-text"
/>
>
<span
class="ant-upload"
role="button"
tabindex="0"
>
<input
accept=""
directory="directory"
style="display:none"
type="file"
webkitdirectory="webkitdirectory"
/>
<button
class="ant-btn"
type="button"
>
<span
aria-label="upload"
class="anticon anticon-upload"
role="img"
>
<svg
aria-hidden="true"
class=""
data-icon="upload"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M400 317.7h73.9V656c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V317.7H624c6.7 0 10.4-7.7 6.3-12.9L518.3 163a8 8 0 00-12.6 0l-112 141.7c-4.1 5.3-.4 13 6.3 13zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"
/>
</svg>
</span>
<span>
Upload Directory
</span>
</button>
</span>
</div>
<div
class="ant-upload-list ant-upload-list-text"
/>
@ -329,7 +494,58 @@ exports[`renders ./components/upload/demo/drag.md correctly 1`] = `
<span>
<div
class="ant-upload ant-upload-drag"
/>
>
<span
class="ant-upload ant-upload-btn"
role="button"
tabindex="0"
>
<input
accept=""
multiple=""
style="display:none"
type="file"
/>
<div
class="ant-upload-drag-container"
>
<p
class="ant-upload-drag-icon"
>
<span
aria-label="inbox"
class="anticon anticon-inbox"
role="img"
>
<svg
aria-hidden="true"
class=""
data-icon="inbox"
fill="currentColor"
focusable="false"
height="1em"
viewBox="0 0 1024 1024"
width="1em"
>
<path
d="M885.2 446.3l-.2-.8-112.2-285.1c-5-16.1-19.9-27.2-36.8-27.2H281.2c-17 0-32.1 11.3-36.9 27.6L139.4 443l-.3.7-.2.8c-1.3 4.9-1.7 9.9-1 14.8-.1 1.6-.2 3.2-.2 4.8V830a60.9 60.9 0 0060.8 60.8h627.2c33.5 0 60.8-27.3 60.9-60.8V464.1c0-1.3 0-2.6-.1-3.7.4-4.9 0-9.6-1.3-14.1zm-295.8-43l-.3 15.7c-.8 44.9-31.8 75.1-77.1 75.1-22.1 0-41.1-7.1-54.8-20.6S436 441.2 435.6 419l-.3-15.7H229.5L309 210h399.2l81.7 193.3H589.4zm-375 76.8h157.3c24.3 57.1 76 90.8 140.4 90.8 33.7 0 65-9.4 90.3-27.2 22.2-15.6 39.5-37.4 50.7-63.6h156.5V814H214.4V480.1z"
/>
</svg>
</span>
</p>
<p
class="ant-upload-text"
>
Click or drag file to this area to upload
</p>
<p
class="ant-upload-hint"
>
Support for a single or bulk upload. Strictly prohibit from uploading company data or other band files
</p>
</div>
</span>
</div>
<div
class="ant-upload-list ant-upload-list-text"
/>
@ -342,7 +558,48 @@ exports[`renders ./components/upload/demo/fileList.md correctly 1`] = `
>
<div
class="ant-upload ant-upload-select ant-upload-select-text"
/>
>
<span
class="ant-upload"
role="button"
tabindex="0"
>
<input
accept=""
multiple=""
style="display:none"
type="file"
/>
<button
class="ant-btn"
type="button"
>
<span
aria-label="upload"
class="anticon anticon-upload"
role="img"
>
<svg
aria-hidden="true"
class=""
data-icon="upload"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M400 317.7h73.9V656c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V317.7H624c6.7 0 10.4-7.7 6.3-12.9L518.3 163a8 8 0 00-12.6 0l-112 141.7c-4.1 5.3-.4 13 6.3 13zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"
/>
</svg>
</span>
<span>
Upload
</span>
</button>
</span>
</div>
<div
class="ant-upload-list ant-upload-list-text"
>
@ -1022,7 +1279,50 @@ exports[`renders ./components/upload/demo/picture-card.md correctly 1`] = `
</div>
<div
class="ant-upload ant-upload-select ant-upload-select-picture-card"
/>
>
<span
class="ant-upload"
role="button"
tabindex="0"
>
<input
accept=""
style="display:none"
type="file"
/>
<div>
<span
aria-label="plus"
class="anticon anticon-plus"
role="img"
>
<svg
aria-hidden="true"
class=""
data-icon="plus"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<defs />
<path
d="M482 152h60q8 0 8 8v704q0 8-8 8h-60q-8 0-8-8V160q0-8 8-8z"
/>
<path
d="M176 474h672q8 0 8 8v60q0 8-8 8H176q-8 0-8-8v-60q0-8 8-8z"
/>
</svg>
</span>
<div
class="ant-upload-text"
>
Upload
</div>
</div>
</span>
</div>
</span>
</div>
`;
@ -1034,7 +1334,47 @@ exports[`renders ./components/upload/demo/picture-style.md correctly 1`] = `
>
<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
class="ant-btn"
type="button"
>
<span
aria-label="upload"
class="anticon anticon-upload"
role="img"
>
<svg
aria-hidden="true"
class=""
data-icon="upload"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M400 317.7h73.9V656c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V317.7H624c6.7 0 10.4-7.7 6.3-12.9L518.3 163a8 8 0 00-12.6 0l-112 141.7c-4.1 5.3-.4 13 6.3 13zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"
/>
</svg>
</span>
<span>
Upload
</span>
</button>
</span>
</div>
<div
class="ant-upload-list ant-upload-list-picture"
>
@ -1227,7 +1567,47 @@ exports[`renders ./components/upload/demo/picture-style.md correctly 1`] = `
>
<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
class="ant-btn"
type="button"
>
<span
aria-label="upload"
class="anticon anticon-upload"
role="img"
>
<svg
aria-hidden="true"
class=""
data-icon="upload"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M400 317.7h73.9V656c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V317.7H624c6.7 0 10.4-7.7 6.3-12.9L518.3 163a8 8 0 00-12.6 0l-112 141.7c-4.1 5.3-.4 13 6.3 13zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"
/>
</svg>
</span>
<span>
Upload
</span>
</button>
</span>
</div>
<div
class="ant-upload-list ant-upload-list-picture"
>
@ -1423,7 +1803,47 @@ exports[`renders ./components/upload/demo/preview-file.md correctly 1`] = `
>
<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
class="ant-btn"
type="button"
>
<span
aria-label="upload"
class="anticon anticon-upload"
role="img"
>
<svg
aria-hidden="true"
class=""
data-icon="upload"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M400 317.7h73.9V656c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V317.7H624c6.7 0 10.4-7.7 6.3-12.9L518.3 163a8 8 0 00-12.6 0l-112 141.7c-4.1 5.3-.4 13 6.3 13zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"
/>
</svg>
</span>
<span>
Upload
</span>
</button>
</span>
</div>
<div
class="ant-upload-list ant-upload-list-picture"
/>
@ -1438,7 +1858,47 @@ exports[`renders ./components/upload/demo/transform-file.md correctly 1`] = `
>
<div
class="ant-upload ant-upload-select ant-upload-select-text"
/>
>
<span
class="ant-upload"
role="button"
tabindex="0"
>
<input
accept=""
style="display:none"
type="file"
/>
<button
class="ant-btn"
type="button"
>
<span
aria-label="upload"
class="anticon anticon-upload"
role="img"
>
<svg
aria-hidden="true"
class=""
data-icon="upload"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M400 317.7h73.9V656c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V317.7H624c6.7 0 10.4-7.7 6.3-12.9L518.3 163a8 8 0 00-12.6 0l-112 141.7c-4.1 5.3-.4 13 6.3 13zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"
/>
</svg>
</span>
<span>
Upload
</span>
</button>
</span>
</div>
<div
class="ant-upload-list ant-upload-list-text"
/>
@ -1453,7 +1913,47 @@ exports[`renders ./components/upload/demo/upload-manually.md correctly 1`] = `
>
<div
class="ant-upload ant-upload-select ant-upload-select-text"
/>
>
<span
class="ant-upload"
role="button"
tabindex="0"
>
<input
accept=""
style="display:none"
type="file"
/>
<button
class="ant-btn"
type="button"
>
<span
aria-label="upload"
class="anticon anticon-upload"
role="img"
>
<svg
aria-hidden="true"
class=""
data-icon="upload"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M400 317.7h73.9V656c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V317.7H624c6.7 0 10.4-7.7 6.3-12.9L518.3 163a8 8 0 00-12.6 0l-112 141.7c-4.1 5.3-.4 13 6.3 13zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"
/>
</svg>
</span>
<span>
Select File
</span>
</button>
</span>
</div>
<div
class="ant-upload-list ant-upload-list-text"
/>
@ -1500,7 +2000,47 @@ exports[`renders ./components/upload/demo/upload-with-aliyun-oss.md correctly 1`
>
<div
class="ant-upload ant-upload-select ant-upload-select-text"
/>
>
<span
class="ant-upload"
role="button"
tabindex="0"
>
<input
accept=""
style="display:none"
type="file"
/>
<button
class="ant-btn"
type="button"
>
<span
aria-label="upload"
class="anticon anticon-upload"
role="img"
>
<svg
aria-hidden="true"
class=""
data-icon="upload"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M400 317.7h73.9V656c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V317.7H624c6.7 0 10.4-7.7 6.3-12.9L518.3 163a8 8 0 00-12.6 0l-112 141.7c-4.1 5.3-.4 13 6.3 13zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"
/>
</svg>
</span>
<span>
Click to Upload
</span>
</button>
</span>
</div>
<div
class="ant-upload-list ant-upload-list-text"
/>

12
docs/react/getting-started.en-US.md

@ -94,23 +94,19 @@ In the real world you will need a development workflow consisting of `compile/bu
## Compatibility
Ant Design React supports all modern browsers and IE9+.
Ant Design React supports all modern browsers and IE11+.
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/opera/opera_48x48.png" alt="Opera" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Opera | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/electron/electron_48x48.png" alt="Electron" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Electron |
| --- | --- | --- | --- | --- | --- |
| IE9, IE10, IE11, Edge | last 2 versions | last 2 versions | last 2 versions | last 2 versions | last 2 versions |
We offer very limited support for IE9/10 which means some styles and animations will be mininal for them. Also, we use Flex layout in a few components.
> Note: Different than Ant Design, Ant Design Pro supports IE11+.
| IE11, Edge | last 2 versions | last 2 versions | last 2 versions | last 2 versions | last 2 versions |
Polyfills are needed for IE browsers. We recommend [babel-preset-env](https://babeljs.io/docs/en/babel-preset-env) for it. You can set `targets` config if you are using [umi](http://umijs.org/).
Ant Design 3.0 supports both React 15 and 16 but we strongly suggest React 16 for better performance and fewer bugs.
#### IE8 note
#### IE note
> We don't support IE8 after `antd@2.0`.
> We drop support of IE8 after `antd@2.0`, IE9/10 after `antd@4.0`,
## Customized Work Flow

12
docs/react/getting-started.zh-CN.md

@ -101,23 +101,19 @@ ReactDOM.render(<App />, document.getElementById('root'));
## 兼容性
Ant Design React 支持所有的现代浏览器和 IE9+。
Ant Design React 支持所有的现代浏览器和 IE11+。
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/opera/opera_48x48.png" alt="Opera" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Opera | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/electron/electron_48x48.png" alt="Electron" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Electron |
| --- | --- | --- | --- | --- | --- |
| IE9, IE10, IE11, Edge | last 2 versions | last 2 versions | last 2 versions | last 2 versions | last 2 versions |
我们对 IE9/10 提供有限度的支持,部分样式和动画在 IE9/10 下的表现会比较裸。少数组件使用到了 Flex 布局,在 IE9/10 下也会有问题。
> 注意,不同于 Ant Design,Ant Design Pro 是只支持到 IE11+ 的。
| IE11, Edge | last 2 versions | last 2 versions | last 2 versions | last 2 versions | last 2 versions |
对于 IE 系列浏览器,需要提供相应的 Polyfill 支持,建议使用 [babel-preset-env](https://babeljs.io/docs/en/babel-preset-env) 来解决浏览器兼容问题。如果你在使用 [umi](http://umijs.org/),可以直接使用 [targets](https://umijs.org/zh/config/#targets) 配置。
Ant Design 3.0 对 React 15/16 两个版本提供支持,但是我们强烈建议你升级到 React 16,以便获得更好的性能和遇到更少的问题。
#### IE8 note
#### IE note
> `antd@2.0` 之后将不再支持 IE8。
> `antd@2.0` 之后将不再支持 IE8,`antd@4.0` 之后将不再支持 IE9/10
## 自行构建

2
docs/react/introduce.en-US.md

@ -34,7 +34,7 @@ Following the Ant Design specification, we developed a React UI library `antd` t
## Environment Support
- Modern browsers and Internet Explorer 9+ (with [polyfills](https://ant.design/docs/react/getting-started#Compatibility))
- Modern browsers and Internet Explorer 11+ (with [polyfills](https://ant.design/docs/react/getting-started#Compatibility))
- Server-side Rendering
- [Electron](http://electron.atom.io/)

2
docs/react/introduce.zh-CN.md

@ -34,7 +34,7 @@ title: Ant Design of React
## 支持环境
- 现代浏览器和 IE9 及以上(需要 [polyfills](https://ant.design/docs/react/getting-started-cn#兼容性))。
- 现代浏览器和 IE11 及以上(需要 [polyfills](https://ant.design/docs/react/getting-started-cn#兼容性))。
- 支持服务端渲染。
- [Electron](https://electronjs.org/)

28
package.json

@ -86,21 +86,15 @@
"last 2 version",
"Firefox ESR",
"> 1%",
"ie >= 9"
"ie >= 11"
],
"dependencies": {
"@ant-design/create-react-context": "^0.2.4",
"@ant-design/icons": "^4.0.0-alpha.11",
"@ant-design/icons-svg": "^4.0.0-alpha.0",
"@types/react-slick": "^0.23.4",
"array-tree-filter": "^2.1.0",
"babel-runtime": "6.x",
"classnames": "~2.2.6",
"copy-to-clipboard": "^3.2.0",
"css-animation": "^1.5.0",
"dom-closest": "^0.2.0",
"dom-scroll-into-view": "^1.2.1",
"enquire.js": "^2.1.6",
"lodash": "^4.17.13",
"moment": "^2.24.0",
"omit.js": "^1.0.2",
@ -115,8 +109,8 @@
"rc-dropdown": "~3.0.0-alpha.0",
"rc-field-form": "^0.0.0-alpha.17",
"rc-input-number": "~4.5.0",
"rc-mentions": "~1.0.0-alpha.0",
"rc-menu": "~8.0.0-alpha.4",
"rc-mentions": "~1.0.0-alpha.3",
"rc-menu": "~8.0.0-alpha.7",
"rc-notification": "~3.3.1",
"rc-pagination": "~1.20.11",
"rc-picker": "^0.0.1-alpha.58",
@ -124,27 +118,27 @@
"rc-rate": "~2.5.0",
"rc-resize-observer": "^0.1.0",
"rc-select": "~10.0.0-alpha.34",
"rc-slider": "~8.7.1",
"rc-slider": "~9.0.0-alpha.0",
"rc-steps": "~3.5.0",
"rc-switch": "~1.9.0",
"rc-table": "~7.0.0-alpha.20",
"rc-tabs": "~9.7.0",
"rc-tabs": "~10.0.0-alpha.0",
"rc-time-picker": "~4.0.0-alpha.2",
"rc-tooltip": "~4.0.0-alpha.3",
"rc-tree": "~3.0.0-alpha.37",
"rc-tree-select": "~3.0.0-alpha.5",
"rc-trigger": "~4.0.0-alpha.7",
"rc-upload": "~2.9.1",
"rc-upload": "~3.0.0-alpha.0",
"rc-util": "~4.16.1",
"rc-virtual-list": "^0.0.0-alpha.25",
"react-lazy-load": "^3.0.13",
"react-lifecycles-compat": "^3.0.4",
"react-slick": "~0.25.2",
"resize-observer-polyfill": "^1.5.1",
"scroll-into-view-if-needed": "^2.2.20",
"shallowequal": "^1.1.0",
"warning": "~4.0.3"
},
"devDependencies": {
"@ant-design/bisheng-plugin": "^2.0.1",
"@ant-design/colors": "^3.2.2",
"@ant-design/tools": "^8.0.4",
"@packtracker/webpack-plugin": "^2.0.1",
@ -166,7 +160,6 @@
"babel-eslint": "^10.0.1",
"babel-plugin-add-react-displayname": "^0.0.5",
"bisheng": "~1.3.3",
"bisheng-plugin-antd": "^1.3.1",
"bisheng-plugin-description": "^0.1.4",
"bisheng-plugin-react": "^1.1.0",
"bisheng-plugin-toc": "^0.4.4",
@ -216,7 +209,6 @@
"rc-footer": "^0.6.0",
"rc-queue-anim": "^1.6.12",
"rc-scroll-anim": "^2.5.8",
"rc-trigger": "^4.0.0-alpha.5",
"rc-tween-one": "^2.4.1",
"react": "^16.9.0",
"react-color": "^2.17.3",
@ -261,11 +253,11 @@
"bundlesize": [
{
"path": "./dist/antd.min.js",
"maxSize": "540 kB"
"maxSize": "300 kB"
},
{
"path": "./dist/antd.min.css",
"maxSize": "60 kB"
"maxSize": "55 kB"
}
],
"title": "Ant Design"

2
site/theme/index.js

@ -48,7 +48,7 @@ module.exports = {
plugins: [
'bisheng-plugin-description',
'bisheng-plugin-toc?maxDepth=2&keepElem',
'bisheng-plugin-antd?injectProvider',
'@ant-design/bisheng-plugin?injectProvider',
'bisheng-plugin-react?lang=__react',
],
routes: {

5
site/theme/static/template.html

@ -20,7 +20,7 @@
}
</style>
<link rel="stylesheet/less" type="text/css" href="{{ root }}color.less" />
<script src="https://polyfill.alicdn.com/polyfill.min.js?features=default,es2015,matchMedia,Intl"></script>
<script src="https://polyfill.alicdn.com/polyfill.min.js?features=default,es2015,Intl"></script>
<script>
(function() {
function isLocalStorageNameSupported() {
@ -82,7 +82,8 @@
<div id="react-content">
{{ content | safe }}
</div>
{% for jsFile in manifest["js"] %}<script src="{{ root }}{{ jsFile }}"></script>
{% for jsFile in manifest["js"] %}
<script src="{{ root }}{{ jsFile }}"></script>
{% endfor %}
<!-- Global Site Tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-72788897-1"></script>

3
tests/__mocks__/create-react-context.js

@ -1,3 +0,0 @@
import createReactContext from '@ant-design/create-react-context/lib/implementation';
export default createReactContext;

10
tests/setup.js

@ -11,6 +11,16 @@ if (typeof window !== 'undefined') {
global.window.dispatchEvent(new Event('resize'));
};
global.window.scrollTo = () => {};
// ref: https://github.com/ant-design/ant-design/issues/18774
if (!global.window.matchMedia) {
Object.defineProperty(global.window, 'matchMedia', {
value: jest.fn(() => ({
matches: true,
addListener: () => {},
removeListener: () => {},
})),
});
}
}
// The built-in requestAnimationFrame and cancelAnimationFrame not working with jest.runFakeTimes()

11
typings/custom-typings.d.ts

@ -23,8 +23,6 @@ declare module 'rc-tabs*';
declare module 'rc-tree';
declare module 'rc-tree/lib/util';
declare module 'rc-calendar';
declare module 'rc-input-number';
declare module 'rc-collapse';
@ -51,12 +49,6 @@ declare module 'rc-switch';
declare module 'rc-upload';
declare module 'react-lazy-load';
declare module 'dom-closest';
declare module 'dom-scroll-into-view';
declare module '*.json' {
const value: any;
export const version: string;
@ -64,6 +56,3 @@ declare module '*.json' {
}
declare module 'react-copy-to-clipboard';
// https://github.com/ant-design/ant-design/pull/19254
declare module 'react-lifecycles-compat';

Loading…
Cancel
Save