Merge pull request #33163 from ant-design/master

chore: merge master into feature
This commit is contained in:
xrkffgg 2021-12-05 15:22:48 +08:00 committed by GitHub
commit a04a4efc8b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
76 changed files with 777 additions and 649 deletions

View File

@ -2,7 +2,7 @@
name: Preview Build
on:
on:
pull_request:
types: [opened, synchronize, reopened]
@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@master
uses: actions/checkout@v2
- name: cache package-lock.json
uses: actions/cache@v2
@ -22,7 +22,7 @@ jobs:
key: lock-${{ github.sha }}
- name: create package-lock.json
run: npm i --package-lock-only
run: npm i --package-lock-only --ignore-scripts
- name: hack for single file
run: |
@ -47,7 +47,7 @@ jobs:
needs: setup
steps:
- name: checkout
uses: actions/checkout@master
uses: actions/checkout@v2
- name: restore cache from package-lock.json
uses: actions/cache@v2

View File

@ -1,6 +1,6 @@
name: Automatic Rebase
on:
on:
issue_comment:
types: [created]
@ -10,7 +10,7 @@ jobs:
if: github.event.issue.pull_request != '' && (contains(github.event.comment.body, '/rebase') || contains(github.event.comment.body, '\rebase'))
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Automatic Rebase

View File

@ -10,7 +10,7 @@ jobs:
if: github.event.ref_type == 'tag' && (contains(github.event.ref, '-') == false)
steps:
- name: checkout
uses: actions/checkout@master
uses: actions/checkout@v2
- name: cache package-lock.json
uses: actions/cache@v2
@ -19,7 +19,7 @@ jobs:
key: lock-${{ github.sha }}
- name: create package-lock.json
run: npm i --package-lock-only
run: npm i --package-lock-only --ignore-scripts
- name: hack for single file
run: |
@ -43,7 +43,7 @@ jobs:
needs: setup
steps:
- name: checkout
uses: actions/checkout@master
uses: actions/checkout@v2
- name: restore cache from package-lock.json
uses: actions/cache@v2

View File

@ -9,7 +9,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@master
uses: actions/checkout@v2
- name: cache package-lock.json
uses: actions/cache@v2
@ -18,7 +18,7 @@ jobs:
key: lock-${{ github.sha }}
- name: create package-lock.json
run: npm i --package-lock-only
run: npm i --package-lock-only --ignore-scripts
- name: hack for single file
run: |
@ -41,7 +41,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@master
uses: actions/checkout@v2
- name: restore cache from package-lock.json
uses: actions/cache@v2
@ -78,7 +78,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@master
uses: actions/checkout@v2
- name: restore cache from package-lock.json
uses: actions/cache@v2
@ -100,7 +100,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@master
uses: actions/checkout@v2
- name: restore cache from package-lock.json
uses: actions/cache@v2
@ -122,7 +122,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@master
uses: actions/checkout@v2
- name: restore cache from package-lock.json
uses: actions/cache@v2
@ -145,7 +145,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@master
uses: actions/checkout@v2
- name: restore cache from package-lock.json
uses: actions/cache@v2
@ -171,7 +171,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@master
uses: actions/checkout@v2
- name: restore cache from package-lock.json
uses: actions/cache@v2
@ -194,7 +194,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@master
uses: actions/checkout@v2
- name: restore cache from package-lock.json
uses: actions/cache@v2
@ -225,7 +225,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@master
uses: actions/checkout@v2
- name: restore cache from package-lock.json
uses: actions/cache@v2
@ -256,7 +256,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@master
uses: actions/checkout@v2
- name: restore cache from package-lock.json
uses: actions/cache@v2
@ -296,7 +296,7 @@ jobs:
REACT: 16
steps:
- name: checkout
uses: actions/checkout@master
uses: actions/checkout@v2
- name: restore cache from package-lock.json
uses: actions/cache@v2
@ -324,7 +324,7 @@ jobs:
REACT: 16
steps:
- name: checkout
uses: actions/checkout@master
uses: actions/checkout@v2
- name: restore cache from package-lock.json
uses: actions/cache@v2
@ -352,7 +352,7 @@ jobs:
REACT: 16
steps:
- name: checkout
uses: actions/checkout@master
uses: actions/checkout@v2
- name: restore cache from package-lock.json
uses: actions/cache@v2
@ -388,7 +388,7 @@ jobs:
REACT: 16
steps:
- name: checkout
uses: actions/checkout@master
uses: actions/checkout@v2
- name: restore cache from package-lock.json
uses: actions/cache@v2
@ -424,7 +424,7 @@ jobs:
REACT: 16
steps:
- name: checkout
uses: actions/checkout@master
uses: actions/checkout@v2
- name: restore cache from package-lock.json
uses: actions/cache@v2
@ -460,7 +460,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@master
uses: actions/checkout@v2
- name: restore cache from package-lock.json
uses: actions/cache@v2
@ -496,4 +496,4 @@ jobs:
- name: lessc mixins
run: npx lessc --js ./es/style/mixins/index.less
needs: setup
needs: setup

View File

@ -12,10 +12,33 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@master
uses: actions/checkout@v2
- name: cache package-lock.json
uses: actions/cache@v2
with:
path: package-temp-dir
key: lock-${{ github.sha }}
- name: create package-lock.json
run: npm i --package-lock-only --ignore-scripts
- name: hack for single file
run: |
if [ ! -d "package-temp-dir" ]; then
mkdir package-temp-dir
fi
cp package-lock.json package-temp-dir
- name: cache node_modules
id: node_modules_cache_id
uses: actions/cache@v2
with:
path: node_modules
key: node_modules-${{ hashFiles('**/package-temp-dir/package-lock.json') }}
- name: install
run: npm install
if: steps.node_modules_cache_id.outputs.cache-hit != 'true'
run: npm ci
- name: test
run: npm run test-image

View File

@ -42,7 +42,7 @@ Uma solução empresarial de design e biblioteca UI para React.
[bundlesize-css-image]: https://img.badgesize.io/https:/unpkg.com/antd/dist/antd.min.css?label=antd.min.css&compression=gzip&style=flat-square
[unpkg-js-url]: https://unpkg.com/browse/antd/dist/antd.min.js
[unpkg-css-url]: https://unpkg.com/browse/antd/dist/antd.min.css
[issues-helper-image]: https://img.shields.io/badge/Issues%20Manage%20By-issues--helper-orange?style=flat-square
[issues-helper-image]: https://img.shields.io/badge/using-issues--helper-orange?style=flat-square
[issues-helper-url]: https://github.com/actions-cool/issues-helper
</div>

View File

@ -42,7 +42,7 @@
[bundlesize-css-image]: https://img.badgesize.io/https:/unpkg.com/antd/dist/antd.min.css?label=antd.min.css&compression=gzip&style=flat-square
[unpkg-js-url]: https://unpkg.com/browse/antd/dist/antd.min.js
[unpkg-css-url]: https://unpkg.com/browse/antd/dist/antd.min.css
[issues-helper-image]: https://img.shields.io/badge/Issues%20Manage%20By-issues--helper-orange?style=flat-square
[issues-helper-image]: https://img.shields.io/badge/using-issues--helper-orange?style=flat-square
[issues-helper-url]: https://github.com/actions-cool/issues-helper
</div>

View File

@ -42,7 +42,7 @@
[bundlesize-css-image]: https://img.badgesize.io/https:/unpkg.com/antd/dist/antd.min.css?label=antd.min.css&compression=gzip&style=flat-square
[unpkg-js-url]: https://unpkg.com/browse/antd/dist/antd.min.js
[unpkg-css-url]: https://unpkg.com/browse/antd/dist/antd.min.css
[issues-helper-image]: https://img.shields.io/badge/Issues%20Manage%20By-issues--helper-orange?style=flat-square
[issues-helper-image]: https://img.shields.io/badge/using-issues--helper-orange?style=flat-square
[issues-helper-url]: https://github.com/actions-cool/issues-helper
</div>

View File

