mirror of
https://gitee.com/ant-design/ant-design.git
synced 2024-12-15 17:31:25 +08:00
Merge pull request #24741 from ant-design/master
chore: merge master into feature
This commit is contained in:
commit
d1bdaee607
3
.github/tests_checker.yml
vendored
Normal file
3
.github/tests_checker.yml
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
comment: 'Could you please add tests to make sure this change works as expected?',
|
||||||
|
fileExtensions: [.ts', '.tsx', '.json']
|
||||||
|
testDir: '__tests__'
|
@ -15,6 +15,29 @@ timeline: true
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## 4.3.1
|
||||||
|
|
||||||
|
`2020-06-02`
|
||||||
|
|
||||||
|
- Tabs
|
||||||
|
- 🐞 Fix Tabs `hideAdd` not working. [#24621](https://github.com/ant-design/ant-design/pull/24621)
|
||||||
|
- 🐞 Fix Tabs dropdown has extra horizontal scrollbar in Firefox. [#24677](https://github.com/ant-design/ant-design/pull/24677)
|
||||||
|
- 🐞 Fix Tabs inkbar border lost when use with `react-sticky`. [#24643](https://github.com/ant-design/ant-design/pull/24643)
|
||||||
|
- 💄 Adjust Tabs `tabBarStyle` style display. [#24620](https://github.com/ant-design/ant-design/pull/24620)
|
||||||
|
- Button
|
||||||
|
- 🐞 Fix Button quick set `loading` from `delay` to `false` will still change to the loading status. [#24678](https://github.com/ant-design/ant-design/pull/24678)
|
||||||
|
- 🐞 Fix the inconsistent style of Text Button in `danger`. [#24622](https://github.com/ant-design/ant-design/pull/24622) [@morenyang](https://github.com/morenyang)
|
||||||
|
- 🐞 Fix Table no showing scrollbar inside Row. [#24661](https://github.com/ant-design/ant-design/pull/24661) [@zt123123](https://github.com/zt123123)
|
||||||
|
- 🐞 Fix Drawer get `dropdownMatchSelectWidth` as dom prop warning. [#24651](https://github.com/ant-design/ant-design/pull/24651)
|
||||||
|
- 🐞 Adjust Steps to support React.Fragment with `children`. [#24644](https://github.com/ant-design/ant-design/pull/24644)
|
||||||
|
- 🐞 Fix Upload delete icon cannot be navigate via keyboard. [#24615](https://github.com/ant-design/ant-design/pull/24615) [@morenyang](https://github.com/morenyang)
|
||||||
|
- 🐞 Fix multiple Select search input cursor missing issue. [#24631](https://github.com/ant-design/ant-design/pull/24631)
|
||||||
|
- 🐞 Fix Radio.Group using `options` get `Element type is invalid` error. [#24631](https://github.com/ant-design/ant-design/pull/24631)
|
||||||
|
- RTL
|
||||||
|
- 💄 Adjust Notification default placement to `topLeft` in RTL. [#24632](https://github.com/ant-design/ant-design/pull/24632)
|
||||||
|
- TypeScript
|
||||||
|
- 🛠 Export Tabs `TabPaneProps` definition. [#24648](https://github.com/ant-design/ant-design/pull/24648)
|
||||||
|
|
||||||
## 4.3.0
|
## 4.3.0
|
||||||
|
|
||||||
`2020-05-31`
|
`2020-05-31`
|
||||||
@ -81,7 +104,7 @@ timeline: true
|
|||||||
- 💄 Optimize Table filter dropdown style in RTL. [#24529](https://github.com/ant-design/ant-design/pull/24529)
|
- 💄 Optimize Table filter dropdown style in RTL. [#24529](https://github.com/ant-design/ant-design/pull/24529)
|
||||||
- 💄 Fix Cascader dropdown style in RTL. [#24520](https://github.com/ant-design/ant-design/pull/24520)
|
- 💄 Fix Cascader dropdown style in RTL. [#24520](https://github.com/ant-design/ant-design/pull/24520)
|
||||||
- TypeScript
|
- TypeScript
|
||||||
- Form export `RuleObject` and `RuleRender` types. [#24541](https://github.com/ant-design/ant-design/pull/24541) [@sorteam](https://github.com/sorteam)
|
- 🛠 Form export `RuleObject` and `RuleRender` types. [#24541](https://github.com/ant-design/ant-design/pull/24541) [@sorteam](https://github.com/sorteam)
|
||||||
|
|
||||||
## 4.2.5
|
## 4.2.5
|
||||||
|
|
||||||
|
@ -15,6 +15,29 @@ timeline: true
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## 4.3.1
|
||||||
|
|
||||||
|
`2020-06-02`
|
||||||
|
|
||||||
|
- Tabs
|
||||||
|
- 🐞 修复 Tabs `hideAdd` 无效的问题。[#24621](https://github.com/ant-design/ant-design/pull/24621)
|
||||||
|
- 🐞 修复 Tabs 下拉菜单内在 Firefox 下出现水平滚动条。[#24677](https://github.com/ant-design/ant-design/pull/24677)
|
||||||
|
- 🐞 修复 Tabs 配合 `react-sticky` 使用时下划线遗失问题。[#24643](https://github.com/ant-design/ant-design/pull/24643)
|
||||||
|
- 💄 调整 Tabs `tabBarStyle` 的展示样式。[#24620](https://github.com/ant-design/ant-design/pull/24620)
|
||||||
|
- Button
|
||||||
|
- 🐞 修复 Button 将 `loading` 从 `delay` 快速切换至 `false` 时仍然会变成加载状态的问题。[#24678](https://github.com/ant-design/ant-design/pull/24678)
|
||||||
|
- 🐞 修复 Text Button 在 `danger` 时样式不一致的问题。[#24622](https://github.com/ant-design/ant-design/pull/24622) [@morenyang](https://github.com/morenyang)
|
||||||
|
- 🐞 修复 Table 包裹在 Row 中时无法展现横向滚动条的问题。[#24661](https://github.com/ant-design/ant-design/pull/24661) [@zt123123](https://github.com/zt123123)
|
||||||
|
- 🐞 修复 Drawer 会报 dom 节点设置 `dropdownMatchSelectWidth` 的警告信息。[#24651](https://github.com/ant-design/ant-design/pull/24651)
|
||||||
|
- 🐞 调整 Steps 现支持 `children` 下使用 React.Fragment。[#24644](https://github.com/ant-design/ant-design/pull/24644)
|
||||||
|
- 🐞 解决 Upload 删除图标键盘无法导航操作的问题。[#24615](https://github.com/ant-design/ant-design/pull/24615) [@morenyang](https://github.com/morenyang)
|
||||||
|
- 🐞 修复多选 Select 输入框的光标展示问题。[#24631](https://github.com/ant-design/ant-design/pull/24631)
|
||||||
|
- 🐞 修复 Radio.Group 设置 `options` 报错的问题。[#24631](https://github.com/ant-design/ant-design/pull/24631)
|
||||||
|
- RTL
|
||||||
|
- 💄 调整 Notification RTL 模式下默认弹窗位置为左上。[#24632](https://github.com/ant-design/ant-design/pull/24632)
|
||||||
|
- TypeScript
|
||||||
|
- 🛠 导出 Tabs `TabPaneProps` 定义。[#24648](https://github.com/ant-design/ant-design/pull/24648)
|
||||||
|
|
||||||
## 4.3.0
|
## 4.3.0
|
||||||
|
|
||||||
`2020-05-31`
|
`2020-05-31`
|
||||||
@ -81,7 +104,7 @@ timeline: true
|
|||||||
- 💄 优化 Table 筛选下拉框在 RTL 模式下样式。[#24529](https://github.com/ant-design/ant-design/pull/24529)
|
- 💄 优化 Table 筛选下拉框在 RTL 模式下样式。[#24529](https://github.com/ant-design/ant-design/pull/24529)
|
||||||
- 💄 优化 Cascader RTL 模式下拉框的样式。[#24520](https://github.com/ant-design/ant-design/pull/24520)
|
- 💄 优化 Cascader RTL 模式下拉框的样式。[#24520](https://github.com/ant-design/ant-design/pull/24520)
|
||||||
- TypeScript
|
- TypeScript
|
||||||
- Form 导出 `RuleObject` 与 `RuleRender` 定义。[#24541](https://github.com/ant-design/ant-design/pull/24541) [@sorteam](https://github.com/sorteam)
|
- 🛠 Form 导出 `RuleObject` 与 `RuleRender` 定义。[#24541](https://github.com/ant-design/ant-design/pull/24541) [@sorteam](https://github.com/sorteam)
|
||||||
|
|
||||||
## 4.2.5
|
## 4.2.5
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { mount, render } from 'enzyme';
|
import { mount, render } from 'enzyme';
|
||||||
|
import { act } from 'react-dom/test-utils';
|
||||||
import { SearchOutlined } from '@ant-design/icons';
|
import { SearchOutlined } from '@ant-design/icons';
|
||||||
import Button from '..';
|
import Button from '..';
|
||||||
import ConfigProvider from '../../config-provider';
|
import ConfigProvider from '../../config-provider';
|
||||||
@ -165,6 +166,24 @@ describe('Button', () => {
|
|||||||
expect(wrapper.hasClass('ant-btn-loading')).toBe(false);
|
expect(wrapper.hasClass('ant-btn-loading')).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('reset when loading back of delay', () => {
|
||||||
|
jest.useFakeTimers();
|
||||||
|
const wrapper = mount(<Button loading={{ delay: 1000 }} />);
|
||||||
|
wrapper.update();
|
||||||
|
wrapper.setProps({ loading: { delay: 2000 } });
|
||||||
|
wrapper.update();
|
||||||
|
wrapper.setProps({ loading: false });
|
||||||
|
|
||||||
|
act(() => {
|
||||||
|
jest.runAllTimers();
|
||||||
|
wrapper.update();
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(wrapper.find('.ant-btn-loading')).toHaveLength(0);
|
||||||
|
|
||||||
|
jest.useRealTimers();
|
||||||
|
});
|
||||||
|
|
||||||
it('should not clickable when button is loading', () => {
|
it('should not clickable when button is loading', () => {
|
||||||
const onClick = jest.fn();
|
const onClick = jest.fn();
|
||||||
const wrapper = mount(
|
const wrapper = mount(
|
||||||
|
@ -121,16 +121,32 @@ interface CompoundedComponent
|
|||||||
__ANT_BUTTON: boolean;
|
__ANT_BUTTON: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Loading = number | boolean;
|
||||||
|
|
||||||
const InternalButton: React.ForwardRefRenderFunction<unknown, ButtonProps> = (props, ref) => {
|
const InternalButton: React.ForwardRefRenderFunction<unknown, ButtonProps> = (props, ref) => {
|
||||||
|
const {
|
||||||
|
loading,
|
||||||
|
prefixCls: customizePrefixCls,
|
||||||
|
type,
|
||||||
|
danger,
|
||||||
|
shape,
|
||||||
|
size: customizeSize,
|
||||||
|
className,
|
||||||
|
children,
|
||||||
|
icon,
|
||||||
|
ghost,
|
||||||
|
block,
|
||||||
|
...rest
|
||||||
|
} = props;
|
||||||
|
|
||||||
const size = React.useContext(SizeContext);
|
const size = React.useContext(SizeContext);
|
||||||
const [loading, setLoading] = React.useState(props.loading);
|
const [innerLoading, setLoading] = React.useState<Loading>(!!loading);
|
||||||
const [hasTwoCNChar, setHasTwoCNChar] = React.useState(false);
|
const [hasTwoCNChar, setHasTwoCNChar] = React.useState(false);
|
||||||
const { getPrefixCls, autoInsertSpaceInButton, direction } = React.useContext(ConfigContext);
|
const { getPrefixCls, autoInsertSpaceInButton, direction } = React.useContext(ConfigContext);
|
||||||
const buttonRef = (ref as any) || React.createRef<HTMLElement>();
|
const buttonRef = (ref as any) || React.createRef<HTMLElement>();
|
||||||
let delayTimeout: number;
|
const delayTimeoutRef = React.useRef<number>();
|
||||||
|
|
||||||
const isNeedInserted = () => {
|
const isNeedInserted = () => {
|
||||||
const { icon, children, type } = props;
|
|
||||||
return React.Children.count(children) === 1 && !icon && type !== 'link' && type !== 'text';
|
return React.Children.count(children) === 1 && !icon && type !== 'link' && type !== 'text';
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -149,18 +165,24 @@ const InternalButton: React.ForwardRefRenderFunction<unknown, ButtonProps> = (pr
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// =============== Update Loading ===============
|
||||||
|
let loadingOrDelay: Loading;
|
||||||
|
if (typeof loading === 'object' && loading.delay) {
|
||||||
|
loadingOrDelay = loading.delay || true;
|
||||||
|
} else {
|
||||||
|
loadingOrDelay = !!loading;
|
||||||
|
}
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (props.loading && typeof props.loading !== 'boolean') {
|
clearTimeout(delayTimeoutRef.current);
|
||||||
clearTimeout(delayTimeout);
|
if (typeof loadingOrDelay === 'number') {
|
||||||
|
delayTimeoutRef.current = window.setTimeout(() => {
|
||||||
|
setLoading(loadingOrDelay);
|
||||||
|
}, loadingOrDelay);
|
||||||
|
} else {
|
||||||
|
setLoading(loadingOrDelay);
|
||||||
}
|
}
|
||||||
if (props.loading && typeof props.loading !== 'boolean' && props.loading.delay) {
|
}, [loadingOrDelay]);
|
||||||
delayTimeout = window.setTimeout(() => {
|
|
||||||
setLoading(props.loading);
|
|
||||||
}, props.loading.delay);
|
|
||||||
} else if (props.loading !== loading) {
|
|
||||||
setLoading(props.loading);
|
|
||||||
}
|
|
||||||
}, [props.loading]);
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
fixTwoCNChar();
|
fixTwoCNChar();
|
||||||
@ -168,26 +190,13 @@ const InternalButton: React.ForwardRefRenderFunction<unknown, ButtonProps> = (pr
|
|||||||
|
|
||||||
const handleClick = (e: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement, MouseEvent>) => {
|
const handleClick = (e: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement, MouseEvent>) => {
|
||||||
const { onClick } = props;
|
const { onClick } = props;
|
||||||
if (loading) {
|
if (innerLoading) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (onClick) {
|
if (onClick) {
|
||||||
(onClick as React.MouseEventHandler<HTMLButtonElement | HTMLAnchorElement>)(e);
|
(onClick as React.MouseEventHandler<HTMLButtonElement | HTMLAnchorElement>)(e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const {
|
|
||||||
prefixCls: customizePrefixCls,
|
|
||||||
type,
|
|
||||||
danger,
|
|
||||||
shape,
|
|
||||||
size: customizeSize,
|
|
||||||
className,
|
|
||||||
children,
|
|
||||||
icon,
|
|
||||||
ghost,
|
|
||||||
block,
|
|
||||||
...rest
|
|
||||||
} = props;
|
|
||||||
|
|
||||||
devWarning(
|
devWarning(
|
||||||
!(typeof icon === 'string' && icon.length > 2),
|
!(typeof icon === 'string' && icon.length > 2),
|
||||||
@ -212,7 +221,7 @@ const InternalButton: React.ForwardRefRenderFunction<unknown, ButtonProps> = (pr
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const iconType = loading ? 'loading' : icon;
|
const iconType = innerLoading ? 'loading' : icon;
|
||||||
|
|
||||||
const classes = classNames(prefixCls, className, {
|
const classes = classNames(prefixCls, className, {
|
||||||
[`${prefixCls}-${type}`]: type,
|
[`${prefixCls}-${type}`]: type,
|
||||||
@ -220,7 +229,7 @@ const InternalButton: React.ForwardRefRenderFunction<unknown, ButtonProps> = (pr
|
|||||||
[`${prefixCls}-${sizeCls}`]: sizeCls,
|
[`${prefixCls}-${sizeCls}`]: sizeCls,
|
||||||
[`${prefixCls}-icon-only`]: !children && children !== 0 && iconType,
|
[`${prefixCls}-icon-only`]: !children && children !== 0 && iconType,
|
||||||
[`${prefixCls}-background-ghost`]: ghost,
|
[`${prefixCls}-background-ghost`]: ghost,
|
||||||
[`${prefixCls}-loading`]: loading,
|
[`${prefixCls}-loading`]: innerLoading,
|
||||||
[`${prefixCls}-two-chinese-chars`]: hasTwoCNChar && autoInsertSpace,
|
[`${prefixCls}-two-chinese-chars`]: hasTwoCNChar && autoInsertSpace,
|
||||||
[`${prefixCls}-block`]: block,
|
[`${prefixCls}-block`]: block,
|
||||||
[`${prefixCls}-dangerous`]: !!danger,
|
[`${prefixCls}-dangerous`]: !!danger,
|
||||||
@ -228,10 +237,10 @@ const InternalButton: React.ForwardRefRenderFunction<unknown, ButtonProps> = (pr
|
|||||||
});
|
});
|
||||||
|
|
||||||
const iconNode =
|
const iconNode =
|
||||||
icon && !loading ? (
|
icon && !innerLoading ? (
|
||||||
icon
|
icon
|
||||||
) : (
|
) : (
|
||||||
<LoadingIcon existIcon={!!icon} prefixCls={prefixCls} loading={loading} />
|
<LoadingIcon existIcon={!!icon} prefixCls={prefixCls} loading={!!innerLoading} />
|
||||||
);
|
);
|
||||||
|
|
||||||
const kids =
|
const kids =
|
||||||
|
@ -23,14 +23,23 @@ class App extends React.Component {
|
|||||||
};
|
};
|
||||||
|
|
||||||
enterLoading = index => {
|
enterLoading = index => {
|
||||||
const newLoadings = [...this.state.loadings];
|
this.setState(({ loadings }) => {
|
||||||
newLoadings[index] = true;
|
const newLoadings = [...loadings];
|
||||||
this.setState({
|
newLoadings[index] = true;
|
||||||
loadings: newLoadings,
|
|
||||||
|
return {
|
||||||
|
loadings: newLoadings,
|
||||||
|
};
|
||||||
});
|
});
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
newLoadings[index] = false;
|
this.setState(({ loadings }) => {
|
||||||
this.setState({ loadings: newLoadings });
|
const newLoadings = [...loadings];
|
||||||
|
newLoadings[index] = false;
|
||||||
|
|
||||||
|
return {
|
||||||
|
loadings: newLoadings,
|
||||||
|
};
|
||||||
|
});
|
||||||
}, 6000);
|
}, 6000);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -127,15 +127,27 @@ describe('Calendar', () => {
|
|||||||
MockDate.reset();
|
MockDate.reset();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should trigger onPanelChange when click last month of date', () => {
|
describe('onPanelChange', () => {
|
||||||
const onPanelChange = jest.fn();
|
it('trigger when click last month of date', () => {
|
||||||
const date = new Moment('1990-09-03');
|
const onPanelChange = jest.fn();
|
||||||
const wrapper = mount(<Calendar onPanelChange={onPanelChange} value={date} />);
|
const date = new Moment('1990-09-03');
|
||||||
|
const wrapper = mount(<Calendar onPanelChange={onPanelChange} value={date} />);
|
||||||
|
|
||||||
wrapper.find('.ant-picker-cell').at(0).simulate('click');
|
wrapper.find('.ant-picker-cell').at(0).simulate('click');
|
||||||
|
|
||||||
expect(onPanelChange).toHaveBeenCalled();
|
expect(onPanelChange).toHaveBeenCalled();
|
||||||
expect(onPanelChange.mock.calls[0][0].month()).toEqual(date.month() - 1);
|
expect(onPanelChange.mock.calls[0][0].month()).toEqual(date.month() - 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('not trigger when in same month', () => {
|
||||||
|
const onPanelChange = jest.fn();
|
||||||
|
const date = new Moment('1990-09-03');
|
||||||
|
const wrapper = mount(<Calendar onPanelChange={onPanelChange} value={date} />);
|
||||||
|
|
||||||
|
wrapper.find('.ant-picker-cell').at(10).simulate('click');
|
||||||
|
|
||||||
|
expect(onPanelChange).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('switch should work correctly without prop mode', async () => {
|
it('switch should work correctly without prop mode', async () => {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
import useMergedState from 'rc-util/lib/hooks/useMergedState';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import padStart from 'lodash/padStart';
|
import padStart from 'lodash/padStart';
|
||||||
import { PickerPanel as RCPickerPanel } from 'rc-picker';
|
import { PickerPanel as RCPickerPanel } from 'rc-picker';
|
||||||
@ -62,13 +63,13 @@ export interface CalendarProps<DateType> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function generateCalendar<DateType>(generateConfig: GenerateConfig<DateType>) {
|
function generateCalendar<DateType>(generateConfig: GenerateConfig<DateType>) {
|
||||||
|
function isSameYear(date1: DateType, date2: DateType) {
|
||||||
|
return date1 && date2 && generateConfig.getYear(date1) === generateConfig.getYear(date2);
|
||||||
|
}
|
||||||
|
|
||||||
function isSameMonth(date1: DateType, date2: DateType) {
|
function isSameMonth(date1: DateType, date2: DateType) {
|
||||||
return (
|
return (
|
||||||
date1 === date2 ||
|
isSameYear(date1, date2) && generateConfig.getMonth(date1) === generateConfig.getMonth(date2)
|
||||||
(date1 &&
|
|
||||||
date2 &&
|
|
||||||
generateConfig.getYear(date1) === generateConfig.getYear(date2) &&
|
|
||||||
generateConfig.getMonth(date1) === generateConfig.getMonth(date2))
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,15 +107,15 @@ function generateCalendar<DateType>(generateConfig: GenerateConfig<DateType>) {
|
|||||||
// ====================== State =======================
|
// ====================== State =======================
|
||||||
|
|
||||||
// Value
|
// Value
|
||||||
const [innerValue, setInnerValue] = React.useState(
|
const [mergedValue, setMergedValue] = useMergedState(() => value || generateConfig.getNow(), {
|
||||||
() => value || defaultValue || generateConfig.getNow(),
|
defaultValue,
|
||||||
);
|
value,
|
||||||
|
});
|
||||||
const mergedValue = value || innerValue;
|
|
||||||
|
|
||||||
// Mode
|
// Mode
|
||||||
const [innerMode, setInnerMode] = React.useState(() => mode || 'month');
|
const [mergedMode, setMergedMode] = useMergedState('month', {
|
||||||
const mergedMode = mode || innerMode;
|
value: mode,
|
||||||
|
});
|
||||||
const panelMode = React.useMemo<'month' | 'date'>(
|
const panelMode = React.useMemo<'month' | 'date'>(
|
||||||
() => (mergedMode === 'year' ? 'month' : 'date'),
|
() => (mergedMode === 'year' ? 'month' : 'date'),
|
||||||
[mergedMode],
|
[mergedMode],
|
||||||
@ -142,10 +143,16 @@ function generateCalendar<DateType>(generateConfig: GenerateConfig<DateType>) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const triggerChange = (date: DateType) => {
|
const triggerChange = (date: DateType) => {
|
||||||
setInnerValue(date);
|
setMergedValue(date);
|
||||||
|
|
||||||
if (!isSameDate(date, mergedValue)) {
|
if (!isSameDate(date, mergedValue)) {
|
||||||
triggerPanelChange(date, mergedMode);
|
// Trigger when month panel switch month
|
||||||
|
if (
|
||||||
|
(panelMode === 'date' && !isSameMonth(date, mergedValue)) ||
|
||||||
|
(panelMode === 'month' && !isSameYear(date, mergedValue))
|
||||||
|
) {
|
||||||
|
triggerPanelChange(date, mergedMode);
|
||||||
|
}
|
||||||
|
|
||||||
if (onChange) {
|
if (onChange) {
|
||||||
onChange(date);
|
onChange(date);
|
||||||
@ -154,7 +161,7 @@ function generateCalendar<DateType>(generateConfig: GenerateConfig<DateType>) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const triggerModeChange = (newMode: CalendarMode) => {
|
const triggerModeChange = (newMode: CalendarMode) => {
|
||||||
setInnerMode(newMode);
|
setMergedMode(newMode);
|
||||||
triggerPanelChange(mergedValue, newMode);
|
triggerPanelChange(mergedValue, newMode);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ import { mount } from 'enzyme';
|
|||||||
import ConfigProvider from '..';
|
import ConfigProvider from '..';
|
||||||
import DatePicker from '../../date-picker';
|
import DatePicker from '../../date-picker';
|
||||||
import Slider from '../../slider';
|
import Slider from '../../slider';
|
||||||
|
import Drawer from '../../drawer';
|
||||||
|
|
||||||
describe('ConfigProvider.GetPopupContainer', () => {
|
describe('ConfigProvider.GetPopupContainer', () => {
|
||||||
it('Datepicker', () => {
|
it('Datepicker', () => {
|
||||||
@ -25,4 +26,15 @@ describe('ConfigProvider.GetPopupContainer', () => {
|
|||||||
wrapper.find('.ant-slider-handle').first().simulate('mouseenter');
|
wrapper.find('.ant-slider-handle').first().simulate('mouseenter');
|
||||||
expect(getPopupContainer).toHaveBeenCalled();
|
expect(getPopupContainer).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('drawer', () => {
|
||||||
|
const getPopupContainer = jest.fn(node => node.parentNode);
|
||||||
|
const Demo = ({ visible }) => (
|
||||||
|
<ConfigProvider getPopupContainer={getPopupContainer}>
|
||||||
|
<Drawer visible={visible} />
|
||||||
|
</ConfigProvider>
|
||||||
|
);
|
||||||
|
mount(<Demo visible />);
|
||||||
|
expect(getPopupContainer).toHaveBeenCalled();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -11,6 +11,21 @@ exports[`renders ./components/drawer/demo/basic-right.md correctly 1`] = `
|
|||||||
</button>
|
</button>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`renders ./components/drawer/demo/config-provider.md correctly 1`] = `
|
||||||
|
<div
|
||||||
|
class="site-drawer-render-in-current-wrapper"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
class="ant-btn ant-btn-primary"
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
Open
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`renders ./components/drawer/demo/form-in-drawer.md correctly 1`] = `
|
exports[`renders ./components/drawer/demo/form-in-drawer.md correctly 1`] = `
|
||||||
<button
|
<button
|
||||||
class="ant-btn ant-btn-primary"
|
class="ant-btn ant-btn-primary"
|
||||||
|
57
components/drawer/demo/config-provider.md
Normal file
57
components/drawer/demo/config-provider.md
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
---
|
||||||
|
order: 99
|
||||||
|
title:
|
||||||
|
zh-CN: ConfigProvider
|
||||||
|
en-US: ConfigProvider
|
||||||
|
debug: true
|
||||||
|
---
|
||||||
|
|
||||||
|
## zh-CN
|
||||||
|
|
||||||
|
支持 ConfigProvider 配置。
|
||||||
|
|
||||||
|
## en-US
|
||||||
|
|
||||||
|
config by ConfigProvider.
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import React, { useState, useRef } from 'react';
|
||||||
|
import { Drawer, ConfigProvider, Button } from 'antd';
|
||||||
|
|
||||||
|
const App: React.FC = () => {
|
||||||
|
const domRef = useRef();
|
||||||
|
const [visible, setVisible] = useState(false);
|
||||||
|
const showDrawer = () => {
|
||||||
|
setVisible(true);
|
||||||
|
};
|
||||||
|
const onClose = () => {
|
||||||
|
setVisible(false);
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<ConfigProvider
|
||||||
|
getPopupContainer={() => {
|
||||||
|
return domRef.current;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div ref={domRef} className="site-drawer-render-in-current-wrapper">
|
||||||
|
<Button type="primary" onClick={showDrawer}>
|
||||||
|
Open
|
||||||
|
</Button>
|
||||||
|
<Drawer
|
||||||
|
style={{ position: 'absolute' }}
|
||||||
|
title="ConfigProvider"
|
||||||
|
placement="right"
|
||||||
|
onClose={onClose}
|
||||||
|
visible={visible}
|
||||||
|
>
|
||||||
|
<p>Some contents...</p>
|
||||||
|
<p>Some contents...</p>
|
||||||
|
<p>Some contents...</p>
|
||||||
|
</Drawer>
|
||||||
|
</div>
|
||||||
|
</ConfigProvider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
ReactDOM.render(<App />, mountNode);
|
||||||
|
```
|
@ -6,7 +6,7 @@ import classNames from 'classnames';
|
|||||||
import omit from 'omit.js';
|
import omit from 'omit.js';
|
||||||
|
|
||||||
import { ConfigConsumerProps } from '../config-provider';
|
import { ConfigConsumerProps } from '../config-provider';
|
||||||
import { withConfigConsumer } from '../config-provider/context';
|
import { withConfigConsumer, ConfigConsumer } from '../config-provider/context';
|
||||||
import { tuple } from '../_util/type';
|
import { tuple } from '../_util/type';
|
||||||
|
|
||||||
const DrawerContext = React.createContext<Drawer | null>(null);
|
const DrawerContext = React.createContext<Drawer | null>(null);
|
||||||
@ -253,54 +253,77 @@ class Drawer extends React.Component<DrawerProps & ConfigConsumerProps, IDrawerS
|
|||||||
|
|
||||||
// render Provider for Multi-level drawer
|
// render Provider for Multi-level drawer
|
||||||
renderProvider = (value: Drawer) => {
|
renderProvider = (value: Drawer) => {
|
||||||
const { prefixCls, placement, className, mask, direction, visible, ...rest } = this.props;
|
|
||||||
this.parentDrawer = value;
|
this.parentDrawer = value;
|
||||||
const drawerClassName = classNames(className, {
|
|
||||||
'no-mask': !mask,
|
|
||||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
|
||||||
});
|
|
||||||
const offsetStyle = mask ? this.getOffsetStyle() : {};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DrawerContext.Provider value={this}>
|
<ConfigConsumer>
|
||||||
<RcDrawer
|
{({ getPopupContainer, getPrefixCls }) => {
|
||||||
handler={false}
|
const {
|
||||||
{...omit(rest, [
|
prefixCls: customizePrefixCls,
|
||||||
'zIndex',
|
placement,
|
||||||
'style',
|
className,
|
||||||
'closable',
|
mask,
|
||||||
'destroyOnClose',
|
direction,
|
||||||
'drawerStyle',
|
visible,
|
||||||
'headerStyle',
|
...rest
|
||||||
'bodyStyle',
|
} = this.props;
|
||||||
'footerStyle',
|
|
||||||
'footer',
|
const prefixCls = getPrefixCls('select', customizePrefixCls);
|
||||||
'locale',
|
const drawerClassName = classNames(className, {
|
||||||
'title',
|
'no-mask': !mask,
|
||||||
'push',
|
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||||
'visible',
|
});
|
||||||
'getPopupContainer',
|
const offsetStyle = mask ? this.getOffsetStyle() : {};
|
||||||
'rootPrefixCls',
|
|
||||||
'getPrefixCls',
|
return (
|
||||||
'renderEmpty',
|
<DrawerContext.Provider value={this}>
|
||||||
'csp',
|
<RcDrawer
|
||||||
'pageHeader',
|
handler={false}
|
||||||
'autoInsertSpaceInButton',
|
{...omit(rest, [
|
||||||
'width',
|
'zIndex',
|
||||||
'height',
|
'style',
|
||||||
'dropdownMatchSelectWidth',
|
'closable',
|
||||||
])}
|
'destroyOnClose',
|
||||||
{...offsetStyle}
|
'drawerStyle',
|
||||||
prefixCls={prefixCls}
|
'headerStyle',
|
||||||
open={visible}
|
'bodyStyle',
|
||||||
showMask={mask}
|
'footerStyle',
|
||||||
placement={placement}
|
'footer',
|
||||||
style={this.getRcDrawerStyle()}
|
'locale',
|
||||||
className={drawerClassName}
|
'title',
|
||||||
>
|
'push',
|
||||||
{this.renderBody()}
|
'visible',
|
||||||
</RcDrawer>
|
'getPopupContainer',
|
||||||
</DrawerContext.Provider>
|
'rootPrefixCls',
|
||||||
|
'getPrefixCls',
|
||||||
|
'renderEmpty',
|
||||||
|
'csp',
|
||||||
|
'pageHeader',
|
||||||
|
'autoInsertSpaceInButton',
|
||||||
|
'width',
|
||||||
|
'height',
|
||||||
|
'dropdownMatchSelectWidth',
|
||||||
|
])}
|
||||||
|
getContainer={
|
||||||
|
// 有可能为 false,所以不能直接判断
|
||||||
|
rest.getContainer === undefined
|
||||||
|
? () => (getPopupContainer ? getPopupContainer(document.body) : undefined)
|
||||||
|
: rest.getContainer
|
||||||
|
}
|
||||||
|
{...offsetStyle}
|
||||||
|
prefixCls={prefixCls}
|
||||||
|
open={visible}
|
||||||
|
showMask={mask}
|
||||||
|
placement={placement}
|
||||||
|
style={this.getRcDrawerStyle()}
|
||||||
|
className={drawerClassName}
|
||||||
|
>
|
||||||
|
{this.renderBody()}
|
||||||
|
</RcDrawer>
|
||||||
|
</DrawerContext.Provider>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
</ConfigConsumer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -12,6 +12,9 @@ cover: https://gw.alipayobjects.com/zos/alicdn/TIIiKrsQT/Dropdown.svg
|
|||||||
|
|
||||||
当页面上的操作命令过多时,用此组件可以收纳操作元素。点击或移入触点,会出现一个下拉菜单。可在列表中进行选择,并执行相应的命令。
|
当页面上的操作命令过多时,用此组件可以收纳操作元素。点击或移入触点,会出现一个下拉菜单。可在列表中进行选择,并执行相应的命令。
|
||||||
|
|
||||||
|
- 用于收罗一组命令操作。
|
||||||
|
- Select 用于选择,而 Dropdown 是命令集合。
|
||||||
|
|
||||||
## API
|
## API
|
||||||
|
|
||||||
属性如下
|
属性如下
|
||||||
|
@ -58,7 +58,6 @@
|
|||||||
border-radius: @border-radius-base;
|
border-radius: @border-radius-base;
|
||||||
outline: none;
|
outline: none;
|
||||||
box-shadow: @box-shadow-base;
|
box-shadow: @box-shadow-base;
|
||||||
-webkit-transform: translate3d(0, 0, 0);
|
|
||||||
|
|
||||||
&-item-group-title {
|
&-item-group-title {
|
||||||
padding: 5px @control-padding-horizontal;
|
padding: 5px @control-padding-horizontal;
|
||||||
@ -118,6 +117,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
> .@{iconfont-css-prefix} + span > a {
|
||||||
|
color: @text-color;
|
||||||
|
transition: all 0.3s;
|
||||||
|
&:hover {
|
||||||
|
color: @text-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&:first-child {
|
&:first-child {
|
||||||
& when (@dropdown-edge-child-vertical-padding = 0) {
|
& when (@dropdown-edge-child-vertical-padding = 0) {
|
||||||
border-radius: @border-radius-base @border-radius-base 0 0;
|
border-radius: @border-radius-base @border-radius-base 0 0;
|
||||||
@ -268,7 +275,8 @@
|
|||||||
}
|
}
|
||||||
.@{dropdown-prefix-cls}-menu-item,
|
.@{dropdown-prefix-cls}-menu-item,
|
||||||
.@{dropdown-prefix-cls}-menu-submenu-title,
|
.@{dropdown-prefix-cls}-menu-submenu-title,
|
||||||
.@{dropdown-prefix-cls}-menu-item > a {
|
.@{dropdown-prefix-cls}-menu-item > a,
|
||||||
|
.@{dropdown-prefix-cls}-menu-item > .@{iconfont-css-prefix} + span > a {
|
||||||
color: @text-color-secondary-dark;
|
color: @text-color-secondary-dark;
|
||||||
.@{dropdown-prefix-cls}-menu-submenu-arrow::after {
|
.@{dropdown-prefix-cls}-menu-submenu-arrow::after {
|
||||||
color: @text-color-secondary-dark;
|
color: @text-color-secondary-dark;
|
||||||
|
@ -7,11 +7,11 @@ title:
|
|||||||
|
|
||||||
## zh-CN
|
## zh-CN
|
||||||
|
|
||||||
动态增加、减少表单项。
|
动态增加、减少表单项。`add` 方法参数可用于设置初始值。
|
||||||
|
|
||||||
## en-US
|
## en-US
|
||||||
|
|
||||||
Add or remove form items dynamically.
|
Add or remove form items dynamically. `add` function support config initial value.
|
||||||
|
|
||||||
```jsx
|
```jsx
|
||||||
import { Form, Input, Button } from 'antd';
|
import { Form, Input, Button } from 'antd';
|
||||||
|
20
components/input/style/IE11.less
Normal file
20
components/input/style/IE11.less
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// Fix Input component height issue in IE11
|
||||||
|
@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {
|
||||||
|
.@{ant-prefix}-input {
|
||||||
|
height: @input-height-base;
|
||||||
|
|
||||||
|
&-lg {
|
||||||
|
height: @input-height-lg;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-sm {
|
||||||
|
height: @input-height-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-affix-wrapper {
|
||||||
|
> input.@{ant-prefix}-input {
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -47,3 +47,4 @@
|
|||||||
|
|
||||||
@import './search-input';
|
@import './search-input';
|
||||||
@import './rtl';
|
@import './rtl';
|
||||||
|
@import './IE11';
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
|
/* eslint-disable no-template-curly-in-string */
|
||||||
import Pagination from 'rc-pagination/lib/locale/he_IL';
|
import Pagination from 'rc-pagination/lib/locale/he_IL';
|
||||||
import DatePicker from '../date-picker/locale/he_IL';
|
import DatePicker from '../date-picker/locale/he_IL';
|
||||||
import TimePicker from '../time-picker/locale/he_IL';
|
import TimePicker from '../time-picker/locale/he_IL';
|
||||||
import Calendar from '../calendar/locale/he_IL';
|
import Calendar from '../calendar/locale/he_IL';
|
||||||
import { Locale } from '../locale-provider';
|
import { Locale } from '../locale-provider';
|
||||||
|
|
||||||
|
const typeTemplate = '${label} הוא לא ${type} תקין';
|
||||||
|
|
||||||
const localeValues: Locale = {
|
const localeValues: Locale = {
|
||||||
locale: 'he',
|
locale: 'he',
|
||||||
Pagination,
|
Pagination,
|
||||||
@ -63,6 +66,55 @@ const localeValues: Locale = {
|
|||||||
PageHeader: {
|
PageHeader: {
|
||||||
back: 'חזרה',
|
back: 'חזרה',
|
||||||
},
|
},
|
||||||
|
Form: {
|
||||||
|
defaultValidateMessages: {
|
||||||
|
default: 'ערך השדה שגוי ${label}',
|
||||||
|
required: 'בבקשה הזן ${label}',
|
||||||
|
enum: '${label} חייב להיות אחד מערכים אלו [${enum}]',
|
||||||
|
whitespace: '${label} לא יכול להיות ריק',
|
||||||
|
date: {
|
||||||
|
format: '${label} תאריך לא תקין',
|
||||||
|
parse: '${label} לא ניתן להמיר לתאריך',
|
||||||
|
invalid: '${label} הוא לא תאריך תקין',
|
||||||
|
},
|
||||||
|
types: {
|
||||||
|
string: typeTemplate,
|
||||||
|
method: typeTemplate,
|
||||||
|
array: typeTemplate,
|
||||||
|
object: typeTemplate,
|
||||||
|
number: typeTemplate,
|
||||||
|
date: typeTemplate,
|
||||||
|
boolean: typeTemplate,
|
||||||
|
integer: typeTemplate,
|
||||||
|
float: typeTemplate,
|
||||||
|
regexp: typeTemplate,
|
||||||
|
email: typeTemplate,
|
||||||
|
url: typeTemplate,
|
||||||
|
hex: typeTemplate,
|
||||||
|
},
|
||||||
|
string: {
|
||||||
|
len: '${label} חייב להיות ${len} תווים',
|
||||||
|
min: '${label} חייב להיות ${min} תווים',
|
||||||
|
max: '${label} מקסימום ${max} תווים',
|
||||||
|
range: '${label} חייב להיות בין ${min}-${max} תווים',
|
||||||
|
},
|
||||||
|
number: {
|
||||||
|
len: '${label} חייב להיות שווה ל ${len}',
|
||||||
|
min: '${label} ערך מינימלי הוא ${min}',
|
||||||
|
max: '${label} ערך מקסימלי הוא ${max}',
|
||||||
|
range: '${label} חייב להיות בין ${min}-${max}',
|
||||||
|
},
|
||||||
|
array: {
|
||||||
|
len: 'חייב להיות ${len} ${label}',
|
||||||
|
min: 'מינימום ${min} ${label}',
|
||||||
|
max: 'מקסימום ${max} ${label}',
|
||||||
|
range: 'הסכום של ${label} חייב להיות בין ${min}-${max}',
|
||||||
|
},
|
||||||
|
pattern: {
|
||||||
|
mismatch: '${label} לא תואם לתבנית ${pattern}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default localeValues;
|
export default localeValues;
|
||||||
|
@ -1302,30 +1302,28 @@ exports[`renders ./components/menu/demo/vertical.md correctly 1`] = `
|
|||||||
class="ant-menu-submenu-title"
|
class="ant-menu-submenu-title"
|
||||||
role="button"
|
role="button"
|
||||||
>
|
>
|
||||||
<span>
|
<span
|
||||||
<span
|
aria-label="appstore"
|
||||||
aria-label="appstore"
|
class="anticon anticon-appstore"
|
||||||
class="anticon anticon-appstore"
|
role="img"
|
||||||
role="img"
|
>
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
class=""
|
||||||
|
data-icon="appstore"
|
||||||
|
fill="currentColor"
|
||||||
|
focusable="false"
|
||||||
|
height="1em"
|
||||||
|
viewBox="64 64 896 896"
|
||||||
|
width="1em"
|
||||||
>
|
>
|
||||||
<svg
|
<path
|
||||||
aria-hidden="true"
|
d="M464 144H160c-8.8 0-16 7.2-16 16v304c0 8.8 7.2 16 16 16h304c8.8 0 16-7.2 16-16V160c0-8.8-7.2-16-16-16zm-52 268H212V212h200v200zm452-268H560c-8.8 0-16 7.2-16 16v304c0 8.8 7.2 16 16 16h304c8.8 0 16-7.2 16-16V160c0-8.8-7.2-16-16-16zm-52 268H612V212h200v200zM464 544H160c-8.8 0-16 7.2-16 16v304c0 8.8 7.2 16 16 16h304c8.8 0 16-7.2 16-16V560c0-8.8-7.2-16-16-16zm-52 268H212V612h200v200zm452-268H560c-8.8 0-16 7.2-16 16v304c0 8.8 7.2 16 16 16h304c8.8 0 16-7.2 16-16V560c0-8.8-7.2-16-16-16zm-52 268H612V612h200v200z"
|
||||||
class=""
|
/>
|
||||||
data-icon="appstore"
|
</svg>
|
||||||
fill="currentColor"
|
</span>
|
||||||
focusable="false"
|
<span>
|
||||||
height="1em"
|
Navigation Two
|
||||||
viewBox="64 64 896 896"
|
|
||||||
width="1em"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M464 144H160c-8.8 0-16 7.2-16 16v304c0 8.8 7.2 16 16 16h304c8.8 0 16-7.2 16-16V160c0-8.8-7.2-16-16-16zm-52 268H212V212h200v200zm452-268H560c-8.8 0-16 7.2-16 16v304c0 8.8 7.2 16 16 16h304c8.8 0 16-7.2 16-16V160c0-8.8-7.2-16-16-16zm-52 268H612V212h200v200zM464 544H160c-8.8 0-16 7.2-16 16v304c0 8.8 7.2 16 16 16h304c8.8 0 16-7.2 16-16V560c0-8.8-7.2-16-16-16zm-52 268H212V612h200v200zm452-268H560c-8.8 0-16 7.2-16 16v304c0 8.8 7.2 16 16 16h304c8.8 0 16-7.2 16-16V560c0-8.8-7.2-16-16-16zm-52 268H612V612h200v200z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</span>
|
|
||||||
<span>
|
|
||||||
Navigation Two
|
|
||||||
</span>
|
|
||||||
</span>
|
</span>
|
||||||
<i
|
<i
|
||||||
class="ant-menu-submenu-arrow"
|
class="ant-menu-submenu-arrow"
|
||||||
|
@ -35,15 +35,7 @@ ReactDOM.render(
|
|||||||
<Menu.Item key="4">Option 4</Menu.Item>
|
<Menu.Item key="4">Option 4</Menu.Item>
|
||||||
</Menu.ItemGroup>
|
</Menu.ItemGroup>
|
||||||
</SubMenu>
|
</SubMenu>
|
||||||
<SubMenu
|
<SubMenu key="sub2" icon={<AppstoreOutlined />} title="Navigation Two">
|
||||||
key="sub2"
|
|
||||||
title={
|
|
||||||
<span>
|
|
||||||
<AppstoreOutlined />
|
|
||||||
<span>Navigation Two</span>
|
|
||||||
</span>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Menu.Item key="5">Option 5</Menu.Item>
|
<Menu.Item key="5">Option 5</Menu.Item>
|
||||||
<Menu.Item key="6">Option 6</Menu.Item>
|
<Menu.Item key="6">Option 6</Menu.Item>
|
||||||
<SubMenu key="sub3" title="Submenu">
|
<SubMenu key="sub3" title="Submenu">
|
||||||
|
@ -27,6 +27,7 @@ const ConfirmDialog = (props: ConfirmDialogProps) => {
|
|||||||
okButtonProps,
|
okButtonProps,
|
||||||
cancelText,
|
cancelText,
|
||||||
cancelButtonProps,
|
cancelButtonProps,
|
||||||
|
direction,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
devWarning(
|
devWarning(
|
||||||
@ -53,6 +54,7 @@ const ConfirmDialog = (props: ConfirmDialogProps) => {
|
|||||||
const classString = classNames(
|
const classString = classNames(
|
||||||
contentPrefixCls,
|
contentPrefixCls,
|
||||||
`${contentPrefixCls}-${props.type}`,
|
`${contentPrefixCls}-${props.type}`,
|
||||||
|
{ [`${contentPrefixCls}-rtl`]: direction === 'rtl' },
|
||||||
props.className,
|
props.className,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -111,6 +111,7 @@ export interface ModalFuncProps {
|
|||||||
autoFocusButton?: null | 'ok' | 'cancel';
|
autoFocusButton?: null | 'ok' | 'cancel';
|
||||||
transitionName?: string;
|
transitionName?: string;
|
||||||
maskTransitionName?: string;
|
maskTransitionName?: string;
|
||||||
|
direction?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ModalLocale {
|
export interface ModalLocale {
|
||||||
|
@ -44,7 +44,9 @@ When requiring users to interact with the application, but without jumping to a
|
|||||||
|
|
||||||
#### Note
|
#### Note
|
||||||
|
|
||||||
> The state of Modal will be preserved at it's component lifecycle by default, if you wish to open it with a brand new state everytime, set `destroyOnClose` on it.
|
> - The state of Modal will be preserved at it's component lifecycle by default, if you wish to open it with a brand new state everytime, set `destroyOnClose` on it.
|
||||||
|
>
|
||||||
|
> - `Modal.method()` RTL mode only supports hooks.
|
||||||
|
|
||||||
### Modal.method()
|
### Modal.method()
|
||||||
|
|
||||||
|
@ -48,7 +48,9 @@ cover: https://gw.alipayobjects.com/zos/alicdn/3StSdUlSH/Modal.svg
|
|||||||
|
|
||||||
#### 注意
|
#### 注意
|
||||||
|
|
||||||
> `<Modal />` 默认关闭后状态不会自动清空, 如果希望每次打开都是新内容,请设置 `destroyOnClose`。
|
> - `<Modal />` 默认关闭后状态不会自动清空, 如果希望每次打开都是新内容,请设置 `destroyOnClose`。
|
||||||
|
>
|
||||||
|
> - `Modal.method()` RTL 模式仅支持 hooks 用法。
|
||||||
|
|
||||||
### Modal.method()
|
### Modal.method()
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
@import '../../style/mixins/index';
|
@import '../../style/mixins/index';
|
||||||
|
|
||||||
@dialog-prefix-cls: ~'@{ant-prefix}-modal';
|
@dialog-prefix-cls: ~'@{ant-prefix}-modal';
|
||||||
|
@confirm-prefix-cls: ~'@{ant-prefix}-modal-confirm';
|
||||||
@dialog-wrap-rtl-cls: ~'@{dialog-prefix-cls}-wrap-rtl';
|
@dialog-wrap-rtl-cls: ~'@{dialog-prefix-cls}-wrap-rtl';
|
||||||
|
|
||||||
.@{dialog-prefix-cls} {
|
.@{dialog-prefix-cls} {
|
||||||
@ -29,6 +30,38 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&-confirm {
|
||||||
|
&-body {
|
||||||
|
.@{dialog-wrap-rtl-cls} & {
|
||||||
|
direction: rtl;
|
||||||
|
}
|
||||||
|
> .@{iconfont-css-prefix} {
|
||||||
|
.@{dialog-wrap-rtl-cls} & {
|
||||||
|
float: right;
|
||||||
|
margin-right: 0;
|
||||||
|
margin-left: 16px;
|
||||||
|
}
|
||||||
|
+ .@{confirm-prefix-cls}-title + .@{confirm-prefix-cls}-content {
|
||||||
|
.@{dialog-wrap-rtl-cls} & {
|
||||||
|
margin-right: 38px;
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&-btns {
|
||||||
|
.@{dialog-wrap-rtl-cls} & {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
button + button {
|
||||||
|
.@{dialog-wrap-rtl-cls} & {
|
||||||
|
margin-right: 8px;
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.@{dialog-prefix-cls}-centered {
|
.@{dialog-prefix-cls}-centered {
|
||||||
|
@ -3,6 +3,7 @@ import { ModalFuncProps } from '../Modal';
|
|||||||
import ConfirmDialog from '../ConfirmDialog';
|
import ConfirmDialog from '../ConfirmDialog';
|
||||||
import defaultLocale from '../../locale/default';
|
import defaultLocale from '../../locale/default';
|
||||||
import LocaleReceiver from '../../locale-provider/LocaleReceiver';
|
import LocaleReceiver from '../../locale-provider/LocaleReceiver';
|
||||||
|
import { ConfigContext } from '../../config-provider';
|
||||||
|
|
||||||
export interface HookModalProps {
|
export interface HookModalProps {
|
||||||
afterClose: () => void;
|
afterClose: () => void;
|
||||||
@ -26,6 +27,7 @@ const HookModal: React.RefForwardingComponent<HookModalRef, HookModalProps> = (
|
|||||||
) => {
|
) => {
|
||||||
const [visible, setVisible] = React.useState(true);
|
const [visible, setVisible] = React.useState(true);
|
||||||
const [innerConfig, setInnerConfig] = React.useState(config);
|
const [innerConfig, setInnerConfig] = React.useState(config);
|
||||||
|
const { direction } = React.useContext(ConfigContext);
|
||||||
|
|
||||||
function close() {
|
function close() {
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
@ -53,6 +55,7 @@ const HookModal: React.RefForwardingComponent<HookModalRef, HookModalProps> = (
|
|||||||
innerConfig.okText ||
|
innerConfig.okText ||
|
||||||
(innerConfig.okCancel ? modalLocale.okText : modalLocale.justOkText)
|
(innerConfig.okCancel ? modalLocale.okText : modalLocale.justOkText)
|
||||||
}
|
}
|
||||||
|
direction={direction}
|
||||||
cancelText={innerConfig.cancelText || modalLocale.cancelText}
|
cancelText={innerConfig.cancelText || modalLocale.cancelText}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
@ -4,4 +4,4 @@ title: Components Overview
|
|||||||
type: Overview
|
type: Overview
|
||||||
---
|
---
|
||||||
|
|
||||||
`antd` provides plenty of UI components to enrich your web applications, and we will improve components expirerence consistently.
|
`antd` provides plenty of UI components to enrich your web applications, and we will improve components expirerence consistently. We also recommand some great [Third-Party Libraries](/docs/react/recommendation) additionlly.
|
||||||
|
@ -4,4 +4,4 @@ title: 组件总览
|
|||||||
type: 组件总览
|
type: 组件总览
|
||||||
---
|
---
|
||||||
|
|
||||||
`antd` 为 Web 应用提供了丰富的基础 UI 组件,我们还将持续探索企业级应用的最佳 UI 实践。
|
`antd` 为 Web 应用提供了丰富的基础 UI 组件,我们还将持续探索企业级应用的最佳 UI 实践。除了官方组件,我们也提供了[社区精选组件](/docs/react/recommendation)作为必要的补充。
|
||||||
|
@ -1,9 +1,16 @@
|
|||||||
import Radio from './radio';
|
import InternalRadio from './radio';
|
||||||
import Group from './group';
|
import Group from './group';
|
||||||
import Button from './radioButton';
|
import Button from './radioButton';
|
||||||
|
import { RadioProps } from './interface';
|
||||||
|
|
||||||
export * from './interface';
|
export * from './interface';
|
||||||
|
interface CompoundedComponent
|
||||||
|
extends React.ForwardRefExoticComponent<RadioProps & React.RefAttributes<HTMLElement>> {
|
||||||
|
Group: typeof Group;
|
||||||
|
Button: typeof Button;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Radio = InternalRadio as CompoundedComponent;
|
||||||
Radio.Button = Button;
|
Radio.Button = Button;
|
||||||
Radio.Group = Group;
|
Radio.Group = Group;
|
||||||
export { Button, Group };
|
export { Button, Group };
|
||||||
|
@ -1,19 +1,11 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import RcCheckbox from 'rc-checkbox';
|
import RcCheckbox from 'rc-checkbox';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import RadioGroup from './group';
|
|
||||||
import RadioButton from './radioButton';
|
|
||||||
import { RadioProps, RadioChangeEvent } from './interface';
|
import { RadioProps, RadioChangeEvent } from './interface';
|
||||||
import { ConfigContext } from '../config-provider';
|
import { ConfigContext } from '../config-provider';
|
||||||
import RadioGroupContext from './context';
|
import RadioGroupContext from './context';
|
||||||
import { composeRef } from '../_util/ref';
|
import { composeRef } from '../_util/ref';
|
||||||
|
|
||||||
interface CompoundedComponent
|
|
||||||
extends React.ForwardRefExoticComponent<RadioProps & React.RefAttributes<HTMLElement>> {
|
|
||||||
Group: typeof RadioGroup;
|
|
||||||
Button: typeof RadioButton;
|
|
||||||
}
|
|
||||||
|
|
||||||
const InternalRadio: React.ForwardRefRenderFunction<unknown, RadioProps> = (props, ref) => {
|
const InternalRadio: React.ForwardRefRenderFunction<unknown, RadioProps> = (props, ref) => {
|
||||||
const context = React.useContext(RadioGroupContext);
|
const context = React.useContext(RadioGroupContext);
|
||||||
const { getPrefixCls, direction } = React.useContext(ConfigContext);
|
const { getPrefixCls, direction } = React.useContext(ConfigContext);
|
||||||
@ -60,10 +52,9 @@ const InternalRadio: React.ForwardRefRenderFunction<unknown, RadioProps> = (prop
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const Radio = React.forwardRef<unknown, RadioProps>(InternalRadio) as CompoundedComponent;
|
const Radio = React.forwardRef<unknown, RadioProps>(InternalRadio);
|
||||||
Radio.displayName = 'Radio';
|
Radio.displayName = 'Radio';
|
||||||
Radio.Group = RadioGroup;
|
|
||||||
Radio.Button = RadioButton;
|
|
||||||
Radio.defaultProps = {
|
Radio.defaultProps = {
|
||||||
type: 'radio',
|
type: 'radio',
|
||||||
};
|
};
|
||||||
|
@ -90,7 +90,7 @@ class Select<ValueType extends SelectValue = SelectValue> extends React.Componen
|
|||||||
className,
|
className,
|
||||||
size: customizeSize,
|
size: customizeSize,
|
||||||
listHeight = 256,
|
listHeight = 256,
|
||||||
listItemHeight = 32,
|
listItemHeight = 24,
|
||||||
getPopupContainer,
|
getPopupContainer,
|
||||||
dropdownClassName,
|
dropdownClassName,
|
||||||
bordered,
|
bordered,
|
||||||
|
@ -574,6 +574,9 @@
|
|||||||
@table-footer-bg: @background-color-light;
|
@table-footer-bg: @background-color-light;
|
||||||
@table-footer-color: @heading-color;
|
@table-footer-color: @heading-color;
|
||||||
@table-header-bg-sm: @table-header-bg;
|
@table-header-bg-sm: @table-header-bg;
|
||||||
|
@table-font-size: @font-size-base;
|
||||||
|
@table-font-size-md: @table-font-size;
|
||||||
|
@table-font-size-sm: @table-font-size;
|
||||||
// Sorter
|
// Sorter
|
||||||
// Legacy: `table-header-sort-active-bg` is used for hover not real active
|
// Legacy: `table-header-sort-active-bg` is used for hover not real active
|
||||||
@table-header-sort-active-bg: darken(@table-header-bg, 3%);
|
@table-header-sort-active-bg: darken(@table-header-bg, 3%);
|
||||||
|
@ -62,7 +62,7 @@ const columns = [
|
|||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
| tableLayout | [table-layout](https://developer.mozilla.org/en-US/docs/Web/CSS/table-layout) attribute of table element | - \| `auto` \| `fixed` | -<hr />`fixed` when header/columns are fixed, or using `column.ellipsis` |
|
| tableLayout | [table-layout](https://developer.mozilla.org/en-US/docs/Web/CSS/table-layout) attribute of table element | - \| `auto` \| `fixed` | -<hr />`fixed` when header/columns are fixed, or using `column.ellipsis` |
|
||||||
| bordered | Whether to show all table borders | boolean | `false` |
|
| bordered | Whether to show all table borders | boolean | `false` |
|
||||||
| columns | Columns of table | [ColumnProps](#Column)\[] | - |
|
| columns | Columns of table | [ColumnsType](#Column)\[] | - |
|
||||||
| components | Override default table elements | [TableComponents](https://git.io/fANxz) | - |
|
| components | Override default table elements | [TableComponents](https://git.io/fANxz) | - |
|
||||||
| dataSource | Data record array to be displayed | object\[] | - |
|
| dataSource | Data record array to be displayed | object\[] | - |
|
||||||
| expandable | Config expandable content | [expandable](#expandable) | - |
|
| expandable | Config expandable content | [expandable](#expandable) | - |
|
||||||
@ -220,14 +220,14 @@ Properties for row selection.
|
|||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
import { Table } from 'antd';
|
import { Table } from 'antd';
|
||||||
import { ColumnProps } from 'antd/es/table';
|
import { ColumnsType } from 'antd/es/table';
|
||||||
|
|
||||||
interface User {
|
interface User {
|
||||||
key: number,
|
key: number,
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const columns: ColumnProps<User>[] = [{
|
const columns: ColumnsType<User>[] = [{
|
||||||
key: 'name',
|
key: 'name',
|
||||||
title: 'Name',
|
title: 'Name',
|
||||||
dataIndex: 'name',
|
dataIndex: 'name',
|
||||||
|
@ -67,7 +67,7 @@ const columns = [
|
|||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
| tableLayout | 表格元素的 [table-layout](https://developer.mozilla.org/zh-CN/docs/Web/CSS/table-layout) 属性,设为 `fixed` 表示内容不会影响列的布局 | - \| `auto` \| `fixed` | 无<hr />固定表头/列或使用了 `column.ellipsis` 时,默认值为 `fixed` |
|
| tableLayout | 表格元素的 [table-layout](https://developer.mozilla.org/zh-CN/docs/Web/CSS/table-layout) 属性,设为 `fixed` 表示内容不会影响列的布局 | - \| `auto` \| `fixed` | 无<hr />固定表头/列或使用了 `column.ellipsis` 时,默认值为 `fixed` |
|
||||||
| bordered | 是否展示外边框和列边框 | boolean | false |
|
| bordered | 是否展示外边框和列边框 | boolean | false |
|
||||||
| columns | 表格列的配置描述,具体项见下表 | [ColumnProps](#Column)\[] | - |
|
| columns | 表格列的配置描述,具体项见下表 | [ColumnsType](#Column)\[] | - |
|
||||||
| components | 覆盖默认的 table 元素 | [TableComponents](https://git.io/fANxz) | - |
|
| components | 覆盖默认的 table 元素 | [TableComponents](https://git.io/fANxz) | - |
|
||||||
| dataSource | 数据数组 | object\[] | - |
|
| dataSource | 数据数组 | object\[] | - |
|
||||||
| expandable | 配置展开属性 | [expandable](#expandable) | - |
|
| expandable | 配置展开属性 | [expandable](#expandable) | - |
|
||||||
@ -225,14 +225,14 @@ const columns = [
|
|||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
import { Table } from 'antd';
|
import { Table } from 'antd';
|
||||||
import { ColumnProps } from 'antd/es/table';
|
import { ColumnsType } from 'antd/es/table';
|
||||||
|
|
||||||
interface User {
|
interface User {
|
||||||
key: number;
|
key: number;
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const columns: ColumnProps<User>[] = [{
|
const columns: ColumnsType<User>[] = [{
|
||||||
key: 'name',
|
key: 'name',
|
||||||
title: 'Name',
|
title: 'Name',
|
||||||
dataIndex: 'name',
|
dataIndex: 'name',
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
@table-header-sort-active-filter-bg: lighten(@table-header-sort-active-bg, 2%);
|
@table-header-sort-active-filter-bg: lighten(@table-header-sort-active-bg, 2%);
|
||||||
|
|
||||||
.@{table-prefix-cls}-wrapper {
|
.@{table-prefix-cls}-wrapper {
|
||||||
|
max-width: 100%;
|
||||||
.clearfix;
|
.clearfix;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -18,6 +19,7 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
clear: both;
|
clear: both;
|
||||||
|
font-size: @table-font-size;
|
||||||
background: @table-bg;
|
background: @table-bg;
|
||||||
border-radius: @border-radius-base;
|
border-radius: @border-radius-base;
|
||||||
|
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
@import './index';
|
@import './index';
|
||||||
|
|
||||||
.table-size(@size, @padding-vertical, @padding-horizontal) {
|
.table-size(@size, @padding-vertical, @padding-horizontal, @font-size) {
|
||||||
.@{table-prefix-cls}.@{table-prefix-cls}-@{size} {
|
.@{table-prefix-cls}.@{table-prefix-cls}-@{size} {
|
||||||
|
font-size: @font-size;
|
||||||
|
|
||||||
.@{table-prefix-cls}-title,
|
.@{table-prefix-cls}-title,
|
||||||
.@{table-prefix-cls}-footer,
|
.@{table-prefix-cls}-footer,
|
||||||
.@{table-prefix-cls}-thead > tr > th,
|
.@{table-prefix-cls}-thead > tr > th,
|
||||||
@ -48,12 +50,12 @@
|
|||||||
// ================================================================
|
// ================================================================
|
||||||
// = Middle =
|
// = Middle =
|
||||||
// ================================================================
|
// ================================================================
|
||||||
.table-size(~'middle', @table-padding-vertical-md, @table-padding-horizontal-md);
|
.table-size(~'middle', @table-padding-vertical-md, @table-padding-horizontal-md, @table-font-size-md);
|
||||||
|
|
||||||
// ================================================================
|
// ================================================================
|
||||||
// = Small =
|
// = Small =
|
||||||
// ================================================================
|
// ================================================================
|
||||||
.table-size(~'small', @table-padding-vertical-sm, @table-padding-horizontal-sm);
|
.table-size(~'small', @table-padding-vertical-sm, @table-padding-horizontal-sm, @table-font-size-sm);
|
||||||
|
|
||||||
.@{table-prefix-cls}-small {
|
.@{table-prefix-cls}-small {
|
||||||
.@{table-prefix-cls}-thead > tr > th {
|
.@{table-prefix-cls}-thead > tr > th {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import RcTabs, { TabPane, TabsProps as RcTabsProps } from 'rc-tabs';
|
import RcTabs, { TabPane, TabsProps as RcTabsProps, TabPaneProps } from 'rc-tabs';
|
||||||
import { TabPaneProps } from 'rc-tabs/lib/sugar/TabPane';
|
|
||||||
import { EditableConfig } from 'rc-tabs/lib/interface';
|
import { EditableConfig } from 'rc-tabs/lib/interface';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import EllipsisOutlined from '@ant-design/icons/EllipsisOutlined';
|
import EllipsisOutlined from '@ant-design/icons/EllipsisOutlined';
|
||||||
|
@ -3,7 +3,8 @@
|
|||||||
@import './index';
|
@import './index';
|
||||||
|
|
||||||
.@{tab-prefix-cls}-card {
|
.@{tab-prefix-cls}-card {
|
||||||
> .@{tab-prefix-cls}-nav {
|
> .@{tab-prefix-cls}-nav,
|
||||||
|
> div > .@{tab-prefix-cls}-nav {
|
||||||
.@{tab-prefix-cls}-tab {
|
.@{tab-prefix-cls}-tab {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: @tabs-card-horizontal-padding;
|
padding: @tabs-card-horizontal-padding;
|
||||||
@ -25,7 +26,8 @@
|
|||||||
// ========================== Top & Bottom ==========================
|
// ========================== Top & Bottom ==========================
|
||||||
&.@{tab-prefix-cls}-top,
|
&.@{tab-prefix-cls}-top,
|
||||||
&.@{tab-prefix-cls}-bottom {
|
&.@{tab-prefix-cls}-bottom {
|
||||||
> .@{tab-prefix-cls}-nav {
|
> .@{tab-prefix-cls}-nav,
|
||||||
|
> div > .@{tab-prefix-cls}-nav {
|
||||||
.@{tab-prefix-cls}-tab:not(:last-of-type) {
|
.@{tab-prefix-cls}-tab:not(:last-of-type) {
|
||||||
margin-right: @tabs-card-gutter;
|
margin-right: @tabs-card-gutter;
|
||||||
}
|
}
|
||||||
@ -33,7 +35,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.@{tab-prefix-cls}-top {
|
&.@{tab-prefix-cls}-top {
|
||||||
> .@{tab-prefix-cls}-nav {
|
> .@{tab-prefix-cls}-nav,
|
||||||
|
> div > .@{tab-prefix-cls}-nav {
|
||||||
.@{tab-prefix-cls}-tab {
|
.@{tab-prefix-cls}-tab {
|
||||||
border-radius: @border-radius-base @border-radius-base 0 0;
|
border-radius: @border-radius-base @border-radius-base 0 0;
|
||||||
|
|
||||||
@ -44,7 +47,8 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
&.@{tab-prefix-cls}-bottom {
|
&.@{tab-prefix-cls}-bottom {
|
||||||
> .@{tab-prefix-cls}-nav {
|
> .@{tab-prefix-cls}-nav,
|
||||||
|
> div > .@{tab-prefix-cls}-nav {
|
||||||
.@{tab-prefix-cls}-tab {
|
.@{tab-prefix-cls}-tab {
|
||||||
border-radius: 0 0 @border-radius-base @border-radius-base;
|
border-radius: 0 0 @border-radius-base @border-radius-base;
|
||||||
|
|
||||||
@ -58,7 +62,8 @@
|
|||||||
// ========================== Left & Right ==========================
|
// ========================== Left & Right ==========================
|
||||||
&.@{tab-prefix-cls}-left,
|
&.@{tab-prefix-cls}-left,
|
||||||
&.@{tab-prefix-cls}-right {
|
&.@{tab-prefix-cls}-right {
|
||||||
> .@{tab-prefix-cls}-nav {
|
> .@{tab-prefix-cls}-nav,
|
||||||
|
> div > .@{tab-prefix-cls}-nav {
|
||||||
.@{tab-prefix-cls}-tab:not(:last-of-type) {
|
.@{tab-prefix-cls}-tab:not(:last-of-type) {
|
||||||
margin-bottom: @tabs-card-gutter;
|
margin-bottom: @tabs-card-gutter;
|
||||||
}
|
}
|
||||||
@ -66,7 +71,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.@{tab-prefix-cls}-left {
|
&.@{tab-prefix-cls}-left {
|
||||||
> .@{tab-prefix-cls}-nav {
|
> .@{tab-prefix-cls}-nav,
|
||||||
|
> div > .@{tab-prefix-cls}-nav {
|
||||||
.@{tab-prefix-cls}-tab {
|
.@{tab-prefix-cls}-tab {
|
||||||
border-radius: @border-radius-base 0 0 @border-radius-base;
|
border-radius: @border-radius-base 0 0 @border-radius-base;
|
||||||
|
|
||||||
@ -77,7 +83,8 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
&.@{tab-prefix-cls}-right {
|
&.@{tab-prefix-cls}-right {
|
||||||
> .@{tab-prefix-cls}-nav {
|
> .@{tab-prefix-cls}-nav,
|
||||||
|
> div > .@{tab-prefix-cls}-nav {
|
||||||
.@{tab-prefix-cls}-tab {
|
.@{tab-prefix-cls}-tab {
|
||||||
border-radius: 0 @border-radius-base @border-radius-base 0;
|
border-radius: 0 @border-radius-base @border-radius-base 0;
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
max-height: 200px;
|
max-height: 200px;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: @dropdown-edge-child-vertical-padding 0;
|
padding: @dropdown-edge-child-vertical-padding 0;
|
||||||
|
overflow-x: hidden;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
|
@ -15,7 +15,8 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
// ========================== Navigation ==========================
|
// ========================== Navigation ==========================
|
||||||
> .@{tab-prefix-cls}-nav {
|
> .@{tab-prefix-cls}-nav,
|
||||||
|
> div > .@{tab-prefix-cls}-nav {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex: none;
|
flex: none;
|
||||||
|
@ -6,7 +6,8 @@
|
|||||||
&-bottom {
|
&-bottom {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
> .@{tab-prefix-cls}-nav {
|
> .@{tab-prefix-cls}-nav,
|
||||||
|
> div > .@{tab-prefix-cls}-nav {
|
||||||
margin: @tabs-bar-margin;
|
margin: @tabs-bar-margin;
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
@ -54,7 +55,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&-top {
|
&-top {
|
||||||
> .@{tab-prefix-cls}-nav {
|
> .@{tab-prefix-cls}-nav,
|
||||||
|
> div > .@{tab-prefix-cls}-nav {
|
||||||
&::before {
|
&::before {
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
}
|
}
|
||||||
@ -66,7 +68,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&-bottom {
|
&-bottom {
|
||||||
> .@{tab-prefix-cls}-nav {
|
> .@{tab-prefix-cls}-nav,
|
||||||
|
> div > .@{tab-prefix-cls}-nav {
|
||||||
order: 1;
|
order: 1;
|
||||||
margin-top: @margin-md;
|
margin-top: @margin-md;
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
@ -80,7 +83,8 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
> .@{tab-prefix-cls}-content-holder {
|
> .@{tab-prefix-cls}-content-holder,
|
||||||
|
> div > .@{tab-prefix-cls}-content-holder {
|
||||||
order: 0;
|
order: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -88,7 +92,8 @@
|
|||||||
// ========================== Left & Right ==========================
|
// ========================== Left & Right ==========================
|
||||||
&-left,
|
&-left,
|
||||||
&-right {
|
&-right {
|
||||||
> .@{tab-prefix-cls}-nav {
|
> .@{tab-prefix-cls}-nav,
|
||||||
|
> div > .@{tab-prefix-cls}-nav {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
min-width: 50px;
|
min-width: 50px;
|
||||||
|
|
||||||
@ -148,13 +153,15 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&-left {
|
&-left {
|
||||||
> .@{tab-prefix-cls}-nav {
|
> .@{tab-prefix-cls}-nav,
|
||||||
|
> div > .@{tab-prefix-cls}-nav {
|
||||||
.@{tab-prefix-cls}-ink-bar {
|
.@{tab-prefix-cls}-ink-bar {
|
||||||
right: 0;
|
right: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
> .@{tab-prefix-cls}-content-holder {
|
> .@{tab-prefix-cls}-content-holder,
|
||||||
|
> div > .@{tab-prefix-cls}-content-holder {
|
||||||
margin-left: -@border-width-base;
|
margin-left: -@border-width-base;
|
||||||
border-left: @border-width-base @border-style-base @border-color-split;
|
border-left: @border-width-base @border-style-base @border-color-split;
|
||||||
|
|
||||||
@ -165,7 +172,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&-right {
|
&-right {
|
||||||
> .@{tab-prefix-cls}-nav {
|
> .@{tab-prefix-cls}-nav,
|
||||||
|
> div > .@{tab-prefix-cls}-nav {
|
||||||
order: 1;
|
order: 1;
|
||||||
|
|
||||||
.@{tab-prefix-cls}-ink-bar {
|
.@{tab-prefix-cls}-ink-bar {
|
||||||
@ -173,7 +181,8 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
> .@{tab-prefix-cls}-content-holder {
|
> .@{tab-prefix-cls}-content-holder,
|
||||||
|
> div > .@{tab-prefix-cls}-content-holder {
|
||||||
order: 0;
|
order: 0;
|
||||||
margin-right: -@border-width-base;
|
margin-right: -@border-width-base;
|
||||||
border-right: @border-width-base @border-style-base @border-color-split;
|
border-right: @border-width-base @border-style-base @border-color-split;
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
@import '../../style/themes/index';
|
@import '../../style/themes/index';
|
||||||
@import '../../style/mixins/index';
|
@import '../../style/mixins/index';
|
||||||
@import './index';
|
|
||||||
|
@tab-prefix-cls: ~'@{ant-prefix}-tabs';
|
||||||
|
|
||||||
.@{tab-prefix-cls}-rtl {
|
.@{tab-prefix-cls}-rtl {
|
||||||
direction: rtl;
|
direction: rtl;
|
||||||
|
|
||||||
> .@{tab-prefix-cls}-nav {
|
.@{tab-prefix-cls}-nav {
|
||||||
.@{tab-prefix-cls}-tab {
|
.@{tab-prefix-cls}-tab {
|
||||||
margin: @tabs-horizontal-margin-rtl;
|
margin: @tabs-horizontal-margin-rtl;
|
||||||
|
|
||||||
@ -59,3 +60,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.@{tab-prefix-cls}-dropdown {
|
||||||
|
&-rtl {
|
||||||
|
direction: rtl;
|
||||||
|
}
|
||||||
|
&-menu-item {
|
||||||
|
.@{tab-prefix-cls}-dropdown-rtl & {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -8,15 +8,19 @@ export interface CheckableTagProps {
|
|||||||
style?: React.CSSProperties;
|
style?: React.CSSProperties;
|
||||||
checked: boolean;
|
checked: boolean;
|
||||||
onChange?: (checked: boolean) => void;
|
onChange?: (checked: boolean) => void;
|
||||||
|
onClick?: (e: React.MouseEventHandler<HTMLElement>) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CheckableTag: React.FC<CheckableTagProps> = props => {
|
const CheckableTag: React.FC<CheckableTagProps> = props => {
|
||||||
const { getPrefixCls } = React.useContext(ConfigContext);
|
const { getPrefixCls } = React.useContext(ConfigContext);
|
||||||
const handleClick = () => {
|
const handleClick = (e: React.MouseEventHandler) => {
|
||||||
const { checked, onChange } = props;
|
const { checked, onChange, onClick } = props;
|
||||||
if (onChange) {
|
if (onChange) {
|
||||||
onChange(!checked);
|
onChange(!checked);
|
||||||
}
|
}
|
||||||
|
if (onClick) {
|
||||||
|
onClick(e);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const { prefixCls: customizePrefixCls, className, checked, ...restProps } = props;
|
const { prefixCls: customizePrefixCls, className, checked, ...restProps } = props;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
exports[`renders ./components/tag/demo/animation.md correctly 1`] = `
|
exports[`renders ./components/tag/demo/animation.md correctly 1`] = `
|
||||||
<div>
|
Array [
|
||||||
<div
|
<div
|
||||||
style="margin-bottom:16px"
|
style="margin-bottom:16px"
|
||||||
>
|
>
|
||||||
@ -97,7 +97,7 @@ exports[`renders ./components/tag/demo/animation.md correctly 1`] = `
|
|||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>,
|
||||||
<span
|
<span
|
||||||
class="ant-tag site-tag-plus"
|
class="ant-tag site-tag-plus"
|
||||||
>
|
>
|
||||||
@ -126,17 +126,17 @@ exports[`renders ./components/tag/demo/animation.md correctly 1`] = `
|
|||||||
</svg>
|
</svg>
|
||||||
</span>
|
</span>
|
||||||
New Tag
|
New Tag
|
||||||
</span>
|
</span>,
|
||||||
</div>
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`renders ./components/tag/demo/basic.md correctly 1`] = `
|
exports[`renders ./components/tag/demo/basic.md correctly 1`] = `
|
||||||
<div>
|
Array [
|
||||||
<span
|
<span
|
||||||
class="ant-tag"
|
class="ant-tag"
|
||||||
>
|
>
|
||||||
Tag 1
|
Tag 1
|
||||||
</span>
|
</span>,
|
||||||
<span
|
<span
|
||||||
class="ant-tag"
|
class="ant-tag"
|
||||||
>
|
>
|
||||||
@ -145,7 +145,7 @@ exports[`renders ./components/tag/demo/basic.md correctly 1`] = `
|
|||||||
>
|
>
|
||||||
Link
|
Link
|
||||||
</a>
|
</a>
|
||||||
</span>
|
</span>,
|
||||||
<span
|
<span
|
||||||
class="ant-tag"
|
class="ant-tag"
|
||||||
>
|
>
|
||||||
@ -171,7 +171,7 @@ exports[`renders ./components/tag/demo/basic.md correctly 1`] = `
|
|||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>,
|
||||||
<span
|
<span
|
||||||
class="ant-tag"
|
class="ant-tag"
|
||||||
>
|
>
|
||||||
@ -197,8 +197,8 @@ exports[`renders ./components/tag/demo/basic.md correctly 1`] = `
|
|||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>,
|
||||||
</div>
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`renders ./components/tag/demo/checkable.md correctly 1`] = `
|
exports[`renders ./components/tag/demo/checkable.md correctly 1`] = `
|
||||||
@ -340,14 +340,14 @@ Array [
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`renders ./components/tag/demo/control.md correctly 1`] = `
|
exports[`renders ./components/tag/demo/control.md correctly 1`] = `
|
||||||
<div>
|
Array [
|
||||||
<span
|
<span
|
||||||
class="ant-tag edit-tag"
|
class="ant-tag edit-tag"
|
||||||
>
|
>
|
||||||
<span>
|
<span>
|
||||||
Unremovable
|
Unremovable
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>,
|
||||||
<span
|
<span
|
||||||
class="ant-tag edit-tag"
|
class="ant-tag edit-tag"
|
||||||
>
|
>
|
||||||
@ -375,7 +375,7 @@ exports[`renders ./components/tag/demo/control.md correctly 1`] = `
|
|||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>,
|
||||||
<span
|
<span
|
||||||
class="ant-tag edit-tag"
|
class="ant-tag edit-tag"
|
||||||
>
|
>
|
||||||
@ -403,7 +403,7 @@ exports[`renders ./components/tag/demo/control.md correctly 1`] = `
|
|||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>,
|
||||||
<span
|
<span
|
||||||
class="ant-tag site-tag-plus"
|
class="ant-tag site-tag-plus"
|
||||||
>
|
>
|
||||||
@ -432,12 +432,12 @@ exports[`renders ./components/tag/demo/control.md correctly 1`] = `
|
|||||||
</svg>
|
</svg>
|
||||||
</span>
|
</span>
|
||||||
New Tag
|
New Tag
|
||||||
</span>
|
</span>,
|
||||||
</div>
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`renders ./components/tag/demo/controlled.md correctly 1`] = `
|
exports[`renders ./components/tag/demo/controlled.md correctly 1`] = `
|
||||||
<div>
|
Array [
|
||||||
<span
|
<span
|
||||||
class="ant-tag"
|
class="ant-tag"
|
||||||
>
|
>
|
||||||
@ -463,8 +463,8 @@ exports[`renders ./components/tag/demo/controlled.md correctly 1`] = `
|
|||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>,
|
||||||
<br />
|
<br />,
|
||||||
<button
|
<button
|
||||||
class="ant-btn ant-btn-sm"
|
class="ant-btn ant-btn-sm"
|
||||||
type="button"
|
type="button"
|
||||||
@ -472,12 +472,12 @@ exports[`renders ./components/tag/demo/controlled.md correctly 1`] = `
|
|||||||
<span>
|
<span>
|
||||||
Toggle
|
Toggle
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>,
|
||||||
</div>
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`renders ./components/tag/demo/icon.md correctly 1`] = `
|
exports[`renders ./components/tag/demo/icon.md correctly 1`] = `
|
||||||
<div>
|
Array [
|
||||||
<span
|
<span
|
||||||
class="ant-tag ant-tag-has-color"
|
class="ant-tag ant-tag-has-color"
|
||||||
style="background-color:#55acee"
|
style="background-color:#55acee"
|
||||||
@ -505,7 +505,7 @@ exports[`renders ./components/tag/demo/icon.md correctly 1`] = `
|
|||||||
<span>
|
<span>
|
||||||
Twitter
|
Twitter
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>,
|
||||||
<span
|
<span
|
||||||
class="ant-tag ant-tag-has-color"
|
class="ant-tag ant-tag-has-color"
|
||||||
style="background-color:#cd201f"
|
style="background-color:#cd201f"
|
||||||
@ -533,7 +533,7 @@ exports[`renders ./components/tag/demo/icon.md correctly 1`] = `
|
|||||||
<span>
|
<span>
|
||||||
Youtube
|
Youtube
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>,
|
||||||
<span
|
<span
|
||||||
class="ant-tag ant-tag-has-color"
|
class="ant-tag ant-tag-has-color"
|
||||||
style="background-color:#3b5999"
|
style="background-color:#3b5999"
|
||||||
@ -561,7 +561,7 @@ exports[`renders ./components/tag/demo/icon.md correctly 1`] = `
|
|||||||
<span>
|
<span>
|
||||||
Facebook
|
Facebook
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>,
|
||||||
<span
|
<span
|
||||||
class="ant-tag ant-tag-has-color"
|
class="ant-tag ant-tag-has-color"
|
||||||
style="background-color:#55acee"
|
style="background-color:#55acee"
|
||||||
@ -589,8 +589,8 @@ exports[`renders ./components/tag/demo/icon.md correctly 1`] = `
|
|||||||
<span>
|
<span>
|
||||||
LinkedIn
|
LinkedIn
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>,
|
||||||
</div>
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`renders ./components/tag/demo/status.md correctly 1`] = `
|
exports[`renders ./components/tag/demo/status.md correctly 1`] = `
|
||||||
|
@ -42,6 +42,30 @@ describe('Tag', () => {
|
|||||||
expect(wrapper.find('.ant-tag:not(.ant-tag-hidden)').length).toBe(1);
|
expect(wrapper.find('.ant-tag:not(.ant-tag-hidden)').length).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should trigger onClick', () => {
|
||||||
|
const onClick = jest.fn();
|
||||||
|
const wrapper = mount(<Tag onClick={onClick} />);
|
||||||
|
wrapper.find('.ant-tag').simulate('click');
|
||||||
|
expect(onClick).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
type: 'click',
|
||||||
|
preventDefault: expect.any(Function),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should trigger onClick on CheckableTag', () => {
|
||||||
|
const onClick = jest.fn();
|
||||||
|
const wrapper = mount(<Tag.CheckableTag onClick={onClick} />);
|
||||||
|
wrapper.find('.ant-tag').simulate('click');
|
||||||
|
expect(onClick).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
type: 'click',
|
||||||
|
preventDefault: expect.any(Function),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
// https://github.com/ant-design/ant-design/issues/20344
|
// https://github.com/ant-design/ant-design/issues/20344
|
||||||
it('should not trigger onClick when click close icon', () => {
|
it('should not trigger onClick when click close icon', () => {
|
||||||
const onClose = jest.fn();
|
const onClose = jest.fn();
|
||||||
|
@ -78,7 +78,7 @@ class EditableTagGroup extends React.Component {
|
|||||||
const { tags, inputVisible, inputValue } = this.state;
|
const { tags, inputVisible, inputValue } = this.state;
|
||||||
const tagChild = tags.map(this.forMap);
|
const tagChild = tags.map(this.forMap);
|
||||||
return (
|
return (
|
||||||
<div>
|
<>
|
||||||
<div style={{ marginBottom: 16 }}>
|
<div style={{ marginBottom: 16 }}>
|
||||||
<TweenOneGroup
|
<TweenOneGroup
|
||||||
enter={{
|
enter={{
|
||||||
@ -113,7 +113,7 @@ class EditableTagGroup extends React.Component {
|
|||||||
<PlusOutlined /> New Tag
|
<PlusOutlined /> New Tag
|
||||||
</Tag>
|
</Tag>
|
||||||
)}
|
)}
|
||||||
</div>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ function preventDefault(e) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<div>
|
<>
|
||||||
<Tag>Tag 1</Tag>
|
<Tag>Tag 1</Tag>
|
||||||
<Tag>
|
<Tag>
|
||||||
<a href="https://github.com/ant-design/ant-design/issues/1862">Link</a>
|
<a href="https://github.com/ant-design/ant-design/issues/1862">Link</a>
|
||||||
@ -37,7 +37,7 @@ ReactDOM.render(
|
|||||||
<Tag closable onClose={preventDefault}>
|
<Tag closable onClose={preventDefault}>
|
||||||
Prevent Default
|
Prevent Default
|
||||||
</Tag>
|
</Tag>
|
||||||
</div>,
|
</>,
|
||||||
mountNode,
|
mountNode,
|
||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
@ -78,7 +78,7 @@ class EditableTagGroup extends React.Component {
|
|||||||
render() {
|
render() {
|
||||||
const { tags, inputVisible, inputValue, editInputIndex, editInputValue } = this.state;
|
const { tags, inputVisible, inputValue, editInputIndex, editInputValue } = this.state;
|
||||||
return (
|
return (
|
||||||
<div>
|
<>
|
||||||
{tags.map((tag, index) => {
|
{tags.map((tag, index) => {
|
||||||
if (editInputIndex === index) {
|
if (editInputIndex === index) {
|
||||||
return (
|
return (
|
||||||
@ -143,7 +143,7 @@ class EditableTagGroup extends React.Component {
|
|||||||
<PlusOutlined /> New Tag
|
<PlusOutlined /> New Tag
|
||||||
</Tag>
|
</Tag>
|
||||||
)}
|
)}
|
||||||
</div>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ class Demo extends React.Component {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<>
|
||||||
<Tag
|
<Tag
|
||||||
closable
|
closable
|
||||||
visible={this.state.visible}
|
visible={this.state.visible}
|
||||||
@ -35,7 +35,7 @@ class Demo extends React.Component {
|
|||||||
<Button size="small" onClick={() => this.setState({ visible: !this.state.visible })}>
|
<Button size="small" onClick={() => this.setState({ visible: !this.state.visible })}>
|
||||||
Toggle
|
Toggle
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ import {
|
|||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<div>
|
<>
|
||||||
<Tag icon={<TwitterOutlined />} color="#55acee">
|
<Tag icon={<TwitterOutlined />} color="#55acee">
|
||||||
Twitter
|
Twitter
|
||||||
</Tag>
|
</Tag>
|
||||||
@ -40,7 +40,7 @@ ReactDOM.render(
|
|||||||
<Tag icon={<LinkedinOutlined />} color="#55acee">
|
<Tag icon={<LinkedinOutlined />} color="#55acee">
|
||||||
LinkedIn
|
LinkedIn
|
||||||
</Tag>
|
</Tag>
|
||||||
</div>,
|
</>,
|
||||||
mountNode,
|
mountNode,
|
||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
@ -3,7 +3,7 @@ order: 9
|
|||||||
title: Third-Party Libraries
|
title: Third-Party Libraries
|
||||||
---
|
---
|
||||||
|
|
||||||
`antd` is designed to provide high-quality React UI components which follow the Ant Design Specification. So, we are not going to implement other functions which are not relative to `antd`'s target, and recommend using the excellent third-party library which have come from the React community:
|
`antd` is built to implement [a set of high-quality React UI components](/components/overview) which follow Ant Design specification. It is impossible to include all useful components in one package, so we also recommend that using other great third-party libraries in React community.
|
||||||
|
|
||||||
| Category | Recommended Components |
|
| Category | Recommended Components |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
@ -32,9 +32,10 @@ title: Third-Party Libraries
|
|||||||
| Context Menu | [react-contextmenu](https://github.com/vkbansal/react-contextmenu/) [react-contexify](https://github.com/fkhadra/react-contexify) |
|
| Context Menu | [react-contextmenu](https://github.com/vkbansal/react-contextmenu/) [react-contexify](https://github.com/fkhadra/react-contexify) |
|
||||||
| Emoji | [emoji-mart](https://github.com/missive/emoji-mart) |
|
| Emoji | [emoji-mart](https://github.com/missive/emoji-mart) |
|
||||||
| Split View | [react-split-pane](https://github.com/tomkp/react-split-pane) |
|
| Split View | [react-split-pane](https://github.com/tomkp/react-split-pane) |
|
||||||
| Image Crop | [react-image-crop](https://github.com/DominicTobias/react-image-crop) |
|
| Image Crop | [antd-img-crop](https://github.com/nanxiaobei/antd-img-crop) [react-image-crop](https://github.com/DominicTobias/react-image-crop) |
|
||||||
| Trend Lines | [react-sparklines](https://github.com/borisyankov/react-sparklines) |
|
| Trend Lines | [react-sparklines](https://github.com/borisyankov/react-sparklines) |
|
||||||
| Keywords highlight | [react-highlight-words](https://github.com/bvaughn/react-highlight-words) |
|
| Keywords highlight | [react-highlight-words](https://github.com/bvaughn/react-highlight-words) |
|
||||||
|
| Text Loop | [react-text-loop](https://github.com/braposo/react-text-loop) |
|
||||||
| Animation | [react-move](https://github.com/react-tools/react-move) [Ant Motion](https://motion.ant.design/components/tween-one) [react-spring](https://www.react-spring.io) |
|
| Animation | [react-move](https://github.com/react-tools/react-move) [Ant Motion](https://motion.ant.design/components/tween-one) [react-spring](https://www.react-spring.io) |
|
||||||
|
|
||||||
## Products we are using ✨
|
## Products we are using ✨
|
||||||
|
@ -3,7 +3,7 @@ order: 9
|
|||||||
title: 社区精选组件
|
title: 社区精选组件
|
||||||
---
|
---
|
||||||
|
|
||||||
`antd` 是 Ant Design 设计规范的 React 实现,所以我们倾向于只提供符合该规范、且带有视觉展现的 UI 组件,也尽量不重复造轮子。我们推荐使用以下社区已有的优秀实现,与 antd 形成互补:
|
`antd` 是基于 Ant Design 设计规范实现的 [高质量 React 组件库](/components/overview),我们倾向于只提供符合该规范且带有视觉展现的 UI 组件,也尽量不重复造轮子。我们推荐使用以下社区已有的优秀实现,与 antd 形成互补。
|
||||||
|
|
||||||
| 类型 | 推荐组件 |
|
| 类型 | 推荐组件 |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
@ -32,9 +32,10 @@ title: 社区精选组件
|
|||||||
| 右键菜单 | [react-contextmenu](https://github.com/vkbansal/react-contextmenu/) [react-contexify](https://github.com/fkhadra/react-contexify) |
|
| 右键菜单 | [react-contextmenu](https://github.com/vkbansal/react-contextmenu/) [react-contexify](https://github.com/fkhadra/react-contexify) |
|
||||||
| Emoji | [emoji-mart](https://github.com/missive/emoji-mart) |
|
| Emoji | [emoji-mart](https://github.com/missive/emoji-mart) |
|
||||||
| 分割面板 | [react-split-pane](https://github.com/tomkp/react-split-pane) |
|
| 分割面板 | [react-split-pane](https://github.com/tomkp/react-split-pane) |
|
||||||
| 图片裁切 | [react-image-crop](https://github.com/DominicTobias/react-image-crop) |
|
| 图片裁切 | [antd-img-crop](https://github.com/nanxiaobei/antd-img-crop) [react-image-crop](https://github.com/DominicTobias/react-image-crop) |
|
||||||
| 趋势线 | [react-sparklines](https://github.com/borisyankov/react-sparklines) |
|
| 趋势线 | [react-sparklines](https://github.com/borisyankov/react-sparklines) |
|
||||||
| 关键字高亮 | [react-highlight-words](https://github.com/bvaughn/react-highlight-words) |
|
| 关键字高亮 | [react-highlight-words](https://github.com/bvaughn/react-highlight-words) |
|
||||||
|
| 文字轮播 | [react-text-loop](https://github.com/braposo/react-text-loop) |
|
||||||
| 动画 | [react-move](https://github.com/react-tools/react-move) [Ant Motion](https://motion.ant.design/components/tween-one) [react-spring](https://www.react-spring.io) |
|
| 动画 | [react-move](https://github.com/react-tools/react-move) [Ant Motion](https://motion.ant.design/components/tween-one) [react-spring](https://www.react-spring.io) |
|
||||||
|
|
||||||
## 推荐产品 ✨
|
## 推荐产品 ✨
|
||||||
|
@ -5,13 +5,13 @@ title: Replace Moment.js
|
|||||||
|
|
||||||
## How to use DatePicker with a custom date library like dayjs
|
## How to use DatePicker with a custom date library like dayjs
|
||||||
|
|
||||||
Consider of bundle size, you can replace momentjs with customize date library. We provide two ways to customize date library:
|
Considering it's bundle size, you might want to replace Moment.js with a different date library of your choice. We provide two ways to customize which date library is used:
|
||||||
|
|
||||||
### Custom component
|
### Custom component
|
||||||
|
|
||||||
The first way is use `generatePicker` (or `generateCalendar`) helps to create Picker components.
|
The first way is use `generatePicker` (or `generateCalendar`) helps to create Picker components.
|
||||||
|
|
||||||
First, we initialize an antd demo of `create-react-app`. You can refer to [Use in TypeScript](/docs/react/use-in-typescript), or you can start directly here [init antd](https://github.com/xiaohuoni/antd4-generate-picker/commit/47fec964e36d48bd15760f8f5abcb9655c259aa6)
|
First, we initialize an antd demo with `create-react-app`. You can refer to [Use in TypeScript](/docs/react/use-in-typescript), or you can start directly here [init antd](https://github.com/xiaohuoni/antd4-generate-picker/commit/47fec964e36d48bd15760f8f5abcb9655c259aa6)
|
||||||
|
|
||||||
#### DatePicker.tsx
|
#### DatePicker.tsx
|
||||||
|
|
||||||
@ -95,12 +95,12 @@ Modify `src/App.tsx`,import `dayjs` and custom component.
|
|||||||
+ import format from 'dayjs';
|
+ import format from 'dayjs';
|
||||||
```
|
```
|
||||||
|
|
||||||
If the above steps do not work correctly, you can refer [antd4-generate-picker/antd-ts](https://github.com/xiaohuoni/antd4-generate-picker/tree/master/antd-ts).
|
If the above steps do not work correctly, you can refer to [antd4-generate-picker/antd-ts](https://github.com/xiaohuoni/antd4-generate-picker/tree/master/antd-ts).
|
||||||
|
|
||||||
If you need JavaScript code, you can refer [antd4-generate-picker/antd-demo](https://github.com/xiaohuoni/antd4-generate-picker/tree/master/antd-demo).
|
If you need JavaScript code, you can refer to [antd4-generate-picker/antd-demo](https://github.com/xiaohuoni/antd4-generate-picker/tree/master/antd-demo).
|
||||||
|
|
||||||
If you are the user of [umi](https://umijs.org/), you can ref [antd4-use-dayjs-replace-moment](https://github.com/xiaohuoni/antd4-use-dayjs-replace-moment).
|
If you use [umi](https://umijs.org/), you can reference [antd4-use-dayjs-replace-moment](https://github.com/xiaohuoni/antd4-use-dayjs-replace-moment).
|
||||||
|
|
||||||
### Webpack plugin
|
### Webpack plugin
|
||||||
|
|
||||||
We also provide another implementation. We provide `antd-dayjs-webpack-plugin` plugin to replace `momentjs` to `Day.js` directly without changing a line of existing code. More info at [antd-dayjs-webpack-plugin](https://github.com/ant-design/antd-dayjs-webpack-plugin).
|
We also provide another implementation, which we provide with `antd-dayjs-webpack-plugin`, replacing `momentjs` with `Day.js` directly without changing a line of existing code. More info can be found at [antd-dayjs-webpack-plugin](https://github.com/ant-design/antd-dayjs-webpack-plugin).
|
||||||
|
@ -138,8 +138,10 @@ module.exports = {
|
|||||||
plugin: CracoLessPlugin,
|
plugin: CracoLessPlugin,
|
||||||
options: {
|
options: {
|
||||||
lessLoaderOptions: {
|
lessLoaderOptions: {
|
||||||
modifyVars: { '@primary-color': '#1DA57A' },
|
lessOptions: {
|
||||||
javascriptEnabled: true,
|
modifyVars: { '@primary-color': '#1DA57A' },
|
||||||
|
javascriptEnabled: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -136,8 +136,10 @@ module.exports = {
|
|||||||
plugin: CracoLessPlugin,
|
plugin: CracoLessPlugin,
|
||||||
options: {
|
options: {
|
||||||
lessLoaderOptions: {
|
lessLoaderOptions: {
|
||||||
modifyVars: { '@primary-color': '#1DA57A' },
|
lessOptions: {
|
||||||
javascriptEnabled: true,
|
modifyVars: { '@primary-color': '#1DA57A' },
|
||||||
|
javascriptEnabled: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -146,8 +146,10 @@ module.exports = {
|
|||||||
plugin: CracoLessPlugin,
|
plugin: CracoLessPlugin,
|
||||||
options: {
|
options: {
|
||||||
lessLoaderOptions: {
|
lessLoaderOptions: {
|
||||||
modifyVars: { '@primary-color': '#1DA57A' },
|
lessOptions: {
|
||||||
javascriptEnabled: true,
|
modifyVars: { '@primary-color': '#1DA57A' },
|
||||||
|
javascriptEnabled: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -148,8 +148,10 @@ module.exports = {
|
|||||||
plugin: CracoLessPlugin,
|
plugin: CracoLessPlugin,
|
||||||
options: {
|
options: {
|
||||||
lessLoaderOptions: {
|
lessLoaderOptions: {
|
||||||
modifyVars: { '@primary-color': '#1DA57A' },
|
lessOptions: {
|
||||||
javascriptEnabled: true,
|
modifyVars: { '@primary-color': '#1DA57A' },
|
||||||
|
javascriptEnabled: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
10
package.json
10
package.json
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "antd",
|
"name": "antd",
|
||||||
"version": "4.3.0",
|
"version": "4.3.1",
|
||||||
"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",
|
||||||
@ -47,7 +47,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"api-collection": "antd-tools run api-collection",
|
"api-collection": "antd-tools run api-collection",
|
||||||
"authors": "git log --format='%aN <%aE>' | sort -u | grep -v 'users.noreply.github.com' | grep -v 'gitter.im' | grep -v '.local>' | grep -v 'alibaba-inc.com' | grep -v 'alipay.com' | grep -v 'taobao.com' > AUTHORS.txt",
|
"authors": "git log --format='%aN <%aE>' | sort -u | grep -v 'users.noreply.github.com' | grep -v 'gitter.im' | grep -v '.local>' | grep -v 'alibaba-inc.com' | grep -v 'alipay.com' | grep -v 'taobao.com' > AUTHORS.txt",
|
||||||
"build": "npm run compile && npm run dist",
|
"build": "npm run compile && NODE_OPTIONS='--max-old-space-size=4096' npm run dist",
|
||||||
"bundlesize": "bundlesize",
|
"bundlesize": "bundlesize",
|
||||||
"check-commit": "node ./scripts/check-commit",
|
"check-commit": "node ./scripts/check-commit",
|
||||||
"prestart": "npm run version",
|
"prestart": "npm run version",
|
||||||
@ -73,7 +73,7 @@
|
|||||||
"lint:md": "remark . -f -q",
|
"lint:md": "remark . -f -q",
|
||||||
"lint:script": "eslint . --ext '.js,.jsx,.ts,.tsx'",
|
"lint:script": "eslint . --ext '.js,.jsx,.ts,.tsx'",
|
||||||
"lint:style": "stylelint '{site,components}/**/*.less' --syntax less",
|
"lint:style": "stylelint '{site,components}/**/*.less' --syntax less",
|
||||||
"pre-publish": "npm run check-commit && npm run test-all",
|
"pre-publish": "npm run test-all -- --skip-build",
|
||||||
"prettier": "prettier -c --write '**/*'",
|
"prettier": "prettier -c --write '**/*'",
|
||||||
"pretty-quick": "pretty-quick",
|
"pretty-quick": "pretty-quick",
|
||||||
"pub": "npm run version && antd-tools run pub",
|
"pub": "npm run version && antd-tools run pub",
|
||||||
@ -136,14 +136,14 @@
|
|||||||
"rc-steps": "~4.0.0",
|
"rc-steps": "~4.0.0",
|
||||||
"rc-switch": "~3.2.0",
|
"rc-switch": "~3.2.0",
|
||||||
"rc-table": "~7.7.2",
|
"rc-table": "~7.7.2",
|
||||||
"rc-tabs": "~11.2.0",
|
"rc-tabs": "~11.3.1",
|
||||||
"rc-tooltip": "~4.2.0",
|
"rc-tooltip": "~4.2.0",
|
||||||
"rc-tree": "~3.3.0",
|
"rc-tree": "~3.3.0",
|
||||||
"rc-tree-select": "~3.2.0",
|
"rc-tree-select": "~3.2.0",
|
||||||
"rc-trigger": "~4.3.0",
|
"rc-trigger": "~4.3.0",
|
||||||
"rc-upload": "~3.1.0",
|
"rc-upload": "~3.1.0",
|
||||||
"rc-util": "^5.0.1",
|
"rc-util": "^5.0.1",
|
||||||
"scroll-into-view-if-needed": "^2.2.20",
|
"scroll-into-view-if-needed": "^2.2.25",
|
||||||
"warning": "^4.0.3"
|
"warning": "^4.0.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -1,24 +1,37 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
cho "[TEST ALL] check-commit" && \
|
if [ "$1" != "--skip-build" ]; then
|
||||||
|
echo "[TEST ALL] dist"
|
||||||
|
npm run dist
|
||||||
|
|
||||||
|
echo "[TEST ALL] compile"
|
||||||
|
npm run compile
|
||||||
|
else
|
||||||
|
echo "Skip build..."
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "[TEST ALL] check-commit"
|
||||||
npm run check-commit
|
npm run check-commit
|
||||||
echo "[TEST ALL] lint" && \
|
|
||||||
npm run lint && \
|
echo "[TEST ALL] lint"
|
||||||
echo "[TEST ALL] dist" && \
|
npm run lint
|
||||||
npm run dist && \
|
|
||||||
echo "[TEST ALL] dekko dist" && \
|
echo "[TEST ALL] dekko dist"
|
||||||
node ./tests/dekko/dist.test.js && \
|
node ./tests/dekko/dist.test.js
|
||||||
echo "[TEST ALL] dist test" && \
|
|
||||||
LIB_DIR=dist npm test && \
|
echo "[TEST ALL] dist test"
|
||||||
echo "[TEST ALL] compile" && \
|
LIB_DIR=dist npm test
|
||||||
npm run compile && \
|
|
||||||
echo "[TEST ALL] dekko lib" && \
|
echo "[TEST ALL] dekko lib"
|
||||||
node ./tests/dekko/lib.test.js && \
|
|
||||||
echo "[TEST ALL] test es" && \
|
echo "[TEST ALL] test es"
|
||||||
LIB_DIR=es npm test && \
|
LIB_DIR=es npm test
|
||||||
echo "[TEST ALL] test lib" && \
|
|
||||||
LIB_DIR=lib npm test && \
|
echo "[TEST ALL] test lib"
|
||||||
echo "[TEST ALL] test" && \
|
LIB_DIR=lib npm test
|
||||||
npm test && \
|
|
||||||
echo "[TEST ALL] test node" && \
|
echo "[TEST ALL] test"
|
||||||
|
npm test
|
||||||
|
|
||||||
|
echo "[TEST ALL] test node"
|
||||||
npm run test-node
|
npm run test-node
|
||||||
|
@ -217,8 +217,8 @@
|
|||||||
.highlight {
|
.highlight {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
.ant-tabs-nav-scroll {
|
.ant-tabs-nav-list {
|
||||||
text-align: center;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
|
@ -7,6 +7,13 @@ import { getChildren } from 'jsonml.js/lib/utils';
|
|||||||
import { getMetaDescription, getLocalizedPathname, getThemeConfig, getMenuItems } from '../utils';
|
import { getMetaDescription, getLocalizedPathname, getThemeConfig, getMenuItems } from '../utils';
|
||||||
import './ComponentOverview.less';
|
import './ComponentOverview.less';
|
||||||
|
|
||||||
|
const onClickCard = href => {
|
||||||
|
window.gtag('event', '点击', {
|
||||||
|
event_category: '组件总览卡片',
|
||||||
|
event_label: href,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const { Title } = Typography;
|
const { Title } = Typography;
|
||||||
const ComponentOverview = ({
|
const ComponentOverview = ({
|
||||||
componentsData = [],
|
componentsData = [],
|
||||||
@ -54,9 +61,10 @@ const ComponentOverview = ({
|
|||||||
const url = `${component.filename
|
const url = `${component.filename
|
||||||
.replace(/(\/index)?((\.zh-cn)|(\.en-us))?\.md$/i, '')
|
.replace(/(\/index)?((\.zh-cn)|(\.en-us))?\.md$/i, '')
|
||||||
.toLowerCase()}/`;
|
.toLowerCase()}/`;
|
||||||
|
const href = getLocalizedPathname(url, locale === 'zh-CN');
|
||||||
return (
|
return (
|
||||||
<Col xs={24} sm={12} lg={8} xl={6} key={component.title}>
|
<Col xs={24} sm={12} lg={8} xl={6} key={component.title}>
|
||||||
<Link to={getLocalizedPathname(url, locale === 'zh-CN')}>
|
<Link to={href} onClick={() => onClickCard(href)}>
|
||||||
<Card
|
<Card
|
||||||
size="small"
|
size="small"
|
||||||
className="components-overview-card"
|
className="components-overview-card"
|
||||||
|
@ -48,7 +48,7 @@ const MORE_LIST: MoreProps[] = [
|
|||||||
title: '折柱饼 +3 个套路,简单图表你真的会用吗?',
|
title: '折柱饼 +3 个套路,简单图表你真的会用吗?',
|
||||||
description: '本文一句话概括:数据可视化中,如何用最简单的图表高效地传递信息。',
|
description: '本文一句话概括:数据可视化中,如何用最简单的图表高效地传递信息。',
|
||||||
img: 'https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*Q1DMQpLCDQgAAAAAAAAAAABkARQnAQ',
|
img: 'https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*Q1DMQpLCDQgAAAAAAAAAAABkARQnAQ',
|
||||||
date: '2020-11-28',
|
date: '2019-11-28',
|
||||||
source: 'zhihu',
|
source: 'zhihu',
|
||||||
href: 'https://zhuanlan.zhihu.com/p/93808863',
|
href: 'https://zhuanlan.zhihu.com/p/93808863',
|
||||||
},
|
},
|
||||||
|
@ -110,7 +110,7 @@ if (process.env.RUN_ENV === 'PRODUCTION') {
|
|||||||
// Reduce non-minified dist files size
|
// Reduce non-minified dist files size
|
||||||
config.optimization.usedExports = true;
|
config.optimization.usedExports = true;
|
||||||
// use esbuild
|
// use esbuild
|
||||||
if (process.env.ESBUILD) {
|
if (process.env.ESBUILD || process.env.CSB_REPO) {
|
||||||
config.optimization.minimizer[0] = new EsbuildPlugin();
|
config.optimization.minimizer[0] = new EsbuildPlugin();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user