mirror of
https://github.com/ant-design/ant-design.git
synced 2025-01-18 22:36:31 +08:00
merge master
This commit is contained in:
commit
1cb346573c
@ -15,6 +15,31 @@ timeline: true
|
||||
|
||||
---
|
||||
|
||||
## 3.21.4
|
||||
|
||||
`2019-08-09`
|
||||
|
||||
- 🐞 Fix the problem that Dropdown.Button requires `title` props.
|
||||
|
||||
## 3.21.3
|
||||
|
||||
`2019-08-09`
|
||||
|
||||
- Timeline
|
||||
- 🐞 Fix the problem that `content` content does not wrap when it is too long. [#18092](https://github.com/ant-design/ant-design/pull/18092) [@xrkffgg](https://github.com/xrkffgg)
|
||||
- 🐞 Fixed inconsistency in styles in `alternate` and `right` modes and width overflow of `content`. [#18093](https://github.com/ant-design/ant-design/pull/18093) [@xrkffgg](https://github.com/xrkffgg)
|
||||
- 🐞 Fix Tabs content with margin collapse with navigation. [#18112](https://github.com/ant-design/ant-design/pull/18112)
|
||||
- 🐞 Fix Textarea `autosize` shows scrollbar after resize. [#18114](https://github.com/ant-design/ant-design/pull/18114)
|
||||
- 🐞 Fix Tooltip not work correctly on `disabled` Checkbox. [#18138](https://github.com/ant-design/ant-design/pull/18138)
|
||||
- 🐞 Fix a Button line-height align issue. [#18139](https://github.com/ant-design/ant-design/pull/18139)
|
||||
- 🐞 Fix missing `blur` and `focus` methods on Mentions. [#18132](https://github.com/ant-design/ant-design/pull/18132) [@yoyo837](https://github.com/yoyo837)
|
||||
- 🐞 Fix missing `title` on Button. [#18130](https://github.com/ant-design/ant-design/pull/18130) [@yoyo837](https://github.com/yoyo837)
|
||||
- 🐞 Fix Upload throw File not defined in IE9. [#18115](https://github.com/ant-design/ant-design/pull/18115)
|
||||
- 🐞 Fix Input clear icon not align correctly. [#18151](https://github.com/ant-design/ant-design/pull/18151)
|
||||
- 🐞 Fix Card broken style when using Button as `actions`. [#18179](https://github.com/ant-design/ant-design/pull/18179)
|
||||
- 🐞 Fix the problem that Modal.confirm can't set `getContainer`. [#18182](https://github.com/ant-design/ant-design/pull/18182)
|
||||
- ⌨️ Improve Divider accessibility by adding role="separator". [#18116](https://github.com/ant-design/ant-design/pull/18116)
|
||||
|
||||
## 3.21.2
|
||||
|
||||
`2019-08-06`
|
||||
|
@ -15,6 +15,31 @@ timeline: true
|
||||
|
||||
---
|
||||
|
||||
## 3.21.4
|
||||
|
||||
`2019-08-09`
|
||||
|
||||
- 🐞 修复 Dropdown.Button 的 `title` 类型。
|
||||
|
||||
## 3.21.3
|
||||
|
||||
`2019-08-09`
|
||||
|
||||
- Timeline
|
||||
- 🐞 修复 `content` 内容连续过长时不换行的问题。[#18092](https://github.com/ant-design/ant-design/pull/18092) [@xrkffgg](https://github.com/xrkffgg)
|
||||
- 🐞 修复 `alternate` 和 `right` 模式下样式不一致和 `content` 的宽度溢出的问题。 [#18093](https://github.com/ant-design/ant-design/pull/18093) [@xrkffgg](https://github.com/xrkffgg)
|
||||
- 🐞 修复 Tabs 内容带有 margin 时会与标题相互作用的问题。[#18112](https://github.com/ant-design/ant-design/pull/18112)
|
||||
- 🐞 修复 Textarea `autosize` 在调整尺寸后仍然显示滚动条的问题。[#18114](https://github.com/ant-design/ant-design/pull/18114)
|
||||
- 🐞 修复 Tooltip 在 `disabled` Checkbox 上不能正确工作的问题。[#18138](https://github.com/ant-design/ant-design/pull/18138)
|
||||
- 🐞 修复 Button 的行高对齐问题。[#18139](https://github.com/ant-design/ant-design/pull/18139)
|
||||
- 🐞 修复 Mentions 没有 `blur` 和 `focus` 方法的问题。[#18132](https://github.com/ant-design/ant-design/pull/18132) [@yoyo837](https://github.com/yoyo837)
|
||||
- 🐞 修复 Button 无法设置 `title` 的问题。[#18130](https://github.com/ant-design/ant-design/pull/18130) [@yoyo837](https://github.com/yoyo837)
|
||||
- 🐞 修复 Upload 在 IE9 下报 File 未定义的问题。[#18115](https://github.com/ant-design/ant-design/pull/18115)
|
||||
- 🐞 修复 Input 清除图标不居中对齐的问题。[#18151](https://github.com/ant-design/ant-design/pull/18151)
|
||||
- 🐞 修复 Card `actions` 内使用 Button 的样式问题。[#18179](https://github.com/ant-design/ant-design/pull/18179)
|
||||
- 🐞 修复 Modal.confirm 无法设置 `getContainer` 的问题。[#18182](https://github.com/ant-design/ant-design/pull/18182)
|
||||
- ⌨️ 增强 Divider 可访问性支持。[#18116](https://github.com/ant-design/ant-design/pull/18116)
|
||||
|
||||
## 3.21.2
|
||||
|
||||
`2019-08-06`
|
||||
|
@ -1,31 +1,11 @@
|
||||
import * as React from 'react';
|
||||
import * as ReactDOM from 'react-dom';
|
||||
|
||||
export interface InputElementProps {
|
||||
children: React.ReactElement<any>;
|
||||
}
|
||||
|
||||
export default class InputElement extends React.Component<InputElementProps, any> {
|
||||
private ele: HTMLInputElement;
|
||||
|
||||
focus = () => {
|
||||
if (this.ele.focus) {
|
||||
this.ele.focus();
|
||||
} else {
|
||||
(ReactDOM.findDOMNode(this.ele) as HTMLInputElement).focus();
|
||||
}
|
||||
};
|
||||
|
||||
blur = () => {
|
||||
if (this.ele.blur) {
|
||||
this.ele.blur();
|
||||
} else {
|
||||
(ReactDOM.findDOMNode(this.ele) as HTMLInputElement).blur();
|
||||
}
|
||||
};
|
||||
|
||||
saveRef = (ele: HTMLInputElement) => {
|
||||
this.ele = ele;
|
||||
const { ref: childRef } = this.props.children as any;
|
||||
if (typeof childRef === 'function') {
|
||||
childRef(ele);
|
||||
|
@ -52,4 +52,29 @@ describe('AutoComplete children could be focus', () => {
|
||||
jest.runAllTimers();
|
||||
expect(handleBlur).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('child.ref should work', () => {
|
||||
const mockRef = jest.fn();
|
||||
mount(
|
||||
<AutoComplete dataSource={[]}>
|
||||
<input ref={mockRef} />
|
||||
</AutoComplete>,
|
||||
);
|
||||
expect(mockRef).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('child.ref instance should support be focused and blured', () => {
|
||||
let inputRef;
|
||||
mount(
|
||||
<AutoComplete dataSource={[]}>
|
||||
<input
|
||||
ref={node => {
|
||||
inputRef = node;
|
||||
}}
|
||||
/>
|
||||
</AutoComplete>,
|
||||
);
|
||||
expect(typeof inputRef.focus).toBe('function');
|
||||
expect(typeof inputRef.blur).toBe('function');
|
||||
});
|
||||
});
|
||||
|
@ -23,13 +23,35 @@ describe('AutoComplete with Custom Input Element Render', () => {
|
||||
expect(dropdownWrapper.find('MenuItem').length).toBe(3);
|
||||
});
|
||||
|
||||
it('child.ref should work', () => {
|
||||
const mockRef = jest.fn();
|
||||
mount(
|
||||
<AutoComplete dataSource={[]}>
|
||||
<input ref={mockRef} />
|
||||
it('AutoComplete should work when dataSource is object array', () => {
|
||||
const wrapper = mount(
|
||||
<AutoComplete dataSource={[{ text: 'text', value: 'value' }, { text: 'abc', value: 'xxx' }]}>
|
||||
<input />
|
||||
</AutoComplete>,
|
||||
);
|
||||
expect(mockRef).toHaveBeenCalled();
|
||||
expect(wrapper.find('input').length).toBe(1);
|
||||
wrapper.find('input').simulate('change', { target: { value: 'a' } });
|
||||
const dropdownWrapper = mount(
|
||||
wrapper
|
||||
.find('Trigger')
|
||||
.instance()
|
||||
.getComponent(),
|
||||
);
|
||||
|
||||
// should not filter data source defaultly
|
||||
expect(dropdownWrapper.find('MenuItem').length).toBe(2);
|
||||
});
|
||||
|
||||
it('AutoComplete throws error when contains invalid dataSource', () => {
|
||||
jest.spyOn(console, 'error').mockImplementation(() => undefined);
|
||||
expect(() => {
|
||||
mount(
|
||||
<AutoComplete dataSource={[() => {}]}>
|
||||
<textarea />
|
||||
</AutoComplete>,
|
||||
);
|
||||
}).toThrow();
|
||||
// eslint-disable-next-line no-console
|
||||
console.error.mockRestore();
|
||||
});
|
||||
});
|
||||
|
@ -23,8 +23,8 @@ const dataSource = ['12345', '23456', '34567'];
|
||||
| allowClear | Show clear button, effective in multiple mode only. | boolean | false | |
|
||||
| autoFocus | get focus when component mounted | boolean | false | |
|
||||
| backfill | backfill selected item the input when using keyboard | boolean | false | |
|
||||
| children (for customize input element) | customize input element | HTMLInputElement / HTMLTextAreaElement / React.ReactElement<InputProps> | `<Input />` | |
|
||||
| children (for dataSource) | Data source for autocomplete | React.ReactElement<OptionProps> / Array<React.ReactElement<OptionProps>> | - | |
|
||||
| children (for customize input element) | customize input element | HTMLInputElement <br /><br /> HTMLTextAreaElement <br /><br /> `React.ReactElement<InputProps>` | `<Input />` | |
|
||||
| children (for dataSource) | Data source to auto complete | `React.ReactElement<OptionProps>` <br /><br /> `Array<React.ReactElement<OptionProps>>` | - | |
|
||||
| dataSource | Data source for autocomplete | [DataSourceItemType](https://git.io/vMMKF)\[] | - | |
|
||||
| defaultActiveFirstOption | Whether active first option by default | boolean | true | |
|
||||
| defaultValue | Initial selected option. | string\|string\[] | - | |
|
||||
|
@ -24,8 +24,8 @@ const dataSource = ['12345', '23456', '34567'];
|
||||
| allowClear | 支持清除, 单选模式有效 | boolean | false | |
|
||||
| autoFocus | 自动获取焦点 | boolean | false | |
|
||||
| backfill | 使用键盘选择选项的时候把选中项回填到输入框中 | boolean | false | |
|
||||
| children (自动完成的数据源) | 自动完成的数据源 | React.ReactElement<OptionProps> / Array<React.ReactElement<OptionProps>> | - | | |
|
||||
| children (自定义输入框) | 自定义输入框 | HTMLInputElement / HTMLTextAreaElement / React.ReactElement<InputProps> | `<Input />` | @todo.muyu |
|
||||
| children (自定义输入框) | 自定义输入框 | HTMLInputElement <br /><br /> HTMLTextAreaElement <br /><br /> `React.ReactElement<InputProps>` | `<Input />` | |
|
||||
| children (自动完成的数据源) | 自动完成的数据源 | `React.ReactElement<OptionProps>` <br /><br /> `Array<React.ReactElement<OptionProps>>` | - | |
|
||||
| dataSource | 自动完成的数据源 | [DataSourceItemType](https://git.io/vMMKF)\[] | | |
|
||||
| defaultActiveFirstOption | 是否默认高亮第一个选项。 | boolean | true | |
|
||||
| defaultValue | 指定默认选中的条目 | string\|string\[]\| 无 | |
|
||||
|
@ -131,6 +131,7 @@ class Button extends React.Component<ButtonProps, ButtonState> {
|
||||
className: PropTypes.string,
|
||||
icon: PropTypes.string,
|
||||
block: PropTypes.bool,
|
||||
title: PropTypes.string,
|
||||
};
|
||||
|
||||
static getDerivedStateFromProps(nextProps: ButtonProps, prevState: ButtonState) {
|
||||
@ -270,7 +271,7 @@ class Button extends React.Component<ButtonProps, ButtonState> {
|
||||
? spaceChildren(children, this.isNeedInserted() && autoInsertSpace)
|
||||
: null;
|
||||
|
||||
const linkButtonRestProps = omit(rest as AnchorButtonProps, ['htmlType']);
|
||||
const linkButtonRestProps = omit(rest as AnchorButtonProps, ['htmlType', 'loading']);
|
||||
if (linkButtonRestProps.href !== undefined) {
|
||||
return (
|
||||
<a
|
||||
|
@ -11,7 +11,7 @@ title:
|
||||
|
||||
## en-US
|
||||
|
||||
`ghost` property will make button's background transparent, it is common used in colored background.
|
||||
`ghost` property will make button's background transparent, it is commonly used in colored background.
|
||||
|
||||
```jsx
|
||||
import { Button } from 'antd';
|
||||
|
@ -12,10 +12,7 @@
|
||||
// Button styles
|
||||
// -----------------------------
|
||||
.@{btn-prefix-cls} {
|
||||
// Fixing https://github.com/ant-design/ant-design/issues/12978
|
||||
// It is a render problem of chrome, which is only happened in the codesandbox demo
|
||||
// 0.001px solution works and I don't why
|
||||
line-height: @line-height-base - 0.001;
|
||||
line-height: @line-height-base;
|
||||
.btn;
|
||||
.btn-default;
|
||||
|
||||
@ -196,7 +193,12 @@
|
||||
}
|
||||
|
||||
a.@{btn-prefix-cls} {
|
||||
// Fixing https://github.com/ant-design/ant-design/issues/12978
|
||||
// It is a render problem of chrome, which is only happened in the codesandbox demo
|
||||
// 0.1px for padding-top solution works and I don't why
|
||||
padding-top: 0.1px;
|
||||
line-height: @btn-height-base - 2px;
|
||||
|
||||
&-lg {
|
||||
line-height: @btn-height-lg - 2px;
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
@card-prefix-cls: ~'@{ant-prefix}-card';
|
||||
@card-head-height: 48px;
|
||||
@card-hover-border: fade(@black, 9%);
|
||||
@card-action-icon-size: 16px;
|
||||
|
||||
@gradient-min: fade(@card-background, 20%);
|
||||
@gradient-max: fade(@card-background, 40%);
|
||||
@ -137,7 +138,7 @@
|
||||
color: @text-color-secondary;
|
||||
text-align: center;
|
||||
|
||||
& > span {
|
||||
> span {
|
||||
position: relative;
|
||||
display: block;
|
||||
min-width: 32px;
|
||||
@ -150,23 +151,23 @@
|
||||
transition: color 0.3s;
|
||||
}
|
||||
|
||||
& > .anticon {
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
a,
|
||||
i {
|
||||
> .anticon {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
color: @text-color-secondary;
|
||||
line-height: 22px;
|
||||
transition: color 0.3s;
|
||||
|
||||
&:hover {
|
||||
color: @primary-color;
|
||||
transition: color 0.3s;
|
||||
}
|
||||
}
|
||||
|
||||
> .anticon {
|
||||
font-size: @card-action-icon-size;
|
||||
line-height: 22px;
|
||||
}
|
||||
}
|
||||
|
||||
&:not(:last-child) {
|
||||
|
@ -496,7 +496,7 @@ class Cascader extends React.Component<CascaderProps, CascaderState> {
|
||||
]);
|
||||
|
||||
let { options } = props;
|
||||
if (options.length > 0) {
|
||||
if (options && options.length > 0) {
|
||||
if (state.inputValue) {
|
||||
options = this.generateFilteredOptions(prefixCls, renderEmpty);
|
||||
}
|
||||
|
@ -46,6 +46,8 @@ export interface CheckboxChangeEvent {
|
||||
class Checkbox extends React.Component<CheckboxProps, {}> {
|
||||
static Group: typeof CheckboxGroup;
|
||||
|
||||
static __ANT_CHECKBOX = true;
|
||||
|
||||
static defaultProps = {
|
||||
indeterminate: false,
|
||||
};
|
||||
|
@ -6750,18 +6750,21 @@ exports[`ConfigProvider components DatePicker WeekPicker prefixCls 1`] = `
|
||||
exports[`ConfigProvider components Divider configProvider 1`] = `
|
||||
<div
|
||||
class="config-divider config-divider-horizontal"
|
||||
role="separator"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`ConfigProvider components Divider normal 1`] = `
|
||||
<div
|
||||
class="ant-divider ant-divider-horizontal"
|
||||
role="separator"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`ConfigProvider components Divider prefixCls 1`] = `
|
||||
<div
|
||||
class="prefix-Divider prefix-Divider-horizontal"
|
||||
role="separator"
|
||||
/>
|
||||
`;
|
||||
|
||||
|
@ -56,7 +56,7 @@ export interface DatePickerProps extends PickerProps, SinglePickerProps {
|
||||
}
|
||||
|
||||
export interface MonthPickerProps extends PickerProps, SinglePickerProps {
|
||||
// - currently no own props -
|
||||
monthCellContentRender?: (date: moment.Moment, locale: any) => React.ReactNode;
|
||||
}
|
||||
|
||||
export type RangePickerValue =
|
||||
|
@ -4,18 +4,22 @@ exports[`renders ./components/divider/demo/customize-style.md correctly 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="ant-divider ant-divider-horizontal"
|
||||
role="separator"
|
||||
style="height:2px;background-color:#7cb305"
|
||||
/>
|
||||
<div
|
||||
class="ant-divider ant-divider-horizontal ant-divider-dashed"
|
||||
role="separator"
|
||||
style="border-color:#7cb305"
|
||||
/>
|
||||
<div
|
||||
class="ant-divider ant-divider-vertical"
|
||||
role="separator"
|
||||
style="height:60px;background-color:#7cb305"
|
||||
/>
|
||||
<div
|
||||
class="ant-divider ant-divider-vertical ant-divider-dashed"
|
||||
role="separator"
|
||||
style="height:60px;border-color:#7cb305"
|
||||
/>
|
||||
</div>
|
||||
@ -28,12 +32,14 @@ exports[`renders ./components/divider/demo/horizontal.md correctly 1`] = `
|
||||
</p>
|
||||
<div
|
||||
class="ant-divider ant-divider-horizontal"
|
||||
role="separator"
|
||||
/>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
</p>
|
||||
<div
|
||||
class="ant-divider ant-divider-horizontal ant-divider-dashed"
|
||||
role="separator"
|
||||
/>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
@ -46,6 +52,7 @@ exports[`renders ./components/divider/demo/vertical.md correctly 1`] = `
|
||||
Text
|
||||
<div
|
||||
class="ant-divider ant-divider-vertical"
|
||||
role="separator"
|
||||
/>
|
||||
<a
|
||||
href="#"
|
||||
@ -54,6 +61,7 @@ exports[`renders ./components/divider/demo/vertical.md correctly 1`] = `
|
||||
</a>
|
||||
<div
|
||||
class="ant-divider ant-divider-vertical"
|
||||
role="separator"
|
||||
/>
|
||||
<a
|
||||
href="#"
|
||||
@ -70,6 +78,7 @@ exports[`renders ./components/divider/demo/with-text.md correctly 1`] = `
|
||||
</p>
|
||||
<div
|
||||
class="ant-divider ant-divider-horizontal ant-divider-with-text-center"
|
||||
role="separator"
|
||||
>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
@ -82,6 +91,7 @@ exports[`renders ./components/divider/demo/with-text.md correctly 1`] = `
|
||||
</p>
|
||||
<div
|
||||
class="ant-divider ant-divider-horizontal ant-divider-with-text-left"
|
||||
role="separator"
|
||||
>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
@ -94,6 +104,7 @@ exports[`renders ./components/divider/demo/with-text.md correctly 1`] = `
|
||||
</p>
|
||||
<div
|
||||
class="ant-divider ant-divider-horizontal ant-divider-with-text-right"
|
||||
role="separator"
|
||||
>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
|
@ -31,7 +31,7 @@ const Divider: React.SFC<DividerProps> = props => (
|
||||
[`${prefixCls}-dashed`]: !!dashed,
|
||||
});
|
||||
return (
|
||||
<div className={classString} {...restProps}>
|
||||
<div className={classString} {...restProps} role="separator">
|
||||
{children && <span className={`${prefixCls}-inner-text`}>{children}</span>}
|
||||
</div>
|
||||
);
|
||||
|
@ -156,6 +156,69 @@ exports[`renders ./components/drawer/demo/placement.md correctly 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/drawer/demo/render-in-current.md correctly 1`] = `
|
||||
<div
|
||||
style="height:200px;overflow:hidden;position:relative;border:1px solid #ebedf0;border-radius:2px;padding:48px;text-align:center;background:#fafafa"
|
||||
>
|
||||
Render in this
|
||||
<div
|
||||
style="margin-top:16px"
|
||||
>
|
||||
<button
|
||||
class="ant-btn ant-btn-primary"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Open
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class=""
|
||||
>
|
||||
<div
|
||||
class="ant-drawer ant-drawer-right"
|
||||
style="position:absolute"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="ant-drawer-mask"
|
||||
/>
|
||||
<div
|
||||
class="ant-drawer-content-wrapper"
|
||||
style="transform:translateX(100%);-ms-transform:translateX(100%);width:256px"
|
||||
>
|
||||
<div
|
||||
class="ant-drawer-content"
|
||||
>
|
||||
<div
|
||||
class="ant-drawer-wrapper-body"
|
||||
style="overflow:auto;height:100%"
|
||||
>
|
||||
<div
|
||||
class="ant-drawer-header"
|
||||
>
|
||||
<div
|
||||
class="ant-drawer-title"
|
||||
>
|
||||
Basic Drawer
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-drawer-body"
|
||||
>
|
||||
<p>
|
||||
Some contents...
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/drawer/demo/user-profile.md correctly 1`] = `
|
||||
<div>
|
||||
<div
|
||||
|
71
components/drawer/demo/render-in-current.md
Normal file
71
components/drawer/demo/render-in-current.md
Normal file
@ -0,0 +1,71 @@
|
||||
---
|
||||
order: 2
|
||||
title:
|
||||
zh-CN: 渲染在当前 DOM
|
||||
en-US: Render in current dom
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
渲染在当前 dom 里。自定义容器,查看 getContainer。
|
||||
|
||||
## en-US
|
||||
|
||||
Render in current dom. custom container, check getContainer.
|
||||
|
||||
```jsx
|
||||
import { Drawer, Button } from 'antd';
|
||||
|
||||
class App extends React.Component {
|
||||
state = { visible: false };
|
||||
|
||||
showDrawer = () => {
|
||||
this.setState({
|
||||
visible: true,
|
||||
});
|
||||
};
|
||||
|
||||
onClose = () => {
|
||||
this.setState({
|
||||
visible: false,
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
height: 200,
|
||||
overflow: 'hidden',
|
||||
position: 'relative',
|
||||
border: '1px solid #ebedf0',
|
||||
borderRadius: 2,
|
||||
padding: 48,
|
||||
textAlign: 'center',
|
||||
background: '#fafafa',
|
||||
}}
|
||||
>
|
||||
Render in this
|
||||
<div style={{ marginTop: 16 }}>
|
||||
<Button type="primary" onClick={this.showDrawer}>
|
||||
Open
|
||||
</Button>
|
||||
</div>
|
||||
<Drawer
|
||||
title="Basic Drawer"
|
||||
placement="right"
|
||||
closable={false}
|
||||
onClose={this.onClose}
|
||||
visible={this.state.visible}
|
||||
getContainer={false}
|
||||
style={{ position: 'absolute' }}
|
||||
>
|
||||
<p>Some contents...</p>
|
||||
</Drawer>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ReactDOM.render(<App />, mountNode);
|
||||
```
|
@ -11,14 +11,15 @@
|
||||
z-index: @zindex-modal;
|
||||
width: 0%;
|
||||
height: 100%;
|
||||
transition: transform @animation-duration-slow @ease-base-out;
|
||||
transition: transform @animation-duration-slow @ease-base-out,
|
||||
height 0s ease @animation-duration-slow, width 0s ease @animation-duration-slow;
|
||||
> * {
|
||||
transition: transform @animation-duration-slow @ease-base-out,
|
||||
box-shadow @animation-duration-slow @ease-base-out;
|
||||
}
|
||||
|
||||
&-content-wrapper {
|
||||
position: fixed;
|
||||
position: absolute;
|
||||
}
|
||||
.@{drawer-prefix-cls}-content {
|
||||
width: 100%;
|
||||
@ -35,6 +36,7 @@
|
||||
}
|
||||
&.@{drawer-prefix-cls}-open {
|
||||
width: 100%;
|
||||
transition: transform @animation-duration-slow @ease-base-out;
|
||||
}
|
||||
&.@{drawer-prefix-cls}-open.no-mask {
|
||||
width: 0%;
|
||||
@ -75,6 +77,7 @@
|
||||
}
|
||||
&.@{drawer-prefix-cls}-open {
|
||||
height: 100%;
|
||||
transition: transform @animation-duration-slow @ease-base-out;
|
||||
}
|
||||
&.@{drawer-prefix-cls}-open.no-mask {
|
||||
height: 0%;
|
||||
@ -186,7 +189,7 @@
|
||||
}
|
||||
|
||||
&-mask {
|
||||
position: fixed;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
|
@ -22,6 +22,7 @@ export interface DropdownButtonProps extends ButtonGroupProps, DropDownProps {
|
||||
icon?: React.ReactNode;
|
||||
href?: string;
|
||||
children?: React.ReactNode;
|
||||
title?: string;
|
||||
}
|
||||
|
||||
export default class DropdownButton extends React.Component<DropdownButtonProps, any> {
|
||||
@ -51,6 +52,7 @@ export default class DropdownButton extends React.Component<DropdownButtonProps,
|
||||
getPopupContainer,
|
||||
href,
|
||||
icon = <Icon type="ellipsis" />,
|
||||
title,
|
||||
...restProps
|
||||
} = this.props;
|
||||
|
||||
@ -70,7 +72,14 @@ export default class DropdownButton extends React.Component<DropdownButtonProps,
|
||||
|
||||
return (
|
||||
<ButtonGroup {...restProps} className={classNames(prefixCls, className)}>
|
||||
<Button type={type} disabled={disabled} onClick={onClick} htmlType={htmlType} href={href}>
|
||||
<Button
|
||||
type={type}
|
||||
disabled={disabled}
|
||||
onClick={onClick}
|
||||
htmlType={htmlType}
|
||||
href={href}
|
||||
title={title}
|
||||
>
|
||||
{children}
|
||||
</Button>
|
||||
<Dropdown {...dropdownProps}>
|
||||
|
@ -91,6 +91,7 @@ exports[`renders ./components/empty/demo/config-provider.md correctly 1`] = `
|
||||
</button>
|
||||
<div
|
||||
class="ant-divider ant-divider-horizontal"
|
||||
role="separator"
|
||||
/>
|
||||
<div
|
||||
class="config-provider"
|
||||
|
@ -1207,7 +1207,7 @@ exports[`renders ./components/form/demo/global-state.md correctly 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/form/demo/horizontal-login.md correctly 1`] = `
|
||||
exports[`renders ./components/form/demo/inline-login.md correctly 1`] = `
|
||||
<form
|
||||
class="ant-form ant-form-inline"
|
||||
id="horizontal_login"
|
||||
|
@ -1,17 +1,17 @@
|
||||
---
|
||||
order: 10
|
||||
title:
|
||||
zh-CN: 水平登录栏
|
||||
en-US: Horizontal Login Form
|
||||
zh-CN: 内联登录栏
|
||||
en-US: Inline Login Form
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
水平登录栏,常用在顶部导航栏中。
|
||||
内联登录栏,常用在顶部导航栏中。
|
||||
|
||||
## en-US
|
||||
|
||||
Horizontal login form is often used in navigation bar.
|
||||
Inline login form is often used in navigation bar.
|
||||
|
||||
```tsx
|
||||
import { Form, Icon, Input, Button } from 'antd';
|
@ -44,7 +44,9 @@
|
||||
.@{ant-prefix}-input-clear-icon {
|
||||
color: @disabled-color;
|
||||
font-size: @font-size-sm;
|
||||
vertical-align: top;
|
||||
// https://github.com/ant-design/ant-design/pull/18151
|
||||
// https://codesandbox.io/s/wizardly-sun-u10br
|
||||
vertical-align: 0;
|
||||
cursor: pointer;
|
||||
transition: color 0.3s;
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import Mentions from '..';
|
||||
import focusTest from '../../../tests/shared/focusTest';
|
||||
|
||||
const { getMentions } = Mentions;
|
||||
|
||||
@ -71,6 +72,8 @@ describe('Mentions', () => {
|
||||
expect(onBlur).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
focusTest(Mentions);
|
||||
|
||||
it('loading', () => {
|
||||
const wrapper = mount(<Mentions loading />);
|
||||
simulateInput(wrapper, '@');
|
||||
|
@ -75,6 +75,8 @@ class Mentions extends React.Component<MentionProps, MentionState> {
|
||||
focused: false,
|
||||
};
|
||||
|
||||
private rcMentions: any;
|
||||
|
||||
onFocus: React.FocusEventHandler<HTMLTextAreaElement> = (...args) => {
|
||||
const { onFocus } = this.props;
|
||||
if (onFocus) {
|
||||
@ -125,6 +127,18 @@ class Mentions extends React.Component<MentionProps, MentionState> {
|
||||
return filterOption;
|
||||
};
|
||||
|
||||
saveMentions = (node: typeof RcMentions) => {
|
||||
this.rcMentions = node;
|
||||
};
|
||||
|
||||
focus() {
|
||||
this.rcMentions.focus();
|
||||
}
|
||||
|
||||
blur() {
|
||||
this.rcMentions.blur();
|
||||
}
|
||||
|
||||
renderMentions = ({ getPrefixCls, renderEmpty }: ConfigConsumerProps) => {
|
||||
const { focused } = this.state;
|
||||
const { prefixCls: customizePrefixCls, className, disabled, ...restProps } = this.props;
|
||||
@ -146,6 +160,7 @@ class Mentions extends React.Component<MentionProps, MentionState> {
|
||||
filterOption={this.getFilterOption()}
|
||||
onFocus={this.onFocus}
|
||||
onBlur={this.onBlur}
|
||||
ref={this.saveMentions}
|
||||
>
|
||||
{this.getOptions()}
|
||||
</RcMentions>
|
||||
|
@ -139,7 +139,7 @@ export default function confirm(config: ModalFuncProps) {
|
||||
}
|
||||
|
||||
function render(props: any) {
|
||||
ReactDOM.render(<ConfirmDialog {...props} getContainer={false} />, div);
|
||||
ReactDOM.render(<ConfirmDialog getContainer={false} {...props} />, div);
|
||||
}
|
||||
|
||||
function close(...args: any[]) {
|
||||
|
@ -36,6 +36,7 @@ exports[`renders ./components/page-header/demo/actions.md correctly 1`] = `
|
||||
</div>
|
||||
<div
|
||||
class="ant-divider ant-divider-vertical"
|
||||
role="separator"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
@ -445,6 +446,7 @@ exports[`renders ./components/page-header/demo/basic.md correctly 1`] = `
|
||||
</div>
|
||||
<div
|
||||
class="ant-divider ant-divider-vertical"
|
||||
role="separator"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
|
@ -31,7 +31,7 @@ A long list can be divided into several pages by `Pagination`, and only one page
|
||||
| showLessItems | show less page items | boolean | false | 3.16.3 |
|
||||
| showQuickJumper | determine whether you can jump to pages directly | boolean \| `{ goButton: ReactNode }` | false | |
|
||||
| showSizeChanger | determine whether `pageSize` can be changed | boolean | false | |
|
||||
| showTitle | show page items title | boolean | true | 3.19.3 |
|
||||
| showTitle | show page items title | boolean | true | |
|
||||
| showTotal | to display the total number and range | Function(total, range) | - | |
|
||||
| simple | whether to use simple mode | boolean | - | |
|
||||
| size | specify the size of `Pagination`, can be set to `small` | string | "" | |
|
||||
|
@ -24,7 +24,7 @@ cols: 1
|
||||
| current | 当前页数 | number | - | |
|
||||
| defaultCurrent | 默认的当前页数 | number | 1 | |
|
||||
| defaultPageSize | 默认的每页条数 | number | 10 | |
|
||||
| disabled | 禁用分页 | boolean | - | 3.10.0 | 3.18.0 |
|
||||
| disabled | 禁用分页 | boolean | - | 3.18.0 |
|
||||
| hideOnSinglePage | 只有一页时是否隐藏分页器 | boolean | false | 3.1.0 |
|
||||
| itemRender | 用于自定义页码的结构,可用于优化 SEO | (page, type: 'page' \| 'prev' \| 'next', originalElement) => React.ReactNode | - | |
|
||||
| pageSize | 每页条数 | number | - | |
|
||||
|
@ -104,6 +104,7 @@ exports[`renders ./components/steps/demo/clickable.md correctly 1`] = `
|
||||
</div>
|
||||
<div
|
||||
class="ant-divider ant-divider-horizontal"
|
||||
role="separator"
|
||||
/>
|
||||
<div
|
||||
class="ant-steps ant-steps-vertical"
|
||||
|
@ -397,6 +397,7 @@ exports[`renders ./components/table/demo/basic.md correctly 1`] = `
|
||||
</a>
|
||||
<div
|
||||
class="ant-divider ant-divider-vertical"
|
||||
role="separator"
|
||||
/>
|
||||
<a
|
||||
href="javascript:;"
|
||||
@ -451,6 +452,7 @@ exports[`renders ./components/table/demo/basic.md correctly 1`] = `
|
||||
</a>
|
||||
<div
|
||||
class="ant-divider ant-divider-vertical"
|
||||
role="separator"
|
||||
/>
|
||||
<a
|
||||
href="javascript:;"
|
||||
@ -510,6 +512,7 @@ exports[`renders ./components/table/demo/basic.md correctly 1`] = `
|
||||
</a>
|
||||
<div
|
||||
class="ant-divider ant-divider-vertical"
|
||||
role="separator"
|
||||
/>
|
||||
<a
|
||||
href="javascript:;"
|
||||
@ -2540,6 +2543,7 @@ exports[`renders ./components/table/demo/dynamic-settings.md correctly 1`] = `
|
||||
</a>
|
||||
<div
|
||||
class="ant-divider ant-divider-vertical"
|
||||
role="separator"
|
||||
/>
|
||||
<a
|
||||
href="javascript:;"
|
||||
@ -2548,6 +2552,7 @@ exports[`renders ./components/table/demo/dynamic-settings.md correctly 1`] = `
|
||||
</a>
|
||||
<div
|
||||
class="ant-divider ant-divider-vertical"
|
||||
role="separator"
|
||||
/>
|
||||
<a
|
||||
class="ant-dropdown-link"
|
||||
@ -2642,6 +2647,7 @@ exports[`renders ./components/table/demo/dynamic-settings.md correctly 1`] = `
|
||||
</a>
|
||||
<div
|
||||
class="ant-divider ant-divider-vertical"
|
||||
role="separator"
|
||||
/>
|
||||
<a
|
||||
href="javascript:;"
|
||||
@ -2650,6 +2656,7 @@ exports[`renders ./components/table/demo/dynamic-settings.md correctly 1`] = `
|
||||
</a>
|
||||
<div
|
||||
class="ant-divider ant-divider-vertical"
|
||||
role="separator"
|
||||
/>
|
||||
<a
|
||||
class="ant-dropdown-link"
|
||||
@ -2744,6 +2751,7 @@ exports[`renders ./components/table/demo/dynamic-settings.md correctly 1`] = `
|
||||
</a>
|
||||
<div
|
||||
class="ant-divider ant-divider-vertical"
|
||||
role="separator"
|
||||
/>
|
||||
<a
|
||||
href="javascript:;"
|
||||
@ -2752,6 +2760,7 @@ exports[`renders ./components/table/demo/dynamic-settings.md correctly 1`] = `
|
||||
</a>
|
||||
<div
|
||||
class="ant-divider ant-divider-vertical"
|
||||
role="separator"
|
||||
/>
|
||||
<a
|
||||
class="ant-dropdown-link"
|
||||
@ -2846,6 +2855,7 @@ exports[`renders ./components/table/demo/dynamic-settings.md correctly 1`] = `
|
||||
</a>
|
||||
<div
|
||||
class="ant-divider ant-divider-vertical"
|
||||
role="separator"
|
||||
/>
|
||||
<a
|
||||
href="javascript:;"
|
||||
@ -2854,6 +2864,7 @@ exports[`renders ./components/table/demo/dynamic-settings.md correctly 1`] = `
|
||||
</a>
|
||||
<div
|
||||
class="ant-divider ant-divider-vertical"
|
||||
role="separator"
|
||||
/>
|
||||
<a
|
||||
class="ant-dropdown-link"
|
||||
@ -2948,6 +2959,7 @@ exports[`renders ./components/table/demo/dynamic-settings.md correctly 1`] = `
|
||||
</a>
|
||||
<div
|
||||
class="ant-divider ant-divider-vertical"
|
||||
role="separator"
|
||||
/>
|
||||
<a
|
||||
href="javascript:;"
|
||||
@ -2956,6 +2968,7 @@ exports[`renders ./components/table/demo/dynamic-settings.md correctly 1`] = `
|
||||
</a>
|
||||
<div
|
||||
class="ant-divider ant-divider-vertical"
|
||||
role="separator"
|
||||
/>
|
||||
<a
|
||||
class="ant-dropdown-link"
|
||||
@ -3050,6 +3063,7 @@ exports[`renders ./components/table/demo/dynamic-settings.md correctly 1`] = `
|
||||
</a>
|
||||
<div
|
||||
class="ant-divider ant-divider-vertical"
|
||||
role="separator"
|
||||
/>
|
||||
<a
|
||||
href="javascript:;"
|
||||
@ -3058,6 +3072,7 @@ exports[`renders ./components/table/demo/dynamic-settings.md correctly 1`] = `
|
||||
</a>
|
||||
<div
|
||||
class="ant-divider ant-divider-vertical"
|
||||
role="separator"
|
||||
/>
|
||||
<a
|
||||
class="ant-dropdown-link"
|
||||
@ -3152,6 +3167,7 @@ exports[`renders ./components/table/demo/dynamic-settings.md correctly 1`] = `
|
||||
</a>
|
||||
<div
|
||||
class="ant-divider ant-divider-vertical"
|
||||
role="separator"
|
||||
/>
|
||||
<a
|
||||
href="javascript:;"
|
||||
@ -3160,6 +3176,7 @@ exports[`renders ./components/table/demo/dynamic-settings.md correctly 1`] = `
|
||||
</a>
|
||||
<div
|
||||
class="ant-divider ant-divider-vertical"
|
||||
role="separator"
|
||||
/>
|
||||
<a
|
||||
class="ant-dropdown-link"
|
||||
@ -3254,6 +3271,7 @@ exports[`renders ./components/table/demo/dynamic-settings.md correctly 1`] = `
|
||||
</a>
|
||||
<div
|
||||
class="ant-divider ant-divider-vertical"
|
||||
role="separator"
|
||||
/>
|
||||
<a
|
||||
href="javascript:;"
|
||||
@ -3262,6 +3280,7 @@ exports[`renders ./components/table/demo/dynamic-settings.md correctly 1`] = `
|
||||
</a>
|
||||
<div
|
||||
class="ant-divider ant-divider-vertical"
|
||||
role="separator"
|
||||
/>
|
||||
<a
|
||||
class="ant-dropdown-link"
|
||||
@ -3356,6 +3375,7 @@ exports[`renders ./components/table/demo/dynamic-settings.md correctly 1`] = `
|
||||
</a>
|
||||
<div
|
||||
class="ant-divider ant-divider-vertical"
|
||||
role="separator"
|
||||
/>
|
||||
<a
|
||||
href="javascript:;"
|
||||
@ -3364,6 +3384,7 @@ exports[`renders ./components/table/demo/dynamic-settings.md correctly 1`] = `
|
||||
</a>
|
||||
<div
|
||||
class="ant-divider ant-divider-vertical"
|
||||
role="separator"
|
||||
/>
|
||||
<a
|
||||
class="ant-dropdown-link"
|
||||
@ -3458,6 +3479,7 @@ exports[`renders ./components/table/demo/dynamic-settings.md correctly 1`] = `
|
||||
</a>
|
||||
<div
|
||||
class="ant-divider ant-divider-vertical"
|
||||
role="separator"
|
||||
/>
|
||||
<a
|
||||
href="javascript:;"
|
||||
@ -3466,6 +3488,7 @@ exports[`renders ./components/table/demo/dynamic-settings.md correctly 1`] = `
|
||||
</a>
|
||||
<div
|
||||
class="ant-divider ant-divider-vertical"
|
||||
role="separator"
|
||||
/>
|
||||
<a
|
||||
class="ant-dropdown-link"
|
||||
@ -10445,6 +10468,7 @@ exports[`renders ./components/table/demo/jsx.md correctly 1`] = `
|
||||
</a>
|
||||
<div
|
||||
class="ant-divider ant-divider-vertical"
|
||||
role="separator"
|
||||
/>
|
||||
<a
|
||||
href="javascript:;"
|
||||
@ -10500,6 +10524,7 @@ exports[`renders ./components/table/demo/jsx.md correctly 1`] = `
|
||||
</a>
|
||||
<div
|
||||
class="ant-divider ant-divider-vertical"
|
||||
role="separator"
|
||||
/>
|
||||
<a
|
||||
href="javascript:;"
|
||||
@ -10560,6 +10585,7 @@ exports[`renders ./components/table/demo/jsx.md correctly 1`] = `
|
||||
</a>
|
||||
<div
|
||||
class="ant-divider ant-divider-vertical"
|
||||
role="separator"
|
||||
/>
|
||||
<a
|
||||
href="javascript:;"
|
||||
|
@ -11,7 +11,7 @@ title:
|
||||
|
||||
## en-US
|
||||
|
||||
Another type Tabs, which doesn't support vertical mode.
|
||||
Another type of Tabs, which doesn't support vertical mode.
|
||||
|
||||
```jsx
|
||||
import { Tabs } from 'antd';
|
||||
|
@ -11,7 +11,7 @@ title:
|
||||
|
||||
## en-US
|
||||
|
||||
use react-sticky.
|
||||
Use react-sticky.
|
||||
|
||||
```jsx
|
||||
import { Tabs } from 'antd';
|
||||
|
@ -11,7 +11,7 @@ title:
|
||||
|
||||
## en-US
|
||||
|
||||
Large size tabs are usally used in page header, and small size could be used in Modal.
|
||||
Large size tabs are usually used in page header, and small size could be used in Modal.
|
||||
|
||||
```jsx
|
||||
import { Tabs, Radio } from 'antd';
|
||||
|
@ -242,10 +242,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Create a empty element to aovid margin merge
|
||||
// Create an empty element to avoid margin collapsing
|
||||
// https://github.com/ant-design/ant-design/issues/18103
|
||||
&-content::before {
|
||||
display: inline-block;
|
||||
display: table;
|
||||
content: '';
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,31 @@ exports[`Tooltip should hide when mouse leave antd disabled component Button 1`]
|
||||
</span>
|
||||
`;
|
||||
|
||||
exports[`Tooltip should hide when mouse leave antd disabled component Checkbox 1`] = `
|
||||
<span
|
||||
style="display: inline-block; cursor: not-allowed;"
|
||||
>
|
||||
<label
|
||||
class="ant-checkbox-wrapper ant-checkbox-wrapper-disabled"
|
||||
style="pointer-events: none;"
|
||||
>
|
||||
<span
|
||||
class="ant-checkbox ant-checkbox-disabled"
|
||||
>
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
disabled=""
|
||||
type="checkbox"
|
||||
value=""
|
||||
/>
|
||||
<span
|
||||
class="ant-checkbox-inner"
|
||||
/>
|
||||
</span>
|
||||
</label>
|
||||
</span>
|
||||
`;
|
||||
|
||||
exports[`Tooltip should hide when mouse leave antd disabled component Switch 1`] = `
|
||||
<span
|
||||
style="display: inline-block; cursor: not-allowed;"
|
||||
|
@ -3,6 +3,7 @@ import { mount } from 'enzyme';
|
||||
import Tooltip from '..';
|
||||
import Button from '../../button';
|
||||
import Switch from '../../switch';
|
||||
import Checkbox from '../../checkbox';
|
||||
import DatePicker from '../../date-picker';
|
||||
import Input from '../../input';
|
||||
import Group from '../../input/Group';
|
||||
@ -107,6 +108,7 @@ describe('Tooltip', () => {
|
||||
|
||||
testComponent('Button', Button);
|
||||
testComponent('Switch', Switch);
|
||||
testComponent('Checkbox', Checkbox);
|
||||
});
|
||||
|
||||
it('should render disabled Button style properly', () => {
|
||||
|
@ -87,7 +87,10 @@ const splitObject = (obj: any, keys: string[]) => {
|
||||
function getDisabledCompatibleChildren(element: React.ReactElement<any>) {
|
||||
const elementType = element.type as any;
|
||||
if (
|
||||
(elementType.__ANT_BUTTON || elementType.__ANT_SWITCH || element.type === 'button') &&
|
||||
(elementType.__ANT_BUTTON ||
|
||||
elementType.__ANT_SWITCH ||
|
||||
elementType.__ANT_CHECKBOX ||
|
||||
element.type === 'button') &&
|
||||
element.props.disabled
|
||||
) {
|
||||
// Pick some layout related style properties up to span
|
||||
|
@ -82,6 +82,7 @@ exports[`renders ./components/typography/demo/basic.md correctly 1`] = `
|
||||
</div>
|
||||
<div
|
||||
class="ant-divider ant-divider-horizontal"
|
||||
role="separator"
|
||||
/>
|
||||
<h1
|
||||
class="ant-typography"
|
||||
|
@ -4,7 +4,7 @@ import { UploadProps } from './interface';
|
||||
|
||||
export type DraggerProps = UploadProps & { height?: number };
|
||||
|
||||
const Dragger = (props: DraggerProps) => (
|
||||
const Dragger: React.FC<DraggerProps> = props => (
|
||||
<Upload {...props} type="drag" style={{ ...props.style, height: props.height }} />
|
||||
);
|
||||
|
||||
|
@ -26,15 +26,12 @@ export default class UploadList extends React.Component<UploadListProps, any> {
|
||||
return;
|
||||
}
|
||||
(items || []).forEach(file => {
|
||||
const isValidateFile =
|
||||
file.originFileObj instanceof File || file.originFileObj instanceof Blob;
|
||||
|
||||
if (
|
||||
typeof document === 'undefined' ||
|
||||
typeof window === 'undefined' ||
|
||||
!(window as any).FileReader ||
|
||||
!(window as any).File ||
|
||||
!isValidateFile ||
|
||||
!(file.originFileObj instanceof File || file.originFileObj instanceof Blob) ||
|
||||
file.thumbUrl !== undefined
|
||||
) {
|
||||
return;
|
||||
|
@ -3,7 +3,7 @@ order: 9
|
||||
title: FAQ
|
||||
---
|
||||
|
||||
Here are the frequently asked questions about Ant Design and antd that you should look up before you ask in the community or create new a issue. We also maintain a [FAQ issues label](http://u.ant.design/faq) for common github issues.
|
||||
Here are the frequently asked questions about Ant Design and antd that you should look up before you ask in the community or create a new issue. We also maintain a [FAQ issues label](http://u.ant.design/faq) for common github issues.
|
||||
|
||||
---
|
||||
|
||||
|
@ -27,7 +27,7 @@ return (
|
||||
|
||||
| 语言 | 文件名 |
|
||||
| ---------------- | ------ |
|
||||
| 阿拉伯 | ar_EG |
|
||||
| 阿拉伯语 | ar_EG |
|
||||
| 保加利亚语 | bg_BG |
|
||||
| 加泰罗尼亚语 | ca_ES |
|
||||
| 捷克语 | cs_CZ |
|
||||
@ -44,14 +44,14 @@ return (
|
||||
| 希伯来语 | he_IL |
|
||||
| 印地语 | hi_IN |
|
||||
| 克罗地亚语 | hr_HR |
|
||||
| 匈牙利 | hu_HU |
|
||||
| 匈牙利语 | hu_HU |
|
||||
| 冰岛语 | is_IS |
|
||||
| 印度尼西亚语 | id_ID |
|
||||
| 意大利语 | it_IT |
|
||||
| 日语 | ja_JP |
|
||||
| 卡纳达语 | kn_IN |
|
||||
| 韩语/朝鲜语 | ko_KR |
|
||||
| 挪威 | nb_NO |
|
||||
| 挪威语 | nb_NO |
|
||||
| 尼泊尔语 | ne_NP |
|
||||
| 荷兰语(比利时) | nl_BE |
|
||||
| 荷兰语 | nl_NL |
|
||||
@ -59,10 +59,10 @@ return (
|
||||
| 葡萄牙语(巴西) | pt_BR |
|
||||
| 葡萄牙语 | pt_PT |
|
||||
| 斯洛伐克语 | sk_SK |
|
||||
| 塞尔维亚 | sr_RS |
|
||||
| 斯洛文尼亚 | sl_SI |
|
||||
| 塞尔维亚语 | sr_RS |
|
||||
| 斯洛文尼亚语 | sl_SI |
|
||||
| 瑞典语 | sv_SE |
|
||||
| 泰米尔人 | ta_IN |
|
||||
| 泰米尔语 | ta_IN |
|
||||
| 泰语 | th_TH |
|
||||
| 土耳其语 | tr_TR |
|
||||
| 俄罗斯语 | ru_RU |
|
||||
|
@ -4,7 +4,7 @@ order: 7
|
||||
title: Keep it Lightweight
|
||||
---
|
||||
|
||||
Fitts's Law is an ergonomic principle that ties the size of a target and its contextual proximity to ease of use.In other words, if a tool is close at hand and large enough to target, then we can improve the user's interaction. Putting tools in context makes for lightweight interaction.
|
||||
Fitts's Law is an ergonomic principle that ties the size of a target and its contextual proximity to ease of use. In other words, if a tool is close at hand and large enough to target, then we can improve the user's interaction. Putting tools in context makes for lightweight interaction.
|
||||
|
||||
> <img src="https://os.alipayobjects.com/rmsportal/wAcbQmeqTWDqsnu.png" width="150" />
|
||||
> ** Fitts's Law **: The time to acquire a target is a function of the distance to and size of the target. It is proportional to the distance to the target and inversely proportional to the width of the target.
|
||||
|
12
package.json
12
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "antd",
|
||||
"version": "4.0.0-alpha.0",
|
||||
"version": "4.0.0-alpha.1",
|
||||
"title": "Ant Design",
|
||||
"description": "An enterprise-class UI design language and React components implementation",
|
||||
"homepage": "http://ant.design/",
|
||||
@ -99,14 +99,13 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ant-design/colors": "^3.1.0",
|
||||
"@ant-design/tools": "^8.0.0",
|
||||
"@ant-design/tools": "^8.0.4",
|
||||
"@packtracker/webpack-plugin": "^2.0.1",
|
||||
"@sentry/browser": "^5.4.0",
|
||||
"@types/classnames": "^2.2.8",
|
||||
"@types/prop-types": "^15.7.1",
|
||||
"@types/react": "~16.9.1",
|
||||
"@types/react-dom": "^16.8.4",
|
||||
"@types/react-intl": "^2.3.17",
|
||||
"@types/warning": "^3.0.0",
|
||||
"@typescript-eslint/eslint-plugin": "^1.13.0",
|
||||
"@typescript-eslint/parser": "^1.13.0",
|
||||
@ -120,7 +119,6 @@
|
||||
"bisheng-plugin-react": "^1.1.0",
|
||||
"bisheng-plugin-toc": "^0.4.4",
|
||||
"chalk": "^2.4.2",
|
||||
"commander": "^2.20.0",
|
||||
"cross-env": "^5.2.0",
|
||||
"css-split-webpack-plugin": "^0.2.6",
|
||||
"dekko": "^0.2.1",
|
||||
@ -170,7 +168,7 @@
|
||||
"react-github-button": "^0.1.11",
|
||||
"react-highlight-words": "^0.16.0",
|
||||
"react-infinite-scroller": "^1.2.4",
|
||||
"react-intl": "^2.9.0",
|
||||
"react-intl": "^3.1.1",
|
||||
"react-resizable": "^1.8.0",
|
||||
"react-router": "^3.2.3",
|
||||
"react-router-dom": "^5.0.1",
|
||||
@ -216,7 +214,7 @@
|
||||
"tsc": "tsc",
|
||||
"start": "rimraf _site && mkdir _site && node ./scripts/generateColorLess.js && cross-env NODE_ENV=development bisheng start -c ./site/bisheng.config.js",
|
||||
"start:preact": "node ./scripts/generateColorLess.js && cross-env NODE_ENV=development REACT_ENV=preact bisheng start -c ./site/bisheng.config.js",
|
||||
"site": "cross-env NODE_ENV=production bisheng build --ssr -c ./site/bisheng.config.js && node ./scripts/generateColorLess.js",
|
||||
"site": "bisheng build --ssr -c ./site/bisheng.config.js && node ./scripts/generateColorLess.js",
|
||||
"predeploy": "antd-tools run clean && npm run site && cp netlify.toml CNAME _site && cp .circleci/config.yml _site",
|
||||
"deploy": "bisheng gh-pages --push-only",
|
||||
"deploy:china-mirror": "git checkout gh-pages && git pull origin gh-pages && git push git@gitee.com:ant-design/ant-design.git gh-pages",
|
||||
@ -244,4 +242,4 @@
|
||||
"> 1%",
|
||||
"ie >= 9"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -125,6 +125,12 @@ module.exports = {
|
||||
|
||||
alertBabelConfig(config.module.rules);
|
||||
|
||||
config.module.rules.push({
|
||||
test: /\.mjs$/,
|
||||
include: /node_modules/,
|
||||
type: 'javascript/auto',
|
||||
});
|
||||
|
||||
config.plugins.push(new CSSSplitWebpackPlugin({ size: 4000 }));
|
||||
|
||||
return config;
|
||||
|
@ -1,8 +1,5 @@
|
||||
const appLocaleData = require('react-intl/locale-data/en');
|
||||
|
||||
module.exports = {
|
||||
locale: 'en-US',
|
||||
data: appLocaleData,
|
||||
messages: {
|
||||
'app.header.search': 'Search...',
|
||||
'app.header.menu.home': 'Home',
|
||||
|
@ -2,7 +2,6 @@ const path = require('path');
|
||||
|
||||
const homeTmpl = './template/Home/index';
|
||||
const contentTmpl = './template/Content/index';
|
||||
const redirectTmpl = './template/Redirect';
|
||||
const appShellTmpl = './template/AppShell';
|
||||
|
||||
function pickerGenerator(module) {
|
||||
@ -43,9 +42,7 @@ module.exports = {
|
||||
}
|
||||
return null;
|
||||
},
|
||||
'docs/pattern': pickerGenerator('pattern'),
|
||||
'docs/react': pickerGenerator('react'),
|
||||
'docs/resource': pickerGenerator('resource'),
|
||||
'docs/spec': pickerGenerator('spec'),
|
||||
},
|
||||
plugins: [
|
||||
@ -67,10 +64,6 @@ module.exports = {
|
||||
path: 'index-cn',
|
||||
component: homeTmpl,
|
||||
},
|
||||
{
|
||||
path: 'docs/pattern/:children',
|
||||
component: redirectTmpl,
|
||||
},
|
||||
{
|
||||
path: 'docs/react/:children',
|
||||
component: contentTmpl,
|
||||
@ -95,22 +88,10 @@ module.exports = {
|
||||
path: 'components/:children/',
|
||||
component: contentTmpl,
|
||||
},
|
||||
{
|
||||
path: 'docs/spec/feature',
|
||||
component: redirectTmpl,
|
||||
},
|
||||
{
|
||||
path: 'docs/spec/feature-cn',
|
||||
component: redirectTmpl,
|
||||
},
|
||||
{
|
||||
path: 'docs/spec/:children',
|
||||
component: contentTmpl,
|
||||
},
|
||||
{
|
||||
path: 'docs/resource/:children',
|
||||
component: redirectTmpl,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
@ -23,7 +23,7 @@
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet/less" type="text/css" href="{{ root }}color.less" />
|
||||
<script src="https://polyfill.alicdn.com/polyfill.min.js?features=default,es2015,matchMedia"></script>
|
||||
<script src="https://polyfill.alicdn.com/polyfill.min.js?features=default,es2015,matchMedia,Intl"></script>
|
||||
<script>
|
||||
(function() {
|
||||
function isLocalStorageNameSupported() {
|
||||
|
@ -1,16 +1,11 @@
|
||||
import React, { Children, cloneElement } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { FormattedMessage, injectIntl } from 'react-intl';
|
||||
import DocumentTitle from 'react-document-title';
|
||||
import { getChildren } from 'jsonml.js/lib/utils';
|
||||
import { Timeline, Alert, Affix } from 'antd';
|
||||
import EditButton from './EditButton';
|
||||
|
||||
export default class Article extends React.Component {
|
||||
static contextTypes = {
|
||||
intl: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
class Article extends React.Component {
|
||||
shouldComponentUpdate(nextProps) {
|
||||
const { location } = this.props;
|
||||
const { location: nextLocation } = nextProps;
|
||||
@ -69,13 +64,13 @@ export default class Article extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { props } = this;
|
||||
const { content } = props;
|
||||
const {
|
||||
content,
|
||||
intl: { locale },
|
||||
utils,
|
||||
} = this.props;
|
||||
const { meta, description } = content;
|
||||
const { title, subtitle, filename } = meta;
|
||||
const {
|
||||
intl: { locale },
|
||||
} = this.context;
|
||||
const isNotTranslated = locale === 'en-US' && typeof title === 'object';
|
||||
return (
|
||||
<DocumentTitle title={`${title[locale] || title} - Ant Design`}>
|
||||
@ -104,22 +99,22 @@ export default class Article extends React.Component {
|
||||
</h1>
|
||||
{!description
|
||||
? null
|
||||
: props.utils.toReactComponent(
|
||||
: utils.toReactComponent(
|
||||
['section', { className: 'markdown' }].concat(getChildren(description)),
|
||||
)}
|
||||
{!content.toc || content.toc.length <= 1 || meta.toc === false ? null : (
|
||||
<Affix className="toc-affix" offsetTop={16}>
|
||||
{props.utils.toReactComponent(
|
||||
{utils.toReactComponent(
|
||||
['ul', { className: 'toc' }].concat(getChildren(content.toc)),
|
||||
)}
|
||||
</Affix>
|
||||
)}
|
||||
{this.getArticle(
|
||||
props.utils.toReactComponent(
|
||||
utils.toReactComponent(
|
||||
['section', { className: 'markdown' }].concat(getChildren(content.content)),
|
||||
),
|
||||
)}
|
||||
{props.utils.toReactComponent(
|
||||
{utils.toReactComponent(
|
||||
[
|
||||
'section',
|
||||
{
|
||||
@ -132,3 +127,5 @@ export default class Article extends React.Component {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default injectIntl(Article);
|
||||
|
@ -1,7 +1,6 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import DocumentTitle from 'react-document-title';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { FormattedMessage, injectIntl } from 'react-intl';
|
||||
import classNames from 'classnames';
|
||||
import { Row, Col, Icon, Affix, Tooltip } from 'antd';
|
||||
import { getChildren } from 'jsonml.js/lib/utils';
|
||||
@ -9,11 +8,7 @@ import Demo from './Demo';
|
||||
import EditButton from './EditButton';
|
||||
import { ping } from '../utils';
|
||||
|
||||
export default class ComponentDoc extends React.Component {
|
||||
static contextTypes = {
|
||||
intl: PropTypes.object,
|
||||
};
|
||||
|
||||
class ComponentDoc extends React.Component {
|
||||
state = {
|
||||
expandAll: false,
|
||||
showRiddleButton: false,
|
||||
@ -57,21 +52,23 @@ export default class ComponentDoc extends React.Component {
|
||||
};
|
||||
|
||||
render() {
|
||||
const { props } = this;
|
||||
const { doc, location } = props;
|
||||
const { content, meta } = doc;
|
||||
const {
|
||||
doc,
|
||||
location,
|
||||
intl: { locale },
|
||||
} = this.context;
|
||||
const demos = Object.keys(props.demos).map(key => props.demos[key]);
|
||||
utils,
|
||||
demos,
|
||||
} = this.props;
|
||||
const { content, meta } = doc;
|
||||
const demoValues = Object.keys(demos).map(key => demos[key]);
|
||||
const { expandAll, showRiddleButton } = this.state;
|
||||
|
||||
const isSingleCol = meta.cols === 1;
|
||||
const leftChildren = [];
|
||||
const rightChildren = [];
|
||||
const showedDemo = demos.some(demo => demo.meta.only)
|
||||
? demos.filter(demo => demo.meta.only)
|
||||
: demos.filter(demo => demo.preview);
|
||||
const showedDemo = demoValues.some(demo => demo.meta.only)
|
||||
? demoValues.filter(demo => demo.meta.only)
|
||||
: demoValues.filter(demo => demo.preview);
|
||||
showedDemo
|
||||
.sort((a, b) => a.meta.order - b.meta.order)
|
||||
.forEach((demoData, index) => {
|
||||
@ -79,7 +76,7 @@ export default class ComponentDoc extends React.Component {
|
||||
<Demo
|
||||
{...demoData}
|
||||
key={demoData.meta.filename}
|
||||
utils={props.utils}
|
||||
utils={utils}
|
||||
expand={expandAll}
|
||||
location={location}
|
||||
/>
|
||||
@ -126,7 +123,7 @@ export default class ComponentDoc extends React.Component {
|
||||
filename={filename}
|
||||
/>
|
||||
</h1>
|
||||
{props.utils.toReactComponent(
|
||||
{utils.toReactComponent(
|
||||
['section', { className: 'markdown' }].concat(getChildren(content)),
|
||||
)}
|
||||
<h2>
|
||||
@ -159,7 +156,7 @@ export default class ComponentDoc extends React.Component {
|
||||
</Col>
|
||||
)}
|
||||
</Row>
|
||||
{props.utils.toReactComponent(
|
||||
{utils.toReactComponent(
|
||||
[
|
||||
'section',
|
||||
{
|
||||
@ -172,3 +169,5 @@ export default class ComponentDoc extends React.Component {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default injectIntl(ComponentDoc);
|
||||
|
@ -1,8 +1,7 @@
|
||||
/* eslint jsx-a11y/no-noninteractive-element-interactions: 0 */
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import PropTypes from 'prop-types';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { FormattedMessage, injectIntl } from 'react-intl';
|
||||
import CopyToClipboard from 'react-copy-to-clipboard';
|
||||
import classNames from 'classnames';
|
||||
import LZString from 'lz-string';
|
||||
@ -19,11 +18,7 @@ function compress(string) {
|
||||
.replace(/=+$/, ''); // Remove ending '='
|
||||
}
|
||||
|
||||
export default class Demo extends React.Component {
|
||||
static contextTypes = {
|
||||
intl: PropTypes.object,
|
||||
};
|
||||
|
||||
class Demo extends React.Component {
|
||||
state = {
|
||||
codeExpand: false,
|
||||
copied: false,
|
||||
@ -114,8 +109,10 @@ export default class Demo extends React.Component {
|
||||
style,
|
||||
highlightedStyle,
|
||||
expand,
|
||||
utils,
|
||||
intl: { locale },
|
||||
} = props;
|
||||
const { copied } = state;
|
||||
const { copied, copyTooltipVisible } = state;
|
||||
if (!this.liveDemo) {
|
||||
this.liveDemo = meta.iframe ? (
|
||||
<BrowserFrame>
|
||||
@ -125,17 +122,14 @@ export default class Demo extends React.Component {
|
||||
preview(React, ReactDOM)
|
||||
);
|
||||
}
|
||||
const codeExpand = state.codeExpand || expand;
|
||||
const codeExpand = this.state.codeExpand || expand;
|
||||
const codeBoxClass = classNames('code-box', {
|
||||
expand: codeExpand,
|
||||
'code-box-debug': meta.debug,
|
||||
});
|
||||
const {
|
||||
intl: { locale },
|
||||
} = this.context;
|
||||
const localizedTitle = meta.title[locale] || meta.title;
|
||||
const localizeIntro = content[locale] || content;
|
||||
const introChildren = props.utils.toReactComponent(['div'].concat(localizeIntro));
|
||||
const introChildren = utils.toReactComponent(['div'].concat(localizeIntro));
|
||||
|
||||
const highlightClass = classNames({
|
||||
'highlight-wrapper': true,
|
||||
@ -295,12 +289,12 @@ ${sourceCode.replace('mountNode', "document.getElementById('container')")}
|
||||
</form>
|
||||
<CopyToClipboard text={sourceCode} onCopy={() => this.handleCodeCopied(meta.id)}>
|
||||
<Tooltip
|
||||
visible={state.copyTooltipVisible}
|
||||
visible={copyTooltipVisible}
|
||||
onVisibleChange={this.onCopyTooltipVisibleChange}
|
||||
title={<FormattedMessage id={`app.demo.${copied ? 'copied' : 'copy'}`} />}
|
||||
>
|
||||
<Icon
|
||||
type={state.copied && state.copyTooltipVisible ? 'check' : 'snippets'}
|
||||
type={copied && copyTooltipVisible ? 'check' : 'snippets'}
|
||||
className="code-box-code-copy"
|
||||
/>
|
||||
</Tooltip>
|
||||
@ -339,3 +333,5 @@ ${sourceCode.replace('mountNode', "document.getElementById('container')")}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default injectIntl(Demo);
|
||||
|
@ -2,7 +2,7 @@ import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Link } from 'bisheng/router';
|
||||
import { Row, Col, Menu, Icon, Affix } from 'antd';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { FormattedMessage, injectIntl } from 'react-intl';
|
||||
import classNames from 'classnames';
|
||||
import get from 'lodash/get';
|
||||
import MobileMenu from 'rc-drawer';
|
||||
@ -14,13 +14,6 @@ import * as utils from '../utils';
|
||||
|
||||
const { SubMenu } = Menu;
|
||||
|
||||
function getActiveMenuItem(props) {
|
||||
const { children } = props.params;
|
||||
return (
|
||||
(children && children.replace('-cn', '')) || props.location.pathname.replace(/(^\/|-cn$)/g, '')
|
||||
);
|
||||
}
|
||||
|
||||
function getModuleData(props) {
|
||||
const { pathname } = props.location;
|
||||
const moduleName = /^\/?components/.test(pathname)
|
||||
@ -69,19 +62,14 @@ const getSubMenuTitle = menuItem => {
|
||||
});
|
||||
return (
|
||||
<h4>
|
||||
{menuItem.title === 'Components' ? (
|
||||
<FormattedMessage id="app.header.menu.components" />
|
||||
) : (
|
||||
menuItem.title
|
||||
)}
|
||||
<FormattedMessage id="app.header.menu.components" />
|
||||
<span className="menu-antd-components-count">{count}</span>
|
||||
</h4>
|
||||
);
|
||||
};
|
||||
|
||||
export default class MainContent extends Component {
|
||||
class MainContent extends Component {
|
||||
static contextTypes = {
|
||||
intl: PropTypes.object.isRequired,
|
||||
isMobile: PropTypes.bool.isRequired,
|
||||
};
|
||||
|
||||
@ -126,10 +114,10 @@ export default class MainContent extends Component {
|
||||
}
|
||||
|
||||
getMenuItems(footerNavIcons = {}) {
|
||||
const { themeConfig } = this.props;
|
||||
const {
|
||||
themeConfig,
|
||||
intl: { locale },
|
||||
} = this.context;
|
||||
} = this.props;
|
||||
const moduleData = getModuleData(this.props);
|
||||
const menuItems = utils.getMenuItems(
|
||||
moduleData,
|
||||
@ -173,6 +161,16 @@ export default class MainContent extends Component {
|
||||
return { prev, next };
|
||||
}
|
||||
|
||||
getActiveMenuItem() {
|
||||
const {
|
||||
params: { children },
|
||||
location,
|
||||
} = this.props;
|
||||
return (
|
||||
(children && children.replace('-cn', '')) || location.pathname.replace(/(^\/|-cn$)/g, '')
|
||||
);
|
||||
}
|
||||
|
||||
handleMenuOpenChange = openKeys => {
|
||||
this.setState({ openKeys });
|
||||
};
|
||||
@ -195,6 +193,9 @@ export default class MainContent extends Component {
|
||||
if (this.scroller) {
|
||||
this.scroller.destroy();
|
||||
}
|
||||
if (!document.querySelector('.markdown > h2, .code-box')) {
|
||||
return;
|
||||
}
|
||||
require('intersection-observer'); // eslint-disable-line
|
||||
const scrollama = require('scrollama'); // eslint-disable-line
|
||||
this.scroller = scrollama();
|
||||
@ -217,7 +218,7 @@ export default class MainContent extends Component {
|
||||
generateMenuItem(isTop, item, { before = null, after = null }) {
|
||||
const {
|
||||
intl: { locale },
|
||||
} = this.context;
|
||||
} = this.props;
|
||||
const key = fileNameToPath(item.filename);
|
||||
if (!item.title) {
|
||||
return null;
|
||||
@ -280,19 +281,18 @@ export default class MainContent extends Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { props } = this;
|
||||
const { isMobile } = this.context;
|
||||
const { openKeys } = this.state;
|
||||
const activeMenuItem = getActiveMenuItem(props);
|
||||
const { localizedPageData, demos } = this.props;
|
||||
const activeMenuItem = this.getActiveMenuItem();
|
||||
const menuItems = this.getMenuItems();
|
||||
const menuItemsForFooterNav = this.getMenuItems({
|
||||
before: <Icon className="footer-nav-icon-before" type="left" />,
|
||||
after: <Icon className="footer-nav-icon-after" type="right" />,
|
||||
});
|
||||
const { prev, next } = this.getFooterNav(menuItemsForFooterNav, activeMenuItem);
|
||||
const { localizedPageData } = props;
|
||||
const mainContainerClass = classNames('main-container', {
|
||||
'main-container-component': !!props.demos,
|
||||
'main-container-component': !!demos,
|
||||
});
|
||||
const menuChild = (
|
||||
<Menu
|
||||
@ -329,10 +329,10 @@ export default class MainContent extends Component {
|
||||
)}
|
||||
<Col xxl={20} xl={19} lg={18} md={24} sm={24} xs={24}>
|
||||
<section className={mainContainerClass}>
|
||||
{props.demos ? (
|
||||
<ComponentDoc {...props} doc={localizedPageData} demos={props.demos} />
|
||||
{demos ? (
|
||||
<ComponentDoc {...this.props} doc={localizedPageData} demos={demos} />
|
||||
) : (
|
||||
<Article {...props} content={localizedPageData} />
|
||||
<Article {...this.props} content={localizedPageData} />
|
||||
)}
|
||||
</section>
|
||||
<PrevAndNext prev={prev} next={next} />
|
||||
@ -343,3 +343,5 @@ export default class MainContent extends Component {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default injectIntl(MainContent);
|
||||
|
@ -1,10 +1,9 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import TweenOne from 'rc-tween-one';
|
||||
import QueueAnim from 'rc-queue-anim';
|
||||
import ScrollParallax from 'rc-scroll-anim/lib/ScrollParallax';
|
||||
import { Link } from 'bisheng/router';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { FormattedMessage, useIntl } from 'react-intl';
|
||||
import GitHubButton from 'react-github-button';
|
||||
import { Button } from 'antd';
|
||||
import BannerImage from './BannerImage';
|
||||
@ -16,96 +15,79 @@ const loop = {
|
||||
repeat: -1,
|
||||
};
|
||||
|
||||
class Banner extends React.PureComponent {
|
||||
static contextTypes = {
|
||||
intl: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
static propTypes = {
|
||||
className: PropTypes.string,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
className: 'banner',
|
||||
};
|
||||
|
||||
render() {
|
||||
const { className, isMobile } = this.props;
|
||||
const {
|
||||
intl: { locale },
|
||||
} = this.context;
|
||||
const isZhCN = locale === 'zh-CN';
|
||||
return (
|
||||
<div className="home-page-wrapper banner-wrapper" id="banner">
|
||||
<div className="banner-bg-wrapper">
|
||||
<svg width="400px" height="576px" viewBox="0 0 400 576" fill="none">
|
||||
<TweenOne component="g" animation={[{ opacity: 0, type: 'from' }, { ...loop, y: 15 }]}>
|
||||
<ellipse cx="100" cy="100" rx="6" ry="6" stroke="#2F54EB" strokeWidth="1.6" />
|
||||
</TweenOne>
|
||||
<TweenOne component="g" animation={[{ opacity: 0, type: 'from' }, { ...loop, y: -15 }]}>
|
||||
<g transform="translate(200 450)">
|
||||
<g style={{ transformOrigin: '50% 50%', transform: 'rotate(-340deg)' }}>
|
||||
<rect stroke="#FADB14" strokeWidth="1.6" width="9" height="9" />
|
||||
</g>
|
||||
const Banner = ({ isMobile }) => {
|
||||
const { locale } = useIntl();
|
||||
const isZhCN = locale === 'zh-CN';
|
||||
return (
|
||||
<div className="home-page-wrapper banner-wrapper" id="banner">
|
||||
<div className="banner-bg-wrapper">
|
||||
<svg width="400px" height="576px" viewBox="0 0 400 576" fill="none">
|
||||
<TweenOne component="g" animation={[{ opacity: 0, type: 'from' }, { ...loop, y: 15 }]}>
|
||||
<ellipse cx="100" cy="100" rx="6" ry="6" stroke="#2F54EB" strokeWidth="1.6" />
|
||||
</TweenOne>
|
||||
<TweenOne component="g" animation={[{ opacity: 0, type: 'from' }, { ...loop, y: -15 }]}>
|
||||
<g transform="translate(200 450)">
|
||||
<g style={{ transformOrigin: '50% 50%', transform: 'rotate(-340deg)' }}>
|
||||
<rect stroke="#FADB14" strokeWidth="1.6" width="9" height="9" />
|
||||
</g>
|
||||
</TweenOne>
|
||||
</svg>
|
||||
<ScrollParallax
|
||||
location="banner"
|
||||
className="banner-bg"
|
||||
animation={{ playScale: [1, 1.5], rotate: 0 }}
|
||||
/>
|
||||
</div>
|
||||
<QueueAnim className={`${className} page`} type="alpha" delay={150}>
|
||||
{isMobile && (
|
||||
<div className="img-wrapper" key="image">
|
||||
<BannerImage />
|
||||
</div>
|
||||
)}
|
||||
<QueueAnim className="text-wrapper" key="text" type="bottom">
|
||||
<h1 key="h1">Ant Design</h1>
|
||||
<p key="p">
|
||||
<FormattedMessage id="app.home.introduce" />
|
||||
</p>
|
||||
<div className="banner-btns" key="buttons">
|
||||
<Link to={utils.getLocalizedPathname('/docs/react/introduce', isZhCN)}>
|
||||
<Button type="primary" className="banner-btn components">
|
||||
<FormattedMessage id="app.home.getting-started" />
|
||||
</Button>
|
||||
</Link>
|
||||
<Link
|
||||
to={utils.getLocalizedPathname('/docs/spec/introduce', isZhCN)}
|
||||
style={{ marginLeft: 16 }}
|
||||
>
|
||||
<Button className="banner-btn language">
|
||||
<FormattedMessage id="app.home.design-language" />
|
||||
</Button>
|
||||
</Link>
|
||||
{!isMobile && (
|
||||
<GitHubButton
|
||||
style={{ marginLeft: 16 }}
|
||||
key="github-button"
|
||||
size="large"
|
||||
type="stargazers"
|
||||
namespace="ant-design"
|
||||
repo="ant-design"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</QueueAnim>
|
||||
{!isMobile && (
|
||||
<div className="img-wrapper" key="image">
|
||||
<ScrollParallax
|
||||
location="banner"
|
||||
component={BannerImage}
|
||||
animation={{ playScale: [1, 1.5], y: 80 }}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</QueueAnim>
|
||||
</g>
|
||||
</TweenOne>
|
||||
</svg>
|
||||
<ScrollParallax
|
||||
location="banner"
|
||||
className="banner-bg"
|
||||
animation={{ playScale: [1, 1.5], rotate: 0 }}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
<QueueAnim className="banner page" type="alpha" delay={150}>
|
||||
{isMobile && (
|
||||
<div className="img-wrapper" key="image">
|
||||
<BannerImage />
|
||||
</div>
|
||||
)}
|
||||
<QueueAnim className="text-wrapper" key="text" type="bottom">
|
||||
<h1 key="h1">Ant Design</h1>
|
||||
<p key="p">
|
||||
<FormattedMessage id="app.home.introduce" />
|
||||
</p>
|
||||
<div className="banner-btns" key="buttons">
|
||||
<Link to={utils.getLocalizedPathname('/docs/react/introduce', isZhCN)}>
|
||||
<Button type="primary" className="banner-btn components">
|
||||
<FormattedMessage id="app.home.getting-started" />
|
||||
</Button>
|
||||
</Link>
|
||||
<Link
|
||||
to={utils.getLocalizedPathname('/docs/spec/introduce', isZhCN)}
|
||||
style={{ marginLeft: 16 }}
|
||||
>
|
||||
<Button className="banner-btn language">
|
||||
<FormattedMessage id="app.home.design-language" />
|
||||
</Button>
|
||||
</Link>
|
||||
{!isMobile && (
|
||||
<GitHubButton
|
||||
style={{ marginLeft: 16 }}
|
||||
key="github-button"
|
||||
size="large"
|
||||
type="stargazers"
|
||||
namespace="ant-design"
|
||||
repo="ant-design"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</QueueAnim>
|
||||
{!isMobile && (
|
||||
<div className="img-wrapper" key="image">
|
||||
<ScrollParallax
|
||||
location="banner"
|
||||
component={BannerImage}
|
||||
animation={{ playScale: [1, 1.5], y: 80 }}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</QueueAnim>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Banner;
|
||||
|
@ -61,12 +61,12 @@ function getStyle() {
|
||||
// eslint-disable-next-line react/prefer-stateless-function
|
||||
class Home extends React.Component {
|
||||
static contextTypes = {
|
||||
intl: PropTypes.object.isRequired,
|
||||
isMobile: PropTypes.bool.isRequired,
|
||||
};
|
||||
|
||||
render() {
|
||||
const { isMobile, intl } = this.context;
|
||||
const { intl } = this.props;
|
||||
const { isMobile } = this.context;
|
||||
const childProps = { ...this.props, isMobile, locale: intl.locale };
|
||||
return (
|
||||
<DocumentTitle title={`Ant Design - ${intl.formatMessage({ id: 'app.home.slogan' })}`}>
|
||||
|
@ -2,14 +2,15 @@ import * as React from 'react';
|
||||
import { message } from 'antd';
|
||||
import { ThemeType } from '../../../../components/icon';
|
||||
import CopyableIcon from './CopyableIcon';
|
||||
import { injectIntl, InjectedIntlProps } from 'react-intl';
|
||||
import { injectIntl } from 'react-intl';
|
||||
import { CategoriesKeys } from './fields';
|
||||
|
||||
interface CategoryProps extends InjectedIntlProps {
|
||||
interface CategoryProps {
|
||||
title: CategoriesKeys;
|
||||
icons: string[];
|
||||
theme: ThemeType;
|
||||
newIcons: string[];
|
||||
intl: any;
|
||||
}
|
||||
|
||||
interface CategoryState {
|
||||
|
@ -3,14 +3,16 @@ import manifest from '@ant-design/icons/lib/manifest';
|
||||
import { ThemeType as ThemeFolderType } from '@ant-design/icons/lib/types';
|
||||
import { Radio, Icon, Input } from 'antd';
|
||||
import { RadioChangeEvent } from 'antd/es/radio/interface';
|
||||
import { injectIntl, InjectedIntlProps } from 'react-intl';
|
||||
import { injectIntl } from 'react-intl';
|
||||
import debounce from 'lodash/debounce';
|
||||
import Category from './Category';
|
||||
import { FilledIcon, OutlinedIcon, TwoToneIcon } from './themeIcons';
|
||||
import { categories, Categories, CategoriesKeys } from './fields';
|
||||
import { ThemeType } from 'antd/es/icon';
|
||||
|
||||
interface IconDisplayProps extends InjectedIntlProps {}
|
||||
interface IconDisplayProps {
|
||||
intl: any;
|
||||
}
|
||||
|
||||
interface IconDisplayState {
|
||||
theme: ThemeType;
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Link } from 'bisheng/router';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { FormattedMessage, injectIntl } from 'react-intl';
|
||||
import classNames from 'classnames';
|
||||
import { Select, Menu, Row, Col, Icon, Popover, Input, Button, Badge } from 'antd';
|
||||
import Santa from './Santa';
|
||||
@ -36,10 +36,9 @@ function initDocSearch(locale) {
|
||||
});
|
||||
}
|
||||
|
||||
export default class Header extends React.Component {
|
||||
class Header extends React.Component {
|
||||
static contextTypes = {
|
||||
router: PropTypes.object.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
isMobile: PropTypes.bool.isRequired,
|
||||
};
|
||||
|
||||
@ -48,7 +47,8 @@ export default class Header extends React.Component {
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
const { intl, router } = this.context;
|
||||
const { intl } = this.props;
|
||||
const { router } = this.context;
|
||||
router.listen(this.handleHideMenu);
|
||||
const { searchInput } = this;
|
||||
document.addEventListener('keyup', event => {
|
||||
@ -108,7 +108,11 @@ export default class Header extends React.Component {
|
||||
const { menuVisible } = this.state;
|
||||
const { isMobile } = this.context;
|
||||
const menuMode = isMobile ? 'inline' : 'horizontal';
|
||||
const { location, themeConfig } = this.props;
|
||||
const {
|
||||
location,
|
||||
themeConfig,
|
||||
intl: { locale },
|
||||
} = this.props;
|
||||
const docVersions = { ...themeConfig.docVersions, [antdVersion]: antdVersion };
|
||||
const versionOptions = Object.keys(docVersions).map(version => (
|
||||
<Option value={docVersions[version]} key={version}>
|
||||
@ -124,9 +128,6 @@ export default class Header extends React.Component {
|
||||
if (activeMenuItem === 'components' || location.pathname === 'changelog') {
|
||||
activeMenuItem = 'docs/react';
|
||||
}
|
||||
const {
|
||||
intl: { locale },
|
||||
} = this.context;
|
||||
const isZhCN = locale === 'zh-CN';
|
||||
|
||||
const headerClassName = classNames({
|
||||
@ -280,3 +281,5 @@ export default class Header extends React.Component {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default injectIntl(Header);
|
||||
|
@ -2,7 +2,7 @@ import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import PropTypes from 'prop-types';
|
||||
import { enquireScreen } from 'enquire-js';
|
||||
import { addLocaleData, IntlProvider } from 'react-intl';
|
||||
import { IntlProvider } from 'react-intl';
|
||||
import 'moment/locale/zh-cn';
|
||||
import { ConfigProvider } from 'antd';
|
||||
import LogRocket from 'logrocket';
|
||||
@ -63,7 +63,6 @@ export default class Layout extends React.Component {
|
||||
super(props);
|
||||
const { pathname } = props.location;
|
||||
const appLocale = utils.isZhCN(pathname) ? cnLocale : enLocale;
|
||||
addLocaleData(appLocale.data);
|
||||
|
||||
this.state = {
|
||||
appLocale,
|
||||
@ -110,10 +109,8 @@ export default class Layout extends React.Component {
|
||||
render() {
|
||||
const { children, ...restProps } = this.props;
|
||||
const { appLocale } = this.state;
|
||||
|
||||
// Temp remove SentryBoundary
|
||||
return (
|
||||
<IntlProvider locale={appLocale.locale} messages={appLocale.messages}>
|
||||
<IntlProvider locale={appLocale.locale} messages={appLocale.messages} defaultLocale="en-US">
|
||||
<ConfigProvider locale={appLocale.locale === 'zh-CN' ? zhCN : null}>
|
||||
<div className="page-wrapper">
|
||||
<Header {...restProps} />
|
||||
|
@ -1,38 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
const redirect = {
|
||||
'/docs/resource/download': '/docs/spec/download',
|
||||
'/docs/resource/download-cn': '/docs/spec/download-cn',
|
||||
'/docs/resource/reference': '/docs/spec/reference',
|
||||
'/docs/resource/reference-cn': '/docs/spec/reference-cn',
|
||||
'/docs/spec/feature': '/docs/spec/values',
|
||||
'/docs/spec/feature-cn': '/docs/spec/values-cn',
|
||||
'/docs/pattern/advanced-search': '/docs/spec/overview',
|
||||
'/docs/pattern/advanced-search-cn': '/docs/spec/overview-cn',
|
||||
'/docs/pattern/complex-table': '/docs/spec/overview',
|
||||
'/docs/pattern/complex-table-cn': '/docs/spec/overview-cn',
|
||||
'/docs/pattern/form': '/docs/spec/overview',
|
||||
'/docs/pattern/form-cn': '/docs/spec/overview-cn',
|
||||
'/docs/pattern/list': '/docs/spec/overview',
|
||||
'/docs/pattern/list-cn': '/docs/spec/overview-cn',
|
||||
'/docs/pattern/navigation': '/docs/spec/navigation',
|
||||
'/docs/pattern/navigation-cn': '/docs/spec/navigation-cn',
|
||||
'/docs/pattern/table': '/docs/spec/overview',
|
||||
'/docs/pattern/table-cn': '/docs/spec/overview-cn',
|
||||
};
|
||||
|
||||
export default class Redirect extends React.Component {
|
||||
componentDidMount() {
|
||||
const { location } = this.props;
|
||||
const pathname = `/${location.pathname}`;
|
||||
Object.keys(redirect).forEach(from => {
|
||||
if (pathname.indexOf(from) === 0) {
|
||||
window.location.href = redirect[from];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
return <div />;
|
||||
}
|
||||
}
|
@ -1,8 +1,5 @@
|
||||
const appLocaleData = require('react-intl/locale-data/zh');
|
||||
|
||||
module.exports = {
|
||||
locale: 'zh-CN',
|
||||
data: appLocaleData,
|
||||
messages: {
|
||||
'app.header.search': '全文本搜索...',
|
||||
'app.header.menu.home': '首页',
|
||||
|
Loading…
Reference in New Issue
Block a user