@ -4,6 +4,7 @@ import Affix, { AffixProps, AffixState } from '..';
import { getObserverEntities } from '../utils';
import Button from '../../button';
import rtlTest from '../../../tests/shared/rtlTest';
import accessibilityTest from '../../../tests/shared/accessibilityTest';
import { sleep } from '../../../tests/utils';
const events: Partial<Record<keyof HTMLElementEventMap, (ev: Partial<Event>) => void>> = {};
@ -53,6 +54,7 @@ class AffixMounter extends React.Component<{
describe('Affix Render', () => {
rtlTest(Affix);
accessibilityTest(Affix);
const domMock = jest.spyOn(HTMLElement.prototype, 'getBoundingClientRect');
let affixMounterWrapper: ReactWrapper<unknown, unknown, AffixMounter>;

View File

@ -92,10 +92,7 @@ class Affix extends React.Component<AffixProps, AffixState> {
componentDidUpdate(prevProps: AffixProps) {
const { prevTarget } = this.state;
const targetFunc = this.getTargetFunc();
let newTarget = null;
if (targetFunc) {
newTarget = targetFunc() || null;
}
const newTarget = targetFunc?.() || null;
if (prevTarget !== newTarget) {
removeObserveTarget(this);
@ -128,12 +125,8 @@ class Affix extends React.Component<AffixProps, AffixState> {
}
getOffsetTop = () => {
const { offsetBottom } = this.props;
let { offsetTop } = this.props;
if (offsetBottom === undefined && offsetTop === undefined) {
offsetTop = 0;
}
return offsetTop;
const { offsetBottom, offsetTop } = this.props;
return (offsetBottom === undefined && offsetTop === undefined) ? 0 : offsetTop;
};
getOffsetBottom = () => this.props.offsetBottom;

View File

@ -1,77 +1,238 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Alert action of Alert custom action 1`] = `
<div
class="ant-alert ant-alert-success"
data-show="true"
role="alert"
<Alert
action={
<Button
size="small"
type="text"
>
UNDO
</Button>
}
closable={true}
message="Success Tips"
showIcon={true}
type="success"
>
<span
aria-label="check-circle"
class="anticon anticon-check-circle ant-alert-icon"
role="img"
<CSSMotion
motionAppear={false}
motionEnter={false}
motionName="ant-alert-motion"
onLeaveStart={[Function]}
visible={true}
>
<svg
aria-hidden="true"
data-icon="check-circle"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm193.5 301.7l-210.6 292a31.8 31.8 0 01-51.7 0L318.5 484.9c-3.8-5.3 0-12.7 6.5-12.7h46.9c10.2 0 19.9 4.9 25.9 13.3l71.2 98.8 157.2-218c6-8.3 15.6-13.3 25.9-13.3H699c6.5 0 10.3 7.4 6.5 12.7z"
/>
</svg>
</span>
<div
class="ant-alert-content"
>
<div
class="ant-alert-message"
>
Success Tips
</div>
</div>
<div
class="ant-alert-action"
>
<button
class="ant-btn ant-btn-text ant-btn-sm"
type="button"
>
<span>
UNDO
</span>
</button>
</div>
<button
class="ant-alert-close-icon"
tabindex="0"
type="button"
>
<span
aria-label="close"
class="anticon anticon-close"
role="img"
>
<svg
aria-hidden="true"
data-icon="close"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
<DomWrapper>
<div
className="ant-alert ant-alert-success"
data-show={true}
role="alert"
style={Object {}}
>
<path
d="M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 00203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z"
/>
</svg>
</span>
</button>
</div>
<ForwardRef(CheckCircleFilled)
className="ant-alert-icon"
>
<AntdIcon
className="ant-alert-icon"
icon={
Object {
"icon": Object {
"attrs": Object {
"focusable": "false",
"viewBox": "64 64 896 896",
},
"children": Array [
Object {
"attrs": Object {
"d": "M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm193.5 301.7l-210.6 292a31.8 31.8 0 01-51.7 0L318.5 484.9c-3.8-5.3 0-12.7 6.5-12.7h46.9c10.2 0 19.9 4.9 25.9 13.3l71.2 98.8 157.2-218c6-8.3 15.6-13.3 25.9-13.3H699c6.5 0 10.3 7.4 6.5 12.7z",
},
"tag": "path",
},
],
"tag": "svg",
},
"name": "check-circle",
"theme": "filled",
}
}
>
<span
aria-label="check-circle"
className="anticon anticon-check-circle ant-alert-icon"
role="img"
>
<IconReact
icon={
Object {
"icon": Object {
"attrs": Object {
"focusable": "false",
"viewBox": "64 64 896 896",
},
"children": Array [
Object {
"attrs": Object {
"d": "M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm193.5 301.7l-210.6 292a31.8 31.8 0 01-51.7 0L318.5 484.9c-3.8-5.3 0-12.7 6.5-12.7h46.9c10.2 0 19.9 4.9 25.9 13.3l71.2 98.8 157.2-218c6-8.3 15.6-13.3 25.9-13.3H699c6.5 0 10.3 7.4 6.5 12.7z",
},
"tag": "path",
},
],
"tag": "svg",
},
"name": "check-circle",
"theme": "filled",
}
}
>
<svg
aria-hidden="true"
data-icon="check-circle"
fill="currentColor"
focusable="false"
height="1em"
key="svg-check-circle"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm193.5 301.7l-210.6 292a31.8 31.8 0 01-51.7 0L318.5 484.9c-3.8-5.3 0-12.7 6.5-12.7h46.9c10.2 0 19.9 4.9 25.9 13.3l71.2 98.8 157.2-218c6-8.3 15.6-13.3 25.9-13.3H699c6.5 0 10.3 7.4 6.5 12.7z"
key="svg-check-circle-svg-0"
/>
</svg>
</IconReact>
</span>
</AntdIcon>
</ForwardRef(CheckCircleFilled)>
<div
className="ant-alert-content"
>
<div
className="ant-alert-message"
>
Success Tips
</div>
</div>
<div
className="ant-alert-action"
>
<Button
size="small"
type="text"
>
<button
className="ant-btn ant-btn-text ant-btn-sm"
onClick={[Function]}
type="button"
>
<LoadingIcon
existIcon={false}
loading={false}
prefixCls="ant-btn"
>
<CSSMotion
motionName="ant-btn-loading-icon-motion"
onAppearActive={[Function]}
onAppearStart={[Function]}
onEnterActive={[Function]}
onEnterStart={[Function]}
onLeaveActive={[Function]}
onLeaveStart={[Function]}
removeOnLeave={true}
visible={false}
>
<DomWrapper />
</CSSMotion>
</LoadingIcon>
<span
key=".0"
>
UNDO
</span>
</button>
</Button>
</div>
<button
className="ant-alert-close-icon"
onClick={[Function]}
tabIndex={0}
type="button"
>
<ForwardRef(CloseOutlined)>
<AntdIcon
icon={
Object {
"icon": Object {
"attrs": Object {
"focusable": "false",
"viewBox": "64 64 896 896",
},
"children": Array [
Object {
"attrs": Object {
"d": "M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 00203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z",
},
"tag": "path",
},
],
"tag": "svg",
},
"name": "close",
"theme": "outlined",
}
}
>
<span
aria-label="close"
className="anticon anticon-close"
role="img"
>
<IconReact
icon={
Object {
"icon": Object {
"attrs": Object {
"focusable": "false",
"viewBox": "64 64 896 896",
},
"children": Array [
Object {
"attrs": Object {
"d": "M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 00203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z",
},
"tag": "path",
},
],
"tag": "svg",
},
"name": "close",
"theme": "outlined",
}
}
>
<svg
aria-hidden="true"
data-icon="close"
fill="currentColor"
focusable="false"
height="1em"
key="svg-close"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 00203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z"
key="svg-close-svg-0"
/>
</svg>
</IconReact>
</span>
</AntdIcon>
</ForwardRef(CloseOutlined)>
</button>
</div>
</DomWrapper>
</CSSMotion>
</Alert>
`;
exports[`Alert could accept none react element icon 1`] = `

View File

@ -1,16 +1,19 @@
import React from 'react';
import { mount, render } from 'enzyme';
import { mount } from 'enzyme';
import { act } from 'react-dom/test-utils';
import Alert from '..';
import Button from '../../button';
import Tooltip from '../../tooltip';
import Popconfirm from '../../popconfirm';
import rtlTest from '../../../tests/shared/rtlTest';
import accessibilityTest from '../../../tests/shared/accessibilityTest';
import { sleep } from '../../../tests/utils';
const { ErrorBoundary } = Alert;
describe('Alert', () => {
rtlTest(Alert);
accessibilityTest(Alert);
beforeAll(() => {
jest.useFakeTimers();
@ -30,14 +33,18 @@ describe('Alert', () => {
onClose={onClose}
/>,
);
wrapper.find('.ant-alert-close-icon').simulate('click');
jest.runAllTimers();
act(() => {
jest.useFakeTimers();
wrapper.find('.ant-alert-close-icon').simulate('click');
jest.runAllTimers();
jest.useRealTimers();
});
expect(onClose).toHaveBeenCalled();
});
describe('action of Alert', () => {
it('custom action', () => {
const wrapper = render(
const wrapper = mount(
<Alert
message="Success Tips"
type="success"
@ -141,7 +148,7 @@ describe('Alert', () => {
it('could accept none react element icon', () => {
const wrapper = mount(<Alert message="Success Tips" type="success" showIcon icon="icon" />);
expect(wrapper).toMatchRenderedSnapshot();
expect(wrapper.render()).toMatchSnapshot();
});
it('should not render message div when no message', () => {

View File

@ -291,7 +291,7 @@ export default class Anchor extends React.Component<AnchorProps, AnchorState, Co
);
const anchorClass = classNames(prefixCls, {
fixed: !affix && !showInkInFixed,
[`${prefixCls}-fixed`]: !affix && !showInkInFixed,
});
const wrapperStyle = {

View File

@ -86,7 +86,7 @@ exports[`renders ./components/anchor/demo/customizeHighlight.md correctly 1`] =
style="max-height:100vh"
>
<div
class="ant-anchor fixed"
class="ant-anchor ant-anchor-fixed"
>
<div
class="ant-anchor-ink"
@ -160,7 +160,7 @@ exports[`renders ./components/anchor/demo/onChange.md correctly 1`] = `
style="max-height:100vh"
>
<div
class="ant-anchor fixed"
class="ant-anchor ant-anchor-fixed"
>
<div
class="ant-anchor-ink"
@ -234,7 +234,7 @@ exports[`renders ./components/anchor/demo/onClick.md correctly 1`] = `
style="max-height:100vh"
>
<div
class="ant-anchor fixed"
class="ant-anchor ant-anchor-fixed"
>
<div
class="ant-anchor-ink"
@ -308,7 +308,7 @@ exports[`renders ./components/anchor/demo/static.md correctly 1`] = `
style="max-height:100vh"
>
<div
class="ant-anchor fixed"
class="ant-anchor ant-anchor-fixed"
>
<div
class="ant-anchor-ink"

View File

@ -50,7 +50,7 @@
}
}
&.fixed &-ink &-ink-ball {
&-fixed &-ink &-ink-ball {
display: none;
}

View File

@ -11,14 +11,15 @@ exports[`AutoComplete legacy dataSource should accept react element option 1`] =
class="ant-select-selection-search"
>
<input
aria-activedescendant="undefined_list_0"
aria-activedescendant="rc_select_TEST_OR_SSR_list_-1"
aria-autocomplete="list"
aria-controls="undefined_list"
aria-controls="rc_select_TEST_OR_SSR_list"
aria-expanded="true"
aria-haspopup="listbox"
aria-owns="undefined_list"
aria-owns="rc_select_TEST_OR_SSR_list"
autocomplete="off"
class="ant-select-selection-search-input"
id="rc_select_TEST_OR_SSR"
role="combobox"
type="search"
value=""
@ -30,19 +31,19 @@ exports[`AutoComplete legacy dataSource should accept react element option 1`] =
</div>
<div>
<div
class="ant-select-dropdown"
style="opacity:0;pointer-events:none"
class="ant-select-dropdown ant-slide-up-appear ant-slide-up-appear-prepare ant-slide-up"
style="opacity: 0; pointer-events: none; min-width: 0; width: 0px;"
>
<div>
<div
id="undefined_list"
id="rc_select_TEST_OR_SSR_list"
role="listbox"
style="height:0;width:0;overflow:hidden"
style="height: 0px; width: 0px; overflow: hidden;"
>
<div
aria-label="ReactNode"
aria-selected="false"
id="undefined_list_0"
id="rc_select_TEST_OR_SSR_list_0"
role="option"
>
key
@ -50,20 +51,20 @@ exports[`AutoComplete legacy dataSource should accept react element option 1`] =
</div>
<div
class="rc-virtual-list"
style="position:relative"
style="position: relative;"
>
<div
class="rc-virtual-list-holder"
style="max-height:256px;overflow-y:auto;overflow-anchor:none"
style="max-height: 256px; overflow-y: auto;"
>
<div>
<div
class="rc-virtual-list-holder-inner"
style="display:flex;flex-direction:column"
style="display: flex; flex-direction: column;"
>
<div
aria-selected="false"
class="ant-select-item ant-select-item-option ant-select-item-option-active"
class="ant-select-item ant-select-item-option"
title="ReactNode"
>
<div
@ -74,7 +75,7 @@ exports[`AutoComplete legacy dataSource should accept react element option 1`] =
<span
aria-hidden="true"
class="ant-select-item-option-state"
style="user-select:none;-webkit-user-select:none"
style="user-select: none;"
unselectable="on"
/>
</div>
@ -99,13 +100,14 @@ exports[`AutoComplete rtl render component should be rendered correctly in RTL d
class="ant-select-selection-search"
>
<input
aria-activedescendant="undefined_list_0"
aria-activedescendant="rc_select_TEST_OR_SSR_list_0"
aria-autocomplete="list"
aria-controls="undefined_list"
aria-controls="rc_select_TEST_OR_SSR_list"
aria-haspopup="listbox"
aria-owns="undefined_list"
aria-owns="rc_select_TEST_OR_SSR_list"
autocomplete="off"
class="ant-select-selection-search-input"
id="rc_select_TEST_OR_SSR"
role="combobox"
type="search"
value=""

View File

@ -56,7 +56,7 @@ describe('AutoComplete', () => {
it('legacy dataSource should accept react element option', () => {
const wrapper = mount(<AutoComplete open dataSource={[<span key="key">ReactNode</span>]} />);
expect(wrapper).toMatchRenderedSnapshot();
expect(wrapper.render()).toMatchSnapshot();
});
it('legacy AutoComplete.Option should be compatiable', () => {

View File

@ -155,7 +155,7 @@ describe('Avatar Render', () => {
it('support size is number', () => {
const wrapper = mount(<Avatar size={100}>TestString</Avatar>);
expect(wrapper).toMatchRenderedSnapshot();
expect(wrapper.render()).toMatchSnapshot();
});
Object.entries(sizes).forEach(([key, value]) => {
@ -189,7 +189,7 @@ describe('Avatar Render', () => {
);
wrapper.find('img').simulate('error');
wrapper.update();
expect(wrapper).toMatchRenderedSnapshot();
expect(wrapper.render()).toMatchSnapshot();
wrapper.detach();
global.document.body.removeChild(div);
});

View File

@ -86,11 +86,14 @@ exports[`Avatar Render adjusts component size to 100 when window size is xxl 1`]
exports[`Avatar Render fallback 1`] = `
<span
class="ant-avatar ant-avatar-circle ant-avatar-image"
class="ant-avatar ant-avatar-circle"
>
<img
src="http://error.url"
/>
<span
class="ant-avatar-string"
style="transform: scale(1) translateX(-50%);"
>
A
</span>
</span>
`;
@ -100,7 +103,7 @@ exports[`Avatar Render rtl render component should be rendered correctly in RTL
>
<span
class="ant-avatar-string"
style="opacity:0"
style="transform: scale(0.72) translateX(-50%);"
/>
</span>
`;
@ -229,11 +232,11 @@ exports[`Avatar Render should show image on success after a failure state 2`] =
exports[`Avatar Render support size is number 1`] = `
<span
class="ant-avatar ant-avatar-circle"
style="width:100px;height:100px;line-height:100px;font-size:18px"
style="width: 100px; height: 100px; line-height: 100px; font-size: 18px;"
>
<span
class="ant-avatar-string"
style="opacity:0"
style="line-height: 100px; transform: scale(0.32) translateX(-50%);"
>
TestString
</span>

View File

@ -173,12 +173,12 @@ exports[`Badge rtl render component should be rendered correctly in RTL directio
<sup
class="ant-scroll-number ant-badge-count"
data-show="true"
style="margin-top:10px;left:10px"
style="margin-top: 10px; left: 10px;"
title="5"
>
<span
class="ant-scroll-number-only"
style="transition:none"
style="transition: none;"
>
<span
class="ant-scroll-number-only-unit current"

View File

@ -69,63 +69,18 @@ exports[`Button renders Chinese characters correctly 2`] = `
`;
exports[`Button renders Chinese characters correctly 3`] = `
<button
class="ant-btn"
type="button"
>
<span
aria-label="search"
class="anticon anticon-search"
role="img"
>
<svg
aria-hidden="true"
data-icon="search"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M909.6 854.5L649.9 594.8C690.2 542.7 712 479 712 412c0-80.2-31.3-155.4-87.9-212.1-56.6-56.7-132-87.9-212.1-87.9s-155.5 31.3-212.1 87.9C143.2 256.5 112 331.8 112 412c0 80.1 31.3 155.5 87.9 212.1C256.5 680.8 331.8 712 412 712c67 0 130.6-21.8 182.7-62l259.7 259.6a8.2 8.2 0 0011.6 0l43.6-43.5a8.2 8.2 0 000-11.6zM570.4 570.4C528 612.7 471.8 636 412 636s-116-23.3-158.4-65.6C211.3 528 188 471.8 188 412s23.3-116.1 65.6-158.4C296 211.3 352.2 188 412 188s116.1 23.2 158.4 65.6S636 352.2 636 412s-23.3 116.1-65.6 158.4z"
/>
</svg>
</span>
<span>
按钮
</span>
</button>
<Button>
<ForwardRef(SearchOutlined) />
按钮
</Button>
`;
exports[`Button renders Chinese characters correctly 4`] = `
<button
class="ant-btn"
type="button"
<Button
icon={<ForwardRef(SearchOutlined) />}
>
<span
aria-label="search"
class="anticon anticon-search"
role="img"
>
<svg
aria-hidden="true"
data-icon="search"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M909.6 854.5L649.9 594.8C690.2 542.7 712 479 712 412c0-80.2-31.3-155.4-87.9-212.1-56.6-56.7-132-87.9-212.1-87.9s-155.5 31.3-212.1 87.9C143.2 256.5 112 331.8 112 412c0 80.1 31.3 155.5 87.9 212.1C256.5 680.8 331.8 712 412 712c67 0 130.6-21.8 182.7-62l259.7 259.6a8.2 8.2 0 0011.6 0l43.6-43.5a8.2 8.2 0 000-11.6zM570.4 570.4C528 612.7 471.8 636 412 636s-116-23.3-158.4-65.6C211.3 528 188 471.8 188 412s23.3-116.1 65.6-158.4C296 211.3 352.2 188 412 188s116.1 23.2 158.4 65.6S636 352.2 636 412s-23.3 116.1-65.6 158.4z"
/>
</svg>
</span>
<span>
按钮
</span>
</button>
按钮
</Button>
`;
exports[`Button renders Chinese characters correctly 5`] = `
@ -169,10 +124,11 @@ exports[`Button renders Chinese characters correctly 6`] = `
>
<span
class="ant-btn-loading-icon"
style="width: 0px; opacity: 0; transform: scale(0);"
>
<span
aria-label="loading"
class="anticon anticon-loading anticon-spin"
class="anticon anticon-loading anticon-spin ant-btn-loading-icon-motion-appear ant-btn-loading-icon-motion-appear-start ant-btn-loading-icon-motion"
role="img"
>
<svg

View File

@ -28,7 +28,7 @@ describe('Button', () => {
rtlTest(() => <Button.Group size="middle" />);
it('renders correctly', () => {
expect(<Button>Follow</Button>).toMatchRenderedSnapshot();
expect(mount(<Button>Follow</Button>).render()).toMatchSnapshot();
});
it('mount correctly', () => {
@ -47,33 +47,37 @@ describe('Button', () => {
});
it('renders Chinese characters correctly', () => {
expect(<Button></Button>).toMatchRenderedSnapshot();
expect(mount(<Button></Button>).render()).toMatchSnapshot();
// should not insert space when there is icon
expect(<Button icon={<SearchOutlined />}></Button>).toMatchRenderedSnapshot();
expect(mount(<Button icon={<SearchOutlined />}></Button>).render()).toMatchSnapshot();
// should not insert space when there is icon
expect(
<Button>
<SearchOutlined />
</Button>,
).toMatchRenderedSnapshot();
).toMatchSnapshot();
// should not insert space when there is icon
expect(<Button icon={<SearchOutlined />}></Button>).toMatchRenderedSnapshot();
expect(<Button icon={<SearchOutlined />}></Button>).toMatchSnapshot();
// should not insert space when there is icon while loading
expect(
<Button icon={<SearchOutlined />} loading>
</Button>,
).toMatchRenderedSnapshot();
mount(
<Button icon={<SearchOutlined />} loading>
</Button>,
).render(),
).toMatchSnapshot();
// should insert space while loading
expect(<Button loading></Button>).toMatchRenderedSnapshot();
expect(mount(<Button loading></Button>).render()).toMatchSnapshot();
// should insert space while only one nested element
expect(
<Button>
<span></span>
</Button>,
).toMatchRenderedSnapshot();
mount(
<Button>
<span></span>
</Button>,
).render(),
).toMatchSnapshot();
});
it('renders Chinese characters correctly in HOC', () => {
@ -206,9 +210,9 @@ describe('Button', () => {
});
it('fixbug renders {0} , 0 and {false}', () => {
expect(<Button>{0}</Button>).toMatchRenderedSnapshot();
expect(<Button>0</Button>).toMatchRenderedSnapshot();
expect(<Button>{false}</Button>).toMatchRenderedSnapshot();
expect(mount(<Button>{0}</Button>).render()).toMatchSnapshot();
expect(mount(<Button>0</Button>).render()).toMatchSnapshot();
expect(mount(<Button>{false}</Button>).render()).toMatchSnapshot();
});
it('should not render as link button when href is undefined', async () => {
@ -320,6 +324,6 @@ describe('Button', () => {
<>text</>
</Button>,
);
expect(wrapper).toMatchRenderedSnapshot();
expect(wrapper.render()).toMatchSnapshot();
});
});

View File

@ -1905,16 +1905,17 @@ exports[`Calendar rtl render component should be rendered correctly in RTL direc
class="ant-select-selection-search"
>
<input
aria-activedescendant="undefined_list_0"
aria-activedescendant="rc_select_TEST_OR_SSR_list_0"
aria-autocomplete="list"
aria-controls="undefined_list"
aria-controls="rc_select_TEST_OR_SSR_list"
aria-haspopup="listbox"
aria-owns="undefined_list"
aria-owns="rc_select_TEST_OR_SSR_list"
autocomplete="off"
class="ant-select-selection-search-input"
id="rc_select_TEST_OR_SSR"
readonly=""
role="combobox"
style="opacity:0"
style="opacity: 0;"
type="search"
unselectable="on"
value=""
@ -1930,7 +1931,7 @@ exports[`Calendar rtl render component should be rendered correctly in RTL direc
<span
aria-hidden="true"
class="ant-select-arrow"
style="user-select:none;-webkit-user-select:none"
style="user-select: none;"
unselectable="on"
>
<span
@ -1964,16 +1965,17 @@ exports[`Calendar rtl render component should be rendered correctly in RTL direc
class="ant-select-selection-search"
>
<input
aria-activedescendant="undefined_list_0"
aria-activedescendant="rc_select_TEST_OR_SSR_list_0"
aria-autocomplete="list"
aria-controls="undefined_list"
aria-controls="rc_select_TEST_OR_SSR_list"
aria-haspopup="listbox"
aria-owns="undefined_list"
aria-owns="rc_select_TEST_OR_SSR_list"
autocomplete="off"
class="ant-select-selection-search-input"
id="rc_select_TEST_OR_SSR"
readonly=""
role="combobox"
style="opacity:0"
style="opacity: 0;"
type="search"
unselectable="on"
value=""
@ -1989,7 +1991,7 @@ exports[`Calendar rtl render component should be rendered correctly in RTL direc
<span
aria-hidden="true"
class="ant-select-arrow"
style="user-select:none;-webkit-user-select:none"
style="user-select: none;"
unselectable="on"
>
<span

View File

@ -12,7 +12,7 @@ exports[`Carousel rtl render component should be rendered correctly in RTL direc
>
<div
class="slick-track"
style="width:0%;left:NaN%"
style="opacity: 1; transform: translate3d(0px, 0px, 0px);"
/>
</div>
</div>

View File

@ -1264,16 +1264,17 @@ exports[`Cascader rtl render component should be rendered correctly in RTL direc
class="ant-select-selection-search"
>
<input
aria-activedescendant="undefined_list_0"
aria-activedescendant="rc_select_TEST_OR_SSR_list_0"
aria-autocomplete="list"
aria-controls="undefined_list"
aria-controls="rc_select_TEST_OR_SSR_list"
aria-haspopup="listbox"
aria-owns="undefined_list"
aria-owns="rc_select_TEST_OR_SSR_list"
autocomplete="off"
class="ant-select-selection-search-input"
id="rc_select_TEST_OR_SSR"
readonly=""
role="combobox"
style="opacity:0"
style="opacity: 0;"
type="search"
unselectable="on"
value=""
@ -1286,7 +1287,7 @@ exports[`Cascader rtl render component should be rendered correctly in RTL direc
<span
aria-hidden="true"
class="ant-select-arrow"
style="user-select:none;-webkit-user-select:none"
style="user-select: none;"
unselectable="on"
>
<span

View File

@ -10,6 +10,7 @@ exports[`Checkbox rtl render component should be rendered correctly in RTL direc
<input
class="ant-checkbox-input"
type="checkbox"
value=""
/>
<span
class="ant-checkbox-inner"

View File

@ -23,6 +23,6 @@ describe('Comment', () => {
datetime="YYYY-MM-DD HH:mm:ss"
/>,
);
expect(wrapper).toMatchRenderedSnapshot();
expect(wrapper.render()).toMatchSnapshot();
});
});

View File

@ -88,7 +88,7 @@ describe('ConfigProvider.Form', () => {
</ConfigProvider>,
);
expect(wrapper).toMatchRenderedSnapshot();
expect(wrapper.render()).toMatchSnapshot();
});
});

View File

@ -113,6 +113,6 @@ describe('ConfigProvider', () => {
</ConfigProvider>,
);
expect(wrapper).toMatchRenderedSnapshot();
expect(wrapper.render()).toMatchSnapshot();
});
});

View File

@ -87,7 +87,7 @@ describe('RangePicker', () => {
open
/>,
);
expect(wrapper).toMatchRenderedSnapshot();
expect(wrapper.render()).toMatchSnapshot();
});
});

View File

@ -118,7 +118,7 @@ Array [
</div>
<div
class="ant-picker-active-bar"
style="left:0;width:0;position:absolute"
style="left: 0px; width: 0px; position: absolute;"
/>
<span
class="ant-picker-suffix"
@ -146,20 +146,20 @@ Array [
</div>,
<div>
<div
class="ant-picker-dropdown ant-picker-dropdown-range"
style="opacity:0;pointer-events:none"
class="ant-picker-dropdown ant-picker-dropdown-range ant-slide-up-appear ant-slide-up-appear-prepare ant-slide-up"
style="opacity: 0; pointer-events: none;"
>
<div
class="ant-picker-range-wrapper ant-picker-date-range-wrapper"
style="min-width:0"
style="min-width: 0;"
>
<div
class="ant-picker-range-arrow"
style="left:0"
style="left: 0px;"
/>
<div
class="ant-picker-panel-container"
style="margin-left:0"
style="margin-left: 0px;"
>
<div
class="ant-picker-panels"
@ -212,7 +212,7 @@ Array [
</div>
<button
class="ant-picker-header-next-btn"
style="visibility:hidden"
style="visibility: hidden;"
tabindex="-1"
type="button"
>
@ -222,7 +222,7 @@ Array [
</button>
<button
class="ant-picker-header-super-next-btn"
style="visibility:hidden"
style="visibility: hidden;"
tabindex="-1"
type="button"
>
@ -712,7 +712,7 @@ Array [
>
<button
class="ant-picker-header-super-prev-btn"
style="visibility:hidden"
style="visibility: hidden;"
tabindex="-1"
type="button"
>
@ -722,7 +722,7 @@ Array [
</button>
<button
class="ant-picker-header-prev-btn"
style="visibility:hidden"
style="visibility: hidden;"
tabindex="-1"
type="button"
>

View File

@ -182,7 +182,7 @@ exports[`mount rtl render component should be rendered correctly in RTL directio
</div>
<div
class="ant-picker-active-bar"
style="right:0;width:0;position:absolute"
style="right: 0px; width: 0px; position: absolute;"
/>
<span
class="ant-picker-suffix"

View File

@ -10,8 +10,8 @@ Array [
</button>,
<div>
<div
class="ant-dropdown"
style="opacity:0;pointer-events:none"
class="ant-dropdown move-up-appear move-up-appear-prepare move-up"
style="opacity: 0; pointer-events: none;"
>
<div>
menu
@ -31,8 +31,8 @@ Array [
</button>,
<div>
<div
class="ant-dropdown"
style="opacity:0;pointer-events:none"
class="ant-dropdown ant-slide-up-appear ant-slide-up-appear-prepare ant-slide-up"
style="opacity: 0; pointer-events: none;"
>
<span>
string

View File

@ -25,7 +25,7 @@ describe('Dropdown', () => {
<button type="button">button</button>
</Dropdown>,
);
expect(wrapper).toMatchRenderedSnapshot();
expect(wrapper.render()).toMatchSnapshot();
});
it('overlay is string', () => {
@ -34,7 +34,7 @@ describe('Dropdown', () => {
<button type="button">button</button>
</Dropdown>,
);
expect(wrapper).toMatchRenderedSnapshot();
expect(wrapper.render()).toMatchSnapshot();
});
it('support Menu expandIcon', async () => {

View File

@ -796,7 +796,7 @@ describe('Form', () => {
</Form.Item>
</Form>,
);
expect(wrapper).toMatchRenderedSnapshot();
expect(wrapper.render()).toMatchSnapshot();
});
it('noStyle should not work when hidden', () => {
@ -807,7 +807,7 @@ describe('Form', () => {
</Form.Item>
</Form>,
);
expect(wrapper).toMatchRenderedSnapshot();
expect(wrapper.render()).toMatchSnapshot();
});
});

View File

@ -28,7 +28,7 @@ exports[`Layout rtl render component should be rendered correctly in RTL directi
exports[`Layout rtl render component should be rendered correctly in RTL direction 3`] = `
<aside
class="ant-layout-sider ant-layout-sider-dark"
style="flex:0 0 200px;max-width:200px;min-width:200px;width:200px"
style="flex: 0 0 200px; max-width: 200px; min-width: 200px; width: 200px;"
>
<div
class="ant-layout-sider-children"

View File

@ -1122,20 +1122,6 @@ exports[`renders ./components/list/demo/infinite-load.md correctly 1`] = `
</div>
`;
exports[`renders ./components/list/demo/infinite-virtualized-load.md correctly 1`] = `
<div
class="ant-list ant-list-split"
>
<div
class="ant-spin-nested-loading"
>
<div
class="ant-spin-container"
/>
</div>
</div>
`;
exports[`renders ./components/list/demo/loadmore.md correctly 1`] = `
<div
class="ant-list ant-list-split ant-list-loading demo-loadmore-list"
@ -2332,3 +2318,34 @@ exports[`renders ./components/list/demo/vertical.md correctly 1`] = `
</div>
</div>
`;
exports[`renders ./components/list/demo/virtual-list.md correctly 1`] = `
<div
class="ant-list ant-list-split"
>
<div
class="ant-spin-nested-loading"
>
<div
class="ant-spin-container"
>
<div
class="rc-virtual-list"
style="position:relative"
>
<div
class="rc-virtual-list-holder"
style="height:400px;overflow-y:auto;overflow-anchor:none"
>
<div>
<div
class="rc-virtual-list-holder-inner"
style="display:flex;flex-direction:column"
/>
</div>
</div>
</div>
</div>
</div>
</div>
`;

View File

@ -1,166 +0,0 @@
---
order: 7
title:
zh-CN: 滚动加载无限长列表
en-US: Infinite & virtualized
---
## zh-CN
结合 [react-virtualized](https://github.com/bvaughn/react-virtualized) 实现滚动加载无限长列表,带有虚拟化([virtualization](https://blog.jscrambler.com/optimizing-react-rendering-through-virtualization/))功能,能够提高数据量大时候长列表的性能。
`virtualized` 是在大数据列表中应用的一种技术,主要是为了减少不可见区域不必要的渲染从而提高性能,特别是数据量在成千上万条效果尤为明显。[了解更多](https://blog.jscrambler.com/optimizing-react-rendering-through-virtualization/)
## en-US
An example of infinite list & virtualized loading using [react-virtualized](https://github.com/bvaughn/react-virtualized). [Learn more](https://blog.jscrambler.com/optimizing-react-rendering-through-virtualization/).
`Virtualized` rendering is a technique to mount big sets of data. It reduces the amount of rendered DOM nodes by tracking and hiding whatever isn't currently visible.
```jsx
import { List, message, Avatar, Spin } from 'antd';
import reqwest from 'reqwest';
import WindowScroller from 'react-virtualized/dist/commonjs/WindowScroller';
import AutoSizer from 'react-virtualized/dist/commonjs/AutoSizer';
import VList from 'react-virtualized/dist/commonjs/List';
import InfiniteLoader from 'react-virtualized/dist/commonjs/InfiniteLoader';
const fakeDataUrl = 'https://randomuser.me/api/?results=5&inc=name,gender,email,nat,picture&noinfo';
class VirtualizedExample extends React.Component {
state = {
data: [],
loading: false,
};
loadedRowsMap = {};
componentDidMount() {
this.fetchData(res => {
this.setState({
data: res.results,
});
});
}
fetchData = callback => {
reqwest({
url: fakeDataUrl,
type: 'json',
method: 'get',
contentType: 'application/json',
success: res => {
callback(res);
},
});
};
handleInfiniteOnLoad = ({ startIndex, stopIndex }) => {
let { data } = this.state;
this.setState({
loading: true,
});
for (let i = startIndex; i <= stopIndex; i++) {
// 1 means loading
this.loadedRowsMap[i] = 1;
}
if (data.length > 19) {
message.warning('Virtualized List loaded all');
this.setState({
loading: false,
});
return;
}
this.fetchData(res => {
data = data.concat(res.results);
this.setState({
data,
loading: false,
});
});
};
isRowLoaded = ({ index }) => !!this.loadedRowsMap[index];
renderItem = ({ index, key, style }) => {
const { data } = this.state;
const item = data[index];
return (
<List.Item key={key} style={style}>
<List.Item.Meta
avatar={<Avatar src={item.picture.large} />}
title={<a href="https://ant.design">{item.name.last}</a>}
description={item.email}
/>
<div>Content</div>
</List.Item>
);
};
render() {
const { data } = this.state;
const vlist = ({ height, isScrolling, onChildScroll, scrollTop, onRowsRendered, width }) => (
<VList
autoHeight
height={height}
isScrolling={isScrolling}
onScroll={onChildScroll}
overscanRowCount={2}
rowCount={data.length}
rowHeight={73}
rowRenderer={this.renderItem}
onRowsRendered={onRowsRendered}
scrollTop={scrollTop}
width={width}
/>
);
const autoSize = ({ height, isScrolling, onChildScroll, scrollTop, onRowsRendered }) => (
<AutoSizer disableHeight>
{({ width }) =>
vlist({
height,
isScrolling,
onChildScroll,
scrollTop,
onRowsRendered,
width,
})
}
</AutoSizer>
);
const infiniteLoader = ({ height, isScrolling, onChildScroll, scrollTop }) => (
<InfiniteLoader
isRowLoaded={this.isRowLoaded}
loadMoreRows={this.handleInfiniteOnLoad}
rowCount={data.length}
>
{({ onRowsRendered }) =>
autoSize({
height,
isScrolling,
onChildScroll,
scrollTop,
onRowsRendered,
})
}
</InfiniteLoader>
);
return (
<List>
{data.length > 0 && <WindowScroller>{infiniteLoader}</WindowScroller>}
{this.state.loading && <Spin className="demo-loading" />}
</List>
);
}
}
ReactDOM.render(<VirtualizedExample />, mountNode);
```
```css
.demo-loading {
position: absolute;
bottom: -40px;
left: 50%;
}
```

View File

@ -15,7 +15,6 @@ Load more list with `loadMore` property.
```jsx
import { List, Avatar, Button, Skeleton } from 'antd';
import reqwest from 'reqwest';
const count = 3;
const fakeDataUrl = `https://randomuser.me/api/?results=${count}&inc=name,gender,email,nat,picture&noinfo`;
@ -29,27 +28,17 @@ class LoadMoreList extends React.Component {
};
componentDidMount() {
this.getData(res => {
this.setState({
initLoading: false,
data: res.results,
list: res.results,
fetch(fakeDataUrl)
.then(res => res.json())
.then(res => {
this.setState({
initLoading: false,
data: res.results,
list: res.results,
});
});
});
}
getData = callback => {
reqwest({
url: fakeDataUrl,
type: 'json',
method: 'get',
contentType: 'application/json',
success: res => {
callback(res);
},
});
};
onLoadMore = () => {
this.setState({
loading: true,
@ -57,22 +46,24 @@ class LoadMoreList extends React.Component {
[...new Array(count)].map(() => ({ loading: true, name: {}, picture: {} })),
),
});
this.getData(res => {
const data = this.state.data.concat(res.results);
this.setState(
{
data,
list: data,
loading: false,
},
() => {
// Resetting window's offsetTop so as to display react-virtualized demo underfloor.
// In real scene, you can using public method of react-virtualized:
// https://stackoverflow.com/questions/46700726/how-to-use-public-method-updateposition-of-react-virtualized
window.dispatchEvent(new Event('resize'));
},
);
});
fetch(fakeDataUrl)
.then(res => res.json())
.then(res => {
const data = this.state.data.concat(res.results);
this.setState(
{
data,
list: data,
loading: false,
},
() => {
// Resetting window's offsetTop so as to display react-virtualized demo underfloor.
// In real scene, you can using public method of react-virtualized:
// https://stackoverflow.com/questions/46700726/how-to-use-public-method-updateposition-of-react-virtualized
window.dispatchEvent(new Event('resize'));
},
);
});
};
render() {
@ -98,22 +89,20 @@ class LoadMoreList extends React.Component {
itemLayout="horizontal"
loadMore={loadMore}
dataSource={list}
renderItem={item =>
console.log(item) || (
<List.Item
actions={[<a key="list-loadmore-edit">edit</a>, <a key="list-loadmore-more">more</a>]}
>
<Skeleton avatar title={false} loading={item.loading} active>
<List.Item.Meta
avatar={<Avatar src={item.picture.large} />}
title={<a href="https://ant.design">{item.name.last}</a>}
description="Ant Design, a design language for background applications, is refined by Ant UED Team"
/>
<div>content</div>
</Skeleton>
</List.Item>
)
}
renderItem={item => (
<List.Item
actions={[<a key="list-loadmore-edit">edit</a>, <a key="list-loadmore-more">more</a>]}
>
<Skeleton avatar title={false} loading={item.loading} active>
<List.Item.Meta
avatar={<Avatar src={item.picture.large} />}
title={<a href="https://ant.design">{item.name.last}</a>}
description="Ant Design, a design language for background applications, is refined by Ant UED Team"
/>
<div>content</div>
</Skeleton>
</List.Item>
)}
/>
);
}

View File

@ -0,0 +1,72 @@
---
order: 7
title:
zh-CN: 滚动加载无限长列表
en-US: virtual list
---
## zh-CN
结合 [rc-virtual-list](https://github.com/react-component/virtual-list) 实现滚动加载无限长列表,能够提高数据量大时候长列表的性能。
## en-US
An example of infinite & virtualized list via using [rc-virtual-list](https://github.com/react-component/virtual-list).
```jsx
import React, { useState, useEffect } from 'react';
import { List, message, Avatar } from 'antd';
import VirtualList from 'rc-virtual-list';
const fakeDataUrl =
'https://randomuser.me/api/?results=20&inc=name,gender,email,nat,picture&noinfo';
const ContainerHeight = 400;
const VirtualizedExample = () => {
const [data, setData] = useState([]);
const appendData = () => {
fetch(fakeDataUrl)
.then(res => res.json())
.then(body => {
setData(data.concat(body.results));
message.success(`${body.results.length} more items loaded!`);
});
};
useEffect(() => {
appendData();
}, []);
const onScroll = e => {
if (e.target.scrollHeight - e.target.scrollTop === ContainerHeight) {
appendData();
}
};
return (
<List>
<VirtualList
data={data}
height={ContainerHeight}
itemHeight={47}
itemKey="email"
onScroll={onScroll}
>
{item => (
<List.Item key={item.email}>
<List.Item.Meta
avatar={<Avatar src={item.picture.large} />}
title={<a href="https://ant.design">{item.name.last}</a>}
description={item.email}
/>
<div>Content</div>
</List.Item>
)}
</VirtualList>
</List>
);
};
ReactDOM.render(<VirtualizedExample />, mountNode);
```

View File

@ -173,6 +173,7 @@ Array [
>
<li
class="ant-menu-item"
data-menu-id="rc-menu-uuid-test-tmp_key-0"
role="menuitem"
tabindex="-1"
>
@ -195,9 +196,11 @@ Array [
role="none"
>
<div
aria-controls="rc-menu-uuid-test-tmp_key-2-popup"
aria-expanded="false"
aria-haspopup="true"
class="ant-menu-submenu-title"
data-menu-id="rc-menu-uuid-test-tmp_key-2"
role="menuitem"
tabindex="-1"
>
@ -212,7 +215,7 @@ Array [
</ul>,
<div
aria-hidden="true"
style="display:none"
style="display: none;"
/>,
]
`;

View File

@ -727,7 +727,7 @@ exports[`Progress rtl render component should be rendered correctly in RTL direc
>
<div
class="ant-progress-bg"
style="width:0%;height:8px;border-radius:"
style="width: 0%; height: 8px;"
/>
</div>
</div>
@ -749,15 +749,15 @@ exports[`Progress should support steps 1`] = `
>
<div
class="ant-progress-steps-item"
style="width:14px;height:8px"
style="width: 14px; height: 8px;"
/>
<div
class="ant-progress-steps-item"
style="width:14px;height:8px"
style="width: 14px; height: 8px;"
/>
<div
class="ant-progress-steps-item"
style="width:14px;height:8px"
style="width: 14px; height: 8px;"
/>
<span
class="ant-progress-text"

View File

@ -158,7 +158,7 @@ describe('Progress', () => {
it('should support steps', () => {
const wrapper = mount(<Progress steps={3} />);
expect(wrapper).toMatchRenderedSnapshot();
expect(wrapper.render()).toMatchSnapshot();
});
it('steps should be changable', () => {

View File

@ -10,6 +10,7 @@ exports[`Radio rtl render component should be rendered correctly in RTL directio
<input
class="ant-radio-input"
type="radio"
value=""
/>
<span
class="ant-radio-inner"
@ -34,6 +35,7 @@ exports[`Radio rtl render component should be rendered correctly in RTL directio
<input
class="ant-radio-button-input"
type="radio"
value=""
/>
<span
class="ant-radio-button-inner"

View File

@ -81,15 +81,17 @@
&-inner {
&::after {
position: absolute;
top: ((@radio-size - @radio-dot-size) / 2) - @radio-border-width;
left: ((@radio-size - @radio-dot-size) / 2) - @radio-border-width;
top: 50%;
left: 50%;
display: block;
width: @radio-dot-size;
height: @radio-dot-size;
width: @radio-size;
height: @radio-size;
margin-top: -(@radio-size / 2);
margin-left: -(@radio-size / 2);
background-color: @radio-dot-color;
border-top: 0;
border-left: 0;
border-radius: @radio-dot-size;
border-radius: @radio-size;
transform: scale(0);
opacity: 0;
transition: all @radio-duration @ease-in-out-circ;
@ -128,7 +130,7 @@
border-color: @radio-dot-color;
&::after {
transform: scale(1);
transform: scale((unit(@radio-dot-size) / unit(@radio-size)));
opacity: 1;
transition: all @radio-duration @ease-in-out-circ;
}

View File

@ -1711,7 +1711,6 @@ exports[`renders ./components/select/demo/responsive.md correctly 1`] = `
exports[`renders ./components/select/demo/search.md correctly 1`] = `
<div
class="ant-select ant-select-single ant-select-show-arrow ant-select-show-search"
style="width:200px"
>
<div
class="ant-select-selector"

View File

@ -132,16 +132,17 @@ exports[`Select rtl render component should be rendered correctly in RTL directi
class="ant-select-selection-search"
>
<input
aria-activedescendant="undefined_list_0"
aria-activedescendant="rc_select_TEST_OR_SSR_list_0"
aria-autocomplete="list"
aria-controls="undefined_list"
aria-controls="rc_select_TEST_OR_SSR_list"
aria-haspopup="listbox"
aria-owns="undefined_list"
aria-owns="rc_select_TEST_OR_SSR_list"
autocomplete="off"
class="ant-select-selection-search-input"
id="rc_select_TEST_OR_SSR"
readonly=""
role="combobox"
style="opacity:0"
style="opacity: 0;"
type="search"
unselectable="on"
value=""
@ -154,7 +155,7 @@ exports[`Select rtl render component should be rendered correctly in RTL directi
<span
aria-hidden="true"
class="ant-select-arrow"
style="user-select:none;-webkit-user-select:none"
style="user-select: none;"
unselectable="on"
>
<span

View File

@ -16,7 +16,7 @@ Search with remote data.
```jsx
import { Select } from 'antd';
import jsonp from 'fetch-jsonp';
import querystring from 'querystring';
import qs from 'qs';
const { Option } = Select;
@ -31,7 +31,7 @@ function fetch(value, callback) {
currentValue = value;
function fake() {
const str = querystring.encode({
const str = qs.stringify({
code: 'utf-8',
q: value,
});

View File

@ -22,14 +22,6 @@ function onChange(value) {
console.log(`selected ${value}`);
}
function onBlur() {
console.log('blur');
}
function onFocus() {
console.log('focus');
}
function onSearch(val) {
console.log('search:', val);
}
@ -37,12 +29,9 @@ function onSearch(val) {
ReactDOM.render(
<Select
showSearch
style={{ width: 200 }}
placeholder="Select a person"
optionFilterProp="children"
onChange={onChange}
onFocus={onFocus}
onBlur={onBlur}
onSearch={onSearch}
filterOption={(input, option) =>
option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0

View File

@ -40,6 +40,7 @@
}
.@{select-prefix-cls}-selection-placeholder {
transition: none;
pointer-events: none;
}

View File

@ -466,7 +466,7 @@ exports[`Skeleton rtl render component should be rendered correctly in RTL direc
>
<h3
class="ant-skeleton-title"
style="width:38%"
style="width: 38%;"
/>
<ul
class="ant-skeleton-paragraph"
@ -474,7 +474,7 @@ exports[`Skeleton rtl render component should be rendered correctly in RTL direc
<li />
<li />
<li
style="width:61%"
style="width: 61%;"
/>
</ul>
</div>

View File

@ -9,7 +9,7 @@ exports[`Slider rtl render component should be rendered correctly in RTL directi
/>
<div
class="ant-slider-track"
style="right:0%;left:auto;width:0%"
style="right: 0%; width: 0%;"
/>
<div
class="ant-slider-step"
@ -21,7 +21,7 @@ exports[`Slider rtl render component should be rendered correctly in RTL directi
aria-valuenow="0"
class="ant-slider-handle"
role="slider"
style="right:0%;left:auto;transform:translateX(+50%)"
style="right: 0%; transform: translateX(+50%);"
tabindex="0"
/>
<div

View File

@ -2,6 +2,6 @@
exports[`Steps rtl render component should be rendered correctly in RTL direction 1`] = `
<div
class="ant-steps ant-steps-horizontal ant-steps-rtl ant-steps-label-horizontal"
class="ant-steps ant-steps-vertical ant-steps-rtl"
/>
`;

View File

@ -126,7 +126,7 @@ exports[`Table rtl render component should be rendered correctly in RTL directio
class="ant-table-content"
>
<table
style="table-layout:auto"
style="table-layout: auto;"
>
<colgroup />
<thead

View File

@ -27,7 +27,7 @@ Setting `rowSelection.preserveSelectedRowKeys` to keep the `key` when enable sel
```jsx
import { Table } from 'antd';
import reqwest from 'reqwest';
import qs from 'qs';
const columns = [
{
@ -84,24 +84,21 @@ class App extends React.Component {
fetch = (params = {}) => {
this.setState({ loading: true });
reqwest({
url: 'https://randomuser.me/api',
method: 'get',
type: 'json',
data: getRandomuserParams(params),
}).then(data => {
console.log(data);
this.setState({
loading: false,
data: data.results,
pagination: {
...params.pagination,
total: 200,
// 200 is mock data, you should read it from server
// total: data.totalCount,
},
fetch(`https://randomuser.me/api?${qs.stringify(getRandomuserParams(params))}`)
.then(res => res.json())
.then(data => {
console.log(data);
this.setState({
loading: false,
data: data.results,
pagination: {
...params.pagination,
total: 200,
// 200 is mock data, you should read it from server
// total: data.totalCount,
},
});
});
});
};
render() {

View File

@ -39,14 +39,16 @@ exports[`Tabs rtl render component should be rendered correctly in RTL direction
>
<div
class="ant-tabs-nav-list"
style="transform:translate(0px, 0px)"
style="transform: translate(0px, 0px);"
>
<div
class="ant-tabs-tab ant-tabs-tab-active"
>
<div
aria-controls="rc-tabs-test-panel-xx"
aria-selected="true"
class="ant-tabs-tab-btn"
id="rc-tabs-test-tab-xx"
role="tab"
tabindex="0"
>
@ -62,13 +64,13 @@ exports[`Tabs rtl render component should be rendered correctly in RTL direction
class="ant-tabs-nav-operations ant-tabs-nav-operations-hidden"
>
<button
aria-controls="null-more-popup"
aria-controls="rc-tabs-test-more-popup"
aria-expanded="false"
aria-haspopup="listbox"
aria-hidden="true"
class="ant-tabs-nav-more"
id="null-more"
style="visibility:hidden;order:1"
id="rc-tabs-test-more"
style="visibility: hidden; order: 1;"
tabindex="-1"
type="button"
>
@ -102,7 +104,9 @@ exports[`Tabs rtl render component should be rendered correctly in RTL direction
>
<div
aria-hidden="false"
aria-labelledby="rc-tabs-test-tab-xx"
class="ant-tabs-tabpane ant-tabs-tabpane-active"
id="rc-tabs-test-panel-xx"
role="tabpanel"
tabindex="0"
/>
@ -124,36 +128,42 @@ exports[`Tabs tabBarGutter should work 1`] = `
>
<div
class="ant-tabs-nav-list"
style="transform:translate(0px, 0px)"
style="transform: translate(0px, 0px);"
>
<div
class="ant-tabs-tab ant-tabs-tab-active"
>
<div
aria-controls="rc-tabs-test-panel-null"
aria-selected="true"
class="ant-tabs-tab-btn"
id="rc-tabs-test-tab-null"
role="tab"
tabindex="0"
/>
</div>
<div
class="ant-tabs-tab ant-tabs-tab-active"
style="margin-left:0"
style="margin-left: 0px;"
>
<div
aria-controls="rc-tabs-test-panel-null"
aria-selected="true"
class="ant-tabs-tab-btn"
id="rc-tabs-test-tab-null"
role="tab"
tabindex="0"
/>
</div>
<div
class="ant-tabs-tab ant-tabs-tab-active"
style="margin-left:0"
style="margin-left: 0px;"
>
<div
aria-controls="rc-tabs-test-panel-null"
aria-selected="true"
class="ant-tabs-tab-btn"
id="rc-tabs-test-tab-null"
role="tab"
tabindex="0"
/>
@ -167,13 +177,13 @@ exports[`Tabs tabBarGutter should work 1`] = `
class="ant-tabs-nav-operations ant-tabs-nav-operations-hidden"
>
<button
aria-controls="null-more-popup"
aria-controls="rc-tabs-test-more-popup"
aria-expanded="false"
aria-haspopup="listbox"
aria-hidden="true"
class="ant-tabs-nav-more"
id="null-more"
style="margin-left:0;visibility:hidden;order:1"
id="rc-tabs-test-more"
style="margin-left: 0px; visibility: hidden; order: 1;"
tabindex="-1"
type="button"
>
@ -207,19 +217,25 @@ exports[`Tabs tabBarGutter should work 1`] = `
>
<div
aria-hidden="false"
aria-labelledby="rc-tabs-test-tab-null"
class="ant-tabs-tabpane ant-tabs-tabpane-active"
id="rc-tabs-test-panel-null"
role="tabpanel"
tabindex="0"
/>
<div
aria-hidden="false"
aria-labelledby="rc-tabs-test-tab-null"
class="ant-tabs-tabpane ant-tabs-tabpane-active"
id="rc-tabs-test-panel-null"
role="tabpanel"
tabindex="0"
/>
<div
aria-hidden="false"
aria-labelledby="rc-tabs-test-tab-null"
class="ant-tabs-tabpane ant-tabs-tabpane-active"
id="rc-tabs-test-panel-null"
role="tabpanel"
tabindex="0"
/>
@ -241,36 +257,42 @@ exports[`Tabs tabBarGutter should work 2`] = `
>
<div
class="ant-tabs-nav-list"
style="transform:translate(0px, 0px)"
style="transform: translate(0px, 0px);"
>
<div
class="ant-tabs-tab ant-tabs-tab-active"
>
<div
aria-controls="rc-tabs-test-panel-null"
aria-selected="true"
class="ant-tabs-tab-btn"
id="rc-tabs-test-tab-null"
role="tab"
tabindex="0"
/>
</div>
<div
class="ant-tabs-tab ant-tabs-tab-active"
style="margin-top:0"
style="margin-top: 0px;"
>
<div
aria-controls="rc-tabs-test-panel-null"
aria-selected="true"
class="ant-tabs-tab-btn"
id="rc-tabs-test-tab-null"
role="tab"
tabindex="0"
/>
</div>
<div
class="ant-tabs-tab ant-tabs-tab-active"
style="margin-top:0"
style="margin-top: 0px;"
>
<div
aria-controls="rc-tabs-test-panel-null"
aria-selected="true"
class="ant-tabs-tab-btn"
id="rc-tabs-test-tab-null"
role="tab"
tabindex="0"
/>
@ -284,13 +306,13 @@ exports[`Tabs tabBarGutter should work 2`] = `
class="ant-tabs-nav-operations ant-tabs-nav-operations-hidden"
>
<button
aria-controls="null-more-popup"
aria-controls="rc-tabs-test-more-popup"
aria-expanded="false"
aria-haspopup="listbox"
aria-hidden="true"
class="ant-tabs-nav-more"
id="null-more"
style="margin-left:0;visibility:hidden;order:1"
id="rc-tabs-test-more"
style="margin-left: 0px; visibility: hidden; order: 1;"
tabindex="-1"
type="button"
>
@ -324,19 +346,25 @@ exports[`Tabs tabBarGutter should work 2`] = `
>
<div
aria-hidden="false"
aria-labelledby="rc-tabs-test-tab-null"
class="ant-tabs-tabpane ant-tabs-tabpane-active"
id="rc-tabs-test-panel-null"
role="tabpanel"
tabindex="0"
/>
<div
aria-hidden="false"
aria-labelledby="rc-tabs-test-tab-null"
class="ant-tabs-tabpane ant-tabs-tabpane-active"
id="rc-tabs-test-panel-null"
role="tabpanel"
tabindex="0"
/>
<div
aria-hidden="false"
aria-labelledby="rc-tabs-test-tab-null"
class="ant-tabs-tabpane ant-tabs-tabpane-active"
id="rc-tabs-test-panel-null"
role="tabpanel"
tabindex="0"
/>

View File

@ -87,9 +87,21 @@ describe('Tabs', () => {
});
it('tabBarGutter should work', () => {
const wrapper = mount(<Tabs tabBarGutter={0}><TabPane /><TabPane /><TabPane /></Tabs>);
expect(wrapper).toMatchRenderedSnapshot();
const wrapper2 = mount(<Tabs tabBarGutter={0} tabPosition="left"><TabPane /><TabPane /><TabPane /></Tabs>);
expect(wrapper2).toMatchRenderedSnapshot();
const wrapper = mount(
<Tabs tabBarGutter={0}>
<TabPane />
<TabPane />
<TabPane />
</Tabs>,
);
expect(wrapper.render()).toMatchSnapshot();
const wrapper2 = mount(
<Tabs tabBarGutter={0} tabPosition="left">
<TabPane />
<TabPane />
<TabPane />
</Tabs>,
);
expect(wrapper2.render()).toMatchSnapshot();
});
});

View File

@ -19,6 +19,7 @@ exports[`Transfer rtl render component should be rendered correctly in RTL direc
<input
class="ant-checkbox-input"
type="checkbox"
value=""
/>
<span
class="ant-checkbox-inner"
@ -177,6 +178,7 @@ exports[`Transfer rtl render component should be rendered correctly in RTL direc
<input
class="ant-checkbox-input"
type="checkbox"
value=""
/>
<span
class="ant-checkbox-inner"
@ -289,6 +291,7 @@ exports[`Transfer should render correctly 1`] = `
checked=""
class="ant-checkbox-input"
type="checkbox"
value=""
/>
<span
class="ant-checkbox-inner"
@ -342,6 +345,7 @@ exports[`Transfer should render correctly 1`] = `
checked=""
class="ant-checkbox-input"
type="checkbox"
value=""
/>
<span
class="ant-checkbox-inner"
@ -365,6 +369,7 @@ exports[`Transfer should render correctly 1`] = `
class="ant-checkbox-input"
disabled=""
type="checkbox"
value=""
/>
<span
class="ant-checkbox-inner"
@ -446,6 +451,7 @@ exports[`Transfer should render correctly 1`] = `
<input
class="ant-checkbox-input"
type="checkbox"
value=""
/>
<span
class="ant-checkbox-inner"
@ -498,6 +504,7 @@ exports[`Transfer should render correctly 1`] = `
<input
class="ant-checkbox-input"
type="checkbox"
value=""
/>
<span
class="ant-checkbox-inner"
@ -533,6 +540,7 @@ exports[`Transfer should show sorted targetKey 1`] = `
<input
class="ant-checkbox-input"
type="checkbox"
value=""
/>
<span
class="ant-checkbox-inner"
@ -586,6 +594,7 @@ exports[`Transfer should show sorted targetKey 1`] = `
<input
class="ant-checkbox-input"
type="checkbox"
value=""
/>
<span
class="ant-checkbox-inner"
@ -670,6 +679,7 @@ exports[`Transfer should show sorted targetKey 1`] = `
<input
class="ant-checkbox-input"
type="checkbox"
value=""
/>
<span
class="ant-checkbox-inner"
@ -723,6 +733,7 @@ exports[`Transfer should show sorted targetKey 1`] = `
<input
class="ant-checkbox-input"
type="checkbox"
value=""
/>
<span
class="ant-checkbox-inner"
@ -748,6 +759,7 @@ exports[`Transfer should show sorted targetKey 1`] = `
<input
class="ant-checkbox-input"
type="checkbox"
value=""
/>
<span
class="ant-checkbox-inner"
@ -785,6 +797,7 @@ exports[`Transfer should support render value and label in item 1`] = `
<input
class="ant-checkbox-input"
type="checkbox"
value=""
/>
<span
class="ant-checkbox-inner"
@ -838,6 +851,7 @@ exports[`Transfer should support render value and label in item 1`] = `
<input
class="ant-checkbox-input"
type="checkbox"
value=""
/>
<span
class="ant-checkbox-inner"
@ -922,6 +936,7 @@ exports[`Transfer should support render value and label in item 1`] = `
<input
class="ant-checkbox-input"
type="checkbox"
value=""
/>
<span
class="ant-checkbox-inner"
@ -1033,6 +1048,7 @@ exports[`immutable data dataSource is frozen 1`] = `
<input
class="ant-checkbox-input"
type="checkbox"
value=""
/>
<span
class="ant-checkbox-inner"
@ -1085,6 +1101,7 @@ exports[`immutable data dataSource is frozen 1`] = `
<input
class="ant-checkbox-input"
type="checkbox"
value=""
/>
<span
class="ant-checkbox-inner"
@ -1167,6 +1184,7 @@ exports[`immutable data dataSource is frozen 1`] = `
<input
class="ant-checkbox-input"
type="checkbox"
value=""
/>
<span
class="ant-checkbox-inner"

View File

@ -16,6 +16,7 @@ exports[`Transfer.List should render correctly 1`] = `
<input
class="ant-checkbox-input"
type="checkbox"
value=""
/>
<span
class="ant-checkbox-inner"
@ -69,6 +70,7 @@ exports[`Transfer.List should render correctly 1`] = `
checked=""
class="ant-checkbox-input"
type="checkbox"
value=""
/>
<span
class="ant-checkbox-inner"
@ -91,6 +93,7 @@ exports[`Transfer.List should render correctly 1`] = `
<input
class="ant-checkbox-input"
type="checkbox"
value=""
/>
<span
class="ant-checkbox-inner"
@ -114,6 +117,7 @@ exports[`Transfer.List should render correctly 1`] = `
class="ant-checkbox-input"
disabled=""
type="checkbox"
value=""
/>
<span
class="ant-checkbox-inner"

View File

@ -98,7 +98,7 @@ describe('Transfer', () => {
it('should render correctly', () => {
const wrapper = mount(<Transfer {...listCommonProps} />);
expect(wrapper).toMatchRenderedSnapshot();
expect(wrapper.render()).toMatchSnapshot();
});
it('should move selected keys to corresponding list', () => {
@ -414,7 +414,7 @@ describe('Transfer', () => {
lazy: false,
};
const wrapper = mount(<Transfer {...sortedTargetKeyProps} render={item => item.title} />);
expect(wrapper).toMatchRenderedSnapshot();
expect(wrapper.render()).toMatchSnapshot();
});
it('should add custom styles when their props are provided', () => {
@ -488,7 +488,7 @@ describe('Transfer', () => {
render={record => ({ value: `${record.title} value`, label: 'label' })}
/>,
);
expect(component).toMatchRenderedSnapshot();
expect(component.render()).toMatchSnapshot();
});
it('should render correct checkbox label when checkboxLabel is defined', () => {
@ -568,6 +568,6 @@ describe('immutable data', () => {
}),
];
const wrapper = mount(<Transfer rowKey={item => item.id} dataSource={mockData} />);
expect(wrapper).toMatchRenderedSnapshot();
expect(wrapper.render()).toMatchSnapshot();
});
});

View File

@ -28,7 +28,7 @@ describe('Transfer.List', () => {
it('should render correctly', () => {
const wrapper = mount(<List {...listCommonProps} />);
wrapper.update();
expect(wrapper).toMatchRenderedSnapshot();
expect(wrapper.render()).toMatchSnapshot();
});
it('should check top Checkbox while all available items are checked', () => {

View File

@ -34,9 +34,9 @@ describe('Transfer.Search', () => {
it('should show cross icon when input value exists', () => {
const wrapper = mount(<Search value="" />);
expect(wrapper).toMatchRenderedSnapshot();
expect(wrapper.render()).toMatchSnapshot();
wrapper.setProps({ value: 'a' });
expect(wrapper).toMatchRenderedSnapshot();
expect(wrapper.render()).toMatchSnapshot();
});
it('onSearch', () => {

View File

@ -263,16 +263,17 @@ exports[`TreeSelect rtl render component should be rendered correctly in RTL dir
class="ant-select-selection-search"
>
<input
aria-activedescendant="undefined_list_0"
aria-activedescendant="rc_select_TEST_OR_SSR_list_0"
aria-autocomplete="list"
aria-controls="undefined_list"
aria-controls="rc_select_TEST_OR_SSR_list"
aria-haspopup="listbox"
aria-owns="undefined_list"
aria-owns="rc_select_TEST_OR_SSR_list"
autocomplete="off"
class="ant-select-selection-search-input"
id="rc_select_TEST_OR_SSR"
readonly=""
role="combobox"
style="opacity:0"
style="opacity: 0;"
type="search"
unselectable="on"
value=""
@ -285,7 +286,7 @@ exports[`TreeSelect rtl render component should be rendered correctly in RTL dir
<span
aria-hidden="true"
class="ant-select-arrow"
style="user-select:none;-webkit-user-select:none"
style="user-select: none;"
unselectable="on"
>
<span

View File

@ -3282,7 +3282,7 @@ exports[`Directory Tree rtl render component should be rendered correctly in RTL
<div>
<input
aria-label="for screen reader"
style="width:0;height:0;display:flex;overflow:hidden;opacity:0;border:0;padding:0;margin:0"
style="width: 0px; height: 0px; display: flex; overflow: hidden; opacity: 0; border: 0px; padding: 0px; margin: 0px;"
tabindex="0"
value=""
/>
@ -3290,7 +3290,7 @@ exports[`Directory Tree rtl render component should be rendered correctly in RTL
<div
aria-hidden="true"
class="ant-tree-treenode"
style="position:absolute;pointer-events:none;visibility:hidden;height:0;overflow:hidden"
style="position: absolute; pointer-events: none; visibility: hidden; height: 0px; overflow: hidden;"
>
<div
class="ant-tree-indent"
@ -3302,7 +3302,7 @@ exports[`Directory Tree rtl render component should be rendered correctly in RTL
</div>
<div
class="ant-tree-list"
style="position:relative"
style="position: relative;"
>
<div
class="ant-tree-list-holder"
@ -3310,7 +3310,7 @@ exports[`Directory Tree rtl render component should be rendered correctly in RTL
<div>
<div
class="ant-tree-list-holder-inner"
style="display:flex;flex-direction:column"
style="display: flex; flex-direction: column;"
/>
</div>
</div>
@ -3326,7 +3326,7 @@ exports[`Directory Tree rtl render component should be rendered correctly in RTL
<div>
<input
aria-label="for screen reader"
style="width:0;height:0;display:flex;overflow:hidden;opacity:0;border:0;padding:0;margin:0"
style="width: 0px; height: 0px; display: flex; overflow: hidden; opacity: 0; border: 0px; padding: 0px; margin: 0px;"
tabindex="0"
value=""
/>
@ -3334,7 +3334,7 @@ exports[`Directory Tree rtl render component should be rendered correctly in RTL
<div
aria-hidden="true"
class="ant-tree-treenode"
style="position:absolute;pointer-events:none;visibility:hidden;height:0;overflow:hidden"
style="position: absolute; pointer-events: none; visibility: hidden; height: 0px; overflow: hidden;"
>
<div
class="ant-tree-indent"
@ -3346,7 +3346,7 @@ exports[`Directory Tree rtl render component should be rendered correctly in RTL
</div>
<div
class="ant-tree-list"
style="position:relative"
style="position: relative;"
>
<div
class="ant-tree-list-holder"
@ -3354,7 +3354,7 @@ exports[`Directory Tree rtl render component should be rendered correctly in RTL
<div>
<div
class="ant-tree-list-holder-inner"
style="display:flex;flex-direction:column"
style="display: flex; flex-direction: column;"
/>
</div>
</div>

View File

@ -6,7 +6,7 @@ exports[`Upload rtl render component should be rendered correctly in RTL directi
>
<div
class="ant-upload ant-upload-select ant-upload-select-text ant-upload-rtl"
style="display:none"
style="display: none;"
>
<span
class="ant-upload"
@ -15,7 +15,7 @@ exports[`Upload rtl render component should be rendered correctly in RTL directi
>
<input
accept=""
style="display:none"
style="display: none;"
type="file"
/>
</span>

View File

@ -16,7 +16,6 @@ Upload files manually after `beforeUpload` returns `false`.
```jsx
import { Upload, Button, message } from 'antd';
import { UploadOutlined } from '@ant-design/icons';
import reqwest from 'reqwest';
class Demo extends React.Component {
state = {
@ -30,31 +29,29 @@ class Demo extends React.Component {
fileList.forEach(file => {
formData.append('files[]', file);
});
this.setState({
uploading: true,
});
// You can use any AJAX library you like
reqwest({
url: 'https://www.mocky.io/v2/5cc8019d300000980a055e76',
method: 'post',
processData: false,
data: formData,
success: () => {
fetch('https://www.mocky.io/v2/5cc8019d300000980a055e76', {
method: 'POST',
body: formData,
})
.then(res => res.json())
.then(() => {
this.setState({
fileList: [],
uploading: false,
});
message.success('upload successfully.');
},
error: () => {
})
.catch(() => {
message.error('upload failed.');
})
.finally(() => {
this.setState({
uploading: false,
});
message.error('upload failed.');
},
});
});
};
render() {

View File

@ -26,7 +26,7 @@ title: Third-Party Libraries
| i18n | [FormatJS](https://github.com/formatjs/formatjs) [react-i18next](https://react.i18next.com) |
| Code highlight | [react-syntax-highlighter](https://github.com/conorhastings/react-syntax-highlighter) |
| Markdown renderer | [react-markdown](https://remarkjs.github.io/react-markdown/) |
| Infinite Scroll | [rc-virtual-list](https://github.com/react-component/virtual-list/) [react-virtualized](https://github.com/bvaughn/react-virtualized) [react-infinite-scroll-component](https://github.com/ankeetmaini/react-infinite-scroll-component) |
| Infinite Scroll | [rc-virtual-list](https://github.com/react-component/virtual-list/) [react-infinite-scroll-component](https://github.com/ankeetmaini/react-infinite-scroll-component) |
| Map | [react-google-maps](https://github.com/tomchentw/react-google-maps) [google-map-react](https://github.com/istarkov/google-map-react) [react-amap](https://github.com/ElemeFE/react-amap) |
| Video | [react-player](https://github.com/CookPete/react-player) [video-react](https://github.com/video-react/video-react) [video.js](http://docs.videojs.com/tutorial-react.html) |
| Context Menu | [react-contextmenu](https://github.com/vkbansal/react-contextmenu/) [react-contexify](https://github.com/fkhadra/react-contexify) |

View File

@ -26,7 +26,7 @@ title: 社区精选组件
| 应用国际化 | [FormatJS](https://github.com/formatjs/formatjs) [react-i18next](https://react.i18next.com) |
| 代码高亮 | [react-syntax-highlighter](https://github.com/conorhastings/react-syntax-highlighter) |
| Markdown 渲染 | [react-markdown](https://remarkjs.github.io/react-markdown/) |
| 无限滚动 | [rc-virtual-list](https://github.com/react-component/virtual-list/) [react-virtualized](https://github.com/bvaughn/react-virtualized) [react-infinite-scroll-component](https://github.com/ankeetmaini/react-infinite-scroll-component) |
| 无限滚动 | [rc-virtual-list](https://github.com/react-component/virtual-list/) [react-infinite-scroll-component](https://github.com/ankeetmaini/react-infinite-scroll-component) |
| 地图 | [react-google-maps](https://github.com/tomchentw/react-google-maps) [google-map-react](https://github.com/istarkov/google-map-react) [react-amap 高德](https://github.com/ElemeFE/react-amap) |
| 视频播放 | [react-player](https://github.com/CookPete/react-player) [video-react](https://github.com/video-react/video-react) [video.js](http://docs.videojs.com/tutorial-react.html) |
| 右键菜单 | [react-contextmenu](https://github.com/vkbansal/react-contextmenu/) [react-contexify](https://github.com/fkhadra/react-contexify) |

View File

@ -98,7 +98,7 @@
"site:test": "jest --config .jest.site.js --cache=false --force-exit",
"test-image": "npm run dist && docker-compose run tests",
"version": "node ./scripts/generate-version",
"install-react-16": "npm i --no-save react@16 react-dom@16 react-test-renderer@16 enzyme-adapter-react-16",
"install-react-16": "npm i --no-save --legacy-peer-deps react@16 react-dom@16 react-test-renderer@16 enzyme-adapter-react-16",
"argos": "argos upload imageSnapshots"
},
"browserslist": [
@ -121,7 +121,7 @@
"lodash": "^4.17.21",
"memoize-one": "^6.0.0",
"moment": "^2.25.3",
"rc-cascader": "~2.2.0",
"rc-cascader": "~2.3.0",
"rc-checkbox": "~2.3.0",
"rc-collapse": "~3.1.0",
"rc-dialog": "~8.6.0",
@ -139,7 +139,7 @@
"rc-progress": "~3.1.0",
"rc-rate": "~2.9.0",
"rc-resize-observer": "^1.1.0",
"rc-select": "~13.1.0-alpha.0",
"rc-select": "~13.2.1",
"rc-slider": "~9.7.4",
"rc-steps": "~4.1.0",
"rc-switch": "~3.2.0",
@ -148,7 +148,7 @@
"rc-textarea": "~0.3.0",
"rc-tooltip": "~5.1.1",
"rc-tree": "~5.3.0",
"rc-tree-select": "~4.7.0",
"rc-tree-select": "~4.8.0",
"rc-trigger": "^5.2.10",
"rc-upload": "~4.3.0",
"rc-util": "^5.14.0",
@ -157,7 +157,7 @@
"devDependencies": {
"@ant-design/bisheng-plugin": "^3.0.1",
"@ant-design/hitu": "^0.0.0-alpha.13",
"@ant-design/tools": "^14.0.0-alpha.3",
"@ant-design/tools": "^14.0.2",
"@docsearch/css": "^3.0.0-alpha.39",
"@docsearch/react": "^3.0.0-alpha.39",
"@qixian.cs/github-contributors-list": "^1.0.3",
@ -166,6 +166,7 @@
"@types/enzyme": "^3.10.5",
"@types/gtag.js": "^0.0.8",
"@types/jest": "^27.0.0",
"@types/jest-axe": "^3.5.3",
"@types/jest-environment-puppeteer": "^4.4.0",
"@types/jest-image-snapshot": "^4.1.0",
"@types/lodash": "^4.14.139",
@ -192,6 +193,7 @@
"cheerio": "^1.0.0-rc.3",
"concurrently": "^6.0.0",
"cross-env": "^7.0.0",
"css-minimizer-webpack-plugin": "^3.2.0",
"dekko": "^0.2.1",
"docsearch.js": "^2.6.3",
"duplicate-package-checker-webpack-plugin": "^3.0.0",
@ -218,29 +220,30 @@
"http-server": "^14.0.0",
"husky": "^7.0.1",
"identity-obj-proxy": "^3.0.0",
"ignore-emit-webpack-plugin": "^2.0.6",
"immer": "^9.0.1",
"immutability-helper": "^3.0.0",
"inquirer": "^8.0.0",
"intersection-observer": "^0.12.0",
"isomorphic-fetch": "^3.0.0",
"jest": "^27.0.3",
"jest-axe": "^5.0.1",
"jest-image-snapshot": "^4.5.1",
"jest-puppeteer": "^6.0.0",
"jquery": "^3.4.1",
"jsdom": "^18.0.0",
"jsdom": "^19.0.0",
"jsonml.js": "^0.1.0",
"less-vars-to-js": "^1.3.0",
"lz-string": "^1.4.4",
"mini-css-extract-plugin": "^2.4.5",
"mockdate": "^3.0.0",
"open": "^8.0.1",
"prettier": "^2.3.2",
"prettier-plugin-jsdoc": "^0.3.0",
"pretty-quick": "^3.0.0",
"querystring": "^0.2.0",
"qs": "^6.10.1",
"rc-footer": "^0.6.6",
"rc-tween-one": "^3.0.3",
"rc-virtual-list": "^3.2.4",
"rc-virtual-list": "^3.4.2",
"react": "^17.0.1",
"react-color": "^2.17.3",
"react-copy-to-clipboard": "^5.0.1",
@ -250,7 +253,7 @@
"react-draggable": "^4.4.3",
"react-fast-marquee": "^1.2.1",
"react-github-button": "^0.1.11",
"react-helmet-async": "~1.1.2",
"react-helmet-async": "~1.2.0",
"react-highlight-words": "^0.17.0",
"react-infinite-scroll-component": "^6.1.0",
"react-intl": "^5.20.4",
@ -260,13 +263,12 @@
"react-sticky": "^6.0.3",
"react-test-renderer": "^17.0.1",
"react-text-loop-next": "0.0.3",
"react-virtualized": "^9.22.0",
"react-window": "^1.8.5",
"remark": "^14.0.1",
"remark-cli": "^10.0.0",
"remark-lint": "^9.0.0",
"remark-preset-lint-recommended": "^6.0.0",
"reqwest": "^2.0.5",
"remove-files-webpack-plugin": "^1.4.5",
"rimraf": "^3.0.0",
"scrollama": "^2.0.0",
"simple-git": "^2.23.0",
@ -281,7 +283,6 @@
"typescript": "~4.5.2",
"webpack-bundle-analyzer": "^4.1.0",
"xhr-mock": "^2.4.1",
"xhr2": "^0.2.0",
"yaml-front-matter": "^4.0.0"
},
"peerDependencies": {

View File

@ -114,6 +114,7 @@ module.exports = {
// Use dev mod to speed up site preview build
// This is used for CI preview build in `preview-build.yml`
if (process.env.SITE_ENV === 'development') {
// eslint-disable-next-line no-console
console.log('Site build with development mode...');
config.mode = 'development';
}

View File

@ -1,21 +0,0 @@
import { render } from 'enzyme';
import { ReactElement } from 'react';
export default function toMatchRenderedSnapshot(
this: jest.MatcherUtils,
jsx: ReactElement<unknown>,
): { message(): string; pass: boolean } {
try {
expect(render(jsx)).toMatchSnapshot();
return {
message: () => 'expected JSX not to match snapshot',
pass: true,
};
} catch (e) {
return {
message: () => `expected JSX to match snapshot: ${e.message}`,
pass: false,
};
}
}

View File

@ -1,5 +1,3 @@
import toMatchRenderedSnapshot from './matchers/rendered-snapshot';
import { toHaveNoViolations } from 'jest-axe';
expect.extend({
toMatchRenderedSnapshot,
});
expect.extend(toHaveNoViolations);

View File

@ -0,0 +1,15 @@
import React from 'react';
import { mount } from 'enzyme';
import { axe } from 'jest-axe';
// eslint-disable-next-line jest/no-export
export default function accessibilityTest(Component: React.ComponentType) {
describe(`accessibility`, () => {
it(`component does not have any violations`, async () => {
jest.useRealTimers();
const wrapper = mount(<Component />);
const results = await axe(wrapper.getDOMNode());
expect(results).toHaveNoViolations();
});
});
}

View File

@ -16,7 +16,7 @@ export default function rtlTest(Component: React.ComponentType, mockDate?: boole
<Component />
</ConfigProvider>,
);
expect(wrapper).toMatchRenderedSnapshot();
expect(wrapper.render()).toMatchSnapshot();
if (mockDate) {
MockDate.reset();
}

2
typings/jest.d.ts vendored
View File

@ -1,5 +1,5 @@
declare namespace jest {
interface Matchers<R> {
toMatchRenderedSnapshot(): R;
toHaveNoViolations(): R;
}
}

View File

@ -2,7 +2,7 @@
// This config is for building dist files
const chalk = require('chalk');
const getWebpackConfig = require('@ant-design/tools/lib/getWebpackConfig');
const IgnoreEmitPlugin = require('ignore-emit-webpack-plugin');
const RemovePlugin = require('remove-files-webpack-plugin');
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
const { ESBuildMinifyPlugin } = require('esbuild-loader');
const DuplicatePackageCheckerPlugin = require('duplicate-package-checker-webpack-plugin');
@ -103,9 +103,22 @@ function processWebpackThemeConfig(themeConfig, theme, vars) {
// apply ${theme} less variables
injectLessVariables(config, vars);
const themeReg = new RegExp(`${theme}(.min)?\\.js(\\.map)?$`);
// ignore emit ${theme} entry js & js.map file
config.plugins.push(new IgnoreEmitPlugin(themeReg));
config.plugins.push(
new RemovePlugin({
after: {
root: './dist',
include: [
`antd.${theme}.js`,
`antd.${theme}.js.map`,
`antd.${theme}.min.js`,
`antd.${theme}.min.js.map`,
],
log: false,
logWarning: false,
},
}),
);
});
}