mirror of
https://gitee.com/ant-design/ant-design.git
synced 2024-12-01 03:29:39 +08:00
commit
0c8a84c4cc
1
.husky/.gitignore
vendored
Normal file
1
.husky/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
_
|
4
.husky/pre-commit
Executable file
4
.husky/pre-commit
Executable file
@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
npx --no-install pretty-quick --staged
|
@ -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`
|
||||
|
@ -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`
|
||||
|
@ -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),
|
||||
});
|
||||
|
@ -62,7 +62,7 @@ const BreadcrumbItem: BreadcrumbItemInterface = ({
|
||||
return (
|
||||
<span>
|
||||
{link}
|
||||
{separator && separator !== '' && (
|
||||
{separator && (
|
||||
<span className={`${prefixCls}-separator`}>{separator}</span>
|
||||
)}
|
||||
</span>
|
||||
|
@ -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();
|
||||
});
|
||||
});
|
||||
|
@ -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);
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { imageDemoTest } from '../../../tests/shared/imageTest';
|
||||
|
||||
describe('Dropdown image', () => {
|
||||
imageDemoTest('dropdown');
|
||||
imageDemoTest('dropdown', { skip: ['dropdown-button.md'] });
|
||||
});
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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` 导致的循环问题。
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
});
|
||||
});
|
||||
|
@ -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) | - | |
|
||||
|
@ -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) | - | |
|
||||
|
@ -239,7 +239,6 @@ a {
|
||||
&[disabled] {
|
||||
color: @disabled-color;
|
||||
cursor: not-allowed;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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.',
|
||||
);
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ import { TimePickerLocale } from '../index';
|
||||
|
||||
const locale: TimePickerLocale = {
|
||||
placeholder: 'Vælg tid',
|
||||
rangePlaceholder: ['Starttidspunkt', 'Sluttidspunkt'],
|
||||
};
|
||||
|
||||
export default locale;
|
||||
|
@ -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;
|
||||
|
@ -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', () => {
|
||||
|
@ -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) ||
|
||||
|
@ -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?
|
||||
|
||||
|
@ -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) |
|
||||
|
@ -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) |
|
||||
|
14
package.json
14
package.json
@ -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",
|
||||
|
@ -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}>
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 (
|
||||
|
Loading…
Reference in New Issue
Block a user