mirror of
https://github.com/ant-design/ant-design.git
synced 2024-12-01 06:49:32 +08:00
Merge pull request #23796 from ant-design/master
chore: Merge master into feature
This commit is contained in:
commit
35e390018c
16
.snyk
Normal file
16
.snyk
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities.
|
||||||
|
version: v1.14.1
|
||||||
|
ignore: {}
|
||||||
|
# patches apply the minimum changes required to fix a vulnerability
|
||||||
|
patch:
|
||||||
|
SNYK-JS-LODASH-567746:
|
||||||
|
- lodash:
|
||||||
|
patched: '2020-05-01T06:50:59.565Z'
|
||||||
|
- '@ant-design/react-slick > lodash':
|
||||||
|
patched: '2020-05-01T06:50:59.565Z'
|
||||||
|
- rc-steps > lodash:
|
||||||
|
patched: '2020-05-01T06:50:59.565Z'
|
||||||
|
- rc-table > lodash:
|
||||||
|
patched: '2020-05-01T06:50:59.565Z'
|
||||||
|
- rc-tabs > lodash:
|
||||||
|
patched: '2020-05-01T06:50:59.565Z'
|
@ -15,6 +15,61 @@ timeline: true
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## 4.2.0
|
||||||
|
|
||||||
|
`2020-04-29`
|
||||||
|
|
||||||
|
- 🆕 List `grid` support all column count like 5. [#23630](https://github.com/ant-design/ant-design/pull/23630)
|
||||||
|
- 🆕 Divider add `plain` prop which allows a non-heading style divider text. [#23405](https://github.com/ant-design/ant-design/pull/23405)
|
||||||
|
- 🆕 Typography `ellipsis` support `onEllipsis` event handler. [#23414](https://github.com/ant-design/ant-design/pull/23414)
|
||||||
|
- 🆕 Space support `align` prop. [#23306](https://github.com/ant-design/ant-design/pull/23306)
|
||||||
|
- 🆕 Upload support `isImageUrl` to force trade file as image. [#23248](https://github.com/ant-design/ant-design/pull/23248) [@onjuju](https://github.com/onjuju)
|
||||||
|
- 🆕 Form.Item support `initialValue` and `getValueProps` props. [#22993](https://github.com/ant-design/ant-design/pull/22993)
|
||||||
|
- ConfigProvider
|
||||||
|
- 🆕 ConfigProvider support `getTargetContainer` to config Affix `target` props. [#23751](https://github.com/ant-design/ant-design/pull/23751)
|
||||||
|
- 🆕 ConfigProvider support `input` prop to config Input `autoComplete`. [#23455](https://github.com/ant-design/ant-design/pull/23455)
|
||||||
|
- 🐞 Fix ConfigProvider `getPopupContainer` not working on DatePicker and Slider. [#23594](https://github.com/ant-design/ant-design/pull/23594) [@hengkx](https://github.com/hengkx)
|
||||||
|
- Table
|
||||||
|
- 🆕 Table `summary` support fixed columns. [#23647](https://github.com/ant-design/ant-design/pull/23647)
|
||||||
|
- 🆕 Table support responsive columns. [#23298](https://github.com/ant-design/ant-design/pull/23298) [@vbudovski](https://github.com/vbudovski)
|
||||||
|
- 🐞 Fix Table pagination default position in RTL. [#23747](https://github.com/ant-design/ant-design/pull/23747)
|
||||||
|
- 🐞 Fix Table crash when `pageSize` is `undefined`. [#23724](https://github.com/ant-design/ant-design/pull/23724)
|
||||||
|
- 🐞 fix Table nested margin when size is `small` or `middle`. [#23602](https://github.com/ant-design/ant-design/pull/23602) [@hengkx](https://github.com/hengkx)
|
||||||
|
- 🐞 Fix RangePicker `ranges` tag color to primary color. [#23705](https://github.com/ant-design/ant-design/pull/23705)
|
||||||
|
- 🐞 Fix Transfer with custom empty style issue. [#23694](https://github.com/ant-design/ant-design/pull/23694) [@hengkx](https://github.com/hengkx)
|
||||||
|
- Input
|
||||||
|
- 🐞 Fix Password caret position. [#23633](https://github.com/ant-design/ant-design/pull/23633) [@huntdream](https://github.com/huntdream)
|
||||||
|
- 💄 Adjust Input.Search icon style. [#23406](https://github.com/ant-design/ant-design/pull/23406)
|
||||||
|
- Button
|
||||||
|
- 🐞 Fix Button align problem of icon only. [#23671](https://github.com/ant-design/ant-design/pull/23671)
|
||||||
|
- 🐞 Fix Button of icon only wrong `loading` style. [#23614](https://github.com/ant-design/ant-design/pull/23614)
|
||||||
|
- 🐞 fix Button cannot be directly called by `react-dnd`. [#23571](https://github.com/ant-design/ant-design/pull/23571) [@hengkx](https://github.com/hengkx)
|
||||||
|
- Menu
|
||||||
|
- 🆕 Menu Item and SubMenu support `icon` prop. [#23629](https://github.com/ant-design/ant-design/pull/23629)
|
||||||
|
- 🐞 Fix Menu duplicated shadow style. [#23664](https://github.com/ant-design/ant-design/pull/23664)
|
||||||
|
- 🐞 Fix Tag cannot be directly called by `react-dnd`. [#23632](https://github.com/ant-design/ant-design/pull/23632) [@hengkx](https://github.com/hengkx)
|
||||||
|
- Anchor
|
||||||
|
- 🐞 Fix Anchor Link with multiple `#` can not jump correctly. [#23595](https://github.com/ant-design/ant-design/pull/23595) [@wuzekang](https://github.com/wuzekang)
|
||||||
|
- 🐞 Fix Input with `suffix` align problem. [#23606](https://github.com/ant-design/ant-design/pull/23606)
|
||||||
|
- 💄 Select arrow won't rotate when open. [#23468](https://github.com/ant-design/ant-design/pull/23468)
|
||||||
|
- 💄 Rate support `direction`. [#23321](https://github.com/ant-design/ant-design/pull/23321)
|
||||||
|
- 💄 Adjust font-size in compact mode. [#23135](https://github.com/ant-design/ant-design/pull/23135)
|
||||||
|
- RTL
|
||||||
|
- 💄 Optimize Result button style in RTL. [#23733](https://github.com/ant-design/ant-design/pull/23733)
|
||||||
|
- 💄 Add Divider RTL support. [#23734](https://github.com/ant-design/ant-design/pull/23734)
|
||||||
|
- 💄 Fix Alert style in RTL when no-icon. [#23714](https://github.com/ant-design/ant-design/pull/23714)
|
||||||
|
- 💄 Optimize Table expand animation and pagination style in RTL. [#23706](https://github.com/ant-design/ant-design/pull/23706)
|
||||||
|
- 💄 Fix Table filter dropdown position in RTL. [#23695](https://github.com/ant-design/ant-design/pull/23695)
|
||||||
|
- 💄 Fix Table rowSelect icon style in RTL. [#23690](https://github.com/ant-design/ant-design/pull/23690)
|
||||||
|
- 💄 Optimize List style in RTL. [#23676](https://github.com/ant-design/ant-design/pull/23676)
|
||||||
|
- 💄 Add Calendar RTL. [#23394](https://github.com/ant-design/ant-design/pull/23394)
|
||||||
|
- 💄 Optimize Input.Search style in RTL. [#23424](https://github.com/ant-design/ant-design/pull/23424)
|
||||||
|
- 💄 Add Notification RTL config. [#23185](https://github.com/ant-design/ant-design/pull/23185)
|
||||||
|
- TypeScript
|
||||||
|
- 🐞 Fix PageHeader `tag` definition. [#23712](https://github.com/ant-design/ant-design/pull/23712) [@hengkx](https://github.com/hengkx)
|
||||||
|
- 🗑 Remove Button deprecated `type="danger"` TypeScript definition and warn it. [#23709](https://github.com/ant-design/ant-design/pull/23709)
|
||||||
|
- 🐞 Fix Table pagination `position` definition. [#23681](https://github.com/ant-design/ant-design/pull/23681) [@hengkx](https://github.com/hengkx)
|
||||||
|
|
||||||
## 4.1.5
|
## 4.1.5
|
||||||
|
|
||||||
`2020-04-25`
|
`2020-04-25`
|
||||||
|
@ -15,6 +15,61 @@ timeline: true
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## 4.2.0
|
||||||
|
|
||||||
|
`2020-04-29`
|
||||||
|
|
||||||
|
- 🆕 List `grid` 支持所有分栏数字,比如分为 5 栏。[#23630](https://github.com/ant-design/ant-design/pull/23630)
|
||||||
|
- 🆕 Divider 新增 `plain` 属性,可用于设置一个非标题样式的分割文字。[#23405](https://github.com/ant-design/ant-design/pull/23405)
|
||||||
|
- 🆕 Typography `ellipsis` 支持 `onEllipsis` 事件。[#23414](https://github.com/ant-design/ant-design/pull/23414)
|
||||||
|
- 🆕 Space 支持 `align` 属性。[#23306](https://github.com/ant-design/ant-design/pull/23306)
|
||||||
|
- 🆕 Upload 添加 `isImageUrl` 属性以强制将文件作为图标文件。[#23248](https://github.com/ant-design/ant-design/pull/23248) [@onjuju](https://github.com/onjuju)
|
||||||
|
- 🆕 Form.Item 支持 `initialValue` 和 `getValueProps` 属性。[#22993](https://github.com/ant-design/ant-design/pull/22993)
|
||||||
|
- ConfigProvider
|
||||||
|
- 🆕 ConfigProvider 支持 `getTargetContainer` 以配置 Affix `target` 属性。[#23751](https://github.com/ant-design/ant-design/pull/23751)
|
||||||
|
- 🆕 ConfigProvider 添加 `input` 属性以支持全局化配置 Input `autoComplete` 的默认值。[#23455](https://github.com/ant-design/ant-design/pull/23455)
|
||||||
|
- 🐞 修复 ConfigProvider `getPopupContainer` 对 DatePicker 和 Slider 不生效的问题。[#23594](https://github.com/ant-design/ant-design/pull/23594) [@hengkx](https://github.com/hengkx)
|
||||||
|
- Table
|
||||||
|
- 🆕 Table `summary` 支持固定列。[#23647](https://github.com/ant-design/ant-design/pull/23647)
|
||||||
|
- 🆕 Table 支持响应式展现列。[#23298](https://github.com/ant-design/ant-design/pull/23298) [@vbudovski](https://github.com/vbudovski)
|
||||||
|
- 🐞 修复 Table pagination 在 RTL 下默认位置。[#23747](https://github.com/ant-design/ant-design/pull/23747)
|
||||||
|
- 🐞 修复 Table 在 `pageSize` 是 `undefined` 时崩溃的问题。[#23724](https://github.com/ant-design/ant-design/pull/23724)
|
||||||
|
- 🐞 修复 Table 大小为 `small` 和 `middle` 时嵌套表格错位的问题。[#23602](https://github.com/ant-design/ant-design/pull/23602) [@hengkx](https://github.com/hengkx)
|
||||||
|
- 🐞 修正 RangePicker 范围标签的颜色为主色。[#23705](https://github.com/ant-design/ant-design/pull/23705)
|
||||||
|
- 🐞 修复 Transfer 为空自定义图片样式问题。[#23694](https://github.com/ant-design/ant-design/pull/23694) [@hengkx](https://github.com/hengkx)
|
||||||
|
- Input
|
||||||
|
- 🐞 修复 Password 组件输入光标位置。[#23633](https://github.com/ant-design/ant-design/pull/23633) [@huntdream](https://github.com/huntdream)
|
||||||
|
- 💄 调整 Input.Search 的搜索图标样式。[#23406](https://github.com/ant-design/ant-design/pull/23406)
|
||||||
|
- Button
|
||||||
|
- 🐞 修复 Button 图标类型按钮的对齐问题。[#23671](https://github.com/ant-design/ant-design/pull/23671)
|
||||||
|
- 🐞 修复 Button 图标按钮 `loading` 样式错误的问题。[#23614](https://github.com/ant-design/ant-design/pull/23614)
|
||||||
|
- 🐞 解决 Button 无法直接被 `react-dnd` 调用的问题。[#23571](https://github.com/ant-design/ant-design/pull/23571) [@hengkx](https://github.com/hengkx)
|
||||||
|
- Menu
|
||||||
|
- 🆕 Menu Item 和 SubMenu 新增 `icon` 属性。[#23629](https://github.com/ant-design/ant-design/pull/23629)
|
||||||
|
- 🐞 修复 Menu 菜单重复阴影的问题。[#23664](https://github.com/ant-design/ant-design/pull/23664)
|
||||||
|
- 🐞 解决 Tag 无法直接被 `react-dnd` 调用的问题。[#23632](https://github.com/ant-design/ant-design/pull/23632) [@hengkx](https://github.com/hengkx)
|
||||||
|
- Anchor
|
||||||
|
- 🐞 修复 Anchor Link 包含多个 `#` 时无法跳转的问题。[#23595](https://github.com/ant-design/ant-design/pull/23595) [@wuzekang](https://github.com/wuzekang)
|
||||||
|
- 🐞 修复 Input 带 `suffix` 时的元素对齐问题。[#23606](https://github.com/ant-design/ant-design/pull/23606)
|
||||||
|
- 💄 Select 箭头打开时不再翻转。[#23468](https://github.com/ant-design/ant-design/pull/23468)
|
||||||
|
- 💄 新增 Rate 的 `direction` 支持优化。[#23321](https://github.com/ant-design/ant-design/pull/23321)
|
||||||
|
- 💄 调整紧凑模式下默认的字体大小。[#23135](https://github.com/ant-design/ant-design/pull/23135)
|
||||||
|
- RTL
|
||||||
|
- 💄 优化 Result RTL 下按钮样式。[#23733](https://github.com/ant-design/ant-design/pull/23733)
|
||||||
|
- 💄 新增 Divider RTL 支持。[#23734](https://github.com/ant-design/ant-design/pull/23734)
|
||||||
|
- 💄 修复 Alert 在 RTL 下无 icon 的间隔问题。[#23714](https://github.com/ant-design/ant-design/pull/23714)
|
||||||
|
- 💄 优化 Table RTL 模式下扩展按钮动画与分页样式问题。[#23706](https://github.com/ant-design/ant-design/pull/23706)
|
||||||
|
- 💄 修复 Table 筛选下拉框在 RTL 下的位置。[#23695](https://github.com/ant-design/ant-design/pull/23695)
|
||||||
|
- 💄 修复 Table 勾选框图标 RTL 样式。[#23690](https://github.com/ant-design/ant-design/pull/23690)
|
||||||
|
- 💄 优化 List RTL 样式。[#23676](https://github.com/ant-design/ant-design/pull/23676)
|
||||||
|
- 💄 新增 Calendar RTL 支持。[#23394](https://github.com/ant-design/ant-design/pull/23394)
|
||||||
|
- 💄 优化 Input.Search RTL 样式。[#23424](https://github.com/ant-design/ant-design/pull/23424)
|
||||||
|
- 💄 增加 Notification RTL 设置。[#23185](https://github.com/ant-design/ant-design/pull/23185)
|
||||||
|
- TypeScript
|
||||||
|
- 🐞 修复 PageHeader `tag` 属性定义错误。[#23712](https://github.com/ant-design/ant-design/pull/23712) [@hengkx](https://github.com/hengkx)
|
||||||
|
- 🗑 移除已废弃的 Button `type="danger"` TypeScript 定义并增加警告信息。[#23709](https://github.com/ant-design/ant-design/pull/23709)
|
||||||
|
- 🐞 修复 Table pagination `position` Typescript 定义错误。[#23681](https://github.com/ant-design/ant-design/pull/23681) [@hengkx](https://github.com/hengkx)
|
||||||
|
|
||||||
## 4.1.5
|
## 4.1.5
|
||||||
|
|
||||||
`2020-04-25`
|
`2020-04-25`
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
export function fillRef<T>(ref: React.Ref<T>, node: T) {
|
export function fillRef<T>(ref: React.Ref<T>, node: T) {
|
||||||
if (typeof ref === 'function') {
|
if (typeof ref === 'function') {
|
||||||
|
@ -1,360 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { mount } from 'enzyme';
|
|
||||||
import Anchor from '..';
|
|
||||||
import { sleep } from '../../../tests/utils';
|
|
||||||
|
|
||||||
const { Link } = Anchor;
|
|
||||||
|
|
||||||
describe('Anchor Render', () => {
|
|
||||||
const getBoundingClientRectMock = jest.spyOn(
|
|
||||||
HTMLHeadingElement.prototype,
|
|
||||||
'getBoundingClientRect',
|
|
||||||
);
|
|
||||||
const getClientRectsMock = jest.spyOn(HTMLHeadingElement.prototype, 'getClientRects');
|
|
||||||
|
|
||||||
beforeAll(() => {
|
|
||||||
getBoundingClientRectMock.mockReturnValue({
|
|
||||||
width: 100,
|
|
||||||
height: 100,
|
|
||||||
top: 1000,
|
|
||||||
});
|
|
||||||
getClientRectsMock.mockReturnValue({ length: 1 });
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(() => {
|
|
||||||
getBoundingClientRectMock.mockRestore();
|
|
||||||
getClientRectsMock.mockRestore();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Anchor render perfectly', () => {
|
|
||||||
const wrapper = mount(
|
|
||||||
<Anchor>
|
|
||||||
<Link href="#API" title="API" />
|
|
||||||
</Anchor>,
|
|
||||||
);
|
|
||||||
|
|
||||||
wrapper.find('a[href="#API"]').simulate('click');
|
|
||||||
|
|
||||||
wrapper.instance().handleScroll();
|
|
||||||
expect(wrapper.instance().state).not.toBe(null);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Anchor render perfectly for complete href - click', () => {
|
|
||||||
const wrapper = mount(
|
|
||||||
<Anchor>
|
|
||||||
<Link href="http://www.example.com/#API" title="API" />
|
|
||||||
</Anchor>,
|
|
||||||
);
|
|
||||||
wrapper.find('a[href="http://www.example.com/#API"]').simulate('click');
|
|
||||||
expect(wrapper.instance().state.activeLink).toBe('http://www.example.com/#API');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Anchor render perfectly for complete href - hash router', async () => {
|
|
||||||
const scrollToSpy = jest.spyOn(window, 'scrollTo');
|
|
||||||
let root = document.getElementById('root');
|
|
||||||
if (!root) {
|
|
||||||
root = document.createElement('div', { id: 'root' });
|
|
||||||
root.id = 'root';
|
|
||||||
document.body.appendChild(root);
|
|
||||||
}
|
|
||||||
mount(<div id="/faq?locale=en#Q1">Q1</div>, { attachTo: root });
|
|
||||||
const wrapper = mount(
|
|
||||||
<Anchor>
|
|
||||||
<Link href="/#/faq?locale=en#Q1" title="Q1" />
|
|
||||||
</Anchor>,
|
|
||||||
);
|
|
||||||
|
|
||||||
wrapper.instance().handleScrollTo('/#/faq?locale=en#Q1');
|
|
||||||
expect(wrapper.instance().state.activeLink).toBe('/#/faq?locale=en#Q1');
|
|
||||||
expect(scrollToSpy).not.toHaveBeenCalled();
|
|
||||||
await sleep(1000);
|
|
||||||
expect(scrollToSpy).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Anchor render perfectly for complete href - scroll', () => {
|
|
||||||
let root = document.getElementById('root');
|
|
||||||
if (!root) {
|
|
||||||
root = document.createElement('div', { id: 'root' });
|
|
||||||
root.id = 'root';
|
|
||||||
document.body.appendChild(root);
|
|
||||||
}
|
|
||||||
mount(<div id="API">Hello</div>, { attachTo: root });
|
|
||||||
const wrapper = mount(
|
|
||||||
<Anchor>
|
|
||||||
<Link href="http://www.example.com/#API" title="API" />
|
|
||||||
</Anchor>,
|
|
||||||
);
|
|
||||||
wrapper.instance().handleScroll();
|
|
||||||
expect(wrapper.instance().state.activeLink).toBe('http://www.example.com/#API');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Anchor render perfectly for complete href - scrollTo', async () => {
|
|
||||||
const scrollToSpy = jest.spyOn(window, 'scrollTo');
|
|
||||||
let root = document.getElementById('root');
|
|
||||||
if (!root) {
|
|
||||||
root = document.createElement('div', { id: 'root' });
|
|
||||||
root.id = 'root';
|
|
||||||
document.body.appendChild(root);
|
|
||||||
}
|
|
||||||
mount(<div id="#API">Hello</div>, { attachTo: root });
|
|
||||||
const wrapper = mount(
|
|
||||||
<Anchor>
|
|
||||||
<Link href="##API" title="API" />
|
|
||||||
</Anchor>,
|
|
||||||
);
|
|
||||||
wrapper.instance().handleScrollTo('##API');
|
|
||||||
expect(wrapper.instance().state.activeLink).toBe('##API');
|
|
||||||
const calls = scrollToSpy.mock.calls.length;
|
|
||||||
await sleep(1000);
|
|
||||||
expect(scrollToSpy.mock.calls.length).toBeGreaterThan(calls);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should remove listener when unmount', async () => {
|
|
||||||
const wrapper = mount(
|
|
||||||
<Anchor>
|
|
||||||
<Link href="#API" title="API" />
|
|
||||||
</Anchor>,
|
|
||||||
);
|
|
||||||
const removeListenerSpy = jest.spyOn(wrapper.instance().scrollEvent, 'remove');
|
|
||||||
wrapper.unmount();
|
|
||||||
expect(removeListenerSpy).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should unregister link when unmount children', async () => {
|
|
||||||
const wrapper = mount(
|
|
||||||
<Anchor>
|
|
||||||
<Link href="#API" title="API" />
|
|
||||||
</Anchor>,
|
|
||||||
);
|
|
||||||
expect(wrapper.instance().links).toEqual(['#API']);
|
|
||||||
wrapper.setProps({ children: null });
|
|
||||||
expect(wrapper.instance().links).toEqual([]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should update links when link href update', async () => {
|
|
||||||
let anchorInstance = null;
|
|
||||||
function AnchorUpdate({ href }) {
|
|
||||||
return (
|
|
||||||
<Anchor
|
|
||||||
ref={c => {
|
|
||||||
anchorInstance = c;
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Link href={href} title="API" />
|
|
||||||
</Anchor>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
const wrapper = mount(<AnchorUpdate href="#API" />);
|
|
||||||
|
|
||||||
expect(anchorInstance.links).toEqual(['#API']);
|
|
||||||
wrapper.setProps({ href: '#API_1' });
|
|
||||||
expect(anchorInstance.links).toEqual(['#API_1']);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Anchor onClick event', () => {
|
|
||||||
let event;
|
|
||||||
let link;
|
|
||||||
const handleClick = (...arg) => {
|
|
||||||
[event, link] = arg;
|
|
||||||
};
|
|
||||||
|
|
||||||
const href = '#API';
|
|
||||||
const title = 'API';
|
|
||||||
|
|
||||||
const wrapper = mount(
|
|
||||||
<Anchor onClick={handleClick}>
|
|
||||||
<Link href={href} title={title} />
|
|
||||||
</Anchor>,
|
|
||||||
);
|
|
||||||
|
|
||||||
wrapper.find(`a[href="${href}"]`).simulate('click');
|
|
||||||
|
|
||||||
wrapper.instance().handleScroll();
|
|
||||||
expect(event).not.toBe(undefined);
|
|
||||||
expect(link).toEqual({ href, title });
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Different function returns the same DOM', async () => {
|
|
||||||
let root = document.getElementById('root');
|
|
||||||
if (!root) {
|
|
||||||
root = document.createElement('div', { id: 'root' });
|
|
||||||
root.id = 'root';
|
|
||||||
document.body.appendChild(root);
|
|
||||||
}
|
|
||||||
mount(<div id="API">Hello</div>, { attachTo: root });
|
|
||||||
const getContainerA = () => {
|
|
||||||
return document.getElementById('API');
|
|
||||||
};
|
|
||||||
const getContainerB = () => {
|
|
||||||
return document.getElementById('API');
|
|
||||||
};
|
|
||||||
|
|
||||||
const wrapper = mount(
|
|
||||||
<Anchor getContainer={getContainerA}>
|
|
||||||
<Link href="#API" title="API" />
|
|
||||||
</Anchor>,
|
|
||||||
);
|
|
||||||
const removeListenerSpy = jest.spyOn(wrapper.instance().scrollEvent, 'remove');
|
|
||||||
await sleep(1000);
|
|
||||||
wrapper.setProps({ getContainer: getContainerB });
|
|
||||||
expect(removeListenerSpy).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Different function returns different DOM', async () => {
|
|
||||||
let root = document.getElementById('root');
|
|
||||||
if (!root) {
|
|
||||||
root = document.createElement('div', { id: 'root' });
|
|
||||||
root.id = 'root';
|
|
||||||
document.body.appendChild(root);
|
|
||||||
}
|
|
||||||
mount(
|
|
||||||
<div>
|
|
||||||
<div id="API1">Hello</div>
|
|
||||||
<div id="API2">World</div>
|
|
||||||
</div>,
|
|
||||||
{ attachTo: root },
|
|
||||||
);
|
|
||||||
const getContainerA = () => {
|
|
||||||
return document.getElementById('API1');
|
|
||||||
};
|
|
||||||
const getContainerB = () => {
|
|
||||||
return document.getElementById('API2');
|
|
||||||
};
|
|
||||||
const wrapper = mount(
|
|
||||||
<Anchor getContainer={getContainerA}>
|
|
||||||
<Link href="#API1" title="API1" />
|
|
||||||
<Link href="#API2" title="API2" />
|
|
||||||
</Anchor>,
|
|
||||||
);
|
|
||||||
const removeListenerSpy = jest.spyOn(wrapper.instance().scrollEvent, 'remove');
|
|
||||||
expect(removeListenerSpy).not.toHaveBeenCalled();
|
|
||||||
await sleep(1000);
|
|
||||||
wrapper.setProps({ getContainer: getContainerB });
|
|
||||||
expect(removeListenerSpy).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Same function returns the same DOM', () => {
|
|
||||||
let root = document.getElementById('root');
|
|
||||||
if (!root) {
|
|
||||||
root = document.createElement('div', { id: 'root' });
|
|
||||||
root.id = 'root';
|
|
||||||
document.body.appendChild(root);
|
|
||||||
}
|
|
||||||
mount(<div id="API">Hello</div>, { attachTo: root });
|
|
||||||
const getContainer = () => document.getElementById('API');
|
|
||||||
const wrapper = mount(
|
|
||||||
<Anchor getContainer={getContainer}>
|
|
||||||
<Link href="#API" title="API" />
|
|
||||||
</Anchor>,
|
|
||||||
);
|
|
||||||
wrapper.find('a[href="#API"]').simulate('click');
|
|
||||||
wrapper.instance().handleScroll();
|
|
||||||
expect(wrapper.instance().state).not.toBe(null);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Same function returns different DOM', async () => {
|
|
||||||
let root = document.getElementById('root');
|
|
||||||
if (!root) {
|
|
||||||
root = document.createElement('div', { id: 'root' });
|
|
||||||
root.id = 'root';
|
|
||||||
document.body.appendChild(root);
|
|
||||||
}
|
|
||||||
mount(
|
|
||||||
<div>
|
|
||||||
<div id="API1">Hello</div>
|
|
||||||
<div id="API2">World</div>
|
|
||||||
</div>,
|
|
||||||
{ attachTo: root },
|
|
||||||
);
|
|
||||||
const holdContainer = {
|
|
||||||
container: document.getElementById('API1'),
|
|
||||||
};
|
|
||||||
const getContainer = () => {
|
|
||||||
return holdContainer.container;
|
|
||||||
};
|
|
||||||
const wrapper = mount(
|
|
||||||
<Anchor getContainer={getContainer}>
|
|
||||||
<Link href="#API1" title="API1" />
|
|
||||||
<Link href="#API2" title="API2" />
|
|
||||||
</Anchor>,
|
|
||||||
);
|
|
||||||
const removeListenerSpy = jest.spyOn(wrapper.instance().scrollEvent, 'remove');
|
|
||||||
expect(removeListenerSpy).not.toHaveBeenCalled();
|
|
||||||
await sleep(1000);
|
|
||||||
holdContainer.container = document.getElementById('API2');
|
|
||||||
wrapper.setProps({ 'data-only-trigger-re-render': true });
|
|
||||||
expect(removeListenerSpy).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Anchor getCurrentAnchor prop', () => {
|
|
||||||
const getCurrentAnchor = () => '#API2';
|
|
||||||
const wrapper = mount(
|
|
||||||
<Anchor getCurrentAnchor={getCurrentAnchor}>
|
|
||||||
<Link href="#API1" title="API1" />
|
|
||||||
<Link href="#API2" title="API2" />
|
|
||||||
</Anchor>,
|
|
||||||
);
|
|
||||||
expect(wrapper.instance().state.activeLink).toBe('#API2');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Anchor targetOffset prop', async () => {
|
|
||||||
let dateNowMock;
|
|
||||||
|
|
||||||
function dataNowMockFn() {
|
|
||||||
let start = 0;
|
|
||||||
|
|
||||||
const handler = () => {
|
|
||||||
return (start += 1000);
|
|
||||||
};
|
|
||||||
|
|
||||||
return jest.spyOn(Date, 'now').mockImplementation(handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
dateNowMock = dataNowMockFn();
|
|
||||||
|
|
||||||
const scrollToSpy = jest.spyOn(window, 'scrollTo');
|
|
||||||
let root = document.getElementById('root');
|
|
||||||
if (!root) {
|
|
||||||
root = document.createElement('div', { id: 'root' });
|
|
||||||
root.id = 'root';
|
|
||||||
document.body.appendChild(root);
|
|
||||||
}
|
|
||||||
mount(<h1 id="API">Hello</h1>, { attachTo: root });
|
|
||||||
const wrapper = mount(
|
|
||||||
<Anchor>
|
|
||||||
<Link href="#API" title="API" />
|
|
||||||
</Anchor>,
|
|
||||||
);
|
|
||||||
wrapper.instance().handleScrollTo('#API');
|
|
||||||
await sleep(30);
|
|
||||||
expect(scrollToSpy).toHaveBeenLastCalledWith(0, 1000);
|
|
||||||
dateNowMock = dataNowMockFn();
|
|
||||||
|
|
||||||
wrapper.setProps({ offsetTop: 100 });
|
|
||||||
wrapper.instance().handleScrollTo('#API');
|
|
||||||
await sleep(30);
|
|
||||||
expect(scrollToSpy).toHaveBeenLastCalledWith(0, 900);
|
|
||||||
dateNowMock = dataNowMockFn();
|
|
||||||
|
|
||||||
wrapper.setProps({ targetOffset: 200 });
|
|
||||||
wrapper.instance().handleScrollTo('#API');
|
|
||||||
await sleep(30);
|
|
||||||
expect(scrollToSpy).toHaveBeenLastCalledWith(0, 800);
|
|
||||||
|
|
||||||
dateNowMock.mockRestore();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Anchor onChange prop', async () => {
|
|
||||||
const onChange = jest.fn();
|
|
||||||
const wrapper = mount(
|
|
||||||
<Anchor onChange={onChange}>
|
|
||||||
<Link href="#API1" title="API1" />
|
|
||||||
<Link href="#API2" title="API2" />
|
|
||||||
</Anchor>,
|
|
||||||
);
|
|
||||||
expect(onChange).toHaveBeenCalledTimes(1);
|
|
||||||
wrapper.instance().handleScrollTo('#API2');
|
|
||||||
expect(onChange).toHaveBeenCalledTimes(2);
|
|
||||||
expect(onChange).toHaveBeenCalledWith('#API2');
|
|
||||||
});
|
|
||||||
});
|
|
360
components/anchor/__tests__/Anchor.test.tsx
Normal file
360
components/anchor/__tests__/Anchor.test.tsx
Normal file
@ -0,0 +1,360 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { mount } from 'enzyme';
|
||||||
|
import Anchor from '..';
|
||||||
|
import { sleep } from '../../../tests/utils';
|
||||||
|
|
||||||
|
const { Link } = Anchor;
|
||||||
|
|
||||||
|
function createGetContainer(id: string) {
|
||||||
|
return () => {
|
||||||
|
const container = document.getElementById(id);
|
||||||
|
if (container == null) {
|
||||||
|
throw new Error();
|
||||||
|
}
|
||||||
|
return container;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function createDiv() {
|
||||||
|
const root = document.createElement('div');
|
||||||
|
document.body.appendChild(root);
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
let idCounter = 0;
|
||||||
|
const getHashUrl = () => `Anchor-API-${idCounter++}`;
|
||||||
|
|
||||||
|
describe('Anchor Render', () => {
|
||||||
|
const getBoundingClientRectMock = jest.spyOn(
|
||||||
|
HTMLHeadingElement.prototype,
|
||||||
|
'getBoundingClientRect',
|
||||||
|
);
|
||||||
|
const getClientRectsMock = jest.spyOn(HTMLHeadingElement.prototype, 'getClientRects');
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
getBoundingClientRectMock.mockReturnValue({
|
||||||
|
width: 100,
|
||||||
|
height: 100,
|
||||||
|
top: 1000,
|
||||||
|
} as DOMRect);
|
||||||
|
getClientRectsMock.mockReturnValue({ length: 1 } as DOMRectList);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
getBoundingClientRectMock.mockRestore();
|
||||||
|
getClientRectsMock.mockRestore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Anchor render perfectly', () => {
|
||||||
|
const hash = getHashUrl();
|
||||||
|
const wrapper = mount<Anchor>(
|
||||||
|
<Anchor>
|
||||||
|
<Link href={`#${hash}`} title={hash} />
|
||||||
|
</Anchor>,
|
||||||
|
);
|
||||||
|
|
||||||
|
wrapper.find(`a[href="#${hash}"]`).simulate('click');
|
||||||
|
|
||||||
|
wrapper.instance().handleScroll();
|
||||||
|
expect(wrapper.instance().state).not.toBe(null);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Anchor render perfectly for complete href - click', () => {
|
||||||
|
const hash = getHashUrl();
|
||||||
|
const wrapper = mount<Anchor>(
|
||||||
|
<Anchor>
|
||||||
|
<Link href={`http://www.example.com/#${hash}`} title={hash} />
|
||||||
|
</Anchor>,
|
||||||
|
);
|
||||||
|
wrapper.find(`a[href="http://www.example.com/#${hash}"]`).simulate('click');
|
||||||
|
expect(wrapper.instance().state.activeLink).toBe(`http://www.example.com/#${hash}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Anchor render perfectly for complete href - hash router', async () => {
|
||||||
|
const root = createDiv();
|
||||||
|
const scrollToSpy = jest.spyOn(window, 'scrollTo');
|
||||||
|
mount(<div id="/faq?locale=en#Q1">Q1</div>, { attachTo: root });
|
||||||
|
const wrapper = mount<Anchor>(
|
||||||
|
<Anchor>
|
||||||
|
<Link href="/#/faq?locale=en#Q1" title="Q1" />
|
||||||
|
</Anchor>,
|
||||||
|
);
|
||||||
|
|
||||||
|
wrapper.instance().handleScrollTo('/#/faq?locale=en#Q1');
|
||||||
|
expect(wrapper.instance().state.activeLink).toBe('/#/faq?locale=en#Q1');
|
||||||
|
expect(scrollToSpy).not.toHaveBeenCalled();
|
||||||
|
await sleep(1000);
|
||||||
|
expect(scrollToSpy).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Anchor render perfectly for complete href - scroll', () => {
|
||||||
|
const hash = getHashUrl();
|
||||||
|
const root = createDiv();
|
||||||
|
mount(<div id={hash}>Hello</div>, { attachTo: root });
|
||||||
|
const wrapper = mount<Anchor>(
|
||||||
|
<Anchor>
|
||||||
|
<Link href={`http://www.example.com/#${hash}`} title={hash} />
|
||||||
|
</Anchor>,
|
||||||
|
);
|
||||||
|
wrapper.instance().handleScroll();
|
||||||
|
expect(wrapper.instance().state.activeLink).toBe(`http://www.example.com/#${hash}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Anchor render perfectly for complete href - scrollTo', async () => {
|
||||||
|
const hash = getHashUrl();
|
||||||
|
const scrollToSpy = jest.spyOn(window, 'scrollTo');
|
||||||
|
const root = createDiv();
|
||||||
|
mount(<div id={`#${hash}`}>Hello</div>, { attachTo: root });
|
||||||
|
const wrapper = mount<Anchor>(
|
||||||
|
<Anchor>
|
||||||
|
<Link href={`##${hash}`} title={hash} />
|
||||||
|
</Anchor>,
|
||||||
|
);
|
||||||
|
wrapper.instance().handleScrollTo(`##${hash}`);
|
||||||
|
expect(wrapper.instance().state.activeLink).toBe(`##${hash}`);
|
||||||
|
const calls = scrollToSpy.mock.calls.length;
|
||||||
|
await sleep(1000);
|
||||||
|
expect(scrollToSpy.mock.calls.length).toBeGreaterThan(calls);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should remove listener when unmount', async () => {
|
||||||
|
const hash = getHashUrl();
|
||||||
|
const wrapper = mount<Anchor>(
|
||||||
|
<Anchor>
|
||||||
|
<Link href={`#${hash}`} title={hash} />
|
||||||
|
</Anchor>,
|
||||||
|
);
|
||||||
|
const removeListenerSpy = jest.spyOn((wrapper.instance() as any).scrollEvent, 'remove');
|
||||||
|
wrapper.unmount();
|
||||||
|
expect(removeListenerSpy).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should unregister link when unmount children', async () => {
|
||||||
|
const hash = getHashUrl();
|
||||||
|
const wrapper = mount<Anchor>(
|
||||||
|
<Anchor>
|
||||||
|
<Link href={`#${hash}`} title={hash} />
|
||||||
|
</Anchor>,
|
||||||
|
);
|
||||||
|
expect((wrapper.instance() as any).links).toEqual([`#${hash}`]);
|
||||||
|
wrapper.setProps({ children: null });
|
||||||
|
expect((wrapper.instance() as any).links).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should update links when link href update', async () => {
|
||||||
|
const hash = getHashUrl();
|
||||||
|
let anchorInstance: Anchor | null = null;
|
||||||
|
function AnchorUpdate({ href }: { href: string }) {
|
||||||
|
return (
|
||||||
|
<Anchor
|
||||||
|
ref={c => {
|
||||||
|
anchorInstance = c;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Link href={href} title={hash} />
|
||||||
|
</Anchor>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const wrapper = mount(<AnchorUpdate href={`#${hash}`} />);
|
||||||
|
|
||||||
|
if (anchorInstance == null) {
|
||||||
|
throw new Error('anchorInstance should not be null');
|
||||||
|
}
|
||||||
|
expect((anchorInstance as any).links).toEqual([`#${hash}`]);
|
||||||
|
wrapper.setProps({ href: `#${hash}_1` });
|
||||||
|
expect((anchorInstance as any).links).toEqual([`#${hash}_1`]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Anchor onClick event', () => {
|
||||||
|
const hash = getHashUrl();
|
||||||
|
let event;
|
||||||
|
let link;
|
||||||
|
const handleClick = (
|
||||||
|
e: React.MouseEvent<HTMLElement>,
|
||||||
|
_link: { title: React.ReactNode; href: string },
|
||||||
|
) => {
|
||||||
|
event = e;
|
||||||
|
link = _link;
|
||||||
|
};
|
||||||
|
|
||||||
|
const href = `#${hash}`;
|
||||||
|
const title = hash;
|
||||||
|
|
||||||
|
const wrapper = mount<Anchor>(
|
||||||
|
<Anchor onClick={handleClick}>
|
||||||
|
<Link href={href} title={title} />
|
||||||
|
</Anchor>,
|
||||||
|
);
|
||||||
|
|
||||||
|
wrapper.find(`a[href="${href}"]`).simulate('click');
|
||||||
|
|
||||||
|
wrapper.instance().handleScroll();
|
||||||
|
expect(event).not.toBe(undefined);
|
||||||
|
expect(link).toEqual({ href, title });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Different function returns the same DOM', async () => {
|
||||||
|
const hash = getHashUrl();
|
||||||
|
const root = createDiv();
|
||||||
|
mount(<div id={hash}>Hello</div>, { attachTo: root });
|
||||||
|
const getContainerA = createGetContainer(hash);
|
||||||
|
const getContainerB = createGetContainer(hash);
|
||||||
|
|
||||||
|
const wrapper = mount<Anchor>(
|
||||||
|
<Anchor getContainer={getContainerA}>
|
||||||
|
<Link href={`#${hash}`} title={hash} />
|
||||||
|
</Anchor>,
|
||||||
|
);
|
||||||
|
const removeListenerSpy = jest.spyOn((wrapper.instance() as any).scrollEvent, 'remove');
|
||||||
|
await sleep(1000);
|
||||||
|
wrapper.setProps({ getContainer: getContainerB });
|
||||||
|
expect(removeListenerSpy).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Different function returns different DOM', async () => {
|
||||||
|
const hash1 = getHashUrl();
|
||||||
|
const hash2 = getHashUrl();
|
||||||
|
const root = createDiv();
|
||||||
|
mount(
|
||||||
|
<div>
|
||||||
|
<div id={hash1}>Hello</div>
|
||||||
|
<div id={hash2}>World</div>
|
||||||
|
</div>,
|
||||||
|
{ attachTo: root },
|
||||||
|
);
|
||||||
|
const getContainerA = createGetContainer(hash1);
|
||||||
|
const getContainerB = createGetContainer(hash2);
|
||||||
|
const wrapper = mount<Anchor>(
|
||||||
|
<Anchor getContainer={getContainerA}>
|
||||||
|
<Link href={`#${hash1}`} title={hash1} />
|
||||||
|
<Link href={`#${hash2}`} title={hash2} />
|
||||||
|
</Anchor>,
|
||||||
|
);
|
||||||
|
const removeListenerSpy = jest.spyOn((wrapper.instance() as any).scrollEvent, 'remove');
|
||||||
|
expect(removeListenerSpy).not.toHaveBeenCalled();
|
||||||
|
await sleep(1000);
|
||||||
|
wrapper.setProps({ getContainer: getContainerB });
|
||||||
|
expect(removeListenerSpy).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Same function returns the same DOM', () => {
|
||||||
|
const hash = getHashUrl();
|
||||||
|
const root = createDiv();
|
||||||
|
mount(<div id={hash}>Hello</div>, { attachTo: root });
|
||||||
|
const getContainer = createGetContainer(hash);
|
||||||
|
const wrapper = mount(
|
||||||
|
<Anchor getContainer={getContainer}>
|
||||||
|
<Link href={`#${hash}`} title={hash} />
|
||||||
|
</Anchor>,
|
||||||
|
);
|
||||||
|
wrapper.find(`a[href="#${hash}"]`).simulate('click');
|
||||||
|
(wrapper.instance() as any).handleScroll();
|
||||||
|
expect(wrapper.instance().state).not.toBe(null);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Same function returns different DOM', async () => {
|
||||||
|
const hash1 = getHashUrl();
|
||||||
|
const hash2 = getHashUrl();
|
||||||
|
const root = createDiv();
|
||||||
|
mount(
|
||||||
|
<div>
|
||||||
|
<div id={hash1}>Hello</div>
|
||||||
|
<div id={hash2}>World</div>
|
||||||
|
</div>,
|
||||||
|
{ attachTo: root },
|
||||||
|
);
|
||||||
|
const holdContainer = {
|
||||||
|
container: document.getElementById(hash1),
|
||||||
|
};
|
||||||
|
const getContainer = () => {
|
||||||
|
if (holdContainer.container == null) {
|
||||||
|
throw new Error('container should not be null');
|
||||||
|
}
|
||||||
|
return holdContainer.container;
|
||||||
|
};
|
||||||
|
const wrapper = mount(
|
||||||
|
<Anchor getContainer={getContainer}>
|
||||||
|
<Link href={`#${hash1}`} title={hash1} />
|
||||||
|
<Link href={`#${hash2}`} title={hash2} />
|
||||||
|
</Anchor>,
|
||||||
|
);
|
||||||
|
const removeListenerSpy = jest.spyOn((wrapper.instance() as any).scrollEvent, 'remove');
|
||||||
|
expect(removeListenerSpy).not.toHaveBeenCalled();
|
||||||
|
await sleep(1000);
|
||||||
|
holdContainer.container = document.getElementById(hash2);
|
||||||
|
wrapper.setProps({ 'data-only-trigger-re-render': true });
|
||||||
|
expect(removeListenerSpy).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Anchor getCurrentAnchor prop', () => {
|
||||||
|
const hash1 = getHashUrl();
|
||||||
|
const hash2 = getHashUrl();
|
||||||
|
const getCurrentAnchor = () => `#${hash2}`;
|
||||||
|
const wrapper = mount<Anchor>(
|
||||||
|
<Anchor getCurrentAnchor={getCurrentAnchor}>
|
||||||
|
<Link href={`#${hash1}`} title={hash1} />
|
||||||
|
<Link href={`#${hash2}`} title={hash2} />
|
||||||
|
</Anchor>,
|
||||||
|
);
|
||||||
|
expect(wrapper.instance().state.activeLink).toBe(`#${hash2}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Anchor targetOffset prop', async () => {
|
||||||
|
const hash = getHashUrl();
|
||||||
|
let dateNowMock;
|
||||||
|
|
||||||
|
function dataNowMockFn() {
|
||||||
|
let start = 0;
|
||||||
|
|
||||||
|
const handler = () => {
|
||||||
|
return (start += 1000);
|
||||||
|
};
|
||||||
|
|
||||||
|
return jest.spyOn(Date, 'now').mockImplementation(handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
dateNowMock = dataNowMockFn();
|
||||||
|
|
||||||
|
const scrollToSpy = jest.spyOn(window, 'scrollTo');
|
||||||
|
const root = createDiv();
|
||||||
|
mount(<h1 id={hash}>Hello</h1>, { attachTo: root });
|
||||||
|
const wrapper = mount<Anchor>(
|
||||||
|
<Anchor>
|
||||||
|
<Link href={`#${hash}`} title={hash} />
|
||||||
|
</Anchor>,
|
||||||
|
);
|
||||||
|
wrapper.instance().handleScrollTo(`#${hash}`);
|
||||||
|
await sleep(30);
|
||||||
|
expect(scrollToSpy).toHaveBeenLastCalledWith(0, 1000);
|
||||||
|
dateNowMock = dataNowMockFn();
|
||||||
|
|
||||||
|
wrapper.setProps({ offsetTop: 100 });
|
||||||
|
wrapper.instance().handleScrollTo(`#${hash}`);
|
||||||
|
await sleep(30);
|
||||||
|
expect(scrollToSpy).toHaveBeenLastCalledWith(0, 900);
|
||||||
|
dateNowMock = dataNowMockFn();
|
||||||
|
|
||||||
|
wrapper.setProps({ targetOffset: 200 });
|
||||||
|
wrapper.instance().handleScrollTo(`#${hash}`);
|
||||||
|
await sleep(30);
|
||||||
|
expect(scrollToSpy).toHaveBeenLastCalledWith(0, 800);
|
||||||
|
|
||||||
|
dateNowMock.mockRestore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Anchor onChange prop', async () => {
|
||||||
|
const hash1 = getHashUrl();
|
||||||
|
const hash2 = getHashUrl();
|
||||||
|
const onChange = jest.fn();
|
||||||
|
const wrapper = mount<Anchor>(
|
||||||
|
<Anchor onChange={onChange}>
|
||||||
|
<Link href={`#${hash1}`} title={hash1} />
|
||||||
|
<Link href={`#${hash2}`} title={hash2} />
|
||||||
|
</Anchor>,
|
||||||
|
);
|
||||||
|
expect(onChange).toHaveBeenCalledTimes(1);
|
||||||
|
wrapper.instance().handleScrollTo(hash2);
|
||||||
|
expect(onChange).toHaveBeenCalledTimes(2);
|
||||||
|
expect(onChange).toHaveBeenCalledWith(hash2);
|
||||||
|
});
|
||||||
|
});
|
@ -1,4 +1,4 @@
|
|||||||
import React from 'react';
|
import * as React from 'react';
|
||||||
import { AntAnchor } from './Anchor';
|
import { AntAnchor } from './Anchor';
|
||||||
|
|
||||||
const AnchorContext = React.createContext<AntAnchor>(null as any);
|
const AnchorContext = React.createContext<AntAnchor>(null as any);
|
||||||
|
@ -150,13 +150,18 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
& > &-loading-icon {
|
& > &-loading-icon {
|
||||||
padding-right: @margin-xs;
|
|
||||||
transition: all 0.3s @ease-in-out;
|
transition: all 0.3s @ease-in-out;
|
||||||
|
|
||||||
|
.@{iconfont-css-prefix} {
|
||||||
|
padding-right: @margin-xs;
|
||||||
|
}
|
||||||
|
|
||||||
&:only-child {
|
&:only-child {
|
||||||
|
.@{iconfont-css-prefix} {
|
||||||
padding-right: 0;
|
padding-right: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&-group {
|
&-group {
|
||||||
.btn-group(@btn-prefix-cls);
|
.btn-group(@btn-prefix-cls);
|
||||||
|
@ -66,8 +66,14 @@ exports[`renders ./components/drawer/demo/multi-level-drawer.md correctly 1`] =
|
|||||||
exports[`renders ./components/drawer/demo/placement.md correctly 1`] = `
|
exports[`renders ./components/drawer/demo/placement.md correctly 1`] = `
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
class="ant-radio-group ant-radio-group-outline"
|
class="ant-space ant-space-horizontal ant-space-align-center"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="ant-space-item"
|
||||||
style="margin-right:8px"
|
style="margin-right:8px"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="ant-radio-group ant-radio-group-outline"
|
||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
class="ant-radio-wrapper"
|
class="ant-radio-wrapper"
|
||||||
@ -147,6 +153,10 @@ exports[`renders ./components/drawer/demo/placement.md correctly 1`] = `
|
|||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="ant-space-item"
|
||||||
|
>
|
||||||
<button
|
<button
|
||||||
class="ant-btn ant-btn-primary"
|
class="ant-btn ant-btn-primary"
|
||||||
type="button"
|
type="button"
|
||||||
@ -155,6 +165,8 @@ exports[`renders ./components/drawer/demo/placement.md correctly 1`] = `
|
|||||||
Open
|
Open
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ title:
|
|||||||
The Drawer can appear from any edge of the screen.
|
The Drawer can appear from any edge of the screen.
|
||||||
|
|
||||||
```jsx
|
```jsx
|
||||||
import { Drawer, Button, Radio } from 'antd';
|
import { Drawer, Button, Radio, Space } from 'antd';
|
||||||
|
|
||||||
const RadioGroup = Radio.Group;
|
const RadioGroup = Radio.Group;
|
||||||
|
|
||||||
@ -42,11 +42,8 @@ class App extends React.Component {
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<RadioGroup
|
<Space>
|
||||||
style={{ marginRight: 8 }}
|
<RadioGroup defaultValue={this.state.placement} onChange={this.onChange}>
|
||||||
defaultValue={this.state.placement}
|
|
||||||
onChange={this.onChange}
|
|
||||||
>
|
|
||||||
<Radio value="top">top</Radio>
|
<Radio value="top">top</Radio>
|
||||||
<Radio value="right">right</Radio>
|
<Radio value="right">right</Radio>
|
||||||
<Radio value="bottom">bottom</Radio>
|
<Radio value="bottom">bottom</Radio>
|
||||||
@ -55,6 +52,7 @@ class App extends React.Component {
|
|||||||
<Button type="primary" onClick={this.showDrawer}>
|
<Button type="primary" onClick={this.showDrawer}>
|
||||||
Open
|
Open
|
||||||
</Button>
|
</Button>
|
||||||
|
</Space>
|
||||||
<Drawer
|
<Drawer
|
||||||
title="Basic Drawer"
|
title="Basic Drawer"
|
||||||
placement={this.state.placement}
|
placement={this.state.placement}
|
||||||
|
@ -194,7 +194,7 @@ Provide linkage between forms. If a sub form with `name` prop update, it will au
|
|||||||
| isFieldValidating | Check fields if is in validating | (name: [NamePath](#NamePath)) => boolean |
|
| isFieldValidating | Check fields if is in validating | (name: [NamePath](#NamePath)) => boolean |
|
||||||
| resetFields | Reset fields to `initialValues` | (fields?: [NamePath](#NamePath)[]) => void |
|
| resetFields | Reset fields to `initialValues` | (fields?: [NamePath](#NamePath)[]) => void |
|
||||||
| scrollToField | Scroll to field position | (name: [NamePath](#NamePath), options: [[ScrollOptions](https://github.com/stipsan/scroll-into-view-if-needed/blob/ece40bd9143f48caf4b99503425ecb16b0ad8249/src/types.ts#L10)]) => void |
|
| scrollToField | Scroll to field position | (name: [NamePath](#NamePath), options: [[ScrollOptions](https://github.com/stipsan/scroll-into-view-if-needed/blob/ece40bd9143f48caf4b99503425ecb16b0ad8249/src/types.ts#L10)]) => void |
|
||||||
| setFields | Set fields status | (fields: FieldData[]) => void |
|
| setFields | Set fields status | (fields: [FieldData](#FieldData)[]) => void |
|
||||||
| setFieldsValue | Set fields value | (values) => void |
|
| setFieldsValue | Set fields value | (values) => void |
|
||||||
| submit | Submit the form. It's same as click `submit` button | () => void |
|
| submit | Submit the form. It's same as click `submit` button | () => void |
|
||||||
| validateFields | Validate fields | (nameList?: [NamePath](#NamePath)[]) => Promise |
|
| validateFields | Validate fields | (nameList?: [NamePath](#NamePath)[]) => Promise |
|
||||||
@ -325,6 +325,16 @@ In most case, we always recommend to use Form `initialValues`. Use Item `initial
|
|||||||
1. Form `initialValues` is the first priority
|
1. Form `initialValues` is the first priority
|
||||||
2. Field `initialValue` is secondary \*. Not work when multiple Item with same `name` setting the `initialValue`
|
2. Field `initialValue` is secondary \*. Not work when multiple Item with same `name` setting the `initialValue`
|
||||||
|
|
||||||
|
### Why `onFieldsChange` trigger three times on change when field set `rules`?
|
||||||
|
|
||||||
|
Validating is also part of the value updating. It pass follow steps:
|
||||||
|
|
||||||
|
1. Trigger value change
|
||||||
|
2. Rule validating
|
||||||
|
3. Rule validated
|
||||||
|
|
||||||
|
In each `onFieldsChange`, you will get `false` > `true` > `false` with `isFieldValidating`.
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.site-form-item-icon {
|
.site-form-item-icon {
|
||||||
color: rgba(0, 0, 0, 0.25);
|
color: rgba(0, 0, 0, 0.25);
|
||||||
|
@ -195,7 +195,7 @@ Form 通过增量更新方式,只更新被修改的字段相关组件以达到
|
|||||||
| isFieldValidating | 检查一组字段是否正在校验 | (name: [NamePath](#NamePath)) => boolean |
|
| isFieldValidating | 检查一组字段是否正在校验 | (name: [NamePath](#NamePath)) => boolean |
|
||||||
| resetFields | 重置一组字段到 `initialValues` | (fields?: [NamePath](#NamePath)[]) => void |
|
| resetFields | 重置一组字段到 `initialValues` | (fields?: [NamePath](#NamePath)[]) => void |
|
||||||
| scrollToField | 滚动到对应字段位置 | (name: [NamePath](#NamePath), options: [[ScrollOptions](https://github.com/stipsan/scroll-into-view-if-needed/blob/ece40bd9143f48caf4b99503425ecb16b0ad8249/src/types.ts#L10)]) => void |
|
| scrollToField | 滚动到对应字段位置 | (name: [NamePath](#NamePath), options: [[ScrollOptions](https://github.com/stipsan/scroll-into-view-if-needed/blob/ece40bd9143f48caf4b99503425ecb16b0ad8249/src/types.ts#L10)]) => void |
|
||||||
| setFields | 设置一组字段状态 | (fields: FieldData[]) => void |
|
| setFields | 设置一组字段状态 | (fields: [FieldData](#FieldData)[]) => void |
|
||||||
| setFieldsValue | 设置表单的值 | (values) => void |
|
| setFieldsValue | 设置表单的值 | (values) => void |
|
||||||
| submit | 提交表单,与点击 `submit` 按钮效果相同 | () => void |
|
| submit | 提交表单,与点击 `submit` 按钮效果相同 | () => void |
|
||||||
| validateFields | 触发表单验证 | (nameList?: [NamePath](#NamePath)[]) => Promise |
|
| validateFields | 触发表单验证 | (nameList?: [NamePath](#NamePath)[]) => Promise |
|
||||||
@ -326,6 +326,16 @@ validator(rule, value, callback) => {
|
|||||||
1. Form 的 `initialValues` 拥有最高优先级
|
1. Form 的 `initialValues` 拥有最高优先级
|
||||||
2. Field 的 `initialValue` 次之 \*. 多个同 `name` Item 都设置 `initialValue` 时,则 Item 的 `initialValue` 不生效
|
2. Field 的 `initialValue` 次之 \*. 多个同 `name` Item 都设置 `initialValue` 时,则 Item 的 `initialValue` 不生效
|
||||||
|
|
||||||
|
### 为什么字段设置 `rules` 后更改值 `onFieldsChange` 会触发三次?
|
||||||
|
|
||||||
|
字段除了本身的值变化外,校验也是其状态之一。因而在触发字段变化会经历以下几个阶段:
|
||||||
|
|
||||||
|
1. Trigger value change
|
||||||
|
2. Rule validating
|
||||||
|
3. Rule validated
|
||||||
|
|
||||||
|
在触发过程中,调用 `isFieldValidating` 会经历 `false` > `true` > `false` 的变化过程。
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.site-form-item-icon {
|
.site-form-item-icon {
|
||||||
color: rgba(0, 0, 0, 0.25);
|
color: rgba(0, 0, 0, 0.25);
|
||||||
|
@ -16,30 +16,26 @@ A simple playground for column count and gutter.
|
|||||||
```jsx
|
```jsx
|
||||||
import { Row, Col, Slider } from 'antd';
|
import { Row, Col, Slider } from 'antd';
|
||||||
|
|
||||||
|
const gutters = {};
|
||||||
|
const vgutters = {};
|
||||||
|
const colCounts = {};
|
||||||
|
|
||||||
|
[8, 16, 24, 32, 40, 48].forEach((value, i) => {
|
||||||
|
gutters[i] = value;
|
||||||
|
});
|
||||||
|
[8, 16, 24, 32, 40, 48].forEach((value, i) => {
|
||||||
|
vgutters[i] = value;
|
||||||
|
});
|
||||||
|
[2, 3, 4, 6, 8, 12].forEach((value, i) => {
|
||||||
|
colCounts[i] = value;
|
||||||
|
});
|
||||||
|
|
||||||
class App extends React.Component {
|
class App extends React.Component {
|
||||||
gutters = {};
|
state = {
|
||||||
|
|
||||||
vgutters = {};
|
|
||||||
|
|
||||||
colCounts = {};
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
this.state = {
|
|
||||||
gutterKey: 1,
|
gutterKey: 1,
|
||||||
vgutterKey: 1,
|
vgutterKey: 1,
|
||||||
colCountKey: 2,
|
colCountKey: 2,
|
||||||
};
|
};
|
||||||
[8, 16, 24, 32, 40, 48].forEach((value, i) => {
|
|
||||||
this.gutters[i] = value;
|
|
||||||
});
|
|
||||||
[8, 16, 24, 32, 40, 48].forEach((value, i) => {
|
|
||||||
this.vgutters[i] = value;
|
|
||||||
});
|
|
||||||
[2, 3, 4, 6, 8, 12].forEach((value, i) => {
|
|
||||||
this.colCounts[i] = value;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onGutterChange = gutterKey => {
|
onGutterChange = gutterKey => {
|
||||||
this.setState({ gutterKey });
|
this.setState({ gutterKey });
|
||||||
@ -56,7 +52,7 @@ class App extends React.Component {
|
|||||||
render() {
|
render() {
|
||||||
const { gutterKey, vgutterKey, colCountKey } = this.state;
|
const { gutterKey, vgutterKey, colCountKey } = this.state;
|
||||||
const cols = [];
|
const cols = [];
|
||||||
const colCount = this.colCounts[colCountKey];
|
const colCount = colCounts[colCountKey];
|
||||||
let colCode = '';
|
let colCode = '';
|
||||||
for (let i = 0; i < colCount; i++) {
|
for (let i = 0; i < colCount; i++) {
|
||||||
cols.push(
|
cols.push(
|
||||||
@ -72,39 +68,42 @@ class App extends React.Component {
|
|||||||
<div style={{ width: '50%' }}>
|
<div style={{ width: '50%' }}>
|
||||||
<Slider
|
<Slider
|
||||||
min={0}
|
min={0}
|
||||||
max={Object.keys(this.gutters).length - 1}
|
max={Object.keys(gutters).length - 1}
|
||||||
value={gutterKey}
|
value={gutterKey}
|
||||||
onChange={this.onGutterChange}
|
onChange={this.onGutterChange}
|
||||||
marks={this.gutters}
|
marks={gutters}
|
||||||
step={null}
|
step={null}
|
||||||
|
tipFormatter={value => gutters[value]}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<span style={{ marginRight: 6 }}>Vertical Gutter (px): </span>
|
<span style={{ marginRight: 6 }}>Vertical Gutter (px): </span>
|
||||||
<div style={{ width: '50%' }}>
|
<div style={{ width: '50%' }}>
|
||||||
<Slider
|
<Slider
|
||||||
min={0}
|
min={0}
|
||||||
max={Object.keys(this.vgutters).length - 1}
|
max={Object.keys(vgutters).length - 1}
|
||||||
value={vgutterKey}
|
value={vgutterKey}
|
||||||
onChange={this.onVGutterChange}
|
onChange={this.onVGutterChange}
|
||||||
marks={this.vgutters}
|
marks={vgutters}
|
||||||
step={null}
|
step={null}
|
||||||
|
tipFormatter={value => vgutters[value]}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<span style={{ marginRight: 6 }}>Column Count:</span>
|
<span style={{ marginRight: 6 }}>Column Count:</span>
|
||||||
<div style={{ width: '50%', marginBottom: 48 }}>
|
<div style={{ width: '50%', marginBottom: 48 }}>
|
||||||
<Slider
|
<Slider
|
||||||
min={0}
|
min={0}
|
||||||
max={Object.keys(this.colCounts).length - 1}
|
max={Object.keys(colCounts).length - 1}
|
||||||
value={colCountKey}
|
value={colCountKey}
|
||||||
onChange={this.onColCountChange}
|
onChange={this.onColCountChange}
|
||||||
marks={this.colCounts}
|
marks={colCounts}
|
||||||
step={null}
|
step={null}
|
||||||
|
tipFormatter={value => colCounts[value]}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<Row gutter={[this.gutters[gutterKey], this.vgutters[vgutterKey]]}>{cols}</Row>
|
<Row gutter={[gutters[gutterKey], vgutters[vgutterKey]]}>{cols}</Row>
|
||||||
<Row gutter={[this.gutters[gutterKey], this.vgutters[vgutterKey]]}>{cols}</Row>
|
<Row gutter={[gutters[gutterKey], vgutters[vgutterKey]]}>{cols}</Row>
|
||||||
<pre className="demo-code">{`<Row gutter={[${this.gutters[gutterKey]}, ${this.vgutters[vgutterKey]}]}>\n${colCode}</Row>`}</pre>
|
<pre className="demo-code">{`<Row gutter={[${gutters[gutterKey]}, ${vgutters[vgutterKey]}]}>\n${colCode}</Row>`}</pre>
|
||||||
<pre className="demo-code">{`<Row gutter={[${this.gutters[gutterKey]}, ${this.vgutters[vgutterKey]}]}>\n${colCode}</Row>`}</pre>
|
<pre className="demo-code">{`<Row gutter={[${gutters[gutterKey]}, ${vgutters[vgutterKey]}]}>\n${colCode}</Row>`}</pre>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -2237,7 +2237,7 @@ Array [
|
|||||||
aria-label="audio"
|
aria-label="audio"
|
||||||
class="anticon anticon-audio"
|
class="anticon anticon-audio"
|
||||||
role="img"
|
role="img"
|
||||||
style="font-size:16px;color:#1890ff;padding-right:4px"
|
style="font-size:16px;color:#1890ff"
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
|
@ -182,6 +182,14 @@ ReactDOM.render(<App />, mountNode);
|
|||||||
.site-input-group-wrapper .site-input-right:hover {
|
.site-input-group-wrapper .site-input-right:hover {
|
||||||
border-left-width: 1px;
|
border-left-width: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.site-input-group-wrapper .ant-input-rtl.site-input-right {
|
||||||
|
border-right-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.site-input-group-wrapper .ant-input-rtl.site-input-right:hover {
|
||||||
|
border-right-width: 1px;
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
@ -24,7 +24,6 @@ const suffix = (
|
|||||||
style={{
|
style={{
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
color: '#1890ff',
|
color: '#1890ff',
|
||||||
paddingRight: 4,
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -17,6 +17,13 @@
|
|||||||
@input-affix-margin: 4px;
|
@input-affix-margin: 4px;
|
||||||
|
|
||||||
.@{ant-prefix}-input {
|
.@{ant-prefix}-input {
|
||||||
|
&-affix-wrapper&-affix-wrapper-rtl {
|
||||||
|
> input.@{ant-prefix}-input {
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&-affix-wrapper-rtl {
|
&-affix-wrapper-rtl {
|
||||||
.@{ant-prefix}-input-prefix {
|
.@{ant-prefix}-input-prefix {
|
||||||
margin: 0 0 0 @input-affix-margin;
|
margin: 0 0 0 @input-affix-margin;
|
||||||
@ -83,6 +90,26 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.@{inputClass}-affix-wrapper {
|
||||||
|
&:not(:first-child) {
|
||||||
|
.@{inputClass}-group-rtl& {
|
||||||
|
border-top-left-radius: @border-radius-base;
|
||||||
|
border-top-right-radius: 0;
|
||||||
|
border-bottom-right-radius: 0;
|
||||||
|
border-bottom-left-radius: @border-radius-base;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(:last-child) {
|
||||||
|
.@{inputClass}-group-rtl& {
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
border-top-right-radius: @border-radius-base;
|
||||||
|
border-bottom-right-radius: @border-radius-base;
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&&-compact {
|
&&-compact {
|
||||||
& > *:not(:last-child) {
|
& > *:not(:last-child) {
|
||||||
.@{inputClass}-group-rtl& {
|
.@{inputClass}-group-rtl& {
|
||||||
@ -127,6 +154,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// search-input
|
// search-input
|
||||||
|
@search-prefix: ~'@{ant-prefix}-input-search';
|
||||||
@search-rtl-cls: ~'@{search-prefix}-rtl';
|
@search-rtl-cls: ~'@{search-prefix}-rtl';
|
||||||
|
|
||||||
.@{search-prefix} {
|
.@{search-prefix} {
|
||||||
@ -166,15 +194,31 @@
|
|||||||
&-enter-button {
|
&-enter-button {
|
||||||
input {
|
input {
|
||||||
.@{search-rtl-cls}& {
|
.@{search-rtl-cls}& {
|
||||||
border: @border-width-base @border-style-base @input-border-color;
|
border-right: @border-width-base @border-style-base @input-border-color;
|
||||||
border-left: 0;
|
border-left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover,
|
&:hover,
|
||||||
&:focus {
|
&:focus {
|
||||||
|
.@{search-rtl-cls}& {
|
||||||
border-color: @input-hover-border-color;
|
border-color: @input-hover-border-color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.@{ant-prefix}-input-affix-wrapper {
|
||||||
|
.@{search-rtl-cls}& {
|
||||||
|
border-right: @border-width-base @border-style-base @input-border-color;
|
||||||
|
border-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:focus {
|
||||||
|
.@{search-rtl-cls}& {
|
||||||
|
border-color: @input-hover-border-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
& + .@{ant-prefix}-input-group-addon,
|
& + .@{ant-prefix}-input-group-addon,
|
||||||
input + .@{ant-prefix}-input-group-addon {
|
input + .@{ant-prefix}-input-group-addon {
|
||||||
|
@ -158,18 +158,19 @@ class InternalMenu extends React.Component<InternalMenuProps, MenuState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getRealMenuMode() {
|
getRealMenuMode() {
|
||||||
|
const { mode } = this.props;
|
||||||
|
const { switchingModeFromInline } = this.state;
|
||||||
const inlineCollapsed = this.getInlineCollapsed();
|
const inlineCollapsed = this.getInlineCollapsed();
|
||||||
if (this.state.switchingModeFromInline && inlineCollapsed) {
|
if (switchingModeFromInline && inlineCollapsed) {
|
||||||
return 'inline';
|
return 'inline';
|
||||||
}
|
}
|
||||||
const { mode } = this.props;
|
|
||||||
return inlineCollapsed ? 'vertical' : mode;
|
return inlineCollapsed ? 'vertical' : mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
getInlineCollapsed() {
|
getInlineCollapsed() {
|
||||||
const { inlineCollapsed } = this.props;
|
const { inlineCollapsed, siderCollapsed } = this.props;
|
||||||
if (this.props.siderCollapsed !== undefined) {
|
if (siderCollapsed !== undefined) {
|
||||||
return this.props.siderCollapsed;
|
return siderCollapsed;
|
||||||
}
|
}
|
||||||
return inlineCollapsed;
|
return inlineCollapsed;
|
||||||
}
|
}
|
||||||
@ -178,6 +179,7 @@ class InternalMenu extends React.Component<InternalMenuProps, MenuState> {
|
|||||||
menuMode: MenuMode,
|
menuMode: MenuMode,
|
||||||
): { openTransitionName?: any; openAnimation?: any; motion?: Object } {
|
): { openTransitionName?: any; openAnimation?: any; motion?: Object } {
|
||||||
const { openTransitionName, openAnimation, motion } = this.props;
|
const { openTransitionName, openAnimation, motion } = this.props;
|
||||||
|
const { switchingModeFromInline } = this.state;
|
||||||
|
|
||||||
// Provides by user
|
// Provides by user
|
||||||
if (motion) {
|
if (motion) {
|
||||||
@ -210,7 +212,7 @@ class InternalMenu extends React.Component<InternalMenuProps, MenuState> {
|
|||||||
// submenu should hide without animation
|
// submenu should hide without animation
|
||||||
return {
|
return {
|
||||||
motion: {
|
motion: {
|
||||||
motionName: this.state.switchingModeFromInline ? '' : 'zoom-big',
|
motionName: switchingModeFromInline ? '' : 'zoom-big',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -277,6 +279,7 @@ class InternalMenu extends React.Component<InternalMenuProps, MenuState> {
|
|||||||
|
|
||||||
renderMenu = ({ getPopupContainer, getPrefixCls, direction }: ConfigConsumerProps) => {
|
renderMenu = ({ getPopupContainer, getPrefixCls, direction }: ConfigConsumerProps) => {
|
||||||
const { prefixCls: customizePrefixCls, className, theme, collapsedWidth } = this.props;
|
const { prefixCls: customizePrefixCls, className, theme, collapsedWidth } = this.props;
|
||||||
|
const { openKeys } = this.state;
|
||||||
const passProps = omit(this.props, ['collapsedWidth', 'siderCollapsed']);
|
const passProps = omit(this.props, ['collapsedWidth', 'siderCollapsed']);
|
||||||
const menuMode = this.getRealMenuMode();
|
const menuMode = this.getRealMenuMode();
|
||||||
const menuOpenMotion = this.getOpenMotionProps(menuMode!);
|
const menuOpenMotion = this.getOpenMotionProps(menuMode!);
|
||||||
@ -287,7 +290,7 @@ class InternalMenu extends React.Component<InternalMenuProps, MenuState> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const menuProps: MenuProps = {
|
const menuProps: MenuProps = {
|
||||||
openKeys: this.state.openKeys,
|
openKeys,
|
||||||
onOpenChange: this.handleOpenChange,
|
onOpenChange: this.handleOpenChange,
|
||||||
className: menuClassName,
|
className: menuClassName,
|
||||||
mode: menuMode,
|
mode: menuMode,
|
||||||
@ -313,7 +316,7 @@ class InternalMenu extends React.Component<InternalMenuProps, MenuState> {
|
|||||||
<MenuContext.Provider
|
<MenuContext.Provider
|
||||||
value={{
|
value={{
|
||||||
inlineCollapsed: this.getInlineCollapsed() || false,
|
inlineCollapsed: this.getInlineCollapsed() || false,
|
||||||
antdMenuTheme: this.props.theme,
|
antdMenuTheme: theme,
|
||||||
direction,
|
direction,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -34,7 +34,13 @@ exports[`renders ./components/message/demo/loading.md correctly 1`] = `
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`renders ./components/message/demo/other.md correctly 1`] = `
|
exports[`renders ./components/message/demo/other.md correctly 1`] = `
|
||||||
<div>
|
<div
|
||||||
|
class="ant-space ant-space-horizontal ant-space-align-center"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="ant-space-item"
|
||||||
|
style="margin-right:8px"
|
||||||
|
>
|
||||||
<button
|
<button
|
||||||
class="ant-btn"
|
class="ant-btn"
|
||||||
type="button"
|
type="button"
|
||||||
@ -43,6 +49,11 @@ exports[`renders ./components/message/demo/other.md correctly 1`] = `
|
|||||||
Success
|
Success
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="ant-space-item"
|
||||||
|
style="margin-right:8px"
|
||||||
|
>
|
||||||
<button
|
<button
|
||||||
class="ant-btn"
|
class="ant-btn"
|
||||||
type="button"
|
type="button"
|
||||||
@ -51,6 +62,10 @@ exports[`renders ./components/message/demo/other.md correctly 1`] = `
|
|||||||
Error
|
Error
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="ant-space-item"
|
||||||
|
>
|
||||||
<button
|
<button
|
||||||
class="ant-btn"
|
class="ant-btn"
|
||||||
type="button"
|
type="button"
|
||||||
@ -59,6 +74,7 @@ exports[`renders ./components/message/demo/other.md correctly 1`] = `
|
|||||||
Warning
|
Warning
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ title:
|
|||||||
Messages of success, error and warning types.
|
Messages of success, error and warning types.
|
||||||
|
|
||||||
```jsx
|
```jsx
|
||||||
import { message, Button } from 'antd';
|
import { message, Button, Space } from 'antd';
|
||||||
|
|
||||||
const success = () => {
|
const success = () => {
|
||||||
message.success('This is a success message');
|
message.success('This is a success message');
|
||||||
@ -29,17 +29,11 @@ const warning = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<div>
|
<Space>
|
||||||
<Button onClick={success}>Success</Button>
|
<Button onClick={success}>Success</Button>
|
||||||
<Button onClick={error}>Error</Button>
|
<Button onClick={error}>Error</Button>
|
||||||
<Button onClick={warning}>Warning</Button>
|
<Button onClick={warning}>Warning</Button>
|
||||||
</div>,
|
</Space>,
|
||||||
mountNode,
|
mountNode,
|
||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
<style>
|
|
||||||
#components-message-demo-other .ant-btn {
|
|
||||||
margin-right: 8px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
@ -14,7 +14,7 @@ title:
|
|||||||
Use `confirm()` to show a confirmation modal dialog.
|
Use `confirm()` to show a confirmation modal dialog.
|
||||||
|
|
||||||
```jsx
|
```jsx
|
||||||
import { Modal, Button } from 'antd';
|
import { Modal, Button, Space } from 'antd';
|
||||||
import { ExclamationCircleOutlined } from '@ant-design/icons';
|
import { ExclamationCircleOutlined } from '@ant-design/icons';
|
||||||
|
|
||||||
const { confirm } = Modal;
|
const { confirm } = Modal;
|
||||||
@ -71,7 +71,7 @@ function showPropsConfirm() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<div>
|
<Space>
|
||||||
<Button onClick={showConfirm}>Confirm</Button>
|
<Button onClick={showConfirm}>Confirm</Button>
|
||||||
<Button onClick={showDeleteConfirm} type="dashed">
|
<Button onClick={showDeleteConfirm} type="dashed">
|
||||||
Delete
|
Delete
|
||||||
@ -79,7 +79,7 @@ ReactDOM.render(
|
|||||||
<Button onClick={showPropsConfirm} type="dashed">
|
<Button onClick={showPropsConfirm} type="dashed">
|
||||||
With extra props
|
With extra props
|
||||||
</Button>
|
</Button>
|
||||||
</div>,
|
</Space>,
|
||||||
mountNode,
|
mountNode,
|
||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
@ -14,7 +14,7 @@ title:
|
|||||||
Use `Modal.useModal` to get `contextHolder` with context accessible issue.
|
Use `Modal.useModal` to get `contextHolder` with context accessible issue.
|
||||||
|
|
||||||
```jsx
|
```jsx
|
||||||
import { Modal, Button } from 'antd';
|
import { Modal, Button, Space } from 'antd';
|
||||||
|
|
||||||
const ReachableContext = React.createContext();
|
const ReachableContext = React.createContext();
|
||||||
const UnreachableContext = React.createContext();
|
const UnreachableContext = React.createContext();
|
||||||
@ -35,6 +35,7 @@ const App = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<ReachableContext.Provider value="Light">
|
<ReachableContext.Provider value="Light">
|
||||||
|
<Space>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
modal.confirm(config);
|
modal.confirm(config);
|
||||||
@ -63,7 +64,7 @@ const App = () => {
|
|||||||
>
|
>
|
||||||
Error
|
Error
|
||||||
</Button>
|
</Button>
|
||||||
|
</Space>
|
||||||
{/* `contextHolder` should always under the context you want to access */}
|
{/* `contextHolder` should always under the context you want to access */}
|
||||||
{contextHolder}
|
{contextHolder}
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ title:
|
|||||||
In the various types of information modal dialog, only one button to close dialog is provided.
|
In the various types of information modal dialog, only one button to close dialog is provided.
|
||||||
|
|
||||||
```jsx
|
```jsx
|
||||||
import { Modal, Button } from 'antd';
|
import { Modal, Button, Space } from 'antd';
|
||||||
|
|
||||||
function info() {
|
function info() {
|
||||||
Modal.info({
|
Modal.info({
|
||||||
@ -50,12 +50,12 @@ function warning() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<div>
|
<Space>
|
||||||
<Button onClick={info}>Info</Button>
|
<Button onClick={info}>Info</Button>
|
||||||
<Button onClick={success}>Success</Button>
|
<Button onClick={success}>Success</Button>
|
||||||
<Button onClick={error}>Error</Button>
|
<Button onClick={error}>Error</Button>
|
||||||
<Button onClick={warning}>Warning</Button>
|
<Button onClick={warning}>Warning</Button>
|
||||||
</div>,
|
</Space>,
|
||||||
mountNode,
|
mountNode,
|
||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
@ -91,12 +91,6 @@ modal.update({
|
|||||||
modal.destroy();
|
modal.destroy();
|
||||||
```
|
```
|
||||||
|
|
||||||
<style>
|
|
||||||
.code-box-demo .ant-btn {
|
|
||||||
margin-right: 8px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
- `Modal.destroyAll`
|
- `Modal.destroyAll`
|
||||||
|
|
||||||
`Modal.destroyAll()` could destroy all confirmation modal dialogs(Modal.info/Modal.success/Modal.error/Modal.warning/Modal.confirm). Usually, you can use it in router change event to destroy confirm modal dialog automatically without use modal reference to close( it's too complex to use for all modal dialogs)
|
`Modal.destroyAll()` could destroy all confirmation modal dialogs(Modal.info/Modal.success/Modal.error/Modal.warning/Modal.confirm). Usually, you can use it in router change event to destroy confirm modal dialog automatically without use modal reference to close( it's too complex to use for all modal dialogs)
|
||||||
|
@ -93,12 +93,6 @@ modal.update({
|
|||||||
modal.destroy();
|
modal.destroy();
|
||||||
```
|
```
|
||||||
|
|
||||||
<style>
|
|
||||||
.code-box-demo .ant-btn {
|
|
||||||
margin-right: 8px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
- `Modal.destroyAll`
|
- `Modal.destroyAll`
|
||||||
|
|
||||||
使用 `Modal.destroyAll()` 可以销毁弹出的确认窗(即上述的 Modal.info、Modal.success、Modal.error、Modal.warning、Modal.confirm)。通常用于路由监听当中,处理路由前进、后退不能销毁确认对话框的问题,而不用各处去使用实例的返回值进行关闭(modal.destroy() 适用于主动关闭,而不是路由这样被动关闭)
|
使用 `Modal.destroyAll()` 可以销毁弹出的确认窗(即上述的 Modal.info、Modal.success、Modal.error、Modal.warning、Modal.confirm)。通常用于路由监听当中,处理路由前进、后退不能销毁确认对话框的问题,而不用各处去使用实例的返回值进行关闭(modal.destroy() 适用于主动关闭,而不是路由这样被动关闭)
|
||||||
|
@ -46,6 +46,13 @@ exports[`renders ./components/notification/demo/duration.md correctly 1`] = `
|
|||||||
|
|
||||||
exports[`renders ./components/notification/demo/hooks.md correctly 1`] = `
|
exports[`renders ./components/notification/demo/hooks.md correctly 1`] = `
|
||||||
Array [
|
Array [
|
||||||
|
<div
|
||||||
|
class="ant-space ant-space-horizontal ant-space-align-center"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="ant-space-item"
|
||||||
|
style="margin-right:8px"
|
||||||
|
>
|
||||||
<button
|
<button
|
||||||
class="ant-btn ant-btn-primary"
|
class="ant-btn ant-btn-primary"
|
||||||
type="button"
|
type="button"
|
||||||
@ -73,7 +80,11 @@ Array [
|
|||||||
<span>
|
<span>
|
||||||
topLeft
|
topLeft
|
||||||
</span>
|
</span>
|
||||||
</button>,
|
</button>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="ant-space-item"
|
||||||
|
>
|
||||||
<button
|
<button
|
||||||
class="ant-btn ant-btn-primary"
|
class="ant-btn ant-btn-primary"
|
||||||
type="button"
|
type="button"
|
||||||
@ -101,11 +112,20 @@ Array [
|
|||||||
<span>
|
<span>
|
||||||
topRight
|
topRight
|
||||||
</span>
|
</span>
|
||||||
</button>,
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>,
|
||||||
<div
|
<div
|
||||||
class="ant-divider ant-divider-horizontal"
|
class="ant-divider ant-divider-horizontal"
|
||||||
role="separator"
|
role="separator"
|
||||||
/>,
|
/>,
|
||||||
|
<div
|
||||||
|
class="ant-space ant-space-horizontal ant-space-align-center"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="ant-space-item"
|
||||||
|
style="margin-right:8px"
|
||||||
|
>
|
||||||
<button
|
<button
|
||||||
class="ant-btn ant-btn-primary"
|
class="ant-btn ant-btn-primary"
|
||||||
type="button"
|
type="button"
|
||||||
@ -133,7 +153,11 @@ Array [
|
|||||||
<span>
|
<span>
|
||||||
bottomLeft
|
bottomLeft
|
||||||
</span>
|
</span>
|
||||||
</button>,
|
</button>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="ant-space-item"
|
||||||
|
>
|
||||||
<button
|
<button
|
||||||
class="ant-btn ant-btn-primary"
|
class="ant-btn ant-btn-primary"
|
||||||
type="button"
|
type="button"
|
||||||
@ -161,12 +185,21 @@ Array [
|
|||||||
<span>
|
<span>
|
||||||
bottomRight
|
bottomRight
|
||||||
</span>
|
</span>
|
||||||
</button>,
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>,
|
||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`renders ./components/notification/demo/placement.md correctly 1`] = `
|
exports[`renders ./components/notification/demo/placement.md correctly 1`] = `
|
||||||
<div>
|
<div>
|
||||||
|
<div
|
||||||
|
class="ant-space ant-space-horizontal ant-space-align-center"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="ant-space-item"
|
||||||
|
style="margin-right:8px"
|
||||||
|
>
|
||||||
<button
|
<button
|
||||||
class="ant-btn ant-btn-primary"
|
class="ant-btn ant-btn-primary"
|
||||||
type="button"
|
type="button"
|
||||||
@ -195,6 +228,10 @@ exports[`renders ./components/notification/demo/placement.md correctly 1`] = `
|
|||||||
topLeft
|
topLeft
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="ant-space-item"
|
||||||
|
>
|
||||||
<button
|
<button
|
||||||
class="ant-btn ant-btn-primary"
|
class="ant-btn ant-btn-primary"
|
||||||
type="button"
|
type="button"
|
||||||
@ -223,10 +260,19 @@ exports[`renders ./components/notification/demo/placement.md correctly 1`] = `
|
|||||||
topRight
|
topRight
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div
|
<div
|
||||||
class="ant-divider ant-divider-horizontal"
|
class="ant-divider ant-divider-horizontal"
|
||||||
role="separator"
|
role="separator"
|
||||||
/>
|
/>
|
||||||
|
<div
|
||||||
|
class="ant-space ant-space-horizontal ant-space-align-center"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="ant-space-item"
|
||||||
|
style="margin-right:8px"
|
||||||
|
>
|
||||||
<button
|
<button
|
||||||
class="ant-btn ant-btn-primary"
|
class="ant-btn ant-btn-primary"
|
||||||
type="button"
|
type="button"
|
||||||
@ -255,6 +301,10 @@ exports[`renders ./components/notification/demo/placement.md correctly 1`] = `
|
|||||||
bottomLeft
|
bottomLeft
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="ant-space-item"
|
||||||
|
>
|
||||||
<button
|
<button
|
||||||
class="ant-btn ant-btn-primary"
|
class="ant-btn ant-btn-primary"
|
||||||
type="button"
|
type="button"
|
||||||
@ -283,6 +333,8 @@ exports[`renders ./components/notification/demo/placement.md correctly 1`] = `
|
|||||||
bottomRight
|
bottomRight
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -309,7 +361,13 @@ exports[`renders ./components/notification/demo/with-btn.md correctly 1`] = `
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`renders ./components/notification/demo/with-icon.md correctly 1`] = `
|
exports[`renders ./components/notification/demo/with-icon.md correctly 1`] = `
|
||||||
<div>
|
<div
|
||||||
|
class="ant-space ant-space-horizontal ant-space-align-center"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="ant-space-item"
|
||||||
|
style="margin-right:8px"
|
||||||
|
>
|
||||||
<button
|
<button
|
||||||
class="ant-btn"
|
class="ant-btn"
|
||||||
type="button"
|
type="button"
|
||||||
@ -318,6 +376,11 @@ exports[`renders ./components/notification/demo/with-icon.md correctly 1`] = `
|
|||||||
Success
|
Success
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="ant-space-item"
|
||||||
|
style="margin-right:8px"
|
||||||
|
>
|
||||||
<button
|
<button
|
||||||
class="ant-btn"
|
class="ant-btn"
|
||||||
type="button"
|
type="button"
|
||||||
@ -326,6 +389,11 @@ exports[`renders ./components/notification/demo/with-icon.md correctly 1`] = `
|
|||||||
Info
|
Info
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="ant-space-item"
|
||||||
|
style="margin-right:8px"
|
||||||
|
>
|
||||||
<button
|
<button
|
||||||
class="ant-btn"
|
class="ant-btn"
|
||||||
type="button"
|
type="button"
|
||||||
@ -334,6 +402,10 @@ exports[`renders ./components/notification/demo/with-icon.md correctly 1`] = `
|
|||||||
Warning
|
Warning
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="ant-space-item"
|
||||||
|
>
|
||||||
<button
|
<button
|
||||||
class="ant-btn"
|
class="ant-btn"
|
||||||
type="button"
|
type="button"
|
||||||
@ -342,5 +414,6 @@ exports[`renders ./components/notification/demo/with-icon.md correctly 1`] = `
|
|||||||
Error
|
Error
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
@ -14,7 +14,7 @@ title:
|
|||||||
Use `notification.useNotification` to get `contextHolder` with context accessible issue.
|
Use `notification.useNotification` to get `contextHolder` with context accessible issue.
|
||||||
|
|
||||||
```jsx
|
```jsx
|
||||||
import { Button, notification, Divider } from 'antd';
|
import { Button, notification, Divider, Space } from 'antd';
|
||||||
import {
|
import {
|
||||||
RadiusUpleftOutlined,
|
RadiusUpleftOutlined,
|
||||||
RadiusUprightOutlined,
|
RadiusUprightOutlined,
|
||||||
@ -38,6 +38,7 @@ const Demo = () => {
|
|||||||
return (
|
return (
|
||||||
<Context.Provider value={{ name: 'Ant Design' }}>
|
<Context.Provider value={{ name: 'Ant Design' }}>
|
||||||
{contextHolder}
|
{contextHolder}
|
||||||
|
<Space>
|
||||||
<Button type="primary" onClick={() => openNotification('topLeft')}>
|
<Button type="primary" onClick={() => openNotification('topLeft')}>
|
||||||
<RadiusUpleftOutlined />
|
<RadiusUpleftOutlined />
|
||||||
topLeft
|
topLeft
|
||||||
@ -46,7 +47,9 @@ const Demo = () => {
|
|||||||
<RadiusUprightOutlined />
|
<RadiusUprightOutlined />
|
||||||
topRight
|
topRight
|
||||||
</Button>
|
</Button>
|
||||||
|
</Space>
|
||||||
<Divider />
|
<Divider />
|
||||||
|
<Space>
|
||||||
<Button type="primary" onClick={() => openNotification('bottomLeft')}>
|
<Button type="primary" onClick={() => openNotification('bottomLeft')}>
|
||||||
<RadiusBottomleftOutlined />
|
<RadiusBottomleftOutlined />
|
||||||
bottomLeft
|
bottomLeft
|
||||||
@ -55,6 +58,7 @@ const Demo = () => {
|
|||||||
<RadiusBottomrightOutlined />
|
<RadiusBottomrightOutlined />
|
||||||
bottomRight
|
bottomRight
|
||||||
</Button>
|
</Button>
|
||||||
|
</Space>
|
||||||
</Context.Provider>
|
</Context.Provider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -14,7 +14,7 @@ title:
|
|||||||
A notification box can appear from the `topRight`, `bottomRight`, `bottomLeft` or `topLeft` of the viewport.
|
A notification box can appear from the `topRight`, `bottomRight`, `bottomLeft` or `topLeft` of the viewport.
|
||||||
|
|
||||||
```jsx
|
```jsx
|
||||||
import { Button, notification, Divider } from 'antd';
|
import { Button, notification, Divider, Space } from 'antd';
|
||||||
import {
|
import {
|
||||||
RadiusUpleftOutlined,
|
RadiusUpleftOutlined,
|
||||||
RadiusUprightOutlined,
|
RadiusUprightOutlined,
|
||||||
@ -33,6 +33,7 @@ const openNotification = placement => {
|
|||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<div>
|
<div>
|
||||||
|
<Space>
|
||||||
<Button type="primary" onClick={() => openNotification('topLeft')}>
|
<Button type="primary" onClick={() => openNotification('topLeft')}>
|
||||||
<RadiusUpleftOutlined />
|
<RadiusUpleftOutlined />
|
||||||
topLeft
|
topLeft
|
||||||
@ -41,7 +42,9 @@ ReactDOM.render(
|
|||||||
<RadiusUprightOutlined />
|
<RadiusUprightOutlined />
|
||||||
topRight
|
topRight
|
||||||
</Button>
|
</Button>
|
||||||
|
</Space>
|
||||||
<Divider />
|
<Divider />
|
||||||
|
<Space>
|
||||||
<Button type="primary" onClick={() => openNotification('bottomLeft')}>
|
<Button type="primary" onClick={() => openNotification('bottomLeft')}>
|
||||||
<RadiusBottomleftOutlined />
|
<RadiusBottomleftOutlined />
|
||||||
bottomLeft
|
bottomLeft
|
||||||
@ -50,6 +53,7 @@ ReactDOM.render(
|
|||||||
<RadiusBottomrightOutlined />
|
<RadiusBottomrightOutlined />
|
||||||
bottomRight
|
bottomRight
|
||||||
</Button>
|
</Button>
|
||||||
|
</Space>
|
||||||
</div>,
|
</div>,
|
||||||
mountNode,
|
mountNode,
|
||||||
);
|
);
|
||||||
|
@ -14,7 +14,7 @@ title:
|
|||||||
A notification box with a icon at the left side.
|
A notification box with a icon at the left side.
|
||||||
|
|
||||||
```jsx
|
```jsx
|
||||||
import { Button, notification } from 'antd';
|
import { Button, notification, Space } from 'antd';
|
||||||
|
|
||||||
const openNotificationWithIcon = type => {
|
const openNotificationWithIcon = type => {
|
||||||
notification[type]({
|
notification[type]({
|
||||||
@ -25,18 +25,12 @@ const openNotificationWithIcon = type => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<div>
|
<Space>
|
||||||
<Button onClick={() => openNotificationWithIcon('success')}>Success</Button>
|
<Button onClick={() => openNotificationWithIcon('success')}>Success</Button>
|
||||||
<Button onClick={() => openNotificationWithIcon('info')}>Info</Button>
|
<Button onClick={() => openNotificationWithIcon('info')}>Info</Button>
|
||||||
<Button onClick={() => openNotificationWithIcon('warning')}>Warning</Button>
|
<Button onClick={() => openNotificationWithIcon('warning')}>Warning</Button>
|
||||||
<Button onClick={() => openNotificationWithIcon('error')}>Error</Button>
|
<Button onClick={() => openNotificationWithIcon('error')}>Error</Button>
|
||||||
</div>,
|
</Space>,
|
||||||
mountNode,
|
mountNode,
|
||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
<style>
|
|
||||||
.code-box-demo .ant-btn {
|
|
||||||
margin-right: 1em;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
@ -85,6 +85,11 @@ ReactDOM.render(
|
|||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
|
.code-box-demo .ant-btn-rtl {
|
||||||
|
margin-right: 0;
|
||||||
|
margin-left: 8px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
#components-popover-demo-placement .ant-btn {
|
#components-popover-demo-placement .ant-btn {
|
||||||
width: 70px;
|
width: 70px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
&:last-child {
|
&:last-child {
|
||||||
.@{result-prefix-cls}-rtl & {
|
.@{result-prefix-cls}-rtl & {
|
||||||
margin-left: 8px;
|
margin-left: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,14 +25,14 @@ To input a value in a range.
|
|||||||
| range | dual thumb mode | boolean | false | |
|
| range | dual thumb mode | boolean | false | |
|
||||||
| reverse | reverse the component | boolean | false | |
|
| reverse | reverse the component | boolean | false | |
|
||||||
| step | The granularity the slider can step through values. Must greater than 0, and be divided by (max - min) . When `marks` no null, `step` can be `null`. | number\|null | 1 | |
|
| step | The granularity the slider can step through values. Must greater than 0, and be divided by (max - min) . When `marks` no null, `step` can be `null`. | number\|null | 1 | |
|
||||||
| tipFormatter | Slider will pass its value to `tipFormatter`, and display its value in Tooltip, and hide Tooltip when return value is null. | Function\|null | IDENTITY | |
|
| tipFormatter | Slider will pass its value to `tipFormatter`, and display its value in Tooltip, and hide Tooltip when return value is null. | value => ReactNode\|null | IDENTITY | |
|
||||||
| value | The value of slider. When `range` is `false`, use `number`, otherwise, use `[number, number]` | number\|\[number, number] | |
|
| value | The value of slider. When `range` is `false`, use `number`, otherwise, use `[number, number]` | number\|\[number, number] | |
|
||||||
| vertical | If true, the slider will be vertical. | Boolean | false | |
|
| vertical | If true, the slider will be vertical. | Boolean | false | |
|
||||||
| onAfterChange | Fire when `onmouseup` is fired. | Function(value) | NOOP | |
|
| onAfterChange | Fire when `onmouseup` is fired. | (value) => void | NOOP | |
|
||||||
| onChange | Callback function that is fired when the user changes the slider's value. | Function(value) | NOOP | |
|
| onChange | Callback function that is fired when the user changes the slider's value. | (value) => void | NOOP | |
|
||||||
| tooltipPlacement | Set Tooltip display position. Ref [`Tooltip`](/components/tooltip/). | string | | |
|
| tooltipPlacement | Set Tooltip display position. Ref [`Tooltip`](/components/tooltip/). | string | | |
|
||||||
| tooltipVisible | If true, Tooltip will show always, or it will not show anyway, even if dragging or hovering. | Boolean | | |
|
| tooltipVisible | If true, Tooltip will show always, or it will not show anyway, even if dragging or hovering. | Boolean | | |
|
||||||
| getTooltipPopupContainer | The DOM container of the Tooltip, the default behavior is to create a div element in body. | Function | () => document.body | |
|
| getTooltipPopupContainer | The DOM container of the Tooltip, the default behavior is to create a div element in body. | (triggerNode) => HTMLElement | () => document.body | |
|
||||||
|
|
||||||
## Methods
|
## Methods
|
||||||
|
|
||||||
|
@ -26,14 +26,14 @@ title: Slider
|
|||||||
| range | 双滑块模式 | boolean | false | |
|
| range | 双滑块模式 | boolean | false | |
|
||||||
| reverse | 反向坐标轴 | boolean | false | |
|
| reverse | 反向坐标轴 | boolean | false | |
|
||||||
| step | 步长,取值必须大于 0,并且可被 (max - min) 整除。当 `marks` 不为空对象时,可以设置 `step` 为 `null`,此时 Slider 的可选值仅有 marks 标出来的部分。 | number\|null | 1 | |
|
| step | 步长,取值必须大于 0,并且可被 (max - min) 整除。当 `marks` 不为空对象时,可以设置 `step` 为 `null`,此时 Slider 的可选值仅有 marks 标出来的部分。 | number\|null | 1 | |
|
||||||
| tipFormatter | Slider 会把当前值传给 `tipFormatter`,并在 Tooltip 中显示 `tipFormatter` 的返回值,若为 null,则隐藏 Tooltip。 | Function\|null | IDENTITY | |
|
| tipFormatter | Slider 会把当前值传给 `tipFormatter`,并在 Tooltip 中显示 `tipFormatter` 的返回值,若为 null,则隐藏 Tooltip。 | value => ReactNode\|null | IDENTITY | |
|
||||||
| value | 设置当前取值。当 `range` 为 `false` 时,使用 `number`,否则用 `[number, number]` | number\|\[number, number] | | |
|
| value | 设置当前取值。当 `range` 为 `false` 时,使用 `number`,否则用 `[number, number]` | number\|\[number, number] | | |
|
||||||
| vertical | 值为 `true` 时,Slider 为垂直方向 | Boolean | false | |
|
| vertical | 值为 `true` 时,Slider 为垂直方向 | Boolean | false | |
|
||||||
| onAfterChange | 与 `onmouseup` 触发时机一致,把当前值作为参数传入。 | Function(value) | NOOP | |
|
| onAfterChange | 与 `onmouseup` 触发时机一致,把当前值作为参数传入。 | (value) => void | NOOP | |
|
||||||
| onChange | 当 Slider 的值发生改变时,会触发 onChange 事件,并把改变后的值作为参数传入。 | Function(value) | NOOP | |
|
| onChange | 当 Slider 的值发生改变时,会触发 onChange 事件,并把改变后的值作为参数传入。 | (value) => void | NOOP | |
|
||||||
| tooltipPlacement | 设置 Tooltip 展示位置。参考 [`Tooltip`](/components/tooltip/)。 | string | | |
|
| tooltipPlacement | 设置 Tooltip 展示位置。参考 [`Tooltip`](/components/tooltip/)。 | string | | |
|
||||||
| tooltipVisible | 值为`true`时,Tooltip 将会始终显示;否则始终不显示,哪怕在拖拽及移入时。 | Boolean | | |
|
| tooltipVisible | 值为`true`时,Tooltip 将会始终显示;否则始终不显示,哪怕在拖拽及移入时。 | Boolean | | |
|
||||||
| getTooltipPopupContainer | Tooltip 渲染父节点,默认渲染到 body 上。 | Function | () => document.body | |
|
| getTooltipPopupContainer | Tooltip 渲染父节点,默认渲染到 body 上。 | (triggerNode) => HTMLElement | () => document.body | |
|
||||||
|
|
||||||
## 方法
|
## 方法
|
||||||
|
|
||||||
|
@ -92,6 +92,7 @@
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
word-break: keep-all;
|
word-break: keep-all;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
&-active {
|
&-active {
|
||||||
color: @text-color;
|
color: @text-color;
|
||||||
|
@ -165,7 +165,13 @@ exports[`renders ./components/spin/demo/nested.md correctly 1`] = `
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`renders ./components/spin/demo/size.md correctly 1`] = `
|
exports[`renders ./components/spin/demo/size.md correctly 1`] = `
|
||||||
<div>
|
<div
|
||||||
|
class="ant-space ant-space-horizontal ant-space-align-center"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="ant-space-item"
|
||||||
|
style="margin-right:16px"
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
class="ant-spin ant-spin-sm ant-spin-spinning"
|
class="ant-spin ant-spin-sm ant-spin-spinning"
|
||||||
>
|
>
|
||||||
@ -186,6 +192,11 @@ exports[`renders ./components/spin/demo/size.md correctly 1`] = `
|
|||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="ant-space-item"
|
||||||
|
style="margin-right:16px"
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
class="ant-spin ant-spin-spinning"
|
class="ant-spin ant-spin-spinning"
|
||||||
>
|
>
|
||||||
@ -206,6 +217,10 @@ exports[`renders ./components/spin/demo/size.md correctly 1`] = `
|
|||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="ant-space-item"
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
class="ant-spin ant-spin-lg ant-spin-spinning"
|
class="ant-spin ant-spin-lg ant-spin-spinning"
|
||||||
>
|
>
|
||||||
@ -226,6 +241,7 @@ exports[`renders ./components/spin/demo/size.md correctly 1`] = `
|
|||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -14,20 +14,14 @@ title:
|
|||||||
A small `Spin` is used for loading text, default sized `Spin` for loading a card-level block, and large `Spin` used for loading a **page**.
|
A small `Spin` is used for loading text, default sized `Spin` for loading a card-level block, and large `Spin` used for loading a **page**.
|
||||||
|
|
||||||
```jsx
|
```jsx
|
||||||
import { Spin } from 'antd';
|
import { Spin, Space } from 'antd';
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<div>
|
<Space size="middle">
|
||||||
<Spin size="small" />
|
<Spin size="small" />
|
||||||
<Spin />
|
<Spin />
|
||||||
<Spin size="large" />
|
<Spin size="large" />
|
||||||
</div>,
|
</Space>,
|
||||||
mountNode,
|
mountNode,
|
||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
<style>
|
|
||||||
.ant-spin.ant-spin-spinning {
|
|
||||||
margin-right: 16px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
@ -93,7 +93,8 @@
|
|||||||
@switch-sm-height: 14px;
|
@switch-sm-height: 14px;
|
||||||
@switch-min-width: 40px;
|
@switch-min-width: 40px;
|
||||||
@switch-sm-min-width: 24px;
|
@switch-sm-min-width: 24px;
|
||||||
@switch-inner-margin: 0 22px 0 4px;
|
@switch-inner-margin-min: 4px;
|
||||||
|
@switch-inner-margin-max: 22px;
|
||||||
|
|
||||||
// Slider
|
// Slider
|
||||||
// ---
|
// ---
|
||||||
|
@ -729,7 +729,8 @@
|
|||||||
@switch-color: @primary-color;
|
@switch-color: @primary-color;
|
||||||
@switch-bg: @component-background;
|
@switch-bg: @component-background;
|
||||||
@switch-shadow-color: fade(#00230b, 20%);
|
@switch-shadow-color: fade(#00230b, 20%);
|
||||||
@switch-inner-margin: 0 24px 0 6px;
|
@switch-inner-margin-min: 6px;
|
||||||
|
@switch-inner-margin-max: 24px;
|
||||||
|
|
||||||
// Pagination
|
// Pagination
|
||||||
// ---
|
// ---
|
||||||
|
@ -23,7 +23,8 @@
|
|||||||
|
|
||||||
&-inner {
|
&-inner {
|
||||||
display: block;
|
display: block;
|
||||||
margin: @switch-inner-margin;
|
margin-right: @switch-inner-margin-min;
|
||||||
|
margin-left: @switch-inner-margin-max;
|
||||||
color: @text-color-inverse;
|
color: @text-color-inverse;
|
||||||
font-size: @font-size-sm;
|
font-size: @font-size-sm;
|
||||||
}
|
}
|
||||||
@ -135,7 +136,8 @@
|
|||||||
background-color: @switch-color;
|
background-color: @switch-color;
|
||||||
|
|
||||||
.@{switch-prefix-cls}-inner {
|
.@{switch-prefix-cls}-inner {
|
||||||
margin: @switch-inner-margin;
|
margin-right: @switch-inner-margin-max;
|
||||||
|
margin-left: @switch-inner-margin-min;
|
||||||
}
|
}
|
||||||
|
|
||||||
&::after {
|
&::after {
|
||||||
|
@ -10,8 +10,8 @@
|
|||||||
|
|
||||||
&-inner {
|
&-inner {
|
||||||
.@{switch-prefix-cls}-rtl & {
|
.@{switch-prefix-cls}-rtl & {
|
||||||
margin-right: 24px;
|
margin-right: @switch-inner-margin-max;
|
||||||
margin-left: 6px;
|
margin-left: @switch-inner-margin-min;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,8 +51,8 @@
|
|||||||
&-checked {
|
&-checked {
|
||||||
.@{switch-prefix-cls}-inner {
|
.@{switch-prefix-cls}-inner {
|
||||||
.@{switch-prefix-cls}-rtl& {
|
.@{switch-prefix-cls}-rtl& {
|
||||||
margin-right: 6px;
|
margin-right: @switch-inner-margin-min;
|
||||||
margin-left: 24px;
|
margin-left: @switch-inner-margin-max;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -403,18 +403,19 @@ function Table<RecordType extends object = any>(props: TableProps<RecordType>) {
|
|||||||
paginationSize = mergedSize === 'small' || mergedSize === 'middle' ? 'small' : undefined;
|
paginationSize = mergedSize === 'small' || mergedSize === 'middle' ? 'small' : undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const renderPagination = (position: string = 'right') => (
|
const renderPagination = (position: string) => (
|
||||||
<Pagination
|
<Pagination
|
||||||
className={`${prefixCls}-pagination ${prefixCls}-pagination-${position}`}
|
className={`${prefixCls}-pagination ${prefixCls}-pagination-${position}`}
|
||||||
{...mergedPagination}
|
{...mergedPagination}
|
||||||
size={paginationSize}
|
size={paginationSize}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
const defaultPosition = direction === 'rtl' ? 'left' : 'right';
|
||||||
if (mergedPagination.position !== null && Array.isArray(mergedPagination.position)) {
|
if (mergedPagination.position !== null && Array.isArray(mergedPagination.position)) {
|
||||||
const topPos = mergedPagination.position.find(p => p.indexOf('top') !== -1);
|
const topPos = mergedPagination.position.find(p => p.indexOf('top') !== -1);
|
||||||
const bottomPos = mergedPagination.position.find(p => p.indexOf('bottom') !== -1);
|
const bottomPos = mergedPagination.position.find(p => p.indexOf('bottom') !== -1);
|
||||||
if (!topPos && !bottomPos) {
|
if (!topPos && !bottomPos) {
|
||||||
bottomPaginationNode = renderPagination();
|
bottomPaginationNode = renderPagination(defaultPosition);
|
||||||
} else {
|
} else {
|
||||||
if (topPos) {
|
if (topPos) {
|
||||||
topPaginationNode = renderPagination(topPos!.toLowerCase().replace('top', ''));
|
topPaginationNode = renderPagination(topPos!.toLowerCase().replace('top', ''));
|
||||||
@ -424,7 +425,7 @@ function Table<RecordType extends object = any>(props: TableProps<RecordType>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
bottomPaginationNode = renderPagination();
|
bottomPaginationNode = renderPagination(defaultPosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,6 +27,9 @@ exports[`Table.rowSelection fix expand on th left when selection column fixed on
|
|||||||
<col
|
<col
|
||||||
class="ant-table-expand-icon-col"
|
class="ant-table-expand-icon-col"
|
||||||
/>
|
/>
|
||||||
|
<col
|
||||||
|
class="ant-table-selection-column"
|
||||||
|
/>
|
||||||
</colgroup>
|
</colgroup>
|
||||||
<thead
|
<thead
|
||||||
class="ant-table-thead"
|
class="ant-table-thead"
|
||||||
@ -354,7 +357,11 @@ exports[`Table.rowSelection fix selection column on the left 1`] = `
|
|||||||
<table
|
<table
|
||||||
style="width:903px;min-width:100%;table-layout:fixed"
|
style="width:903px;min-width:100%;table-layout:fixed"
|
||||||
>
|
>
|
||||||
<colgroup />
|
<colgroup>
|
||||||
|
<col
|
||||||
|
class="ant-table-selection-column"
|
||||||
|
/>
|
||||||
|
</colgroup>
|
||||||
<thead
|
<thead
|
||||||
class="ant-table-thead"
|
class="ant-table-thead"
|
||||||
>
|
>
|
||||||
@ -634,7 +641,11 @@ exports[`Table.rowSelection fix selection column on the left when any other colu
|
|||||||
<table
|
<table
|
||||||
style="width:903px;min-width:100%;table-layout:fixed"
|
style="width:903px;min-width:100%;table-layout:fixed"
|
||||||
>
|
>
|
||||||
<colgroup />
|
<colgroup>
|
||||||
|
<col
|
||||||
|
class="ant-table-selection-column"
|
||||||
|
/>
|
||||||
|
</colgroup>
|
||||||
<thead
|
<thead
|
||||||
class="ant-table-thead"
|
class="ant-table-thead"
|
||||||
>
|
>
|
||||||
@ -945,7 +956,11 @@ exports[`Table.rowSelection should support getPopupContainer 1`] = `
|
|||||||
<table
|
<table
|
||||||
style="table-layout: auto;"
|
style="table-layout: auto;"
|
||||||
>
|
>
|
||||||
<colgroup />
|
<colgroup>
|
||||||
|
<col
|
||||||
|
class="ant-table-selection-column"
|
||||||
|
/>
|
||||||
|
</colgroup>
|
||||||
<thead
|
<thead
|
||||||
class="ant-table-thead"
|
class="ant-table-thead"
|
||||||
>
|
>
|
||||||
@ -1268,7 +1283,11 @@ exports[`Table.rowSelection should support getPopupContainer from ConfigProvider
|
|||||||
<table
|
<table
|
||||||
style="table-layout: auto;"
|
style="table-layout: auto;"
|
||||||
>
|
>
|
||||||
<colgroup />
|
<colgroup>
|
||||||
|
<col
|
||||||
|
class="ant-table-selection-column"
|
||||||
|
/>
|
||||||
|
</colgroup>
|
||||||
<thead
|
<thead
|
||||||
class="ant-table-thead"
|
class="ant-table-thead"
|
||||||
>
|
>
|
||||||
@ -1591,7 +1610,11 @@ exports[`Table.rowSelection use column as selection column when key is \`selecti
|
|||||||
<table
|
<table
|
||||||
style="table-layout:auto"
|
style="table-layout:auto"
|
||||||
>
|
>
|
||||||
<colgroup />
|
<colgroup>
|
||||||
|
<col
|
||||||
|
class="ant-table-selection-column"
|
||||||
|
/>
|
||||||
|
</colgroup>
|
||||||
<thead
|
<thead
|
||||||
class="ant-table-thead"
|
class="ant-table-thead"
|
||||||
>
|
>
|
||||||
|
@ -2378,6 +2378,9 @@ exports[`renders ./components/table/demo/dynamic-settings.md correctly 1`] = `
|
|||||||
<col
|
<col
|
||||||
class="ant-table-expand-icon-col"
|
class="ant-table-expand-icon-col"
|
||||||
/>
|
/>
|
||||||
|
<col
|
||||||
|
class="ant-table-selection-column"
|
||||||
|
/>
|
||||||
</colgroup>
|
</colgroup>
|
||||||
<thead
|
<thead
|
||||||
class="ant-table-thead"
|
class="ant-table-thead"
|
||||||
@ -4932,7 +4935,9 @@ exports[`renders ./components/table/demo/expand-children.md correctly 1`] = `
|
|||||||
style="table-layout:auto"
|
style="table-layout:auto"
|
||||||
>
|
>
|
||||||
<colgroup>
|
<colgroup>
|
||||||
<col />
|
<col
|
||||||
|
class="ant-table-selection-column"
|
||||||
|
/>
|
||||||
<col />
|
<col />
|
||||||
<col
|
<col
|
||||||
style="width:12%;min-width:12%"
|
style="width:12%;min-width:12%"
|
||||||
@ -10821,9 +10826,14 @@ exports[`renders ./components/table/demo/pagination.md correctly 1`] = `
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`renders ./components/table/demo/reset-filter.md correctly 1`] = `
|
exports[`renders ./components/table/demo/reset-filter.md correctly 1`] = `
|
||||||
<div>
|
Array [
|
||||||
<div
|
<div
|
||||||
class="table-operations"
|
class="ant-space ant-space-horizontal ant-space-align-center"
|
||||||
|
style="margin-bottom:16px"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="ant-space-item"
|
||||||
|
style="margin-right:8px"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
class="ant-btn"
|
class="ant-btn"
|
||||||
@ -10833,6 +10843,11 @@ exports[`renders ./components/table/demo/reset-filter.md correctly 1`] = `
|
|||||||
Sort age
|
Sort age
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="ant-space-item"
|
||||||
|
style="margin-right:8px"
|
||||||
|
>
|
||||||
<button
|
<button
|
||||||
class="ant-btn"
|
class="ant-btn"
|
||||||
type="button"
|
type="button"
|
||||||
@ -10841,6 +10856,10 @@ exports[`renders ./components/table/demo/reset-filter.md correctly 1`] = `
|
|||||||
Clear filters
|
Clear filters
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="ant-space-item"
|
||||||
|
>
|
||||||
<button
|
<button
|
||||||
class="ant-btn"
|
class="ant-btn"
|
||||||
type="button"
|
type="button"
|
||||||
@ -10850,6 +10869,7 @@ exports[`renders ./components/table/demo/reset-filter.md correctly 1`] = `
|
|||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>,
|
||||||
<div
|
<div
|
||||||
class="ant-table-wrapper"
|
class="ant-table-wrapper"
|
||||||
>
|
>
|
||||||
@ -11317,8 +11337,8 @@ exports[`renders ./components/table/demo/reset-filter.md correctly 1`] = `
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>,
|
||||||
</div>
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`renders ./components/table/demo/resizable-column.md correctly 1`] = `
|
exports[`renders ./components/table/demo/resizable-column.md correctly 1`] = `
|
||||||
@ -11852,7 +11872,11 @@ exports[`renders ./components/table/demo/row-selection.md correctly 1`] = `
|
|||||||
<table
|
<table
|
||||||
style="table-layout:auto"
|
style="table-layout:auto"
|
||||||
>
|
>
|
||||||
<colgroup />
|
<colgroup>
|
||||||
|
<col
|
||||||
|
class="ant-table-selection-column"
|
||||||
|
/>
|
||||||
|
</colgroup>
|
||||||
<thead
|
<thead
|
||||||
class="ant-table-thead"
|
class="ant-table-thead"
|
||||||
>
|
>
|
||||||
@ -12195,7 +12219,11 @@ exports[`renders ./components/table/demo/row-selection-and-operation.md correctl
|
|||||||
<table
|
<table
|
||||||
style="table-layout:auto"
|
style="table-layout:auto"
|
||||||
>
|
>
|
||||||
<colgroup />
|
<colgroup>
|
||||||
|
<col
|
||||||
|
class="ant-table-selection-column"
|
||||||
|
/>
|
||||||
|
</colgroup>
|
||||||
<thead
|
<thead
|
||||||
class="ant-table-thead"
|
class="ant-table-thead"
|
||||||
>
|
>
|
||||||
@ -12778,7 +12806,11 @@ exports[`renders ./components/table/demo/row-selection-custom.md correctly 1`] =
|
|||||||
<table
|
<table
|
||||||
style="table-layout:auto"
|
style="table-layout:auto"
|
||||||
>
|
>
|
||||||
<colgroup />
|
<colgroup>
|
||||||
|
<col
|
||||||
|
class="ant-table-selection-column"
|
||||||
|
/>
|
||||||
|
</colgroup>
|
||||||
<thead
|
<thead
|
||||||
class="ant-table-thead"
|
class="ant-table-thead"
|
||||||
>
|
>
|
||||||
@ -13388,7 +13420,11 @@ exports[`renders ./components/table/demo/row-selection-custom-debug.md correctly
|
|||||||
<table
|
<table
|
||||||
style="table-layout:auto"
|
style="table-layout:auto"
|
||||||
>
|
>
|
||||||
<colgroup />
|
<colgroup>
|
||||||
|
<col
|
||||||
|
class="ant-table-selection-column"
|
||||||
|
/>
|
||||||
|
</colgroup>
|
||||||
<thead
|
<thead
|
||||||
class="ant-table-thead"
|
class="ant-table-thead"
|
||||||
>
|
>
|
||||||
|
@ -14,7 +14,7 @@ title:
|
|||||||
Implement a customized column search example via `filterDropdown`.
|
Implement a customized column search example via `filterDropdown`.
|
||||||
|
|
||||||
```jsx
|
```jsx
|
||||||
import { Table, Input, Button } from 'antd';
|
import { Table, Input, Button, Space } from 'antd';
|
||||||
import Highlighter from 'react-highlight-words';
|
import Highlighter from 'react-highlight-words';
|
||||||
import { SearchOutlined } from '@ant-design/icons';
|
import { SearchOutlined } from '@ant-design/icons';
|
||||||
|
|
||||||
@ -64,26 +64,25 @@ class App extends React.Component {
|
|||||||
onPressEnter={() => this.handleSearch(selectedKeys, confirm, dataIndex)}
|
onPressEnter={() => this.handleSearch(selectedKeys, confirm, dataIndex)}
|
||||||
style={{ width: 188, marginBottom: 8, display: 'block' }}
|
style={{ width: 188, marginBottom: 8, display: 'block' }}
|
||||||
/>
|
/>
|
||||||
|
<Space>
|
||||||
<Button
|
<Button
|
||||||
type="primary"
|
type="primary"
|
||||||
onClick={() => this.handleSearch(selectedKeys, confirm, dataIndex)}
|
onClick={() => this.handleSearch(selectedKeys, confirm, dataIndex)}
|
||||||
icon={<SearchOutlined />}
|
icon={<SearchOutlined />}
|
||||||
size="small"
|
size="small"
|
||||||
style={{ width: 90, marginRight: 8 }}
|
style={{ width: 90 }}
|
||||||
>
|
>
|
||||||
Search
|
Search
|
||||||
</Button>
|
</Button>
|
||||||
<Button onClick={() => this.handleReset(clearFilters)} size="small" style={{ width: 90 }}>
|
<Button onClick={() => this.handleReset(clearFilters)} size="small" style={{ width: 90 }}>
|
||||||
Reset
|
Reset
|
||||||
</Button>
|
</Button>
|
||||||
|
</Space>
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
filterIcon: filtered => <SearchOutlined style={{ color: filtered ? '#1890ff' : undefined }} />,
|
filterIcon: filtered => <SearchOutlined style={{ color: filtered ? '#1890ff' : undefined }} />,
|
||||||
onFilter: (value, record) =>
|
onFilter: (value, record) =>
|
||||||
record[dataIndex]
|
record[dataIndex].toString().toLowerCase().includes(value.toLowerCase()),
|
||||||
.toString()
|
|
||||||
.toLowerCase()
|
|
||||||
.includes(value.toLowerCase()),
|
|
||||||
onFilterDropdownVisibleChange: visible => {
|
onFilterDropdownVisibleChange: visible => {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
setTimeout(() => this.searchInput.select());
|
setTimeout(() => this.searchInput.select());
|
||||||
|
@ -22,7 +22,7 @@ Control filters and sorters by `filteredValue` and `sortOrder`.
|
|||||||
> 3. `column.key` is required.
|
> 3. `column.key` is required.
|
||||||
|
|
||||||
```jsx
|
```jsx
|
||||||
import { Table, Button } from 'antd';
|
import { Table, Button, Space } from 'antd';
|
||||||
|
|
||||||
const data = [
|
const data = [
|
||||||
{
|
{
|
||||||
@ -128,27 +128,17 @@ class App extends React.Component {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
return (
|
return (
|
||||||
<div>
|
<>
|
||||||
<div className="table-operations">
|
<Space style={{ marginBottom: 16 }}>
|
||||||
<Button onClick={this.setAgeSort}>Sort age</Button>
|
<Button onClick={this.setAgeSort}>Sort age</Button>
|
||||||
<Button onClick={this.clearFilters}>Clear filters</Button>
|
<Button onClick={this.clearFilters}>Clear filters</Button>
|
||||||
<Button onClick={this.clearAll}>Clear filters and sorters</Button>
|
<Button onClick={this.clearAll}>Clear filters and sorters</Button>
|
||||||
</div>
|
</Space>
|
||||||
<Table columns={columns} dataSource={data} onChange={this.handleChange} />
|
<Table columns={columns} dataSource={data} onChange={this.handleChange} />
|
||||||
</div>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReactDOM.render(<App />, mountNode);
|
ReactDOM.render(<App />, mountNode);
|
||||||
```
|
```
|
||||||
|
|
||||||
```css
|
|
||||||
.table-operations {
|
|
||||||
margin-bottom: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-operations > button {
|
|
||||||
margin-right: 8px;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import DownOutlined from '@ant-design/icons/DownOutlined';
|
import DownOutlined from '@ant-design/icons/DownOutlined';
|
||||||
|
import { INTERNAL_COL_DEFINE } from 'rc-table';
|
||||||
import { FixedType } from 'rc-table/lib/interface';
|
import { FixedType } from 'rc-table/lib/interface';
|
||||||
import Checkbox, { CheckboxProps } from '../../checkbox';
|
import Checkbox, { CheckboxProps } from '../../checkbox';
|
||||||
import Dropdown from '../../dropdown';
|
import Dropdown from '../../dropdown';
|
||||||
@ -440,6 +441,9 @@ export default function useSelection<RecordType>(
|
|||||||
className: `${prefixCls}-selection-column`,
|
className: `${prefixCls}-selection-column`,
|
||||||
title: rowSelection.columnTitle || title,
|
title: rowSelection.columnTitle || title,
|
||||||
render: renderSelectionCell,
|
render: renderSelectionCell,
|
||||||
|
[INTERNAL_COL_DEFINE]: {
|
||||||
|
className: `${prefixCls}-selection-column`,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
if (expandType === 'row' && columns.length && !expandIconColumnIndex) {
|
if (expandType === 'row' && columns.length && !expandIconColumnIndex) {
|
||||||
|
@ -360,6 +360,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&-selection-column,
|
||||||
table tr th&-selection-column,
|
table tr th&-selection-column,
|
||||||
table tr td&-selection-column {
|
table tr td&-selection-column {
|
||||||
width: @table-selection-column-width;
|
width: @table-selection-column-width;
|
||||||
|
@ -2526,9 +2526,18 @@ exports[`renders ./components/tabs/demo/nest.md correctly 1`] = `
|
|||||||
exports[`renders ./components/tabs/demo/position.md correctly 1`] = `
|
exports[`renders ./components/tabs/demo/position.md correctly 1`] = `
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
|
class="ant-space ant-space-horizontal ant-space-align-center"
|
||||||
style="margin-bottom:16px"
|
style="margin-bottom:16px"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="ant-space-item"
|
||||||
|
style="margin-right:8px"
|
||||||
>
|
>
|
||||||
Tab position:
|
Tab position:
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="ant-space-item"
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
class="ant-select ant-select-single ant-select-show-arrow"
|
class="ant-select ant-select-single ant-select-show-arrow"
|
||||||
>
|
>
|
||||||
@ -2587,6 +2596,7 @@ exports[`renders ./components/tabs/demo/position.md correctly 1`] = `
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<div
|
<div
|
||||||
class="ant-tabs ant-tabs-top ant-tabs-line"
|
class="ant-tabs ant-tabs-top ant-tabs-line"
|
||||||
>
|
>
|
||||||
|
@ -14,7 +14,7 @@ title:
|
|||||||
Tab's position: left, right, top or bottom.
|
Tab's position: left, right, top or bottom.
|
||||||
|
|
||||||
```jsx
|
```jsx
|
||||||
import { Tabs, Select } from 'antd';
|
import { Tabs, Select, Space } from 'antd';
|
||||||
|
|
||||||
const { TabPane } = Tabs;
|
const { TabPane } = Tabs;
|
||||||
const { Option } = Select;
|
const { Option } = Select;
|
||||||
@ -31,7 +31,7 @@ class Demo extends React.Component {
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div style={{ marginBottom: 16 }}>
|
<Space style={{ marginBottom: 16 }}>
|
||||||
Tab position:
|
Tab position:
|
||||||
<Select
|
<Select
|
||||||
value={this.state.tabPosition}
|
value={this.state.tabPosition}
|
||||||
@ -43,7 +43,7 @@ class Demo extends React.Component {
|
|||||||
<Option value="left">left</Option>
|
<Option value="left">left</Option>
|
||||||
<Option value="right">right</Option>
|
<Option value="right">right</Option>
|
||||||
</Select>
|
</Select>
|
||||||
</div>
|
</Space>
|
||||||
<Tabs tabPosition={this.state.tabPosition}>
|
<Tabs tabPosition={this.state.tabPosition}>
|
||||||
<TabPane tab="Tab 1" key="1">
|
<TabPane tab="Tab 1" key="1">
|
||||||
Content of Tab 1
|
Content of Tab 1
|
||||||
|
@ -204,19 +204,29 @@ exports[`renders ./components/tag/demo/basic.md correctly 1`] = `
|
|||||||
exports[`renders ./components/tag/demo/checkable.md correctly 1`] = `
|
exports[`renders ./components/tag/demo/checkable.md correctly 1`] = `
|
||||||
Array [
|
Array [
|
||||||
<span
|
<span
|
||||||
class="ant-tag ant-tag-checkable"
|
style="margin-right:8px"
|
||||||
>
|
>
|
||||||
Tag1
|
Categories:
|
||||||
</span>,
|
</span>,
|
||||||
<span
|
<span
|
||||||
class="ant-tag ant-tag-checkable"
|
class="ant-tag ant-tag-checkable"
|
||||||
>
|
>
|
||||||
Tag2
|
Movies
|
||||||
|
</span>,
|
||||||
|
<span
|
||||||
|
class="ant-tag ant-tag-checkable ant-tag-checkable-checked"
|
||||||
|
>
|
||||||
|
Books
|
||||||
</span>,
|
</span>,
|
||||||
<span
|
<span
|
||||||
class="ant-tag ant-tag-checkable"
|
class="ant-tag ant-tag-checkable"
|
||||||
>
|
>
|
||||||
Tag3
|
Music
|
||||||
|
</span>,
|
||||||
|
<span
|
||||||
|
class="ant-tag ant-tag-checkable"
|
||||||
|
>
|
||||||
|
Sports
|
||||||
</span>,
|
</span>,
|
||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
@ -456,36 +466,6 @@ exports[`renders ./components/tag/demo/controlled.md correctly 1`] = `
|
|||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`renders ./components/tag/demo/hot-tags.md correctly 1`] = `
|
|
||||||
Array [
|
|
||||||
<span
|
|
||||||
style="margin-right:8px"
|
|
||||||
>
|
|
||||||
Categories:
|
|
||||||
</span>,
|
|
||||||
<span
|
|
||||||
class="ant-tag ant-tag-checkable"
|
|
||||||
>
|
|
||||||
Movies
|
|
||||||
</span>,
|
|
||||||
<span
|
|
||||||
class="ant-tag ant-tag-checkable ant-tag-checkable-checked"
|
|
||||||
>
|
|
||||||
Books
|
|
||||||
</span>,
|
|
||||||
<span
|
|
||||||
class="ant-tag ant-tag-checkable"
|
|
||||||
>
|
|
||||||
Music
|
|
||||||
</span>,
|
|
||||||
<span
|
|
||||||
class="ant-tag ant-tag-checkable"
|
|
||||||
>
|
|
||||||
Sports
|
|
||||||
</span>,
|
|
||||||
]
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`renders ./components/tag/demo/icon.md correctly 1`] = `
|
exports[`renders ./components/tag/demo/icon.md correctly 1`] = `
|
||||||
<div>
|
<div>
|
||||||
<span
|
<span
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
order: 3
|
order: 3
|
||||||
title:
|
title:
|
||||||
zh-CN: 可选择
|
zh-CN: 可选择标签
|
||||||
en-US: Checkable
|
en-US: Checkable
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -22,12 +22,38 @@ import { Tag } from 'antd';
|
|||||||
|
|
||||||
const { CheckableTag } = Tag;
|
const { CheckableTag } = Tag;
|
||||||
|
|
||||||
ReactDOM.render(
|
const tagsData = ['Movies', 'Books', 'Music', 'Sports'];
|
||||||
|
|
||||||
|
class HotTags extends React.Component {
|
||||||
|
state = {
|
||||||
|
selectedTags: ['Books'],
|
||||||
|
};
|
||||||
|
|
||||||
|
handleChange(tag, checked) {
|
||||||
|
const { selectedTags } = this.state;
|
||||||
|
const nextSelectedTags = checked ? [...selectedTags, tag] : selectedTags.filter(t => t !== tag);
|
||||||
|
console.log('You are interested in: ', nextSelectedTags);
|
||||||
|
this.setState({ selectedTags: nextSelectedTags });
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { selectedTags } = this.state;
|
||||||
|
return (
|
||||||
<>
|
<>
|
||||||
<CheckableTag>Tag1</CheckableTag>
|
<span style={{ marginRight: 8 }}>Categories:</span>
|
||||||
<CheckableTag>Tag2</CheckableTag>
|
{tagsData.map(tag => (
|
||||||
<CheckableTag>Tag3</CheckableTag>
|
<CheckableTag
|
||||||
</>,
|
key={tag}
|
||||||
mountNode,
|
checked={selectedTags.indexOf(tag) > -1}
|
||||||
);
|
onChange={checked => this.handleChange(tag, checked)}
|
||||||
|
>
|
||||||
|
{tag}
|
||||||
|
</CheckableTag>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReactDOM.render(<HotTags />, mountNode);
|
||||||
```
|
```
|
||||||
|
@ -44,12 +44,6 @@ ReactDOM.render(
|
|||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
```css
|
|
||||||
.ant-tag {
|
|
||||||
margin-bottom: 8px;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.code-box-demo .ant-tag {
|
.code-box-demo .ant-tag {
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
|
@ -1,55 +0,0 @@
|
|||||||
---
|
|
||||||
order: 4
|
|
||||||
title:
|
|
||||||
zh-CN: 热门标签
|
|
||||||
en-US: Hot Tags
|
|
||||||
---
|
|
||||||
|
|
||||||
## zh-CN
|
|
||||||
|
|
||||||
选择你感兴趣的话题。
|
|
||||||
|
|
||||||
## en-US
|
|
||||||
|
|
||||||
Select your favourite topics.
|
|
||||||
|
|
||||||
```jsx
|
|
||||||
import { Tag } from 'antd';
|
|
||||||
|
|
||||||
const { CheckableTag } = Tag;
|
|
||||||
|
|
||||||
const tagsData = ['Movies', 'Books', 'Music', 'Sports'];
|
|
||||||
|
|
||||||
class HotTags extends React.Component {
|
|
||||||
state = {
|
|
||||||
selectedTags: ['Books'],
|
|
||||||
};
|
|
||||||
|
|
||||||
handleChange(tag, checked) {
|
|
||||||
const { selectedTags } = this.state;
|
|
||||||
const nextSelectedTags = checked ? [...selectedTags, tag] : selectedTags.filter(t => t !== tag);
|
|
||||||
console.log('You are interested in: ', nextSelectedTags);
|
|
||||||
this.setState({ selectedTags: nextSelectedTags });
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { selectedTags } = this.state;
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<span style={{ marginRight: 8 }}>Categories:</span>
|
|
||||||
{tagsData.map(tag => (
|
|
||||||
<CheckableTag
|
|
||||||
key={tag}
|
|
||||||
checked={selectedTags.indexOf(tag) > -1}
|
|
||||||
onChange={checked => this.handleChange(tag, checked)}
|
|
||||||
>
|
|
||||||
{tag}
|
|
||||||
</CheckableTag>
|
|
||||||
))}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ReactDOM.render(<HotTags />, mountNode);
|
|
||||||
```
|
|
@ -297,4 +297,22 @@ describe('Tooltip', () => {
|
|||||||
await sleep(500);
|
await sleep(500);
|
||||||
expect(wrapper.instance().getPopupDomNode().className).toContain('placement-topRight');
|
expect(wrapper.instance().getPopupDomNode().className).toContain('placement-topRight');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should works for mismatch placement', async () => {
|
||||||
|
const wrapper = mount(
|
||||||
|
<Tooltip
|
||||||
|
title="xxxxx"
|
||||||
|
align={{
|
||||||
|
points: ['bc', 'tl'],
|
||||||
|
}}
|
||||||
|
mouseEnterDelay={0}
|
||||||
|
>
|
||||||
|
<span>Hello world!</span>
|
||||||
|
</Tooltip>,
|
||||||
|
);
|
||||||
|
const button = wrapper.find('span').at(0);
|
||||||
|
button.simulate('mouseenter');
|
||||||
|
await sleep(600);
|
||||||
|
expect(wrapper.instance().getPopupDomNode().className).toContain('ant-tooltip');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -28,10 +28,3 @@ ReactDOM.render(
|
|||||||
mountNode,
|
mountNode,
|
||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
<style>
|
|
||||||
.code-box-demo .ant-btn {
|
|
||||||
margin-right: 1em;
|
|
||||||
margin-bottom: 1em;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
@ -46,10 +46,3 @@ ReactDOM.render(
|
|||||||
mountNode,
|
mountNode,
|
||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
<style>
|
|
||||||
.code-box-demo .ant-btn {
|
|
||||||
margin-right: 1em;
|
|
||||||
margin-bottom: 1em;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
@ -79,6 +79,11 @@ ReactDOM.render(
|
|||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
|
.code-box-demo .ant-btn-rtl {
|
||||||
|
margin-right: 0;
|
||||||
|
margin-left: 8px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
#components-tooltip-demo-placement .ant-btn {
|
#components-tooltip-demo-placement .ant-btn {
|
||||||
width: 70px;
|
width: 70px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
@ -186,6 +186,9 @@ class Tooltip extends React.Component<TooltipProps, any> {
|
|||||||
placements[key].points[0] === align.points[0] &&
|
placements[key].points[0] === align.points[0] &&
|
||||||
placements[key].points[1] === align.points[1],
|
placements[key].points[1] === align.points[1],
|
||||||
)[0];
|
)[0];
|
||||||
|
if (!placement) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
// 根据当前坐标设置动画点
|
// 根据当前坐标设置动画点
|
||||||
const rect = domNode.getBoundingClientRect();
|
const rect = domNode.getBoundingClientRect();
|
||||||
const transformOrigin = {
|
const transformOrigin = {
|
||||||
|
@ -2243,7 +2243,11 @@ exports[`renders ./components/transfer/demo/table-transfer.md correctly 1`] = `
|
|||||||
<table
|
<table
|
||||||
style="table-layout:auto"
|
style="table-layout:auto"
|
||||||
>
|
>
|
||||||
<colgroup />
|
<colgroup>
|
||||||
|
<col
|
||||||
|
class="ant-table-selection-column"
|
||||||
|
/>
|
||||||
|
</colgroup>
|
||||||
<thead
|
<thead
|
||||||
class="ant-table-thead"
|
class="ant-table-thead"
|
||||||
>
|
>
|
||||||
@ -2920,7 +2924,11 @@ exports[`renders ./components/transfer/demo/table-transfer.md correctly 1`] = `
|
|||||||
<table
|
<table
|
||||||
style="table-layout:auto"
|
style="table-layout:auto"
|
||||||
>
|
>
|
||||||
<colgroup />
|
<colgroup>
|
||||||
|
<col
|
||||||
|
class="ant-table-selection-column"
|
||||||
|
/>
|
||||||
|
</colgroup>
|
||||||
<thead
|
<thead
|
||||||
class="ant-table-thead"
|
class="ant-table-thead"
|
||||||
>
|
>
|
||||||
|
@ -33,7 +33,7 @@ Uploading is the process of publishing information (web pages, text, pictures, v
|
|||||||
| multiple | Whether to support selected multiple file. `IE10+` supported. You can select multiple files with CTRL holding down while multiple is set to be true | boolean | false | |
|
| multiple | Whether to support selected multiple file. `IE10+` supported. You can select multiple files with CTRL holding down while multiple is set to be true | boolean | false | |
|
||||||
| name | The name of uploading file | string | 'file' | |
|
| name | The name of uploading file | string | 'file' | |
|
||||||
| previewFile | Customize preview file logic | (file: File \| Blob) => Promise<dataURL: string> | - | |
|
| previewFile | Customize preview file logic | (file: File \| Blob) => Promise<dataURL: string> | - | |
|
||||||
| isImageUrl | Customize if render <img /> in thumbnail | (file: UploadFile) => boolean | [inside implementation](https://github.com/ant-design/ant-design/blob/4ad5830eecfb87471cd8ac588c5d992862b70770/components/upload/utils.tsx#L47-L68) | |
|
| isImageUrl | Customize if render `<img />` in thumbnail | (file: UploadFile) => boolean | [inside implementation](https://github.com/ant-design/ant-design/blob/4ad5830eecfb87471cd8ac588c5d992862b70770/components/upload/utils.tsx#L47-L68) | |
|
||||||
| showUploadList | Whether to show default upload list, could be an object to specify `showPreviewIcon`, `showRemoveIcon`, `showDownloadIcon`, `removeIcon` and `downloadIcon` individually | Boolean or { showPreviewIcon?: boolean, showDownloadIcon?: boolean, showRemoveIcon?: boolean, removeIcon?: React.ReactNode, downloadIcon?: React.ReactNode } | true | |
|
| showUploadList | Whether to show default upload list, could be an object to specify `showPreviewIcon`, `showRemoveIcon`, `showDownloadIcon`, `removeIcon` and `downloadIcon` individually | Boolean or { showPreviewIcon?: boolean, showDownloadIcon?: boolean, showRemoveIcon?: boolean, removeIcon?: React.ReactNode, downloadIcon?: React.ReactNode } | true | |
|
||||||
| supportServerRender | Need to be turned on while the server side is rendering | boolean | false | |
|
| supportServerRender | Need to be turned on while the server side is rendering | boolean | false | |
|
||||||
| withCredentials | ajax upload with cookie sent | boolean | false | |
|
| withCredentials | ajax upload with cookie sent | boolean | false | |
|
||||||
|
@ -34,7 +34,7 @@ title: Upload
|
|||||||
| multiple | 是否支持多选文件,`ie10+` 支持。开启后按住 ctrl 可选择多个文件 | boolean | false | |
|
| multiple | 是否支持多选文件,`ie10+` 支持。开启后按住 ctrl 可选择多个文件 | boolean | false | |
|
||||||
| name | 发到后台的文件参数名 | string | 'file' | |
|
| name | 发到后台的文件参数名 | string | 'file' | |
|
||||||
| previewFile | 自定义文件预览逻辑 | (file: File \| Blob) => Promise<dataURL: string> | 无 | |
|
| previewFile | 自定义文件预览逻辑 | (file: File \| Blob) => Promise<dataURL: string> | 无 | |
|
||||||
| isImageUrl | 自定义缩略图是否使用 img 标签进行显示 | (file: UploadFile) => boolean | [内部实现](https://github.com/ant-design/ant-design/blob/4ad5830eecfb87471cd8ac588c5d992862b70770/components/upload/utils.tsx#L47-L68) | |
|
| isImageUrl | 自定义缩略图是否使用 `<img />` 标签进行显示 | (file: UploadFile) => boolean | [内部实现](https://github.com/ant-design/ant-design/blob/4ad5830eecfb87471cd8ac588c5d992862b70770/components/upload/utils.tsx#L47-L68) | |
|
||||||
| showUploadList | 是否展示文件列表, 可设为一个对象,用于单独设定 `showPreviewIcon`, `showRemoveIcon`, `showDownloadIcon`, `removeIcon` 和 `downloadIcon` | Boolean or { showPreviewIcon?: boolean, showRemoveIcon?: boolean, showDownloadIcon?: boolean, removeIcon?: React.ReactNode, downloadIcon?: React.ReactNode } | true | |
|
| showUploadList | 是否展示文件列表, 可设为一个对象,用于单独设定 `showPreviewIcon`, `showRemoveIcon`, `showDownloadIcon`, `removeIcon` 和 `downloadIcon` | Boolean or { showPreviewIcon?: boolean, showRemoveIcon?: boolean, showDownloadIcon?: boolean, removeIcon?: React.ReactNode, downloadIcon?: React.ReactNode } | true | |
|
||||||
| supportServerRender | 服务端渲染时需要打开这个 | boolean | false | |
|
| supportServerRender | 服务端渲染时需要打开这个 | boolean | false | |
|
||||||
| withCredentials | 上传请求时是否携带 cookie | boolean | false | |
|
| withCredentials | 上传请求时是否携带 cookie | boolean | false | |
|
||||||
|
@ -47,45 +47,34 @@ const LinksList = () => (
|
|||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="http://ng.ant.design" target="_blank">
|
<a href="http://ng.ant.design" target="_blank">
|
||||||
NG-ZORRO - Ant Design of Angular<LinkIcon />
|
NG-ZORRO - Ant Design of Angular
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="http://ng.mobile.ant.design" target="_blank">
|
<a href="http://ng.mobile.ant.design" target="_blank">
|
||||||
NG-ZORRO-MOBILE - Ant Design Mobile of Angular<LinkIcon />
|
NG-ZORRO-MOBILE - Ant Design Mobile of Angular
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="http://vue.ant.design" target="_blank">Ant Design of Vue<LinkIcon /></a>
|
<a href="http://vue.ant.design" target="_blank">Ant Design of Vue</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="https://ecomfe.github.io/santd" target="_blank">
|
<a href="https://ecomfe.github.io/santd" target="_blank">
|
||||||
San UI Toolkit for Ant Design<LinkIcon />
|
San UI Toolkit for Ant Design
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="https://github.com/FE-Driver/vue-beauty" target="_blank">
|
|
||||||
vue-beauty (vue)<LinkIcon />
|
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="https://github.com/priornix/antizer" target="_blank">
|
<a href="https://github.com/priornix/antizer" target="_blank">
|
||||||
antizer (ClojureScript)<LinkIcon />
|
antizer (ClojureScript)
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="https://github.com/idcos/antd-ember" target="_blank">
|
<a href="https://ant-design-blazor.github.io/" target="_blank">
|
||||||
antd-ember<LinkIcon />
|
ant-design-blazor/ant-design-blazor
|
||||||
</a>
|
</a>
|
||||||
</li>
|
<span class="ant-divider ant-divider-vertical" />
|
||||||
<li>
|
|
||||||
<a href="https://github.com/zzuu666/antue" target="_blank">
|
|
||||||
antue (vue)<LinkIcon />
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="https://append-it.github.io/ant-design-blazor/" target="_blank">
|
<a href="https://append-it.github.io/ant-design-blazor/" target="_blank">
|
||||||
Ant Design of Blazor<LinkIcon />
|
append-it/ant-design-blazor
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -47,45 +47,36 @@ const LinksList = () => (
|
|||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="http://ng.ant.design" target="_blank">
|
<a href="http://ng.ant.design" target="_blank">
|
||||||
NG-ZORRO - Ant Design of Angular<LinkIcon />
|
NG-ZORRO - Ant Design of Angular
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="http://ng.mobile.ant.design" target="_blank">
|
<a href="http://ng.mobile.ant.design" target="_blank">
|
||||||
NG-ZORRO-MOBILE - Ant Design Mobile of Angular<LinkIcon />
|
NG-ZORRO-MOBILE - Ant Design Mobile of Angular
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="http://vue.ant.design" target="_blank">Ant Design of Vue<LinkIcon /></a>
|
<a href="http://vue.ant.design" target="_blank">Ant Design of Vue</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="https://ecomfe.github.io/santd" target="_blank">
|
<a href="https://ecomfe.github.io/santd" target="_blank">
|
||||||
San UI Toolkit for Ant Design<LinkIcon />
|
San UI Toolkit for Ant Design
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="https://github.com/FE-Driver/vue-beauty" target="_blank">
|
|
||||||
vue-beauty (vue)<LinkIcon />
|
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="https://github.com/priornix/antizer" target="_blank">
|
<a href="https://github.com/priornix/antizer" target="_blank">
|
||||||
antizer (ClojureScript)<LinkIcon />
|
antizer (ClojureScript)
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="https://github.com/idcos/antd-ember" target="_blank">
|
<a href="https://ant-design-blazor.github.io/" target="_blank">
|
||||||
antd-ember<LinkIcon />
|
ant-design-blazor/ant-design-blazor
|
||||||
</a>
|
</a>
|
||||||
</li>
|
<span class="ant-divider ant-divider-vertical" />
|
||||||
<li>
|
<a href="https://append-it.github.io/ant-design-blazor/" target="_blank">
|
||||||
<a href="https://github.com/zzuu666/antue" target="_blank">
|
append-it/ant-design-blazor
|
||||||
antue (vue)<LinkIcon />
|
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
|
||||||
<a href="https://append-it.github.io/ant-design-blazor/" target="_blank">Ant Design of Blazor<LinkIcon /></a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
17
package.json
17
package.json
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "antd",
|
"name": "antd",
|
||||||
"version": "4.1.5",
|
"version": "4.2.0",
|
||||||
"description": "An enterprise-class UI design language and React components implementation",
|
"description": "An enterprise-class UI design language and React components implementation",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"ant",
|
"ant",
|
||||||
@ -71,7 +71,7 @@
|
|||||||
"prettier": "prettier -c --write '**/*'",
|
"prettier": "prettier -c --write '**/*'",
|
||||||
"pretty-quick": "pretty-quick",
|
"pretty-quick": "pretty-quick",
|
||||||
"pub": "antd-tools run pub",
|
"pub": "antd-tools run pub",
|
||||||
"prepublish": "antd-tools run guard",
|
"prepublish": "npm run snyk-protect && antd-tools run guard",
|
||||||
"site": "cross-env NODE_ICU_DATA=node_modules/full-icu concurrently \"bisheng build --ssr -c ./site/bisheng.config.js\" \"node ./scripts/generateColorLess.js\"",
|
"site": "cross-env NODE_ICU_DATA=node_modules/full-icu concurrently \"bisheng build --ssr -c ./site/bisheng.config.js\" \"node ./scripts/generateColorLess.js\"",
|
||||||
"sort": "npx sort-package-json",
|
"sort": "npx sort-package-json",
|
||||||
"sort-api": "antd-tools run sort-api-table",
|
"sort-api": "antd-tools run sort-api-table",
|
||||||
@ -82,7 +82,8 @@
|
|||||||
"test-all": "./scripts/test-all.sh",
|
"test-all": "./scripts/test-all.sh",
|
||||||
"test-node": "jest --config .jest.node.js --no-cache",
|
"test-node": "jest --config .jest.node.js --no-cache",
|
||||||
"tsc": "tsc",
|
"tsc": "tsc",
|
||||||
"site:test": "jest --config .jest.site.js --cache=false"
|
"site:test": "jest --config .jest.site.js --cache=false",
|
||||||
|
"snyk-protect": "snyk protect"
|
||||||
},
|
},
|
||||||
"husky": {
|
"husky": {
|
||||||
"hooks": {
|
"hooks": {
|
||||||
@ -103,7 +104,7 @@
|
|||||||
"copy-to-clipboard": "^3.2.0",
|
"copy-to-clipboard": "^3.2.0",
|
||||||
"css-animation": "^1.5.0",
|
"css-animation": "^1.5.0",
|
||||||
"lodash": "^4.17.13",
|
"lodash": "^4.17.13",
|
||||||
"moment": "^2.24.0",
|
"moment": "~2.24.0",
|
||||||
"omit.js": "^1.0.2",
|
"omit.js": "^1.0.2",
|
||||||
"prop-types": "^15.7.2",
|
"prop-types": "^15.7.2",
|
||||||
"raf": "^3.4.1",
|
"raf": "^3.4.1",
|
||||||
@ -128,7 +129,7 @@
|
|||||||
"rc-slider": "~9.2.3",
|
"rc-slider": "~9.2.3",
|
||||||
"rc-steps": "~3.5.0",
|
"rc-steps": "~3.5.0",
|
||||||
"rc-switch": "~1.9.0",
|
"rc-switch": "~1.9.0",
|
||||||
"rc-table": "~7.5.2",
|
"rc-table": "~7.5.3",
|
||||||
"rc-tabs": "~10.1.1",
|
"rc-tabs": "~10.1.1",
|
||||||
"rc-tooltip": "~4.0.2",
|
"rc-tooltip": "~4.0.2",
|
||||||
"rc-tree": "~3.1.0",
|
"rc-tree": "~3.1.0",
|
||||||
@ -139,7 +140,8 @@
|
|||||||
"rc-virtual-list": "^1.1.0",
|
"rc-virtual-list": "^1.1.0",
|
||||||
"resize-observer-polyfill": "^1.5.1",
|
"resize-observer-polyfill": "^1.5.1",
|
||||||
"scroll-into-view-if-needed": "^2.2.20",
|
"scroll-into-view-if-needed": "^2.2.20",
|
||||||
"warning": "~4.0.3"
|
"warning": "~4.0.3",
|
||||||
|
"snyk": "^1.316.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@ant-design/bisheng-plugin": "^2.3.0",
|
"@ant-design/bisheng-plugin": "^2.3.0",
|
||||||
@ -290,5 +292,6 @@
|
|||||||
"tnpm": {
|
"tnpm": {
|
||||||
"mode": "npm"
|
"mode": "npm"
|
||||||
},
|
},
|
||||||
"title": "Ant Design"
|
"title": "Ant Design",
|
||||||
|
"snyk": true
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
@import './colors';
|
@import './colors';
|
||||||
|
|
||||||
.rc-footer {
|
.rc-footer {
|
||||||
z-index: 9;
|
z-index: 8;
|
||||||
|
|
||||||
&-container {
|
&-container {
|
||||||
max-width: unset;
|
max-width: unset;
|
||||||
|
@ -258,16 +258,6 @@ export default function DesignPage() {
|
|||||||
{IconComponent}
|
{IconComponent}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
|
||||||
<a
|
|
||||||
href="https://append-it.github.io/ant-design-blazor/"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>
|
|
||||||
Ant Design of Blazor
|
|
||||||
{IconComponent}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</Col>
|
</Col>
|
||||||
<Col xs={24} sm={15} style={{ alignSelf: 'flex-end', textAlign: 'right' }}>
|
<Col xs={24} sm={15} style={{ alignSelf: 'flex-end', textAlign: 'right' }}>
|
||||||
|
@ -79,11 +79,6 @@ class Footer extends React.Component<WrappedComponentProps> {
|
|||||||
url: 'https://vue.ant.design',
|
url: 'https://vue.ant.design',
|
||||||
openExternal: true,
|
openExternal: true,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
title: 'Ant Design Blazor',
|
|
||||||
url: 'https://append-it.github.io/ant-design-blazor/',
|
|
||||||
openExternal: true,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: 'Ant Design Landing',
|
title: 'Ant Design Landing',
|
||||||
description: <FormattedMessage id="app.footer.landing" />,
|
description: <FormattedMessage id="app.footer.landing" />,
|
||||||
|
@ -37,16 +37,6 @@ export function getEcosystemGroup({ isZhCN }: SharedProps): React.ReactElement {
|
|||||||
Ant Design of Vue
|
Ant Design of Vue
|
||||||
</a>
|
</a>
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
<Menu.Item key="blazor">
|
|
||||||
<a
|
|
||||||
href="https://append-it.github.io/ant-design-blazor/"
|
|
||||||
className="header-link"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>
|
|
||||||
Ant Design of Blazor
|
|
||||||
</a>
|
|
||||||
</Menu.Item>
|
|
||||||
{isZhCN ? (
|
{isZhCN ? (
|
||||||
<Menu.Item key="course" className="hide-in-home-page">
|
<Menu.Item key="course" className="hide-in-home-page">
|
||||||
<a
|
<a
|
||||||
|
Loading…
Reference in New Issue
Block a user