chore: auto merge branchs (#30202)

chore: merge master into feature
This commit is contained in:
github-actions[bot] 2021-04-20 08:32:10 +00:00 committed by GitHub
commit 0c8a84c4cc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 178 additions and 68 deletions

1
.husky/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
_

4
.husky/pre-commit Executable file
View File

@ -0,0 +1,4 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npx --no-install pretty-quick --staged

View File

@ -15,6 +15,20 @@ timeline: true
---
## 4.15.2
`2021-04-19`
- 🐞 Fix Tabs `centered` doesn't work. [#30106](https://github.com/ant-design/ant-design/pull/30106) [@kerm1it](https://github.com/kerm1it)
- 💄 Fix Button `type="link"` disabled cursor style missing. [#30197](https://github.com/ant-design/ant-design/pull/30197)
- 🐞 Fix TextArea `onChange` event return `target` object is not a HTMLTextArea object. [#30124](https://github.com/ant-design/ant-design/pull/30124)
- 🐞 Files in Upload `fileList` will always have uid. [#30087](https://github.com/ant-design/ant-design/pull/30087) [@jameslahm](https://github.com/jameslahm)
- 💄 Fix Badge toggle style when `status` is `warning`. [#30090](https://github.com/ant-design/ant-design/pull/30090) [@jameslahm](https://github.com/jameslahm)
- 🌐 Add Image component `preview` text in zh_HK and zh_TW. [#30100](https://github.com/ant-design/ant-design/pull/30100) [@jameslahm](https://github.com/jameslahm)
- 🌐 add da_DK locale TimePicker.RangePicker. [#30128](https://github.com/ant-design/ant-design/pull/30128) [@themitvp](https://github.com/themitvp)
- TypeScript
- 🤖 Modify LIST_IGNORE field is of string type. [#30188](https://github.com/ant-design/ant-design/pull/30188) [@hello-chinese](https://github.com/hello-chinese)
## 4.15.1
`2021-04-10`

View File

@ -15,6 +15,20 @@ timeline: true
---
## 4.15.2
`2021-04-19`
- 🐞 修复 Tabs `centered` 失效问题。[#30106](https://github.com/ant-design/ant-design/pull/30106) [@kerm1it](https://github.com/kerm1it)
- 💄 修复 Badge `status="warning"` 时切换样式异常的问题。[#30090](https://github.com/ant-design/ant-design/pull/30090) [@jameslahm](https://github.com/jameslahm)
- 💄 修复 Button 为 `type="link"` 时禁用手型丢失的问题。[#30197](https://github.com/ant-design/ant-design/pull/30197)
- 🐞 修复 TextArea `onChange` 事件返回 `target` 对象不是 HTMLTextArea 对象的问题。[#30124](https://github.com/ant-design/ant-design/pull/30124)
- 🐞 Upload `fileList` 中的文件将总是有 uid。[#30087](https://github.com/ant-design/ant-design/pull/30087) [@jameslahm](https://github.com/jameslahm)
- 🌐 补充遗漏的 TimePicker 丹麦语国际化。[#30128](https://github.com/ant-design/ant-design/pull/30128) [@themitvp](https://github.com/themitvp)
- 🌐 增加 Image 组件 `preview` 繁體文案。[#30100](https://github.com/ant-design/ant-design/pull/30100) [@jameslahm](https://github.com/jameslahm)
- TypeScript
- 🤖 修改 LIST_IGNORE 字段为 string 类型。[#30188](https://github.com/ant-design/ant-design/pull/30188) [@hello-chinese](https://github.com/hello-chinese)
## 4.15.1
`2021-04-10`

View File

@ -191,7 +191,7 @@ const Badge: CompoundedComponent = ({
[`${prefixCls}-count`]: !isDot && !isHidden,
[`${prefixCls}-count-sm`]: !isDot && !isHidden && size === 'small',
[`${prefixCls}-multiple-words`]:
!isDot && displayCount && displayCount?.toString().length > 1,
!isDot && displayCount && displayCount.toString().length > 1,
[`${prefixCls}-status-${status}`]: !!status,
[`${prefixCls}-status-${color}`]: isPresetColor(color),
});

View File

@ -62,7 +62,7 @@ const BreadcrumbItem: BreadcrumbItemInterface = ({
return (
<span>
{link}
{separator && separator !== '' && (
{separator && (
<span className={`${prefixCls}-separator`}>{separator}</span>
)}
</span>

View File

@ -300,4 +300,15 @@ describe('Button', () => {
},
});
});
it('should not redirect when button is disabled', () => {
const onClick = jest.fn();
const wrapper = mount(
<Button href="https://ant.design" onClick={onClick} disabled>
click me
</Button>,
);
wrapper.simulate('click');
expect(onClick).not.toHaveBeenCalled();
});
});

View File

@ -193,8 +193,10 @@ const InternalButton: React.ForwardRefRenderFunction<unknown, ButtonProps> = (pr
React.useEffect(fixTwoCNChar, [buttonRef]);
const handleClick = (e: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement, MouseEvent>) => {
const { onClick } = props;
if (innerLoading) {
const { onClick, disabled } = props;
// https://github.com/ant-design/ant-design/issues/30207
if (innerLoading || disabled) {
e.preventDefault();
return;
}
(onClick as React.MouseEventHandler<HTMLButtonElement | HTMLAnchorElement>)?.(e);

View File

@ -1,5 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Dropdown image', () => {
imageDemoTest('dropdown');
imageDemoTest('dropdown', { skip: ['dropdown-button.md'] });
});

View File

@ -11,7 +11,7 @@ title:
有部分定制的样式代码,由于输入标签长度不确定,需要根据具体情况自行调整。
> 🛎️ 想要 3 分钟实现? 试试 ProFrom 的[查询表单](https://procomponents.ant.design/components/form#%E6%9F%A5%E8%AF%A2%E7%AD%9B%E9%80%89)
> 🛎️ 想要 3 分钟实现? 试试 ProForm 的[查询表单](https://procomponents.ant.design/components/form#%E6%9F%A5%E8%AF%A2%E7%AD%9B%E9%80%89)
## en-US

View File

@ -9,7 +9,7 @@ title:
当用户访问一个展示了某个列表的页面,想新建一项但又不想跳转页面时,可以用 Modal 弹出一个表单,用户填写必要信息后创建新的项。
> 🛎️ 想要 3 分钟实现?试试 ProFrom 的 [Modal 表单](https://procomponents.ant.design/components/form#modal-%E8%A1%A8%E5%8D%95)
> 🛎️ 想要 3 分钟实现?试试 ProForm 的 [Modal 表单](https://procomponents.ant.design/components/form#modal-%E8%A1%A8%E5%8D%95)
## en-US

View File

@ -9,7 +9,7 @@ title:
普通的登录框,可以容纳更多的元素。
> 🛎️ 想要 3 分钟实现?试试 [ProFrom](https://procomponents.ant.design/components/form/#%E7%99%BB%E5%BD%95)
> 🛎️ 想要 3 分钟实现?试试 [ProForm](https://procomponents.ant.design/components/form/#%E7%99%BB%E5%BD%95)
## en-US

View File

@ -79,7 +79,7 @@ Form field component for data bidirectional binding, validation, layout, and so
| getValueProps | Additional props with sub component | (value: any) => any | - | 4.2.0 |
| hasFeedback | Used with `validateStatus`, this option specifies the validation status icon. Recommended to be used only with `Input` | boolean | false | |
| help | The prompt message. If not provided, the prompt message will be generated by the validation rule. | ReactNode | - | |
| hidden | Whether to hide Form.Item (still collect and validate value) | boolean | false | |
| hidden | Whether to hide Form.Item (still collect and validate value) | boolean | false | 4.4.0 |
| htmlFor | Set sub label `htmlFor` | string | - | |
| initialValue | Config sub default value. Form `initialValues` get higher priority when conflict | string | - | 4.2.0 |
| label | Label text | ReactNode | - | |
@ -203,9 +203,9 @@ Some operator functions in render form of Form.List.
New in 4.7.0. Show error messages, should only work with `rules` of Form.List. See [example](#components-form-demo-dynamic-form-item).
| Property | Description | Type | Default |
| --- | --- | --- | --- |
| errors | Error list | ReactNode\[] | - |
| Property | Description | Type | Default |
| -------- | ----------- | ------------ | ------- |
| errors | Error list | ReactNode\[] | - |
## Form.Provider
@ -286,13 +286,13 @@ validateFields()
#### FieldData
| Name | Description | Type |
| --- | --- | --- |
| errors | Error messages | string\[] |
| name | Field name path | [NamePath](#NamePath)\[] |
| touched | Whether is operated | boolean |
| validating | Whether is in validating | boolean |
| value | Field value | any |
| Name | Description | Type |
| ---------- | ------------------------ | ------------------------ |
| errors | Error messages | string\[] |
| name | Field name path | [NamePath](#NamePath)\[] |
| touched | Whether is operated | boolean |
| validating | Whether is in validating | boolean |
| value | Field value | any |
#### Rule
@ -435,3 +435,7 @@ React can not get correct interaction of controlled component with async value u
See similar issues: [#28370](https://github.com/ant-design/ant-design/issues/28370) [#27994](https://github.com/ant-design/ant-design/issues/27994)
`scrollToFirstError` and `scrollToField` deps on `id` attribute passed to form control, please mark sure that it hasn't been ignored in your custom form control. Check [codesandbox](https://codesandbox.io/s/antd-reproduction-template-forked-25nul?file=/index.js) for solution.
### `setFieldsValue` do not trigger `onFieldsChange` or `onValuesChange`?
It's by design. Only user interactive can trigger the change event. This design is aim to avoid call `setFieldsValue` in change event which may makes loop calling.

View File

@ -34,7 +34,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/ORmcdeaoO/Form.svg
| scrollToFirstError | 提交失败自动滚动到第一个错误字段 | boolean \| [Options](https://github.com/stipsan/scroll-into-view-if-needed/tree/ece40bd9143f48caf4b99503425ecb16b0ad8249#options) | false | |
| size | 设置字段组件的尺寸(仅限 antd 组件) | `small` \| `middle` \| `large` | - | |
| validateMessages | 验证提示模板,说明[见下](#validateMessages) | [ValidateMessages](https://github.com/react-component/field-form/blob/master/src/utils/messages.ts) | - | |
| validateTrigger | 统一设置字段校验规则 | string \| string\[] | `onChange` | 4.3.0 |
| validateTrigger | 统一设置字段触发验证的时机 | string \| string\[] | `onChange` | 4.3.0 |
| wrapperCol | 需要为输入控件设置布局样式时,使用该属性,用法同 labelCol | [object](/components/grid/#Col) | - | |
| onFieldsChange | 字段更新时触发回调事件 | function(changedFields, allFields) | - | |
| onFinish | 提交表单且数据验证成功后回调事件 | function(values) | - | |
@ -80,7 +80,7 @@ const validateMessages = {
| getValueProps | 为子元素添加额外的属性 | (value: any) => any | - | 4.2.0 |
| hasFeedback | 配合 `validateStatus` 属性使用,展示校验状态图标,建议只配合 Input 组件使用 | boolean | false | |
| help | 提示信息,如不设置,则会根据校验规则自动生成 | ReactNode | - | |
| hidden | 是否隐藏字段(依然会收集和校验字段) | boolean | false | |
| hidden | 是否隐藏字段(依然会收集和校验字段) | boolean | false | 4.4.0 |
| htmlFor | 设置子元素 label `htmlFor` 属性 | string | - | |
| initialValue | 设置子元素默认值,如果与 Form 的 `initialValues` 冲突则以 Form 为准 | string | - | 4.2.0 |
| label | `label` 标签的文本 | ReactNode | - | |
@ -192,19 +192,19 @@ Form 通过增量更新方式,只更新被修改的字段相关组件以达到
Form.List 渲染表单相关操作函数。
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| add | 新增表单项 | (defaultValue?: any, insertIndex?: number) => void | insertIndex: 4.6.0 |
| move | 移动表单项 | (from: number, to: number) => void | - |
| remove | 删除表单项 | (index: number \| number\[]) => void | number\[]: 4.5.0 |
| 参数 | 说明 | 类型 | 默认值 |
| ------ | ---------- | -------------------------------------------------- | ------------------ |
| add | 新增表单项 | (defaultValue?: any, insertIndex?: number) => void | insertIndex: 4.6.0 |
| move | 移动表单项 | (from: number, to: number) => void | - |
| remove | 删除表单项 | (index: number \| number\[]) => void | number\[]: 4.5.0 |
## Form.ErrorList
4.7.0 新增。错误展示组件,仅限配合 Form.List 的 rules 一同使用。参考[示例](#components-form-demo-dynamic-form-item)。
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| errors | 错误列表 | ReactNode\[] | - |
| 参数 | 说明 | 类型 | 默认值 |
| ------ | -------- | ------------ | ------ |
| errors | 错误列表 | ReactNode\[] | - |
## Form.Provider
@ -285,13 +285,13 @@ validateFields()
#### FieldData
| 名称 | 说明 | 类型 |
| --- | --- | --- |
| errors | 错误信息 | string\[] |
| name | 字段名称 | [NamePath](#NamePath)\[] |
| touched | 是否被用户操作过 | boolean |
| validating | 是否正在校验 | boolean |
| value | 字段对应值 | any |
| 名称 | 说明 | 类型 |
| ---------- | ---------------- | ------------------------ |
| errors | 错误信息 | string\[] |
| name | 字段名称 | [NamePath](#NamePath)\[] |
| touched | 是否被用户操作过 | boolean |
| validating | 是否正在校验 | boolean |
| value | 字段对应值 | any |
#### Rule
@ -434,3 +434,7 @@ React 中异步更新会导致受控组件交互行为异常。当用户交互
类似问题:[#28370](https://github.com/ant-design/ant-design/issues/28370) [#27994](https://github.com/ant-design/ant-design/issues/27994)
滚动依赖于表单控件元素上绑定的 `id` 字段,如果自定义控件没有将 `id` 赋到正确的元素上,这个功能将失效。你可以参考这个 [codesandbox](https://codesandbox.io/s/antd-reproduction-template-forked-25nul?file=/index.js)。
### `setFieldsValue` 不会触发 `onFieldsChange``onValuesChange`
是的change 事件仅当用户交互才会触发。该设计是为了防止在 change 事件中调用 `setFieldsValue` 导致的循环问题。

View File

@ -86,7 +86,7 @@ const TextArea = React.forwardRef<TextAreaRef, TextAreaProps>(
// Patch composition onChange when value changed
if (triggerValue !== value) {
handleSetValue(triggerValue);
resolveOnChange(innerRef.current as any, e, onChange, triggerValue);
resolveOnChange(e.currentTarget, e, onChange, triggerValue);
}
onCompositionEnd?.(e);
@ -99,7 +99,7 @@ const TextArea = React.forwardRef<TextAreaRef, TextAreaProps>(
}
handleSetValue(triggerValue);
resolveOnChange(innerRef.current as any, e, onChange, triggerValue);
resolveOnChange(e.currentTarget, e, onChange, triggerValue);
};
// ============================== Reset ===============================
@ -107,7 +107,7 @@ const TextArea = React.forwardRef<TextAreaRef, TextAreaProps>(
handleSetValue('', () => {
innerRef.current?.focus();
});
resolveOnChange(innerRef.current as any, e, onChange);
resolveOnChange(innerRef.current?.resizableTextArea?.textArea!, e, onChange);
};
const prefixCls = getPrefixCls('input', customizePrefixCls);

View File

@ -379,4 +379,36 @@ describe('TextArea allowClear', () => {
const wrapper = mount(<Input.TextArea defaultValue="Light" value={undefined} />);
expect(wrapper.find('textarea').at(0).getDOMNode().value).toBe('Light');
});
it('onChange event should return HTMLInputElement', () => {
const onChange = jest.fn();
const wrapper = mount(<Input.TextArea onChange={onChange} allowClear />);
function isNativeElement() {
expect(onChange).toHaveBeenCalledWith(
expect.objectContaining({
target: wrapper.find('textarea').instance(),
}),
);
onChange.mockReset();
}
// Change
wrapper.find('textarea').simulate('change', {
target: {
value: 'bamboo',
},
});
isNativeElement();
// Composition End
wrapper.find('textarea').instance().value = 'light'; // enzyme not support change `currentTarget`
wrapper.find('textarea').simulate('compositionEnd');
isNativeElement();
// Reset
wrapper.find('.ant-input-clear-icon').first().simulate('click');
isNativeElement();
});
});

View File

@ -38,5 +38,5 @@ A long list can be divided into several pages using `Pagination`, and only one p
| simple | Whether to use simple mode | boolean | - | |
| size | Specify the size of `Pagination`, can be set to `small` | `default` \| `small` | `default` | |
| total | Total number of data items | number | 0 | |
| onChange | Called when the page number is changed, and it takes the resulting page number and pageSize as its arguments | function(page, pageSize) | - | |
| onChange | Called when the page number or `pageSize` is changed, and it takes the resulting page number and pageSize as its arguments | function(page, pageSize) | - | |
| onShowSizeChange | Called when `pageSize` is changed | function(current, size) | - | |

View File

@ -39,5 +39,5 @@ cover: https://gw.alipayobjects.com/zos/alicdn/1vqv2bj68/Pagination.svg
| simple | 当添加该属性时,显示为简单分页 | boolean | - | |
| size | 当为 `small` 时,是小尺寸分页 | `default` \| `small` | `default` | |
| total | 数据总数 | number | 0 | |
| onChange | 页码改变的回调,参数是改变后的页码及每页条数 | function(page, pageSize) | - | |
| onChange | 页码`pageSize` 改变的回调,参数是改变后的页码及每页条数 | function(page, pageSize) | - | |
| onShowSizeChange | pageSize 变化的回调 | function(current, size) | - | |

View File

@ -239,7 +239,6 @@ a {
&[disabled] {
color: @disabled-color;
cursor: not-allowed;
pointer-events: none;
}
}

View File

@ -452,7 +452,7 @@ export default function useSelection<RecordType>(
if (expandType === 'nest') {
mergedIndeterminate = indeterminate;
devWarning(
!(typeof checkboxProps?.indeterminate === 'boolean'),
typeof checkboxProps?.indeterminate !== 'boolean',
'Table',
'set `indeterminate` using `rowSelection.getCheckboxProps` is not allowed with tree structured dataSource.',
);

View File

@ -289,7 +289,7 @@ Besides, the breaking change is changing `dataIndex` from nest string path like
## FAQ
### How to hide pagination when single page or not data?
### How to hide pagination when single page or no data?
You can set `hideOnSinglePage` with `pagination` prop.

View File

@ -47,14 +47,12 @@
.@{tab-prefix-cls}-nav-list {
position: relative;
display: flex;
flex: 1 0 auto; // fix safari scroll problem
transition: transform @animation-duration-slow;
}
// >>>>>>>> Operations
.@{tab-prefix-cls}-nav-operations {
display: flex;
flex: 1 0 auto; // fix safari scroll problem
align-self: stretch;
&-hidden {

View File

@ -146,6 +146,7 @@
.@{tab-prefix-cls}-nav-list,
.@{tab-prefix-cls}-nav-operations {
flex: 1 0 auto; // fix safari scroll problem
flex-direction: column;
}
}

View File

@ -2,6 +2,7 @@ import { TimePickerLocale } from '../index';
const locale: TimePickerLocale = {
placeholder: 'Vælg tid',
rangePlaceholder: ['Starttidspunkt', 'Sluttidspunkt'],
};
export default locale;

View File

@ -73,7 +73,7 @@ const InternalUpload: React.ForwardRefRenderFunction<unknown, UploadProps> = (pr
}, []);
// Control mode will auto fill file uid if not provided
React.useEffect(() => {
React.useMemo(() => {
const timestamp = Date.now();
(fileList || []).forEach((file, index) => {
@ -403,7 +403,7 @@ interface CompoundedComponent
React.PropsWithChildren<UploadProps> & React.RefAttributes<any>
> {
Dragger: typeof Dragger;
LIST_IGNORE: {};
LIST_IGNORE: string;
}
const Upload = React.forwardRef<unknown, UploadProps>(InternalUpload) as CompoundedComponent;

View File

@ -1,12 +1,12 @@
/* eslint-disable react/no-string-refs, react/prefer-es6-class */
import React from 'react';
import { mount } from 'enzyme';
import { mount, render } from 'enzyme';
import { act } from 'react-dom/test-utils';
import produce from 'immer';
import { cloneDeep } from 'lodash';
import Upload from '..';
import Form from '../../form';
import { getFileItem, removeFileItem } from '../utils';
import { getFileItem, removeFileItem, isImageUrl } from '../utils';
import { setup, teardown } from './mock';
import { resetWarned } from '../../_util/devWarning';
import mountTest from '../../../tests/shared/mountTest';
@ -285,6 +285,20 @@ describe('Upload', () => {
jest.useRealTimers();
});
it('should be able to get uid at first', () => {
const fileList = [
{
name: 'foo.png',
status: 'done',
url: 'http://www.baidu.com/xxx.png',
},
];
render(<Upload fileList={fileList} />);
fileList.forEach(file => {
expect(file.uid).toBeDefined();
});
});
describe('util', () => {
it('should be able to get fileItem', () => {
const file = { uid: '-1', name: 'item.jpg' };
@ -353,6 +367,13 @@ describe('Upload', () => {
const targetItem = removeFileItem(file, fileList);
expect(targetItem).toBe(null);
});
it('isImageUrl should work correctly when file.url is null', () => {
const file = {
url: null,
};
expect(isImageUrl(file)).toBe(true);
});
});
it('should support linkProps as object', () => {

View File

@ -54,7 +54,7 @@ export const isImageUrl = (file: UploadFile): boolean => {
if (file.type && !file.thumbUrl) {
return isImageFileType(file.type);
}
const url: string = (file.thumbUrl || file.url) as string;
const url: string = (file.thumbUrl || file.url || '') as string;
const extension = extname(url);
if (
/^data:image\//.test(url) ||

View File

@ -125,7 +125,7 @@ Where the src/myStylesReplacement.less file loads the same files as the index.le
### Use a postcss processor to scope all styles
See an example of usage with gulp and [postcss-prefixwrap](https://github.com/dbtedman/postcss-prefixwrap) : https://gist.github.com/sbusch/a90eafaf5a5b61c6d6172da6ff76ddaa
See an example of usage with [gulp and postcss-prefixwrap](https://gist.github.com/sbusch/a90eafaf5a5b61c6d6172da6ff76ddaa).
## Not working?

View File

@ -9,8 +9,9 @@ title: Third-Party Libraries
| --- | --- |
| Visualization and charts | [AntV Data Visualization](https://antv.vision/en) [🔥 AntV Charting Library](https://g2plot.antv.vision/en) [BizCharts](https://github.com/alibaba/BizCharts) [recharts](https://github.com/recharts/recharts/) [viser](https://viserjs.github.io/) |
| React Hooks Library | [ahooks](https://github.com/alibaba/hooks) |
| React Form Library | [Formily](https://github.com/alibaba/formily) [react-hook-form](https://github.com/react-hook-form/react-hook-form) [formik](https://github.com/formium/formik) |
| Router | [react-router](https://github.com/ReactTraining/react-router) |
| Layout |[react-grid-layout](https://github.com/react-grid-layout/react-grid-layout) [react-grid-system](https://github.com/sealninja/react-grid-system) [rc-dock](https://github.com/ticlo/rc-dock) |
| Layout | [react-grid-layout](https://github.com/react-grid-layout/react-grid-layout) [react-grid-system](https://github.com/sealninja/react-grid-system) [rc-dock](https://github.com/ticlo/rc-dock) |
| Drag and drop | [react-beautiful-dnd](https://github.com/atlassian/react-beautiful-dnd/) [react-dnd](https://github.com/gaearon/react-dnd) [react-sortable-hoc](https://github.com/clauderic/react-sortable-hoc) |
| Code Editor | [react-codemirror2](https://github.com/scniro/react-codemirror2) [react-monaco-editor](https://github.com/superRaytin/react-monaco-editor) |
| Rich Text Editor | [react-quill](https://github.com/zenoamaro/react-quill) [braft-editor](https://github.com/margox/braft-editor) |

View File

@ -9,8 +9,9 @@ title: 社区精选组件
| --- | --- |
| 可视化图表 | [AntV 数据可视化解决方案](https://antv.vision/zh) [🔥 AntV 图表库](https://g2plot.antv.vision/zh) [BizCharts](https://github.com/alibaba/BizCharts) [recharts](https://github.com/recharts/recharts/) [viser](https://viserjs.github.io/) |
| React Hooks 库 | [ahooks](https://github.com/alibaba/hooks) |
| React 表单库 | [Formily](https://github.com/alibaba/formily) [react-hook-form](https://github.com/react-hook-form/react-hook-form) [formik](https://github.com/formium/formik) |
| 路由 | [react-router](https://github.com/ReactTraining/react-router) |
| 布局 |[react-grid-layout](https://github.com/react-grid-layout/react-grid-layout) [react-grid-system](https://github.com/sealninja/react-grid-system) [rc-dock](https://github.com/ticlo/rc-dock) |
| 布局 | [react-grid-layout](https://github.com/react-grid-layout/react-grid-layout) [react-grid-system](https://github.com/sealninja/react-grid-system) [rc-dock](https://github.com/ticlo/rc-dock) |
| 拖拽 | [react-beautiful-dnd](https://github.com/atlassian/react-beautiful-dnd/) [react-dnd](https://github.com/gaearon/react-dnd) [react-sortable-hoc](https://github.com/clauderic/react-sortable-hoc) |
| 代码编辑器 | [react-codemirror2](https://github.com/scniro/react-codemirror2) [react-monaco-editor](https://github.com/superRaytin/react-monaco-editor) |
| 富文本编辑器 | [react-quill](https://github.com/zenoamaro/react-quill) [braft-editor](https://github.com/margox/braft-editor) |

View File

@ -1,6 +1,6 @@
{
"name": "antd",
"version": "4.15.1",
"version": "4.15.2",
"description": "An enterprise-class UI design language and React components implementation",
"title": "Ant Design",
"keywords": [
@ -46,6 +46,7 @@
"unpkg": "dist/antd.min.js",
"typings": "lib/index.d.ts",
"scripts": {
"prepare": "husky install",
"api-collection": "antd-tools run api-collection",
"authors": "node ./scripts/generate-authors",
"build": "npm run compile && NODE_OPTIONS='--max-old-space-size=4096' npm run dist",
@ -97,11 +98,6 @@
"install-react-16": "npm i --no-save react@16 react-dom@16 react-test-renderer@16 enzyme-adapter-react-16",
"argos": "argos upload imageSnapshots"
},
"husky": {
"hooks": {
"pre-commit": "pretty-quick --staged"
}
},
"browserslist": [
"> 0.5%",
"last 2 versions",
@ -211,13 +207,13 @@
"eslint-plugin-markdown": "^2.0.0",
"eslint-plugin-react": "^7.20.6",
"eslint-plugin-react-hooks": "^4.1.2",
"eslint-plugin-unicorn": "^29.0.0",
"eslint-plugin-unicorn": "^30.0.0",
"fetch-jsonp": "^1.1.3",
"fs-extra": "^9.0.0",
"full-icu": "^1.3.0",
"glob": "^7.1.4",
"http-server": "^0.12.0",
"husky": "^4.0.3",
"husky": "^6.0.0",
"identity-obj-proxy": "^3.0.0",
"ignore-emit-webpack-plugin": "^2.0.6",
"immer": "^9.0.1",
@ -226,7 +222,7 @@
"intersection-observer": "^0.12.0",
"jest": "^26.0.0",
"jest-image-snapshot": "^4.0.0",
"jest-puppeteer": "^4.4.0",
"jest-puppeteer": "^5.0.1",
"jquery": "^3.4.1",
"jsdom": "^16.0.0",
"jsonml.js": "^0.1.0",

View File

@ -149,8 +149,8 @@ class ComponentDoc extends React.Component {
return (
<article>
<Helmet encodeSpecialCharacters={false}>
{helmetTitle && <title>{helmetTitle}</title>}
{helmetTitle && <meta property="og:title" content={helmetTitle} />}
<title>{helmetTitle}</title>
<meta property="og:title" content={helmetTitle} />
{contentChild && <meta name="description" content={contentChild} />}
</Helmet>
<Affix className="toc-affix" offsetTop={16}>

View File

@ -115,7 +115,7 @@ class MainContent extends Component {
if (this.scroller) {
this.scroller.destroy();
}
window.removeEventListener('load', this.handleInitialHashOnLoad);
window.removeEventListener('load', this.handleLoad);
window.removeEventListener('hashchange', this.handleHashChange);
clearTimeout(this.timeout);
}

View File

@ -22,11 +22,17 @@ export default ({ isZhCN, responsive, onTriggerFocus }: SearchBoxProps) => {
}
React.useEffect(() => {
document.addEventListener('keyup', event => {
function keyupHandler(event: KeyboardEvent) {
if (event.keyCode === 83 && event.target === document.body) {
inputRef.current.focus();
}
});
}
document.addEventListener('keyup', keyupHandler);
return () => {
document.removeEventListener('keyup', keyupHandler);
};
}, []);
return (