mirror of
https://gitee.com/ant-design/ant-design.git
synced 2024-12-15 09:21:22 +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
|
||||
|
||||
`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)
|
||||
- 💄 Fix Cascader dropdown style in RTL. [#24520](https://github.com/ant-design/ant-design/pull/24520)
|
||||
- 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
|
||||
|
||||
|
@ -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
|
||||
|
||||
`2020-05-31`
|
||||
@ -81,7 +104,7 @@ timeline: true
|
||||
- 💄 优化 Table 筛选下拉框在 RTL 模式下样式。[#24529](https://github.com/ant-design/ant-design/pull/24529)
|
||||
- 💄 优化 Cascader RTL 模式下拉框的样式。[#24520](https://github.com/ant-design/ant-design/pull/24520)
|
||||
- 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
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
import React, { Component } from 'react';
|
||||
import { mount, render } from 'enzyme';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import { SearchOutlined } from '@ant-design/icons';
|
||||
import Button from '..';
|
||||
import ConfigProvider from '../../config-provider';
|
||||
@ -165,6 +166,24 @@ describe('Button', () => {
|
||||
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', () => {
|
||||
const onClick = jest.fn();
|
||||
const wrapper = mount(
|
||||
|
@ -121,16 +121,32 @@ interface CompoundedComponent
|
||||
__ANT_BUTTON: boolean;
|
||||
}
|
||||
|
||||
type Loading = number | boolean;
|
||||
|
||||
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 [loading, setLoading] = React.useState(props.loading);
|
||||
const [innerLoading, setLoading] = React.useState<Loading>(!!loading);
|
||||
const [hasTwoCNChar, setHasTwoCNChar] = React.useState(false);
|
||||
const { getPrefixCls, autoInsertSpaceInButton, direction } = React.useContext(ConfigContext);
|
||||
const buttonRef = (ref as any) || React.createRef<HTMLElement>();
|
||||
let delayTimeout: number;
|
||||
const delayTimeoutRef = React.useRef<number>();
|
||||
|
||||
const isNeedInserted = () => {
|
||||
const { icon, children, type } = props;
|
||||
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(() => {
|
||||
if (props.loading && typeof props.loading !== 'boolean') {
|
||||
clearTimeout(delayTimeout);
|
||||
clearTimeout(delayTimeoutRef.current);
|
||||
if (typeof loadingOrDelay === 'number') {
|
||||
delayTimeoutRef.current = window.setTimeout(() => {
|
||||
setLoading(loadingOrDelay);
|
||||
}, loadingOrDelay);
|
||||
} else {
|
||||
setLoading(loadingOrDelay);
|
||||
}
|
||||
if (props.loading && typeof props.loading !== 'boolean' && props.loading.delay) {
|
||||
delayTimeout = window.setTimeout(() => {
|
||||
setLoading(props.loading);
|
||||
}, props.loading.delay);
|
||||
} else if (props.loading !== loading) {
|
||||
setLoading(props.loading);
|
||||
}
|
||||
}, [props.loading]);
|
||||
}, [loadingOrDelay]);
|
||||
|
||||
React.useEffect(() => {
|
||||
fixTwoCNChar();
|
||||
@ -168,26 +190,13 @@ const InternalButton: React.ForwardRefRenderFunction<unknown, ButtonProps> = (pr
|
||||
|
||||
const handleClick = (e: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement, MouseEvent>) => {
|
||||
const { onClick } = props;
|
||||
if (loading) {
|
||||
if (innerLoading) {
|
||||
return;
|
||||
}
|
||||
if (onClick) {
|
||||
(onClick as React.MouseEventHandler<HTMLButtonElement | HTMLAnchorElement>)(e);
|
||||
}
|
||||
};
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
type,
|
||||
danger,
|
||||
shape,
|
||||
size: customizeSize,
|
||||
className,
|
||||
children,
|
||||
icon,
|
||||
ghost,
|
||||
block,
|
||||
...rest
|
||||
} = props;
|
||||
|
||||
devWarning(
|
||||
!(typeof icon === 'string' && icon.length > 2),
|
||||
@ -212,7 +221,7 @@ const InternalButton: React.ForwardRefRenderFunction<unknown, ButtonProps> = (pr
|
||||
break;
|
||||
}
|
||||
|
||||
const iconType = loading ? 'loading' : icon;
|
||||
const iconType = innerLoading ? 'loading' : icon;
|
||||
|
||||
const classes = classNames(prefixCls, className, {
|
||||
[`${prefixCls}-${type}`]: type,
|
||||
@ -220,7 +229,7 @@ const InternalButton: React.ForwardRefRenderFunction<unknown, ButtonProps> = (pr
|
||||
[`${prefixCls}-${sizeCls}`]: sizeCls,
|
||||
[`${prefixCls}-icon-only`]: !children && children !== 0 && iconType,
|
||||
[`${prefixCls}-background-ghost`]: ghost,
|
||||
[`${prefixCls}-loading`]: loading,
|
||||
[`${prefixCls}-loading`]: innerLoading,
|
||||
[`${prefixCls}-two-chinese-chars`]: hasTwoCNChar && autoInsertSpace,
|
||||
[`${prefixCls}-block`]: block,
|
||||
[`${prefixCls}-dangerous`]: !!danger,
|
||||
@ -228,10 +237,10 @@ const InternalButton: React.ForwardRefRenderFunction<unknown, ButtonProps> = (pr
|
||||
});
|
||||
|
||||
const iconNode =
|
||||
icon && !loading ? (
|
||||
icon && !innerLoading ? (
|
||||
icon
|
||||
) : (
|
||||
<LoadingIcon existIcon={!!icon} prefixCls={prefixCls} loading={loading} />
|
||||
<LoadingIcon existIcon={!!icon} prefixCls={prefixCls} loading={!!innerLoading} />
|
||||
);
|
||||
|
||||
const kids =
|
||||
|
@ -23,14 +23,23 @@ class App extends React.Component {
|
||||
};
|
||||
|
||||
enterLoading = index => {
|
||||
const newLoadings = [...this.state.loadings];
|
||||
newLoadings[index] = true;
|
||||
this.setState({
|
||||
loadings: newLoadings,
|
||||
this.setState(({ loadings }) => {
|
||||
const newLoadings = [...loadings];
|
||||
newLoadings[index] = true;
|
||||
|
||||
return {
|
||||
loadings: newLoadings,
|
||||
};
|
||||
});
|
||||
setTimeout(() => {
|
||||
newLoadings[index] = false;
|
||||
this.setState({ loadings: newLoadings });
|
||||
this.setState(({ loadings }) => {
|
||||
const newLoadings = [...loadings];
|
||||
newLoadings[index] = false;
|
||||
|
||||
return {
|
||||
loadings: newLoadings,
|
||||
};
|
||||
});
|
||||
}, 6000);
|
||||
};
|
||||
|
||||
|
@ -127,15 +127,27 @@ describe('Calendar', () => {
|
||||
MockDate.reset();
|
||||
});
|
||||
|
||||
it('should trigger onPanelChange when click last month of date', () => {
|
||||
const onPanelChange = jest.fn();
|
||||
const date = new Moment('1990-09-03');
|
||||
const wrapper = mount(<Calendar onPanelChange={onPanelChange} value={date} />);
|
||||
describe('onPanelChange', () => {
|
||||
it('trigger when click last month of date', () => {
|
||||
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(0).simulate('click');
|
||||
wrapper.find('.ant-picker-cell').at(0).simulate('click');
|
||||
|
||||
expect(onPanelChange).toHaveBeenCalled();
|
||||
expect(onPanelChange.mock.calls[0][0].month()).toEqual(date.month() - 1);
|
||||
expect(onPanelChange).toHaveBeenCalled();
|
||||
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 () => {
|
||||
|
@ -1,4 +1,5 @@
|
||||
import * as React from 'react';
|
||||
import useMergedState from 'rc-util/lib/hooks/useMergedState';
|
||||
import classNames from 'classnames';
|
||||
import padStart from 'lodash/padStart';
|
||||
import { PickerPanel as RCPickerPanel } from 'rc-picker';
|
||||
@ -62,13 +63,13 @@ export interface CalendarProps<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) {
|
||||
return (
|
||||
date1 === date2 ||
|
||||
(date1 &&
|
||||
date2 &&
|
||||
generateConfig.getYear(date1) === generateConfig.getYear(date2) &&
|
||||
generateConfig.getMonth(date1) === generateConfig.getMonth(date2))
|
||||
isSameYear(date1, date2) && generateConfig.getMonth(date1) === generateConfig.getMonth(date2)
|
||||
);
|
||||
}
|
||||
|
||||
@ -106,15 +107,15 @@ function generateCalendar<DateType>(generateConfig: GenerateConfig<DateType>) {
|
||||
// ====================== State =======================
|
||||
|
||||
// Value
|
||||
const [innerValue, setInnerValue] = React.useState(
|
||||
() => value || defaultValue || generateConfig.getNow(),
|
||||
);
|
||||
|
||||
const mergedValue = value || innerValue;
|
||||
const [mergedValue, setMergedValue] = useMergedState(() => value || generateConfig.getNow(), {
|
||||
defaultValue,
|
||||
value,
|
||||
});
|
||||
|
||||
// Mode
|
||||
const [innerMode, setInnerMode] = React.useState(() => mode || 'month');
|
||||
const mergedMode = mode || innerMode;
|
||||
const [mergedMode, setMergedMode] = useMergedState('month', {
|
||||
value: mode,
|
||||
});
|
||||
const panelMode = React.useMemo<'month' | 'date'>(
|
||||
() => (mergedMode === 'year' ? 'month' : 'date'),
|
||||
[mergedMode],
|
||||
@ -142,10 +143,16 @@ function generateCalendar<DateType>(generateConfig: GenerateConfig<DateType>) {
|
||||
};
|
||||
|
||||
const triggerChange = (date: DateType) => {
|
||||
setInnerValue(date);
|
||||
setMergedValue(date);
|
||||
|
||||
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) {
|
||||
onChange(date);
|
||||
@ -154,7 +161,7 @@ function generateCalendar<DateType>(generateConfig: GenerateConfig<DateType>) {
|
||||
};
|
||||
|
||||
const triggerModeChange = (newMode: CalendarMode) => {
|
||||
setInnerMode(newMode);
|
||||
setMergedMode(newMode);
|
||||
triggerPanelChange(mergedValue, newMode);
|
||||
};
|
||||
|
||||
|
@ -3,6 +3,7 @@ import { mount } from 'enzyme';
|
||||
import ConfigProvider from '..';
|
||||
import DatePicker from '../../date-picker';
|
||||
import Slider from '../../slider';
|
||||
import Drawer from '../../drawer';
|
||||
|
||||
describe('ConfigProvider.GetPopupContainer', () => {
|
||||
it('Datepicker', () => {
|
||||
@ -25,4 +26,15 @@ describe('ConfigProvider.GetPopupContainer', () => {
|
||||
wrapper.find('.ant-slider-handle').first().simulate('mouseenter');
|
||||
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>
|
||||
`;
|
||||
|
||||
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`] = `
|
||||
<button
|
||||
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 { ConfigConsumerProps } from '../config-provider';
|
||||
import { withConfigConsumer } from '../config-provider/context';
|
||||
import { withConfigConsumer, ConfigConsumer } from '../config-provider/context';
|
||||
import { tuple } from '../_util/type';
|
||||
|
||||
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
|
||||
renderProvider = (value: Drawer) => {
|
||||
const { prefixCls, placement, className, mask, direction, visible, ...rest } = this.props;
|
||||
this.parentDrawer = value;
|
||||
const drawerClassName = classNames(className, {
|
||||
'no-mask': !mask,
|
||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||
});
|
||||
const offsetStyle = mask ? this.getOffsetStyle() : {};
|
||||
|
||||
return (
|
||||
<DrawerContext.Provider value={this}>
|
||||
<RcDrawer
|
||||
handler={false}
|
||||
{...omit(rest, [
|
||||
'zIndex',
|
||||
'style',
|
||||
'closable',
|
||||
'destroyOnClose',
|
||||
'drawerStyle',
|
||||
'headerStyle',
|
||||
'bodyStyle',
|
||||
'footerStyle',
|
||||
'footer',
|
||||
'locale',
|
||||
'title',
|
||||
'push',
|
||||
'visible',
|
||||
'getPopupContainer',
|
||||
'rootPrefixCls',
|
||||
'getPrefixCls',
|
||||
'renderEmpty',
|
||||
'csp',
|
||||
'pageHeader',
|
||||
'autoInsertSpaceInButton',
|
||||
'width',
|
||||
'height',
|
||||
'dropdownMatchSelectWidth',
|
||||
])}
|
||||
{...offsetStyle}
|
||||
prefixCls={prefixCls}
|
||||
open={visible}
|
||||
showMask={mask}
|
||||
placement={placement}
|
||||
style={this.getRcDrawerStyle()}
|
||||
className={drawerClassName}
|
||||
>
|
||||
{this.renderBody()}
|
||||
</RcDrawer>
|
||||
</DrawerContext.Provider>
|
||||
<ConfigConsumer>
|
||||
{({ getPopupContainer, getPrefixCls }) => {
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
placement,
|
||||
className,
|
||||
mask,
|
||||
direction,
|
||||
visible,
|
||||
...rest
|
||||
} = this.props;
|
||||
|
||||
const prefixCls = getPrefixCls('select', customizePrefixCls);
|
||||
const drawerClassName = classNames(className, {
|
||||
'no-mask': !mask,
|
||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||
});
|
||||
const offsetStyle = mask ? this.getOffsetStyle() : {};
|
||||
|
||||
return (
|
||||
<DrawerContext.Provider value={this}>
|
||||
<RcDrawer
|
||||
handler={false}
|
||||
{...omit(rest, [
|
||||
'zIndex',
|
||||
'style',
|
||||
'closable',
|
||||
'destroyOnClose',
|
||||
'drawerStyle',
|
||||
'headerStyle',
|
||||
'bodyStyle',
|
||||
'footerStyle',
|
||||
'footer',
|
||||
'locale',
|
||||
'title',
|
||||
'push',
|
||||
'visible',
|
||||
'getPopupContainer',
|
||||
'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
|
||||
|
||||
属性如下
|
||||
|
@ -58,7 +58,6 @@
|
||||
border-radius: @border-radius-base;
|
||||
outline: none;
|
||||
box-shadow: @box-shadow-base;
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
|
||||
&-item-group-title {
|
||||
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 {
|
||||
& when (@dropdown-edge-child-vertical-padding = 0) {
|
||||
border-radius: @border-radius-base @border-radius-base 0 0;
|
||||
@ -268,7 +275,8 @@
|
||||
}
|
||||
.@{dropdown-prefix-cls}-menu-item,
|
||||
.@{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;
|
||||
.@{dropdown-prefix-cls}-menu-submenu-arrow::after {
|
||||
color: @text-color-secondary-dark;
|
||||
|
@ -7,11 +7,11 @@ title:
|
||||
|
||||
## zh-CN
|
||||
|
||||
动态增加、减少表单项。
|
||||
动态增加、减少表单项。`add` 方法参数可用于设置初始值。
|
||||
|
||||
## en-US
|
||||
|
||||
Add or remove form items dynamically.
|
||||
Add or remove form items dynamically. `add` function support config initial value.
|
||||
|
||||
```jsx
|
||||
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 './rtl';
|
||||
@import './IE11';
|
||||
|
@ -1,9 +1,12 @@
|
||||
/* eslint-disable no-template-curly-in-string */
|
||||
import Pagination from 'rc-pagination/lib/locale/he_IL';
|
||||
import DatePicker from '../date-picker/locale/he_IL';
|
||||
import TimePicker from '../time-picker/locale/he_IL';
|
||||
import Calendar from '../calendar/locale/he_IL';
|
||||
import { Locale } from '../locale-provider';
|
||||
|
||||
const typeTemplate = '${label} הוא לא ${type} תקין';
|
||||
|
||||
const localeValues: Locale = {
|
||||
locale: 'he',
|
||||
Pagination,
|
||||
@ -63,6 +66,55 @@ const localeValues: Locale = {
|
||||
PageHeader: {
|
||||
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;
|
||||
|
@ -1302,30 +1302,28 @@ exports[`renders ./components/menu/demo/vertical.md correctly 1`] = `
|
||||
class="ant-menu-submenu-title"
|
||||
role="button"
|
||||
>
|
||||
<span>
|
||||
<span
|
||||
aria-label="appstore"
|
||||
class="anticon anticon-appstore"
|
||||
role="img"
|
||||
<span
|
||||
aria-label="appstore"
|
||||
class="anticon anticon-appstore"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="appstore"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="appstore"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
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>
|
||||
<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>
|
||||
<i
|
||||
class="ant-menu-submenu-arrow"
|
||||
|
@ -35,15 +35,7 @@ ReactDOM.render(
|
||||
<Menu.Item key="4">Option 4</Menu.Item>
|
||||
</Menu.ItemGroup>
|
||||
</SubMenu>
|
||||
<SubMenu
|
||||
key="sub2"
|
||||
title={
|
||||
<span>
|
||||
<AppstoreOutlined />
|
||||
<span>Navigation Two</span>
|
||||
</span>
|
||||
}
|
||||
>
|
||||
<SubMenu key="sub2" icon={<AppstoreOutlined />} title="Navigation Two">
|
||||
<Menu.Item key="5">Option 5</Menu.Item>
|
||||
<Menu.Item key="6">Option 6</Menu.Item>
|
||||
<SubMenu key="sub3" title="Submenu">
|
||||
|
@ -27,6 +27,7 @@ const ConfirmDialog = (props: ConfirmDialogProps) => {
|
||||
okButtonProps,
|
||||
cancelText,
|
||||
cancelButtonProps,
|
||||
direction,
|
||||
} = props;
|
||||
|
||||
devWarning(
|
||||
@ -53,6 +54,7 @@ const ConfirmDialog = (props: ConfirmDialogProps) => {
|
||||
const classString = classNames(
|
||||
contentPrefixCls,
|
||||
`${contentPrefixCls}-${props.type}`,
|
||||
{ [`${contentPrefixCls}-rtl`]: direction === 'rtl' },
|
||||
props.className,
|
||||
);
|
||||
|
||||
|
@ -111,6 +111,7 @@ export interface ModalFuncProps {
|
||||
autoFocusButton?: null | 'ok' | 'cancel';
|
||||
transitionName?: string;
|
||||
maskTransitionName?: string;
|
||||
direction?: string;
|
||||
}
|
||||
|
||||
export interface ModalLocale {
|
||||
|
@ -44,7 +44,9 @@ When requiring users to interact with the application, but without jumping to a
|
||||
|
||||
#### 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()
|
||||
|
||||
|
@ -48,7 +48,9 @@ cover: https://gw.alipayobjects.com/zos/alicdn/3StSdUlSH/Modal.svg
|
||||
|
||||
#### 注意
|
||||
|
||||
> `<Modal />` 默认关闭后状态不会自动清空, 如果希望每次打开都是新内容,请设置 `destroyOnClose`。
|
||||
> - `<Modal />` 默认关闭后状态不会自动清空, 如果希望每次打开都是新内容,请设置 `destroyOnClose`。
|
||||
>
|
||||
> - `Modal.method()` RTL 模式仅支持 hooks 用法。
|
||||
|
||||
### Modal.method()
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
@import '../../style/mixins/index';
|
||||
|
||||
@dialog-prefix-cls: ~'@{ant-prefix}-modal';
|
||||
@confirm-prefix-cls: ~'@{ant-prefix}-modal-confirm';
|
||||
@dialog-wrap-rtl-cls: ~'@{dialog-prefix-cls}-wrap-rtl';
|
||||
|
||||
.@{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 {
|
||||
|
@ -3,6 +3,7 @@ import { ModalFuncProps } from '../Modal';
|
||||
import ConfirmDialog from '../ConfirmDialog';
|
||||
import defaultLocale from '../../locale/default';
|
||||
import LocaleReceiver from '../../locale-provider/LocaleReceiver';
|
||||
import { ConfigContext } from '../../config-provider';
|
||||
|
||||
export interface HookModalProps {
|
||||
afterClose: () => void;
|
||||
@ -26,6 +27,7 @@ const HookModal: React.RefForwardingComponent<HookModalRef, HookModalProps> = (
|
||||
) => {
|
||||
const [visible, setVisible] = React.useState(true);
|
||||
const [innerConfig, setInnerConfig] = React.useState(config);
|
||||
const { direction } = React.useContext(ConfigContext);
|
||||
|
||||
function close() {
|
||||
setVisible(false);
|
||||
@ -53,6 +55,7 @@ const HookModal: React.RefForwardingComponent<HookModalRef, HookModalProps> = (
|
||||
innerConfig.okText ||
|
||||
(innerConfig.okCancel ? modalLocale.okText : modalLocale.justOkText)
|
||||
}
|
||||
direction={direction}
|
||||
cancelText={innerConfig.cancelText || modalLocale.cancelText}
|
||||
/>
|
||||
)}
|
||||
|
@ -4,4 +4,4 @@ title: Components 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: 组件总览
|
||||
---
|
||||
|
||||
`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 Button from './radioButton';
|
||||
import { RadioProps } 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.Group = Group;
|
||||
export { Button, Group };
|
||||
|
@ -1,19 +1,11 @@
|
||||
import * as React from 'react';
|
||||
import RcCheckbox from 'rc-checkbox';
|
||||
import classNames from 'classnames';
|
||||
import RadioGroup from './group';
|
||||
import RadioButton from './radioButton';
|
||||
import { RadioProps, RadioChangeEvent } from './interface';
|
||||
import { ConfigContext } from '../config-provider';
|
||||
import RadioGroupContext from './context';
|
||||
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 context = React.useContext(RadioGroupContext);
|
||||
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.Group = RadioGroup;
|
||||
Radio.Button = RadioButton;
|
||||
|
||||
Radio.defaultProps = {
|
||||
type: 'radio',
|
||||
};
|
||||
|
@ -90,7 +90,7 @@ class Select<ValueType extends SelectValue = SelectValue> extends React.Componen
|
||||
className,
|
||||
size: customizeSize,
|
||||
listHeight = 256,
|
||||
listItemHeight = 32,
|
||||
listItemHeight = 24,
|
||||
getPopupContainer,
|
||||
dropdownClassName,
|
||||
bordered,
|
||||
|
@ -574,6 +574,9 @@
|
||||
@table-footer-bg: @background-color-light;
|
||||
@table-footer-color: @heading-color;
|
||||
@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
|
||||
// Legacy: `table-header-sort-active-bg` is used for hover not real active
|
||||
@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` |
|
||||
| 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) | - |
|
||||
| dataSource | Data record array to be displayed | object\[] | - |
|
||||
| expandable | Config expandable content | [expandable](#expandable) | - |
|
||||
@ -220,14 +220,14 @@ Properties for row selection.
|
||||
|
||||
```tsx
|
||||
import { Table } from 'antd';
|
||||
import { ColumnProps } from 'antd/es/table';
|
||||
import { ColumnsType } from 'antd/es/table';
|
||||
|
||||
interface User {
|
||||
key: number,
|
||||
name: string;
|
||||
}
|
||||
|
||||
const columns: ColumnProps<User>[] = [{
|
||||
const columns: ColumnsType<User>[] = [{
|
||||
key: 'name',
|
||||
title: '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` |
|
||||
| bordered | 是否展示外边框和列边框 | boolean | false |
|
||||
| columns | 表格列的配置描述,具体项见下表 | [ColumnProps](#Column)\[] | - |
|
||||
| columns | 表格列的配置描述,具体项见下表 | [ColumnsType](#Column)\[] | - |
|
||||
| components | 覆盖默认的 table 元素 | [TableComponents](https://git.io/fANxz) | - |
|
||||
| dataSource | 数据数组 | object\[] | - |
|
||||
| expandable | 配置展开属性 | [expandable](#expandable) | - |
|
||||
@ -225,14 +225,14 @@ const columns = [
|
||||
|
||||
```tsx
|
||||
import { Table } from 'antd';
|
||||
import { ColumnProps } from 'antd/es/table';
|
||||
import { ColumnsType } from 'antd/es/table';
|
||||
|
||||
interface User {
|
||||
key: number;
|
||||
name: string;
|
||||
}
|
||||
|
||||
const columns: ColumnProps<User>[] = [{
|
||||
const columns: ColumnsType<User>[] = [{
|
||||
key: 'name',
|
||||
title: 'Name',
|
||||
dataIndex: 'name',
|
||||
|
@ -10,6 +10,7 @@
|
||||
@table-header-sort-active-filter-bg: lighten(@table-header-sort-active-bg, 2%);
|
||||
|
||||
.@{table-prefix-cls}-wrapper {
|
||||
max-width: 100%;
|
||||
.clearfix;
|
||||
}
|
||||
|
||||
@ -18,6 +19,7 @@
|
||||
position: relative;
|
||||
z-index: 0;
|
||||
clear: both;
|
||||
font-size: @table-font-size;
|
||||
background: @table-bg;
|
||||
border-radius: @border-radius-base;
|
||||
|
||||
|
@ -1,7 +1,9 @@
|
||||
@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} {
|
||||
font-size: @font-size;
|
||||
|
||||
.@{table-prefix-cls}-title,
|
||||
.@{table-prefix-cls}-footer,
|
||||
.@{table-prefix-cls}-thead > tr > th,
|
||||
@ -48,12 +50,12 @@
|
||||
// ================================================================
|
||||
// = 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 =
|
||||
// ================================================================
|
||||
.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}-thead > tr > th {
|
||||
|
@ -1,6 +1,5 @@
|
||||
import * as React from 'react';
|
||||
import RcTabs, { TabPane, TabsProps as RcTabsProps } from 'rc-tabs';
|
||||
import { TabPaneProps } from 'rc-tabs/lib/sugar/TabPane';
|
||||
import RcTabs, { TabPane, TabsProps as RcTabsProps, TabPaneProps } from 'rc-tabs';
|
||||
import { EditableConfig } from 'rc-tabs/lib/interface';
|
||||
import classNames from 'classnames';
|
||||
import EllipsisOutlined from '@ant-design/icons/EllipsisOutlined';
|
||||
|
@ -3,7 +3,8 @@
|
||||
@import './index';
|
||||
|
||||
.@{tab-prefix-cls}-card {
|
||||
> .@{tab-prefix-cls}-nav {
|
||||
> .@{tab-prefix-cls}-nav,
|
||||
> div > .@{tab-prefix-cls}-nav {
|
||||
.@{tab-prefix-cls}-tab {
|
||||
margin: 0;
|
||||
padding: @tabs-card-horizontal-padding;
|
||||
@ -25,7 +26,8 @@
|
||||
// ========================== Top & Bottom ==========================
|
||||
&.@{tab-prefix-cls}-top,
|
||||
&.@{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) {
|
||||
margin-right: @tabs-card-gutter;
|
||||
}
|
||||
@ -33,7 +35,8 @@
|
||||
}
|
||||
|
||||
&.@{tab-prefix-cls}-top {
|
||||
> .@{tab-prefix-cls}-nav {
|
||||
> .@{tab-prefix-cls}-nav,
|
||||
> div > .@{tab-prefix-cls}-nav {
|
||||
.@{tab-prefix-cls}-tab {
|
||||
border-radius: @border-radius-base @border-radius-base 0 0;
|
||||
|
||||
@ -44,7 +47,8 @@
|
||||
}
|
||||
}
|
||||
&.@{tab-prefix-cls}-bottom {
|
||||
> .@{tab-prefix-cls}-nav {
|
||||
> .@{tab-prefix-cls}-nav,
|
||||
> div > .@{tab-prefix-cls}-nav {
|
||||
.@{tab-prefix-cls}-tab {
|
||||
border-radius: 0 0 @border-radius-base @border-radius-base;
|
||||
|
||||
@ -58,7 +62,8 @@
|
||||
// ========================== Left & Right ==========================
|
||||
&.@{tab-prefix-cls}-left,
|
||||
&.@{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) {
|
||||
margin-bottom: @tabs-card-gutter;
|
||||
}
|
||||
@ -66,7 +71,8 @@
|
||||
}
|
||||
|
||||
&.@{tab-prefix-cls}-left {
|
||||
> .@{tab-prefix-cls}-nav {
|
||||
> .@{tab-prefix-cls}-nav,
|
||||
> div > .@{tab-prefix-cls}-nav {
|
||||
.@{tab-prefix-cls}-tab {
|
||||
border-radius: @border-radius-base 0 0 @border-radius-base;
|
||||
|
||||
@ -77,7 +83,8 @@
|
||||
}
|
||||
}
|
||||
&.@{tab-prefix-cls}-right {
|
||||
> .@{tab-prefix-cls}-nav {
|
||||
> .@{tab-prefix-cls}-nav,
|
||||
> div > .@{tab-prefix-cls}-nav {
|
||||
.@{tab-prefix-cls}-tab {
|
||||
border-radius: 0 @border-radius-base @border-radius-base 0;
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
max-height: 200px;
|
||||
margin: 0;
|
||||
padding: @dropdown-edge-child-vertical-padding 0;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
text-align: left;
|
||||
list-style-type: none;
|
||||
|
@ -15,7 +15,8 @@
|
||||
overflow: hidden;
|
||||
|
||||
// ========================== Navigation ==========================
|
||||
> .@{tab-prefix-cls}-nav {
|
||||
> .@{tab-prefix-cls}-nav,
|
||||
> div > .@{tab-prefix-cls}-nav {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex: none;
|
||||
|
@ -6,7 +6,8 @@
|
||||
&-bottom {
|
||||
flex-direction: column;
|
||||
|
||||
> .@{tab-prefix-cls}-nav {
|
||||
> .@{tab-prefix-cls}-nav,
|
||||
> div > .@{tab-prefix-cls}-nav {
|
||||
margin: @tabs-bar-margin;
|
||||
|
||||
&::before {
|
||||
@ -54,7 +55,8 @@
|
||||
}
|
||||
|
||||
&-top {
|
||||
> .@{tab-prefix-cls}-nav {
|
||||
> .@{tab-prefix-cls}-nav,
|
||||
> div > .@{tab-prefix-cls}-nav {
|
||||
&::before {
|
||||
bottom: 0;
|
||||
}
|
||||
@ -66,7 +68,8 @@
|
||||
}
|
||||
|
||||
&-bottom {
|
||||
> .@{tab-prefix-cls}-nav {
|
||||
> .@{tab-prefix-cls}-nav,
|
||||
> div > .@{tab-prefix-cls}-nav {
|
||||
order: 1;
|
||||
margin-top: @margin-md;
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -88,7 +92,8 @@
|
||||
// ========================== Left & Right ==========================
|
||||
&-left,
|
||||
&-right {
|
||||
> .@{tab-prefix-cls}-nav {
|
||||
> .@{tab-prefix-cls}-nav,
|
||||
> div > .@{tab-prefix-cls}-nav {
|
||||
flex-direction: column;
|
||||
min-width: 50px;
|
||||
|
||||
@ -148,13 +153,15 @@
|
||||
}
|
||||
|
||||
&-left {
|
||||
> .@{tab-prefix-cls}-nav {
|
||||
> .@{tab-prefix-cls}-nav,
|
||||
> div > .@{tab-prefix-cls}-nav {
|
||||
.@{tab-prefix-cls}-ink-bar {
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
> .@{tab-prefix-cls}-content-holder {
|
||||
> .@{tab-prefix-cls}-content-holder,
|
||||
> div > .@{tab-prefix-cls}-content-holder {
|
||||
margin-left: -@border-width-base;
|
||||
border-left: @border-width-base @border-style-base @border-color-split;
|
||||
|
||||
@ -165,7 +172,8 @@
|
||||
}
|
||||
|
||||
&-right {
|
||||
> .@{tab-prefix-cls}-nav {
|
||||
> .@{tab-prefix-cls}-nav,
|
||||
> div > .@{tab-prefix-cls}-nav {
|
||||
order: 1;
|
||||
|
||||
.@{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;
|
||||
margin-right: -@border-width-base;
|
||||
border-right: @border-width-base @border-style-base @border-color-split;
|
||||
|
@ -1,11 +1,12 @@
|
||||
@import '../../style/themes/index';
|
||||
@import '../../style/mixins/index';
|
||||
@import './index';
|
||||
|
||||
@tab-prefix-cls: ~'@{ant-prefix}-tabs';
|
||||
|
||||
.@{tab-prefix-cls}-rtl {
|
||||
direction: rtl;
|
||||
|
||||
> .@{tab-prefix-cls}-nav {
|
||||
.@{tab-prefix-cls}-nav {
|
||||
.@{tab-prefix-cls}-tab {
|
||||
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;
|
||||
checked: boolean;
|
||||
onChange?: (checked: boolean) => void;
|
||||
onClick?: (e: React.MouseEventHandler<HTMLElement>) => void;
|
||||
}
|
||||
|
||||
const CheckableTag: React.FC<CheckableTagProps> = props => {
|
||||
const { getPrefixCls } = React.useContext(ConfigContext);
|
||||
const handleClick = () => {
|
||||
const { checked, onChange } = props;
|
||||
const handleClick = (e: React.MouseEventHandler) => {
|
||||
const { checked, onChange, onClick } = props;
|
||||
if (onChange) {
|
||||
onChange(!checked);
|
||||
}
|
||||
if (onClick) {
|
||||
onClick(e);
|
||||
}
|
||||
};
|
||||
|
||||
const { prefixCls: customizePrefixCls, className, checked, ...restProps } = props;
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`renders ./components/tag/demo/animation.md correctly 1`] = `
|
||||
<div>
|
||||
Array [
|
||||
<div
|
||||
style="margin-bottom:16px"
|
||||
>
|
||||
@ -97,7 +97,7 @@ exports[`renders ./components/tag/demo/animation.md correctly 1`] = `
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
<span
|
||||
class="ant-tag site-tag-plus"
|
||||
>
|
||||
@ -126,17 +126,17 @@ exports[`renders ./components/tag/demo/animation.md correctly 1`] = `
|
||||
</svg>
|
||||
</span>
|
||||
New Tag
|
||||
</span>
|
||||
</div>
|
||||
</span>,
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`renders ./components/tag/demo/basic.md correctly 1`] = `
|
||||
<div>
|
||||
Array [
|
||||
<span
|
||||
class="ant-tag"
|
||||
>
|
||||
Tag 1
|
||||
</span>
|
||||
</span>,
|
||||
<span
|
||||
class="ant-tag"
|
||||
>
|
||||
@ -145,7 +145,7 @@ exports[`renders ./components/tag/demo/basic.md correctly 1`] = `
|
||||
>
|
||||
Link
|
||||
</a>
|
||||
</span>
|
||||
</span>,
|
||||
<span
|
||||
class="ant-tag"
|
||||
>
|
||||
@ -171,7 +171,7 @@ exports[`renders ./components/tag/demo/basic.md correctly 1`] = `
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</span>,
|
||||
<span
|
||||
class="ant-tag"
|
||||
>
|
||||
@ -197,8 +197,8 @@ exports[`renders ./components/tag/demo/basic.md correctly 1`] = `
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</span>,
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`renders ./components/tag/demo/checkable.md correctly 1`] = `
|
||||
@ -340,14 +340,14 @@ Array [
|
||||
`;
|
||||
|
||||
exports[`renders ./components/tag/demo/control.md correctly 1`] = `
|
||||
<div>
|
||||
Array [
|
||||
<span
|
||||
class="ant-tag edit-tag"
|
||||
>
|
||||
<span>
|
||||
Unremovable
|
||||
</span>
|
||||
</span>
|
||||
</span>,
|
||||
<span
|
||||
class="ant-tag edit-tag"
|
||||
>
|
||||
@ -375,7 +375,7 @@ exports[`renders ./components/tag/demo/control.md correctly 1`] = `
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</span>,
|
||||
<span
|
||||
class="ant-tag edit-tag"
|
||||
>
|
||||
@ -403,7 +403,7 @@ exports[`renders ./components/tag/demo/control.md correctly 1`] = `
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</span>,
|
||||
<span
|
||||
class="ant-tag site-tag-plus"
|
||||
>
|
||||
@ -432,12 +432,12 @@ exports[`renders ./components/tag/demo/control.md correctly 1`] = `
|
||||
</svg>
|
||||
</span>
|
||||
New Tag
|
||||
</span>
|
||||
</div>
|
||||
</span>,
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`renders ./components/tag/demo/controlled.md correctly 1`] = `
|
||||
<div>
|
||||
Array [
|
||||
<span
|
||||
class="ant-tag"
|
||||
>
|
||||
@ -463,8 +463,8 @@ exports[`renders ./components/tag/demo/controlled.md correctly 1`] = `
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
<br />
|
||||
</span>,
|
||||
<br />,
|
||||
<button
|
||||
class="ant-btn ant-btn-sm"
|
||||
type="button"
|
||||
@ -472,12 +472,12 @@ exports[`renders ./components/tag/demo/controlled.md correctly 1`] = `
|
||||
<span>
|
||||
Toggle
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</button>,
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`renders ./components/tag/demo/icon.md correctly 1`] = `
|
||||
<div>
|
||||
Array [
|
||||
<span
|
||||
class="ant-tag ant-tag-has-color"
|
||||
style="background-color:#55acee"
|
||||
@ -505,7 +505,7 @@ exports[`renders ./components/tag/demo/icon.md correctly 1`] = `
|
||||
<span>
|
||||
Twitter
|
||||
</span>
|
||||
</span>
|
||||
</span>,
|
||||
<span
|
||||
class="ant-tag ant-tag-has-color"
|
||||
style="background-color:#cd201f"
|
||||
@ -533,7 +533,7 @@ exports[`renders ./components/tag/demo/icon.md correctly 1`] = `
|
||||
<span>
|
||||
Youtube
|
||||
</span>
|
||||
</span>
|
||||
</span>,
|
||||
<span
|
||||
class="ant-tag ant-tag-has-color"
|
||||
style="background-color:#3b5999"
|
||||
@ -561,7 +561,7 @@ exports[`renders ./components/tag/demo/icon.md correctly 1`] = `
|
||||
<span>
|
||||
Facebook
|
||||
</span>
|
||||
</span>
|
||||
</span>,
|
||||
<span
|
||||
class="ant-tag ant-tag-has-color"
|
||||
style="background-color:#55acee"
|
||||
@ -589,8 +589,8 @@ exports[`renders ./components/tag/demo/icon.md correctly 1`] = `
|
||||
<span>
|
||||
LinkedIn
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</span>,
|
||||
]
|
||||
`;
|
||||
|
||||
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);
|
||||
});
|
||||
|
||||
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
|
||||
it('should not trigger onClick when click close icon', () => {
|
||||
const onClose = jest.fn();
|
||||
|
@ -78,7 +78,7 @@ class EditableTagGroup extends React.Component {
|
||||
const { tags, inputVisible, inputValue } = this.state;
|
||||
const tagChild = tags.map(this.forMap);
|
||||
return (
|
||||
<div>
|
||||
<>
|
||||
<div style={{ marginBottom: 16 }}>
|
||||
<TweenOneGroup
|
||||
enter={{
|
||||
@ -113,7 +113,7 @@ class EditableTagGroup extends React.Component {
|
||||
<PlusOutlined /> New Tag
|
||||
</Tag>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ function preventDefault(e) {
|
||||
}
|
||||
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<>
|
||||
<Tag>Tag 1</Tag>
|
||||
<Tag>
|
||||
<a href="https://github.com/ant-design/ant-design/issues/1862">Link</a>
|
||||
@ -37,7 +37,7 @@ ReactDOM.render(
|
||||
<Tag closable onClose={preventDefault}>
|
||||
Prevent Default
|
||||
</Tag>
|
||||
</div>,
|
||||
</>,
|
||||
mountNode,
|
||||
);
|
||||
```
|
||||
|
@ -78,7 +78,7 @@ class EditableTagGroup extends React.Component {
|
||||
render() {
|
||||
const { tags, inputVisible, inputValue, editInputIndex, editInputValue } = this.state;
|
||||
return (
|
||||
<div>
|
||||
<>
|
||||
{tags.map((tag, index) => {
|
||||
if (editInputIndex === index) {
|
||||
return (
|
||||
@ -143,7 +143,7 @@ class EditableTagGroup extends React.Component {
|
||||
<PlusOutlined /> New Tag
|
||||
</Tag>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ class Demo extends React.Component {
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<>
|
||||
<Tag
|
||||
closable
|
||||
visible={this.state.visible}
|
||||
@ -35,7 +35,7 @@ class Demo extends React.Component {
|
||||
<Button size="small" onClick={() => this.setState({ visible: !this.state.visible })}>
|
||||
Toggle
|
||||
</Button>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ import {
|
||||
} from '@ant-design/icons';
|
||||
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<>
|
||||
<Tag icon={<TwitterOutlined />} color="#55acee">
|
||||
Twitter
|
||||
</Tag>
|
||||
@ -40,7 +40,7 @@ ReactDOM.render(
|
||||
<Tag icon={<LinkedinOutlined />} color="#55acee">
|
||||
LinkedIn
|
||||
</Tag>
|
||||
</div>,
|
||||
</>,
|
||||
mountNode,
|
||||
);
|
||||
```
|
||||
|
@ -3,7 +3,7 @@ order: 9
|
||||
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 |
|
||||
| --- | --- |
|
||||
@ -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) |
|
||||
| Emoji | [emoji-mart](https://github.com/missive/emoji-mart) |
|
||||
| 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) |
|
||||
| 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) |
|
||||
|
||||
## Products we are using ✨
|
||||
|
@ -3,7 +3,7 @@ order: 9
|
||||
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) |
|
||||
| Emoji | [emoji-mart](https://github.com/missive/emoji-mart) |
|
||||
| 分割面板 | [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-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) |
|
||||
|
||||
## 推荐产品 ✨
|
||||
|
@ -5,13 +5,13 @@ title: Replace Moment.js
|
||||
|
||||
## 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
|
||||
|
||||
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
|
||||
|
||||
@ -95,12 +95,12 @@ Modify `src/App.tsx`,import `dayjs` and custom component.
|
||||
+ 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
|
||||
|
||||
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,
|
||||
options: {
|
||||
lessLoaderOptions: {
|
||||
modifyVars: { '@primary-color': '#1DA57A' },
|
||||
javascriptEnabled: true,
|
||||
lessOptions: {
|
||||
modifyVars: { '@primary-color': '#1DA57A' },
|
||||
javascriptEnabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -136,8 +136,10 @@ module.exports = {
|
||||
plugin: CracoLessPlugin,
|
||||
options: {
|
||||
lessLoaderOptions: {
|
||||
modifyVars: { '@primary-color': '#1DA57A' },
|
||||
javascriptEnabled: true,
|
||||
lessOptions: {
|
||||
modifyVars: { '@primary-color': '#1DA57A' },
|
||||
javascriptEnabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -146,8 +146,10 @@ module.exports = {
|
||||
plugin: CracoLessPlugin,
|
||||
options: {
|
||||
lessLoaderOptions: {
|
||||
modifyVars: { '@primary-color': '#1DA57A' },
|
||||
javascriptEnabled: true,
|
||||
lessOptions: {
|
||||
modifyVars: { '@primary-color': '#1DA57A' },
|
||||
javascriptEnabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -148,8 +148,10 @@ module.exports = {
|
||||
plugin: CracoLessPlugin,
|
||||
options: {
|
||||
lessLoaderOptions: {
|
||||
modifyVars: { '@primary-color': '#1DA57A' },
|
||||
javascriptEnabled: true,
|
||||
lessOptions: {
|
||||
modifyVars: { '@primary-color': '#1DA57A' },
|
||||
javascriptEnabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
10
package.json
10
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "antd",
|
||||
"version": "4.3.0",
|
||||
"version": "4.3.1",
|
||||
"description": "An enterprise-class UI design language and React components implementation",
|
||||
"keywords": [
|
||||
"ant",
|
||||
@ -47,7 +47,7 @@
|
||||
"scripts": {
|
||||
"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",
|
||||
"build": "npm run compile && npm run dist",
|
||||
"build": "npm run compile && NODE_OPTIONS='--max-old-space-size=4096' npm run dist",
|
||||
"bundlesize": "bundlesize",
|
||||
"check-commit": "node ./scripts/check-commit",
|
||||
"prestart": "npm run version",
|
||||
@ -73,7 +73,7 @@
|
||||
"lint:md": "remark . -f -q",
|
||||
"lint:script": "eslint . --ext '.js,.jsx,.ts,.tsx'",
|
||||
"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 '**/*'",
|
||||
"pretty-quick": "pretty-quick",
|
||||
"pub": "npm run version && antd-tools run pub",
|
||||
@ -136,14 +136,14 @@
|
||||
"rc-steps": "~4.0.0",
|
||||
"rc-switch": "~3.2.0",
|
||||
"rc-table": "~7.7.2",
|
||||
"rc-tabs": "~11.2.0",
|
||||
"rc-tabs": "~11.3.1",
|
||||
"rc-tooltip": "~4.2.0",
|
||||
"rc-tree": "~3.3.0",
|
||||
"rc-tree-select": "~3.2.0",
|
||||
"rc-trigger": "~4.3.0",
|
||||
"rc-upload": "~3.1.0",
|
||||
"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"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -1,24 +1,37 @@
|
||||
#!/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
|
||||
echo "[TEST ALL] lint" && \
|
||||
npm run lint && \
|
||||
echo "[TEST ALL] dist" && \
|
||||
npm run dist && \
|
||||
echo "[TEST ALL] dekko dist" && \
|
||||
node ./tests/dekko/dist.test.js && \
|
||||
echo "[TEST ALL] dist test" && \
|
||||
LIB_DIR=dist npm test && \
|
||||
echo "[TEST ALL] compile" && \
|
||||
npm run compile && \
|
||||
echo "[TEST ALL] dekko lib" && \
|
||||
node ./tests/dekko/lib.test.js && \
|
||||
echo "[TEST ALL] test es" && \
|
||||
LIB_DIR=es npm test && \
|
||||
echo "[TEST ALL] test lib" && \
|
||||
LIB_DIR=lib npm test && \
|
||||
echo "[TEST ALL] test" && \
|
||||
npm test && \
|
||||
echo "[TEST ALL] test node" && \
|
||||
|
||||
echo "[TEST ALL] lint"
|
||||
npm run lint
|
||||
|
||||
echo "[TEST ALL] dekko dist"
|
||||
node ./tests/dekko/dist.test.js
|
||||
|
||||
echo "[TEST ALL] dist test"
|
||||
LIB_DIR=dist npm test
|
||||
|
||||
echo "[TEST ALL] dekko lib"
|
||||
|
||||
echo "[TEST ALL] test es"
|
||||
LIB_DIR=es npm test
|
||||
|
||||
echo "[TEST ALL] test lib"
|
||||
LIB_DIR=lib npm test
|
||||
|
||||
echo "[TEST ALL] test"
|
||||
npm test
|
||||
|
||||
echo "[TEST ALL] test node"
|
||||
npm run test-node
|
||||
|
@ -217,8 +217,8 @@
|
||||
.highlight {
|
||||
position: relative;
|
||||
|
||||
.ant-tabs-nav-scroll {
|
||||
text-align: center;
|
||||
.ant-tabs-nav-list {
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
pre {
|
||||
|
@ -7,6 +7,13 @@ import { getChildren } from 'jsonml.js/lib/utils';
|
||||
import { getMetaDescription, getLocalizedPathname, getThemeConfig, getMenuItems } from '../utils';
|
||||
import './ComponentOverview.less';
|
||||
|
||||
const onClickCard = href => {
|
||||
window.gtag('event', '点击', {
|
||||
event_category: '组件总览卡片',
|
||||
event_label: href,
|
||||
});
|
||||
};
|
||||
|
||||
const { Title } = Typography;
|
||||
const ComponentOverview = ({
|
||||
componentsData = [],
|
||||
@ -54,9 +61,10 @@ const ComponentOverview = ({
|
||||
const url = `${component.filename
|
||||
.replace(/(\/index)?((\.zh-cn)|(\.en-us))?\.md$/i, '')
|
||||
.toLowerCase()}/`;
|
||||
const href = getLocalizedPathname(url, locale === 'zh-CN');
|
||||
return (
|
||||
<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
|
||||
size="small"
|
||||
className="components-overview-card"
|
||||
|
@ -48,7 +48,7 @@ const MORE_LIST: MoreProps[] = [
|
||||
title: '折柱饼 +3 个套路,简单图表你真的会用吗?',
|
||||
description: '本文一句话概括:数据可视化中,如何用最简单的图表高效地传递信息。',
|
||||
img: 'https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*Q1DMQpLCDQgAAAAAAAAAAABkARQnAQ',
|
||||
date: '2020-11-28',
|
||||
date: '2019-11-28',
|
||||
source: 'zhihu',
|
||||
href: 'https://zhuanlan.zhihu.com/p/93808863',
|
||||
},
|
||||
|
@ -110,7 +110,7 @@ if (process.env.RUN_ENV === 'PRODUCTION') {
|
||||
// Reduce non-minified dist files size
|
||||
config.optimization.usedExports = true;
|
||||
// use esbuild
|
||||
if (process.env.ESBUILD) {
|
||||
if (process.env.ESBUILD || process.env.CSB_REPO) {
|
||||
config.optimization.minimizer[0] = new EsbuildPlugin();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user