mirror of
https://github.com/ant-design/ant-design.git
synced 2025-01-18 06:03:38 +08:00
chore: merge master
This commit is contained in:
commit
91245c16ad
@ -15,6 +15,17 @@ timeline: true
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## 4.21.3
|
||||||
|
|
||||||
|
`2022-06-17`
|
||||||
|
|
||||||
|
- 🐞 Fix Table customize `filterDropdown` with Menu should not break default `selectable`. [#36098](https://github.com/ant-design/ant-design/pull/36098)
|
||||||
|
- 🐞 Fix Input.Textarea cannot focus after click clear icon in controlled mode. [#34728](https://github.com/ant-design/ant-design/pull/34728) [@Pulset](https://github.com/Pulset)
|
||||||
|
- TypeScript
|
||||||
|
- 🤖 Tree.DirectoryTree supports generic DataNode type. [#36092](https://github.com/ant-design/ant-design/pull/36092) [@JaylanChen](https://github.com/JaylanChen)
|
||||||
|
- 🤖 Export `RefSelectProps` from `Select`. [#34732](https://github.com/ant-design/ant-design/pull/34732) [@chentsulin](https://github.com/chentsulin)
|
||||||
|
- 🤖 Export `FormRule`, `FormListFieldData`, `FormListOperation` from `Form`. [#34735](https://github.com/ant-design/ant-design/pull/34735) [@chentsulin](https://github.com/chentsulin)
|
||||||
|
|
||||||
## 4.21.2
|
## 4.21.2
|
||||||
|
|
||||||
`2022-06-15`
|
`2022-06-15`
|
||||||
|
@ -15,6 +15,17 @@ timeline: true
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## 4.21.3
|
||||||
|
|
||||||
|
`2022-06-17`
|
||||||
|
|
||||||
|
- 🐞 修复 Table 自定义 `filterDropdown` 中使用 Menu 会被修改默认 `selectable` 的问题。[#36098](https://github.com/ant-design/ant-design/pull/36098)
|
||||||
|
- 🐞 修复 Input.Textarea 受控时点击清除图标后无法聚焦的问题。[#34728](https://github.com/ant-design/ant-design/pull/34728) [@Pulset](https://github.com/Pulset)
|
||||||
|
- TypeScript
|
||||||
|
- 🤖 修复 Tree.DirectoryTree 不支持泛型的问题。[#36092](https://github.com/ant-design/ant-design/pull/36092) [@JaylanChen](https://github.com/JaylanChen)
|
||||||
|
- 🤖 从 `Select` 导出类型 `RefSelectProps`。[#34732](https://github.com/ant-design/ant-design/pull/34732) [@chentsulin](https://github.com/chentsulin)
|
||||||
|
- 🤖 从 Form 导出类型 `FormRule`、`FormListFieldData`、`FormListOperation`。[#34735](https://github.com/ant-design/ant-design/pull/34735) [@chentsulin](https://github.com/chentsulin)
|
||||||
|
|
||||||
## 4.21.2
|
## 4.21.2
|
||||||
|
|
||||||
`2022-06-15`
|
`2022-06-15`
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
import * as React from 'react';
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import ResizeObserver from 'rc-resize-observer';
|
import ResizeObserver from 'rc-resize-observer';
|
||||||
import { composeRef } from 'rc-util/lib/ref';
|
import { composeRef } from 'rc-util/lib/ref';
|
||||||
|
import * as React from 'react';
|
||||||
import { ConfigContext } from '../config-provider';
|
import { ConfigContext } from '../config-provider';
|
||||||
import warning from '../_util/warning';
|
import useBreakpoint from '../grid/hooks/useBreakpoint';
|
||||||
import type { Breakpoint } from '../_util/responsiveObserve';
|
import type { Breakpoint } from '../_util/responsiveObserve';
|
||||||
import { responsiveArray } from '../_util/responsiveObserve';
|
import { responsiveArray } from '../_util/responsiveObserve';
|
||||||
import useBreakpoint from '../grid/hooks/useBreakpoint';
|
import warning from '../_util/warning';
|
||||||
import useStyle from './style';
|
|
||||||
import type { AvatarSize } from './SizeContext';
|
import type { AvatarSize } from './SizeContext';
|
||||||
import SizeContext from './SizeContext';
|
import SizeContext from './SizeContext';
|
||||||
|
import useStyle from './style';
|
||||||
|
|
||||||
export interface AvatarProps {
|
export interface AvatarProps {
|
||||||
/** Shape of avatar, options: `circle`, `square` */
|
/** Shape of avatar, options: `circle`, `square` */
|
||||||
@ -241,7 +241,9 @@ const InternalAvatar: React.ForwardRefRenderFunction<unknown, AvatarProps> = (pr
|
|||||||
};
|
};
|
||||||
|
|
||||||
const Avatar = React.forwardRef<unknown, AvatarProps>(InternalAvatar);
|
const Avatar = React.forwardRef<unknown, AvatarProps>(InternalAvatar);
|
||||||
Avatar.displayName = 'Avatar';
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
Avatar.displayName = 'Avatar';
|
||||||
|
}
|
||||||
|
|
||||||
Avatar.defaultProps = {
|
Avatar.defaultProps = {
|
||||||
shape: 'circle' as AvatarProps['shape'],
|
shape: 'circle' as AvatarProps['shape'],
|
||||||
|
@ -318,8 +318,9 @@ const InternalButton: React.ForwardRefRenderFunction<unknown, ButtonProps> = (pr
|
|||||||
};
|
};
|
||||||
|
|
||||||
const Button = React.forwardRef<unknown, ButtonProps>(InternalButton) as CompoundedComponent;
|
const Button = React.forwardRef<unknown, ButtonProps>(InternalButton) as CompoundedComponent;
|
||||||
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
Button.displayName = 'Button';
|
Button.displayName = 'Button';
|
||||||
|
}
|
||||||
|
|
||||||
Button.Group = Group;
|
Button.Group = Group;
|
||||||
Button.__ANT_BUTTON = true;
|
Button.__ANT_BUTTON = true;
|
||||||
|
@ -50,4 +50,9 @@ When data is in the form of dates, such as schedules, timetables, prices calenda
|
|||||||
|
|
||||||
## FAQ
|
## FAQ
|
||||||
|
|
||||||
- [How to use Calendar with customize date library](/docs/react/use-custom-date-library#Calendar)
|
<<<<<<< HEAD
|
||||||
|
|
||||||
|
- # [How to use Calendar with customize date library](/docs/react/use-custom-date-library#Calendar)
|
||||||
|
- [How to use Calendar with customize date library like dayjs](/docs/react/replace-moment#Calendar)
|
||||||
|
- [How to set locale for date-related components](/components/date-picker/#Localization)
|
||||||
|
> > > > > > > origin/master
|
||||||
|
@ -51,4 +51,9 @@ cover: https://gw.alipayobjects.com/zos/antfincdn/dPQmLq08DI/Calendar.svg
|
|||||||
|
|
||||||
## FAQ
|
## FAQ
|
||||||
|
|
||||||
- [如何在 Calendar 中使用自定义日期库](/docs/react/use-custom-date-library#Calendar)
|
<<<<<<< HEAD
|
||||||
|
|
||||||
|
- # [如何在 Calendar 中使用自定义日期库](/docs/react/use-custom-date-library#Calendar)
|
||||||
|
- [如何在 Calendar 中使用自定义日期库(如 dayjs )](/docs/react/replace-moment#Calendar)
|
||||||
|
- [如何给日期类组件配置国际化](/components/date-picker/#%E5%9B%BD%E9%99%85%E5%8C%96%E9%85%8D%E7%BD%AE)
|
||||||
|
> > > > > > > origin/master
|
||||||
|
@ -1,33 +1,34 @@
|
|||||||
import * as React from 'react';
|
import LeftOutlined from '@ant-design/icons/LeftOutlined';
|
||||||
|
import LoadingOutlined from '@ant-design/icons/LoadingOutlined';
|
||||||
|
import RightOutlined from '@ant-design/icons/RightOutlined';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import RcCascader from 'rc-cascader';
|
|
||||||
import type {
|
import type {
|
||||||
SingleCascaderProps as RcSingleCascaderProps,
|
|
||||||
MultipleCascaderProps as RcMultipleCascaderProps,
|
|
||||||
ShowSearchType,
|
|
||||||
FieldNames,
|
|
||||||
BaseOptionType,
|
BaseOptionType,
|
||||||
DefaultOptionType,
|
DefaultOptionType,
|
||||||
|
FieldNames,
|
||||||
|
MultipleCascaderProps as RcMultipleCascaderProps,
|
||||||
|
ShowSearchType,
|
||||||
|
SingleCascaderProps as RcSingleCascaderProps,
|
||||||
} from 'rc-cascader';
|
} from 'rc-cascader';
|
||||||
|
import RcCascader from 'rc-cascader';
|
||||||
import omit from 'rc-util/lib/omit';
|
import omit from 'rc-util/lib/omit';
|
||||||
import RightOutlined from '@ant-design/icons/RightOutlined';
|
import * as React from 'react';
|
||||||
import LoadingOutlined from '@ant-design/icons/LoadingOutlined';
|
|
||||||
import LeftOutlined from '@ant-design/icons/LeftOutlined';
|
|
||||||
import { useContext } from 'react';
|
import { useContext } from 'react';
|
||||||
import warning from '../_util/warning';
|
|
||||||
import { ConfigContext } from '../config-provider';
|
import { ConfigContext } from '../config-provider';
|
||||||
import defaultRenderEmpty from '../config-provider/defaultRenderEmpty';
|
import defaultRenderEmpty from '../config-provider/defaultRenderEmpty';
|
||||||
|
import DisabledContext from '../config-provider/DisabledContext';
|
||||||
import type { SizeType } from '../config-provider/SizeContext';
|
import type { SizeType } from '../config-provider/SizeContext';
|
||||||
import SizeContext from '../config-provider/SizeContext';
|
import SizeContext from '../config-provider/SizeContext';
|
||||||
import DisabledContext from '../config-provider/DisabledContext';
|
import { FormItemInputContext } from '../form/context';
|
||||||
import getIcons from '../select/utils/iconUtil';
|
import getIcons from '../select/utils/iconUtil';
|
||||||
import type { SelectCommonPlacement } from '../_util/motion';
|
import type { SelectCommonPlacement } from '../_util/motion';
|
||||||
import { getTransitionName, getTransitionDirection } from '../_util/motion';
|
import { getTransitionDirection, getTransitionName } from '../_util/motion';
|
||||||
import { FormItemInputContext } from '../form/context';
|
|
||||||
import useStyle from './style';
|
|
||||||
import useSelectStyle from '../select/style';
|
|
||||||
import type { InputStatus } from '../_util/statusUtils';
|
import type { InputStatus } from '../_util/statusUtils';
|
||||||
import { getMergedStatus, getStatusClassNames } from '../_util/statusUtils';
|
import { getMergedStatus, getStatusClassNames } from '../_util/statusUtils';
|
||||||
|
import warning from '../_util/warning';
|
||||||
|
|
||||||
|
import useSelectStyle from '../select/style';
|
||||||
|
import useStyle from './style';
|
||||||
|
|
||||||
// Align the design since we use `rc-select` in root. This help:
|
// Align the design since we use `rc-select` in root. This help:
|
||||||
// - List search content will show all content
|
// - List search content will show all content
|
||||||
@ -317,8 +318,9 @@ const Cascader = React.forwardRef((props: CascaderProps<any>, ref: React.Ref<Cas
|
|||||||
SHOW_PARENT: typeof SHOW_PARENT;
|
SHOW_PARENT: typeof SHOW_PARENT;
|
||||||
SHOW_CHILD: typeof SHOW_CHILD;
|
SHOW_CHILD: typeof SHOW_CHILD;
|
||||||
};
|
};
|
||||||
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
Cascader.displayName = 'Cascader';
|
Cascader.displayName = 'Cascader';
|
||||||
|
}
|
||||||
Cascader.SHOW_PARENT = SHOW_PARENT;
|
Cascader.SHOW_PARENT = SHOW_PARENT;
|
||||||
Cascader.SHOW_CHILD = SHOW_CHILD;
|
Cascader.SHOW_CHILD = SHOW_CHILD;
|
||||||
|
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
import * as React from 'react';
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import RcCheckbox from 'rc-checkbox';
|
import RcCheckbox from 'rc-checkbox';
|
||||||
|
import * as React from 'react';
|
||||||
import { useContext } from 'react';
|
import { useContext } from 'react';
|
||||||
import { FormItemInputContext } from '../form/context';
|
|
||||||
import { GroupContext } from './Group';
|
|
||||||
import { ConfigContext } from '../config-provider';
|
import { ConfigContext } from '../config-provider';
|
||||||
|
import { FormItemInputContext } from '../form/context';
|
||||||
import warning from '../_util/warning';
|
import warning from '../_util/warning';
|
||||||
|
import { GroupContext } from './Group';
|
||||||
|
|
||||||
import useStyle from './style';
|
import useStyle from './style';
|
||||||
|
|
||||||
export interface AbstractCheckboxProps<T> {
|
export interface AbstractCheckboxProps<T> {
|
||||||
@ -143,7 +144,8 @@ const InternalCheckbox: React.ForwardRefRenderFunction<HTMLInputElement, Checkbo
|
|||||||
};
|
};
|
||||||
|
|
||||||
const Checkbox = React.forwardRef<unknown, CheckboxProps>(InternalCheckbox);
|
const Checkbox = React.forwardRef<unknown, CheckboxProps>(InternalCheckbox);
|
||||||
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
Checkbox.displayName = 'Checkbox';
|
Checkbox.displayName = 'Checkbox';
|
||||||
|
}
|
||||||
|
|
||||||
export default Checkbox;
|
export default Checkbox;
|
||||||
|
@ -117,8 +117,9 @@ export function withConfigConsumer<ExportProps extends BasicExportProps>(config:
|
|||||||
const cons: ConstructorProps = Component.constructor as ConstructorProps;
|
const cons: ConstructorProps = Component.constructor as ConstructorProps;
|
||||||
const name = (cons && cons.displayName) || Component.name || 'Component';
|
const name = (cons && cons.displayName) || Component.name || 'Component';
|
||||||
|
|
||||||
SFC.displayName = `withConfigConsumer(${name})`;
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
SFC.displayName = `withConfigConsumer(${name})`;
|
||||||
|
}
|
||||||
return SFC;
|
return SFC;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -337,7 +337,8 @@ const Drawer = React.forwardRef<DrawerRef, DrawerProps>(
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
Drawer.displayName = 'Drawer';
|
Drawer.displayName = 'Drawer';
|
||||||
|
}
|
||||||
|
|
||||||
export default Drawer;
|
export default Drawer;
|
||||||
|
@ -8194,6 +8194,232 @@ exports[`renders ./components/dropdown/demo/placement.md extend context correctl
|
|||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`renders ./components/dropdown/demo/selectable.md extend context correctly 1`] = `
|
||||||
|
Array [
|
||||||
|
<a
|
||||||
|
class="ant-typography ant-dropdown-trigger"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="ant-space ant-space-horizontal ant-space-align-center"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="ant-space-item"
|
||||||
|
style="margin-right:8px"
|
||||||
|
>
|
||||||
|
Selectable
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="ant-space-item"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
aria-label="down"
|
||||||
|
class="anticon anticon-down"
|
||||||
|
role="img"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
data-icon="down"
|
||||||
|
fill="currentColor"
|
||||||
|
focusable="false"
|
||||||
|
height="1em"
|
||||||
|
viewBox="64 64 896 896"
|
||||||
|
width="1em"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a>,
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="ant-dropdown"
|
||||||
|
style="opacity:0"
|
||||||
|
>
|
||||||
|
<ul
|
||||||
|
class="ant-dropdown-menu ant-dropdown-menu-root ant-dropdown-menu-vertical ant-dropdown-menu-light"
|
||||||
|
data-menu-list="true"
|
||||||
|
role="menu"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<li
|
||||||
|
class="ant-dropdown-menu-item ant-dropdown-menu-item-only-child"
|
||||||
|
role="menuitem"
|
||||||
|
tabindex="-1"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-dropdown-menu-title-content"
|
||||||
|
>
|
||||||
|
Item 1
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="ant-tooltip ant-dropdown-menu-inline-collapsed-tooltip"
|
||||||
|
style="opacity:0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="ant-tooltip-content"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="ant-tooltip-arrow"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-tooltip-arrow-content"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="ant-tooltip-inner"
|
||||||
|
role="tooltip"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<li
|
||||||
|
class="ant-dropdown-menu-item ant-dropdown-menu-item-only-child"
|
||||||
|
role="menuitem"
|
||||||
|
tabindex="-1"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-dropdown-menu-title-content"
|
||||||
|
>
|
||||||
|
Item 2
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="ant-tooltip ant-dropdown-menu-inline-collapsed-tooltip"
|
||||||
|
style="opacity:0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="ant-tooltip-content"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="ant-tooltip-arrow"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-tooltip-arrow-content"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="ant-tooltip-inner"
|
||||||
|
role="tooltip"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<li
|
||||||
|
class="ant-dropdown-menu-item ant-dropdown-menu-item-selected ant-dropdown-menu-item-only-child"
|
||||||
|
role="menuitem"
|
||||||
|
tabindex="-1"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-dropdown-menu-title-content"
|
||||||
|
>
|
||||||
|
Item 3
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="ant-tooltip ant-dropdown-menu-inline-collapsed-tooltip"
|
||||||
|
style="opacity:0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="ant-tooltip-content"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="ant-tooltip-arrow"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-tooltip-arrow-content"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="ant-tooltip-inner"
|
||||||
|
role="tooltip"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ul>
|
||||||
|
<div
|
||||||
|
aria-hidden="true"
|
||||||
|
style="display:none"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="ant-tooltip ant-dropdown-menu-inline-collapsed-tooltip"
|
||||||
|
style="opacity:0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="ant-tooltip-content"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="ant-tooltip-arrow"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-tooltip-arrow-content"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="ant-tooltip-inner"
|
||||||
|
role="tooltip"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="ant-tooltip ant-dropdown-menu-inline-collapsed-tooltip"
|
||||||
|
style="opacity:0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="ant-tooltip-content"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="ant-tooltip-arrow"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-tooltip-arrow-content"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="ant-tooltip-inner"
|
||||||
|
role="tooltip"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="ant-tooltip ant-dropdown-menu-inline-collapsed-tooltip"
|
||||||
|
style="opacity:0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="ant-tooltip-content"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="ant-tooltip-arrow"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-tooltip-arrow-content"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="ant-tooltip-inner"
|
||||||
|
role="tooltip"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>,
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`renders ./components/dropdown/demo/sub-menu.md extend context correctly 1`] = `
|
exports[`renders ./components/dropdown/demo/sub-menu.md extend context correctly 1`] = `
|
||||||
Array [
|
Array [
|
||||||
<a
|
<a
|
||||||
|
@ -858,6 +858,46 @@ exports[`renders ./components/dropdown/demo/placement.md correctly 1`] = `
|
|||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`renders ./components/dropdown/demo/selectable.md correctly 1`] = `
|
||||||
|
<a
|
||||||
|
class="ant-typography ant-dropdown-trigger"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="ant-space ant-space-horizontal ant-space-align-center"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="ant-space-item"
|
||||||
|
style="margin-right:8px"
|
||||||
|
>
|
||||||
|
Selectable
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="ant-space-item"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
aria-label="down"
|
||||||
|
class="anticon anticon-down"
|
||||||
|
role="img"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
data-icon="down"
|
||||||
|
fill="currentColor"
|
||||||
|
focusable="false"
|
||||||
|
height="1em"
|
||||||
|
viewBox="64 64 896 896"
|
||||||
|
width="1em"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`renders ./components/dropdown/demo/sub-menu.md correctly 1`] = `
|
exports[`renders ./components/dropdown/demo/sub-menu.md correctly 1`] = `
|
||||||
<a
|
<a
|
||||||
class="ant-dropdown-trigger"
|
class="ant-dropdown-trigger"
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import React from 'react';
|
|
||||||
import { mount } from 'enzyme';
|
import { mount } from 'enzyme';
|
||||||
|
import React from 'react';
|
||||||
import Dropdown from '..';
|
import Dropdown from '..';
|
||||||
import Menu from '../../menu';
|
|
||||||
import mountTest from '../../../tests/shared/mountTest';
|
import mountTest from '../../../tests/shared/mountTest';
|
||||||
import rtlTest from '../../../tests/shared/rtlTest';
|
import rtlTest from '../../../tests/shared/rtlTest';
|
||||||
import { sleep } from '../../../tests/utils';
|
import { act, fireEvent, render, sleep } from '../../../tests/utils';
|
||||||
|
import Menu from '../../menu';
|
||||||
|
|
||||||
describe('Dropdown', () => {
|
describe('Dropdown', () => {
|
||||||
mountTest(() => (
|
mountTest(() => (
|
||||||
@ -99,4 +99,54 @@ describe('Dropdown', () => {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('menu item with group', () => {
|
||||||
|
jest.useFakeTimers();
|
||||||
|
const { container } = render(
|
||||||
|
<Dropdown
|
||||||
|
trigger="click"
|
||||||
|
overlay={
|
||||||
|
<Menu
|
||||||
|
items={[
|
||||||
|
{
|
||||||
|
label: 'grp',
|
||||||
|
type: 'group',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
label: '1',
|
||||||
|
key: 1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<a />
|
||||||
|
</Dropdown>,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Open
|
||||||
|
fireEvent.click(container.querySelector('a'));
|
||||||
|
act(() => {
|
||||||
|
jest.runAllTimers();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Close
|
||||||
|
fireEvent.click(container.querySelector('.ant-dropdown-menu-item'));
|
||||||
|
|
||||||
|
// Force Motion move on
|
||||||
|
for (let i = 0; i < 10; i += 1) {
|
||||||
|
act(() => {
|
||||||
|
jest.runAllTimers();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Motion End
|
||||||
|
fireEvent.animationEnd(container.querySelector('.ant-slide-up-leave-active'));
|
||||||
|
|
||||||
|
expect(container.querySelector('.ant-dropdown-hidden')).toBeTruthy();
|
||||||
|
|
||||||
|
jest.useRealTimers();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
54
components/dropdown/demo/selectable.md
Normal file
54
components/dropdown/demo/selectable.md
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
---
|
||||||
|
order: 10
|
||||||
|
title:
|
||||||
|
zh-CN: 菜单可选选择
|
||||||
|
en-US: Selectable Menu
|
||||||
|
---
|
||||||
|
|
||||||
|
## zh-CN
|
||||||
|
|
||||||
|
为 Menu 添加 `selectable` 属性可以开启选择能力。
|
||||||
|
|
||||||
|
## en-US
|
||||||
|
|
||||||
|
Config Menu `selectable` prop to enable selectable ability.
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { DownOutlined } from '@ant-design/icons';
|
||||||
|
import { Dropdown, Menu, Space, Typography } from 'antd';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
const menu = (
|
||||||
|
<Menu
|
||||||
|
selectable
|
||||||
|
defaultSelectedKeys={['3']}
|
||||||
|
items={[
|
||||||
|
{
|
||||||
|
key: '1',
|
||||||
|
label: 'Item 1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: '2',
|
||||||
|
label: 'Item 2',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: '3',
|
||||||
|
label: 'Item 3',
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
const App: React.FC = () => (
|
||||||
|
<Dropdown overlay={menu}>
|
||||||
|
<Typography.Link>
|
||||||
|
<Space>
|
||||||
|
Selectable
|
||||||
|
<DownOutlined />
|
||||||
|
</Space>
|
||||||
|
</Typography.Link>
|
||||||
|
</Dropdown>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default App;
|
||||||
|
```
|
@ -1,10 +1,11 @@
|
|||||||
import RightOutlined from '@ant-design/icons/RightOutlined';
|
import RightOutlined from '@ant-design/icons/RightOutlined';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import RcDropdown from 'rc-dropdown';
|
import RcDropdown from 'rc-dropdown';
|
||||||
|
import useEvent from 'rc-util/lib/hooks/useEvent';
|
||||||
|
import useMergedState from 'rc-util/lib/hooks/useMergedState';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { ConfigContext } from '../config-provider';
|
import { ConfigContext } from '../config-provider';
|
||||||
import type { OverrideContextProps } from '../menu/OverrideContext';
|
import { OverrideProvider } from '../menu/OverrideContext';
|
||||||
import OverrideContext from '../menu/OverrideContext';
|
|
||||||
import getPlacements from '../_util/placements';
|
import getPlacements from '../_util/placements';
|
||||||
import { cloneElement } from '../_util/reactNode';
|
import { cloneElement } from '../_util/reactNode';
|
||||||
import { tuple } from '../_util/type';
|
import { tuple } from '../_util/type';
|
||||||
@ -118,6 +119,8 @@ const Dropdown: DropdownInterface = props => {
|
|||||||
disabled,
|
disabled,
|
||||||
getPopupContainer,
|
getPopupContainer,
|
||||||
overlayClassName,
|
overlayClassName,
|
||||||
|
visible,
|
||||||
|
onVisibleChange,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const prefixCls = getPrefixCls('dropdown', customizePrefixCls);
|
const prefixCls = getPrefixCls('dropdown', customizePrefixCls);
|
||||||
@ -136,42 +139,35 @@ const Dropdown: DropdownInterface = props => {
|
|||||||
disabled,
|
disabled,
|
||||||
});
|
});
|
||||||
|
|
||||||
const overlayClassNameCustomized = classNames(overlayClassName, hashId, {
|
|
||||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
|
||||||
});
|
|
||||||
|
|
||||||
const triggerActions = disabled ? [] : trigger;
|
const triggerActions = disabled ? [] : trigger;
|
||||||
let alignPoint;
|
let alignPoint;
|
||||||
if (triggerActions && triggerActions.indexOf('contextMenu') !== -1) {
|
if (triggerActions && triggerActions.indexOf('contextMenu') !== -1) {
|
||||||
alignPoint = true;
|
alignPoint = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// =========================== Visible ============================
|
||||||
|
const [mergedVisible, setVisible] = useMergedState(false, {
|
||||||
|
value: visible,
|
||||||
|
});
|
||||||
|
|
||||||
|
const onInnerVisibleChange = useEvent((nextVisible: boolean) => {
|
||||||
|
onVisibleChange?.(nextVisible);
|
||||||
|
setVisible(nextVisible);
|
||||||
|
});
|
||||||
|
|
||||||
|
// =========================== Overlay ============================
|
||||||
|
const overlayClassNameCustomized = classNames(overlayClassName, hashId, {
|
||||||
|
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||||
|
});
|
||||||
|
|
||||||
const builtinPlacements = getPlacements({
|
const builtinPlacements = getPlacements({
|
||||||
arrowPointAtCenter: typeof arrow === 'object' && arrow.pointAtCenter,
|
arrowPointAtCenter: typeof arrow === 'object' && arrow.pointAtCenter,
|
||||||
autoAdjustOverflow: true,
|
autoAdjustOverflow: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
const overlayContext = React.useMemo<OverrideContextProps>(
|
const onMenuClick = React.useCallback(() => {
|
||||||
() => ({
|
setVisible(false);
|
||||||
prefixCls: `${prefixCls}-menu`,
|
}, []);
|
||||||
expandIcon: (
|
|
||||||
<span className={`${prefixCls}-menu-submenu-arrow`}>
|
|
||||||
<RightOutlined className={`${prefixCls}-menu-submenu-arrow-icon`} />
|
|
||||||
</span>
|
|
||||||
),
|
|
||||||
mode: 'vertical',
|
|
||||||
selectable: false,
|
|
||||||
validator: ({ mode }) => {
|
|
||||||
// Warning if use other mode
|
|
||||||
warning(
|
|
||||||
!mode || mode === 'vertical',
|
|
||||||
'Dropdown',
|
|
||||||
`mode="${mode}" is not supported for Dropdown's Menu.`,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
[prefixCls],
|
|
||||||
);
|
|
||||||
|
|
||||||
const renderOverlay = () => {
|
const renderOverlay = () => {
|
||||||
// rc-dropdown already can process the function of overlay, but we have check logic here.
|
// rc-dropdown already can process the function of overlay, but we have check logic here.
|
||||||
@ -189,14 +185,36 @@ const Dropdown: DropdownInterface = props => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<OverrideContext.Provider value={overlayContext}>{overlayNode}</OverrideContext.Provider>
|
<OverrideProvider
|
||||||
|
prefixCls={`${prefixCls}-menu`}
|
||||||
|
expandIcon={
|
||||||
|
<span className={`${prefixCls}-menu-submenu-arrow`}>
|
||||||
|
<RightOutlined className={`${prefixCls}-menu-submenu-arrow-icon`} />
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
mode="vertical"
|
||||||
|
selectable={false}
|
||||||
|
onClick={onMenuClick}
|
||||||
|
validator={({ mode }) => {
|
||||||
|
// Warning if use other mode
|
||||||
|
warning(
|
||||||
|
!mode || mode === 'vertical',
|
||||||
|
'Dropdown',
|
||||||
|
`mode="${mode}" is not supported for Dropdown's Menu.`,
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{overlayNode}
|
||||||
|
</OverrideProvider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ============================ Render ============================
|
||||||
return wrapSSR(
|
return wrapSSR(
|
||||||
<RcDropdown
|
<RcDropdown
|
||||||
alignPoint={alignPoint}
|
alignPoint={alignPoint}
|
||||||
{...props}
|
{...props}
|
||||||
|
visible={mergedVisible}
|
||||||
builtinPlacements={builtinPlacements}
|
builtinPlacements={builtinPlacements}
|
||||||
arrow={!!arrow}
|
arrow={!!arrow}
|
||||||
overlayClassName={overlayClassNameCustomized}
|
overlayClassName={overlayClassNameCustomized}
|
||||||
@ -206,6 +224,7 @@ const Dropdown: DropdownInterface = props => {
|
|||||||
trigger={triggerActions}
|
trigger={triggerActions}
|
||||||
overlay={renderOverlay}
|
overlay={renderOverlay}
|
||||||
placement={getPlacement()}
|
placement={getPlacement()}
|
||||||
|
onVisibleChange={onInnerVisibleChange}
|
||||||
>
|
>
|
||||||
{dropdownTrigger}
|
{dropdownTrigger}
|
||||||
</RcDropdown>,
|
</RcDropdown>,
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import { Rule, RuleObject, RuleRender } from 'rc-field-form/lib/interface';
|
import { Rule, RuleObject, RuleRender } from 'rc-field-form/lib/interface';
|
||||||
import InternalForm, { useForm, FormInstance, FormProps, useWatch } from './Form';
|
|
||||||
import Item, { FormItemProps } from './FormItem';
|
|
||||||
import ErrorList, { ErrorListProps } from './ErrorList';
|
|
||||||
import List, { FormListProps } from './FormList';
|
|
||||||
import { FormProvider } from './context';
|
|
||||||
import warning from '../_util/warning';
|
import warning from '../_util/warning';
|
||||||
|
import { FormProvider } from './context';
|
||||||
|
import ErrorList, { ErrorListProps } from './ErrorList';
|
||||||
|
import InternalForm, { FormInstance, FormProps, useForm, useWatch } from './Form';
|
||||||
|
import Item, { FormItemProps } from './FormItem';
|
||||||
|
import List, { FormListFieldData, FormListOperation, FormListProps } from './FormList';
|
||||||
import useFormInstance from './hooks/useFormInstance';
|
import useFormInstance from './hooks/useFormInstance';
|
||||||
|
|
||||||
type InternalFormType = typeof InternalForm;
|
type InternalFormType = typeof InternalForm;
|
||||||
@ -48,6 +48,8 @@ export {
|
|||||||
RuleObject,
|
RuleObject,
|
||||||
RuleRender,
|
RuleRender,
|
||||||
FormListProps,
|
FormListProps,
|
||||||
|
FormListFieldData,
|
||||||
|
FormListOperation,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Form;
|
export default Form;
|
||||||
|
@ -137,6 +137,8 @@ const Col = React.forwardRef<HTMLDivElement, ColProps>((props, ref) => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
Col.displayName = 'Col';
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
Col.displayName = 'Col';
|
||||||
|
}
|
||||||
|
|
||||||
export default Col;
|
export default Col;
|
||||||
|
@ -134,6 +134,8 @@ const Row = React.forwardRef<HTMLDivElement, RowProps>((props, ref) => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
Row.displayName = 'Row';
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
Row.displayName = 'Row';
|
||||||
|
}
|
||||||
|
|
||||||
export default Row;
|
export default Row;
|
||||||
|
@ -16,213 +16,154 @@ if (
|
|||||||
}
|
}
|
||||||
/* @remove-on-es-build-end */
|
/* @remove-on-es-build-end */
|
||||||
|
|
||||||
export type { AffixProps } from './affix';
|
|
||||||
export { default as Affix } from './affix';
|
export { default as Affix } from './affix';
|
||||||
|
export type { AffixProps } from './affix';
|
||||||
export type { AnchorProps, AnchorLinkProps } from './anchor';
|
|
||||||
export { default as Anchor } from './anchor';
|
|
||||||
|
|
||||||
export type { AutoCompleteProps } from './auto-complete';
|
|
||||||
export { default as AutoComplete } from './auto-complete';
|
|
||||||
|
|
||||||
export type { AlertProps } from './alert';
|
|
||||||
export { default as Alert } from './alert';
|
export { default as Alert } from './alert';
|
||||||
|
export type { AlertProps } from './alert';
|
||||||
export type { AvatarProps } from './avatar';
|
export { default as Anchor } from './anchor';
|
||||||
|
export type { AnchorLinkProps, AnchorProps } from './anchor';
|
||||||
|
export { default as AutoComplete } from './auto-complete';
|
||||||
|
export type { AutoCompleteProps } from './auto-complete';
|
||||||
export { default as Avatar } from './avatar';
|
export { default as Avatar } from './avatar';
|
||||||
|
export type { AvatarProps } from './avatar';
|
||||||
export type { BackTopProps } from './back-top';
|
|
||||||
export { default as BackTop } from './back-top';
|
export { default as BackTop } from './back-top';
|
||||||
|
export type { BackTopProps } from './back-top';
|
||||||
export type { BadgeProps } from './badge';
|
|
||||||
export { default as Badge } from './badge';
|
export { default as Badge } from './badge';
|
||||||
|
export type { BadgeProps } from './badge';
|
||||||
export type { BreadcrumbProps, BreadcrumbItemProps } from './breadcrumb';
|
|
||||||
export { default as Breadcrumb } from './breadcrumb';
|
export { default as Breadcrumb } from './breadcrumb';
|
||||||
|
export type { BreadcrumbItemProps, BreadcrumbProps } from './breadcrumb';
|
||||||
export type { ButtonProps } from './button';
|
|
||||||
export { default as Button } from './button';
|
export { default as Button } from './button';
|
||||||
|
export type { ButtonProps } from './button';
|
||||||
export type { CalendarProps } from './calendar';
|
|
||||||
export { default as Calendar } from './calendar';
|
export { default as Calendar } from './calendar';
|
||||||
|
export type { CalendarProps } from './calendar';
|
||||||
export type { CardProps } from './card';
|
|
||||||
export { default as Card } from './card';
|
export { default as Card } from './card';
|
||||||
|
export type { CardProps } from './card';
|
||||||
export type { CollapseProps, CollapsePanelProps } from './collapse';
|
|
||||||
export { default as Collapse } from './collapse';
|
|
||||||
|
|
||||||
export type { CarouselProps } from './carousel';
|
|
||||||
export { default as Carousel } from './carousel';
|
export { default as Carousel } from './carousel';
|
||||||
|
export type { CarouselProps } from './carousel';
|
||||||
export type { CascaderProps } from './cascader';
|
|
||||||
export { default as Cascader } from './cascader';
|
export { default as Cascader } from './cascader';
|
||||||
|
export type { CascaderProps } from './cascader';
|
||||||
export type { CheckboxProps, CheckboxOptionType } from './checkbox';
|
|
||||||
export { default as Checkbox } from './checkbox';
|
export { default as Checkbox } from './checkbox';
|
||||||
|
export type { CheckboxOptionType, CheckboxProps } from './checkbox';
|
||||||
export type { ColProps } from './col';
|
|
||||||
export { default as Col } from './col';
|
export { default as Col } from './col';
|
||||||
|
export type { ColProps } from './col';
|
||||||
export type { CommentProps } from './comment';
|
export { default as Collapse } from './collapse';
|
||||||
|
export type { CollapsePanelProps, CollapseProps } from './collapse';
|
||||||
export { default as Comment } from './comment';
|
export { default as Comment } from './comment';
|
||||||
|
export type { CommentProps } from './comment';
|
||||||
export { default as ConfigProvider } from './config-provider';
|
export { default as ConfigProvider } from './config-provider';
|
||||||
|
|
||||||
export type { DatePickerProps } from './date-picker';
|
|
||||||
export { default as DatePicker } from './date-picker';
|
export { default as DatePicker } from './date-picker';
|
||||||
|
export type { DatePickerProps } from './date-picker';
|
||||||
export type { DescriptionsProps } from './descriptions';
|
|
||||||
export { default as Descriptions } from './descriptions';
|
export { default as Descriptions } from './descriptions';
|
||||||
|
export type { DescriptionsProps } from './descriptions';
|
||||||
export type { DividerProps } from './divider';
|
|
||||||
export { default as Divider } from './divider';
|
export { default as Divider } from './divider';
|
||||||
|
export type { DividerProps } from './divider';
|
||||||
|
export { default as Drawer } from './drawer';
|
||||||
|
export type { DrawerProps } from './drawer';
|
||||||
|
export { default as Dropdown } from './dropdown';
|
||||||
export type {
|
export type {
|
||||||
DropdownProps,
|
DropdownProps,
|
||||||
// typo, but we need to support it for backwards compatibility
|
// typo, but we need to support it for backwards compatibility
|
||||||
// https://github.com/ant-design/ant-design/pull/35161
|
// https://github.com/ant-design/ant-design/pull/35161
|
||||||
DropdownProps as DropDownProps,
|
DropdownProps as DropDownProps,
|
||||||
} from './dropdown';
|
} from './dropdown';
|
||||||
export { default as Dropdown } from './dropdown';
|
|
||||||
|
|
||||||
export type { DrawerProps } from './drawer';
|
|
||||||
export { default as Drawer } from './drawer';
|
|
||||||
|
|
||||||
export type { EmptyProps } from './empty';
|
|
||||||
export { default as Empty } from './empty';
|
export { default as Empty } from './empty';
|
||||||
|
export type { EmptyProps } from './empty';
|
||||||
export type { FormInstance, FormProps, FormItemProps } from './form';
|
|
||||||
export { default as Form } from './form';
|
export { default as Form } from './form';
|
||||||
|
|
||||||
export { default as Grid } from './grid';
|
|
||||||
|
|
||||||
export type { InputProps, InputRef } from './input';
|
|
||||||
export { default as Input } from './input';
|
|
||||||
|
|
||||||
export type { ImageProps } from './image';
|
|
||||||
export { default as Image } from './image';
|
|
||||||
|
|
||||||
export type { InputNumberProps } from './input-number';
|
|
||||||
export { default as InputNumber } from './input-number';
|
|
||||||
|
|
||||||
export type { LayoutProps, SiderProps } from './layout';
|
|
||||||
export { default as Layout } from './layout';
|
|
||||||
|
|
||||||
export type { ListProps } from './list';
|
|
||||||
export { default as List } from './list';
|
|
||||||
|
|
||||||
export type { ArgsProps as MessageArgsProps } from './message';
|
|
||||||
export { default as message } from './message';
|
|
||||||
|
|
||||||
export type { MenuProps, MenuTheme, SubMenuProps, MenuItemProps } from './menu';
|
|
||||||
export { default as Menu } from './menu';
|
|
||||||
|
|
||||||
export type { MentionProps } from './mentions';
|
|
||||||
export { default as Mentions } from './mentions';
|
|
||||||
|
|
||||||
export type { ModalProps, ModalFuncProps } from './modal';
|
|
||||||
export { default as Modal } from './modal';
|
|
||||||
|
|
||||||
export type { StatisticProps } from './statistic';
|
|
||||||
export { default as Statistic } from './statistic';
|
|
||||||
|
|
||||||
export { default as notification } from './notification';
|
|
||||||
|
|
||||||
export type { PageHeaderProps } from './page-header';
|
|
||||||
export { default as PageHeader } from './page-header';
|
|
||||||
|
|
||||||
export type { PaginationProps } from './pagination';
|
|
||||||
export { default as Pagination } from './pagination';
|
|
||||||
|
|
||||||
export type { PopconfirmProps } from './popconfirm';
|
|
||||||
export { default as Popconfirm } from './popconfirm';
|
|
||||||
|
|
||||||
export type { PopoverProps } from './popover';
|
|
||||||
export { default as Popover } from './popover';
|
|
||||||
|
|
||||||
export type { ProgressProps } from './progress';
|
|
||||||
export { default as Progress } from './progress';
|
|
||||||
|
|
||||||
export type { RadioProps, RadioChangeEvent, RadioGroupProps } from './radio';
|
|
||||||
export { default as Radio } from './radio';
|
|
||||||
|
|
||||||
export type { RateProps } from './rate';
|
|
||||||
export { default as Rate } from './rate';
|
|
||||||
|
|
||||||
export type { ResultProps } from './result';
|
|
||||||
export { default as Result } from './result';
|
|
||||||
|
|
||||||
export type { RowProps } from './row';
|
|
||||||
export { default as Row } from './row';
|
|
||||||
|
|
||||||
export type { SelectProps } from './select';
|
|
||||||
export { default as Select } from './select';
|
|
||||||
|
|
||||||
export type { SegmentedProps } from './segmented';
|
|
||||||
export { default as Segmented } from './segmented';
|
|
||||||
|
|
||||||
export type { SkeletonProps } from './skeleton';
|
|
||||||
export { default as Skeleton } from './skeleton';
|
|
||||||
|
|
||||||
export type { SliderSingleProps } from './slider';
|
|
||||||
export { default as Slider } from './slider';
|
|
||||||
|
|
||||||
export type { SpaceProps } from './space';
|
|
||||||
export { default as Space } from './space';
|
|
||||||
|
|
||||||
export type { SpinProps } from './spin';
|
|
||||||
export { default as Spin } from './spin';
|
|
||||||
|
|
||||||
export type { StepProps, StepsProps } from './steps';
|
|
||||||
export { default as Steps } from './steps';
|
|
||||||
|
|
||||||
export type { SwitchProps } from './switch';
|
|
||||||
export { default as Switch } from './switch';
|
|
||||||
|
|
||||||
export type {
|
export type {
|
||||||
TableProps,
|
FormInstance,
|
||||||
TablePaginationConfig,
|
FormItemProps,
|
||||||
|
FormListFieldData,
|
||||||
|
FormListOperation,
|
||||||
|
FormProps,
|
||||||
|
Rule as FormRule,
|
||||||
|
} from './form';
|
||||||
|
export { default as Grid } from './grid';
|
||||||
|
export { default as Image } from './image';
|
||||||
|
export type { ImageProps } from './image';
|
||||||
|
export { default as Input } from './input';
|
||||||
|
export type { InputProps, InputRef } from './input';
|
||||||
|
export { default as InputNumber } from './input-number';
|
||||||
|
export type { InputNumberProps } from './input-number';
|
||||||
|
export { default as Layout } from './layout';
|
||||||
|
export type { LayoutProps, SiderProps } from './layout';
|
||||||
|
export { default as List } from './list';
|
||||||
|
export type { ListProps } from './list';
|
||||||
|
export { default as Mentions } from './mentions';
|
||||||
|
export type { MentionProps } from './mentions';
|
||||||
|
export { default as Menu } from './menu';
|
||||||
|
export type { MenuItemProps, MenuProps, MenuTheme, SubMenuProps } from './menu';
|
||||||
|
export { default as message } from './message';
|
||||||
|
export type { ArgsProps as MessageArgsProps } from './message';
|
||||||
|
export { default as Modal } from './modal';
|
||||||
|
export type { ModalFuncProps, ModalProps } from './modal';
|
||||||
|
export { default as notification } from './notification';
|
||||||
|
export { default as PageHeader } from './page-header';
|
||||||
|
export type { PageHeaderProps } from './page-header';
|
||||||
|
export { default as Pagination } from './pagination';
|
||||||
|
export type { PaginationProps } from './pagination';
|
||||||
|
export { default as Popconfirm } from './popconfirm';
|
||||||
|
export type { PopconfirmProps } from './popconfirm';
|
||||||
|
export { default as Popover } from './popover';
|
||||||
|
export type { PopoverProps } from './popover';
|
||||||
|
export { default as Progress } from './progress';
|
||||||
|
export type { ProgressProps } from './progress';
|
||||||
|
export { default as Radio } from './radio';
|
||||||
|
export type { RadioChangeEvent, RadioGroupProps, RadioProps } from './radio';
|
||||||
|
export { default as Rate } from './rate';
|
||||||
|
export type { RateProps } from './rate';
|
||||||
|
export { default as Result } from './result';
|
||||||
|
export type { ResultProps } from './result';
|
||||||
|
export { default as Row } from './row';
|
||||||
|
export type { RowProps } from './row';
|
||||||
|
export { default as Segmented } from './segmented';
|
||||||
|
export type { SegmentedProps } from './segmented';
|
||||||
|
export { default as Select } from './select';
|
||||||
|
export type { RefSelectProps, SelectProps } from './select';
|
||||||
|
export { default as Skeleton } from './skeleton';
|
||||||
|
export type { SkeletonProps } from './skeleton';
|
||||||
|
export { default as Slider } from './slider';
|
||||||
|
export type { SliderSingleProps } from './slider';
|
||||||
|
export { default as Space } from './space';
|
||||||
|
export type { SpaceProps } from './space';
|
||||||
|
export { default as Spin } from './spin';
|
||||||
|
export type { SpinProps } from './spin';
|
||||||
|
export { default as Statistic } from './statistic';
|
||||||
|
export type { StatisticProps } from './statistic';
|
||||||
|
export { default as Steps } from './steps';
|
||||||
|
export type { StepProps, StepsProps } from './steps';
|
||||||
|
export { default as Switch } from './switch';
|
||||||
|
export type { SwitchProps } from './switch';
|
||||||
|
export { default as Table } from './table';
|
||||||
|
export type {
|
||||||
ColumnGroupType as TableColumnGroupType,
|
ColumnGroupType as TableColumnGroupType,
|
||||||
ColumnType as TableColumnType,
|
|
||||||
ColumnProps as TableColumnProps,
|
ColumnProps as TableColumnProps,
|
||||||
ColumnsType as TableColumnsType,
|
ColumnsType as TableColumnsType,
|
||||||
|
ColumnType as TableColumnType,
|
||||||
|
TablePaginationConfig,
|
||||||
|
TableProps,
|
||||||
} from './table';
|
} from './table';
|
||||||
export { default as Table } from './table';
|
export { default as Tabs } from './tabs';
|
||||||
|
export type { TabPaneProps, TabsProps } from './tabs';
|
||||||
export type { TransferProps } from './transfer';
|
export { default as Tag } from './tag';
|
||||||
|
export type { TagProps, TagType } from './tag';
|
||||||
|
export { default as TimePicker } from './time-picker';
|
||||||
|
export type { TimePickerProps, TimeRangePickerProps } from './time-picker';
|
||||||
|
export { default as Timeline } from './timeline';
|
||||||
|
export type { TimelineItemProps, TimelineProps } from './timeline';
|
||||||
|
export { default as Tooltip } from './tooltip';
|
||||||
|
export type { TooltipProps } from './tooltip';
|
||||||
export { default as Transfer } from './transfer';
|
export { default as Transfer } from './transfer';
|
||||||
|
export type { TransferProps } from './transfer';
|
||||||
|
export { default as Tree } from './tree';
|
||||||
export type {
|
export type {
|
||||||
TreeProps,
|
|
||||||
AntTreeNodeProps as TreeNodeProps,
|
AntTreeNodeProps as TreeNodeProps,
|
||||||
DataNode as TreeDataNode,
|
DataNode as TreeDataNode,
|
||||||
|
TreeProps,
|
||||||
} from './tree';
|
} from './tree';
|
||||||
export { default as Tree } from './tree';
|
|
||||||
|
|
||||||
export type { TreeSelectProps } from './tree-select';
|
|
||||||
export { default as TreeSelect } from './tree-select';
|
export { default as TreeSelect } from './tree-select';
|
||||||
|
export type { TreeSelectProps } from './tree-select';
|
||||||
export type { TabsProps, TabPaneProps } from './tabs';
|
|
||||||
export { default as Tabs } from './tabs';
|
|
||||||
|
|
||||||
export type { TagProps, TagType } from './tag';
|
|
||||||
export { default as Tag } from './tag';
|
|
||||||
|
|
||||||
export type { TimePickerProps, TimeRangePickerProps } from './time-picker';
|
|
||||||
export { default as TimePicker } from './time-picker';
|
|
||||||
|
|
||||||
export type { TimelineProps, TimelineItemProps } from './timeline';
|
|
||||||
export { default as Timeline } from './timeline';
|
|
||||||
|
|
||||||
export type { TooltipProps } from './tooltip';
|
|
||||||
export { default as Tooltip } from './tooltip';
|
|
||||||
|
|
||||||
export type { TypographyProps } from './typography';
|
|
||||||
export { default as Typography } from './typography';
|
export { default as Typography } from './typography';
|
||||||
|
export type { TypographyProps } from './typography';
|
||||||
export type { UploadProps } from './upload';
|
|
||||||
|
|
||||||
export { default as Upload } from './upload';
|
export { default as Upload } from './upload';
|
||||||
|
export type { UploadFile, UploadProps } from './upload';
|
||||||
export { default as version } from './version';
|
export { default as version } from './version';
|
||||||
|
@ -11,9 +11,9 @@ import type { SizeType } from '../config-provider/SizeContext';
|
|||||||
import SizeContext from '../config-provider/SizeContext';
|
import SizeContext from '../config-provider/SizeContext';
|
||||||
import { FormItemInputContext, NoFormStyle } from '../form/context';
|
import { FormItemInputContext, NoFormStyle } from '../form/context';
|
||||||
import { cloneElement } from '../_util/reactNode';
|
import { cloneElement } from '../_util/reactNode';
|
||||||
import useStyle from './style';
|
|
||||||
import type { InputStatus } from '../_util/statusUtils';
|
import type { InputStatus } from '../_util/statusUtils';
|
||||||
import { getMergedStatus, getStatusClassNames } from '../_util/statusUtils';
|
import { getMergedStatus, getStatusClassNames } from '../_util/statusUtils';
|
||||||
|
import useStyle from './style';
|
||||||
|
|
||||||
type ValueType = string | number;
|
type ValueType = string | number;
|
||||||
|
|
||||||
@ -95,7 +95,6 @@ const InputNumber = React.forwardRef<HTMLInputElement, InputNumberProps>((props,
|
|||||||
[`${prefixCls}-lg`]: mergeSize === 'large',
|
[`${prefixCls}-lg`]: mergeSize === 'large',
|
||||||
[`${prefixCls}-sm`]: mergeSize === 'small',
|
[`${prefixCls}-sm`]: mergeSize === 'small',
|
||||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||||
[`${prefixCls}-readonly`]: readOnly,
|
|
||||||
[`${prefixCls}-borderless`]: !bordered,
|
[`${prefixCls}-borderless`]: !bordered,
|
||||||
[`${prefixCls}-in-form-item`]: isFormItemInput,
|
[`${prefixCls}-in-form-item`]: isFormItemInput,
|
||||||
},
|
},
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
import * as React from 'react';
|
import EyeInvisibleOutlined from '@ant-design/icons/EyeInvisibleOutlined';
|
||||||
|
import EyeOutlined from '@ant-design/icons/EyeOutlined';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import omit from 'rc-util/lib/omit';
|
import omit from 'rc-util/lib/omit';
|
||||||
import EyeOutlined from '@ant-design/icons/EyeOutlined';
|
import * as React from 'react';
|
||||||
import EyeInvisibleOutlined from '@ant-design/icons/EyeInvisibleOutlined';
|
|
||||||
|
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import type { InputRef, InputProps } from './Input';
|
|
||||||
import Input from './Input';
|
|
||||||
import type { ConfigConsumerProps } from '../config-provider';
|
import type { ConfigConsumerProps } from '../config-provider';
|
||||||
import { ConfigConsumer } from '../config-provider';
|
import { ConfigConsumer } from '../config-provider';
|
||||||
|
import type { InputProps, InputRef } from './Input';
|
||||||
|
import Input from './Input';
|
||||||
|
|
||||||
export interface PasswordProps extends InputProps {
|
export interface PasswordProps extends InputProps {
|
||||||
readonly inputPrefixCls?: string;
|
readonly inputPrefixCls?: string;
|
||||||
@ -98,6 +98,8 @@ Password.defaultProps = {
|
|||||||
iconRender: (visible: boolean) => (visible ? <EyeOutlined /> : <EyeInvisibleOutlined />),
|
iconRender: (visible: boolean) => (visible ? <EyeOutlined /> : <EyeInvisibleOutlined />),
|
||||||
};
|
};
|
||||||
|
|
||||||
Password.displayName = 'Password';
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
Password.displayName = 'Password';
|
||||||
|
}
|
||||||
|
|
||||||
export default Password;
|
export default Password;
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
import * as React from 'react';
|
import SearchOutlined from '@ant-design/icons/SearchOutlined';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { composeRef } from 'rc-util/lib/ref';
|
import { composeRef } from 'rc-util/lib/ref';
|
||||||
import SearchOutlined from '@ant-design/icons/SearchOutlined';
|
import * as React from 'react';
|
||||||
|
import Button from '../button';
|
||||||
|
import { ConfigContext } from '../config-provider';
|
||||||
|
import SizeContext from '../config-provider/SizeContext';
|
||||||
|
import { cloneElement } from '../_util/reactNode';
|
||||||
import type { InputProps, InputRef } from './Input';
|
import type { InputProps, InputRef } from './Input';
|
||||||
import Input from './Input';
|
import Input from './Input';
|
||||||
import Button from '../button';
|
|
||||||
import SizeContext from '../config-provider/SizeContext';
|
|
||||||
import { ConfigContext } from '../config-provider';
|
|
||||||
import { cloneElement } from '../_util/reactNode';
|
|
||||||
|
|
||||||
export interface SearchProps extends InputProps {
|
export interface SearchProps extends InputProps {
|
||||||
inputPrefixCls?: string;
|
inputPrefixCls?: string;
|
||||||
@ -165,7 +165,8 @@ const Search = React.forwardRef<InputRef, SearchProps>((props, ref) => {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
Search.displayName = 'Search';
|
Search.displayName = 'Search';
|
||||||
|
}
|
||||||
|
|
||||||
export default Search;
|
export default Search;
|
||||||
|
@ -14,11 +14,13 @@ title:
|
|||||||
Focus with additional option.
|
Focus with additional option.
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
|
import type { InputRef } from 'antd';
|
||||||
|
|
||||||
import { Button, Input, Space, Switch } from 'antd';
|
import { Button, Input, Space, Switch } from 'antd';
|
||||||
import React, { useRef, useState } from 'react';
|
import React, { useRef, useState } from 'react';
|
||||||
|
|
||||||
const App: React.FC = () => {
|
const App: React.FC = () => {
|
||||||
const inputRef = useRef<any>(null);
|
const inputRef = useRef<InputRef>(null);
|
||||||
const [input, setInput] = useState(true);
|
const [input, setInput] = useState(true);
|
||||||
|
|
||||||
const sharedProps = {
|
const sharedProps = {
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
import * as React from 'react';
|
import BarsOutlined from '@ant-design/icons/BarsOutlined';
|
||||||
import { useContext, useRef, useState, useEffect } from 'react';
|
import LeftOutlined from '@ant-design/icons/LeftOutlined';
|
||||||
|
import RightOutlined from '@ant-design/icons/RightOutlined';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import omit from 'rc-util/lib/omit';
|
import omit from 'rc-util/lib/omit';
|
||||||
import BarsOutlined from '@ant-design/icons/BarsOutlined';
|
import * as React from 'react';
|
||||||
import RightOutlined from '@ant-design/icons/RightOutlined';
|
import { useContext, useEffect, useRef, useState } from 'react';
|
||||||
import LeftOutlined from '@ant-design/icons/LeftOutlined';
|
|
||||||
|
|
||||||
import { LayoutContext } from './layout';
|
|
||||||
import { ConfigContext } from '../config-provider';
|
import { ConfigContext } from '../config-provider';
|
||||||
import isNumeric from '../_util/isNumeric';
|
import isNumeric from '../_util/isNumeric';
|
||||||
|
import { LayoutContext } from './layout';
|
||||||
|
|
||||||
const dimensionMaxMap = {
|
const dimensionMaxMap = {
|
||||||
xs: '479.98px',
|
xs: '479.98px',
|
||||||
@ -225,6 +225,8 @@ const Sider = React.forwardRef<HTMLDivElement, SiderProps>(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
Sider.displayName = 'Sider';
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
Sider.displayName = 'Sider';
|
||||||
|
}
|
||||||
|
|
||||||
export default Sider;
|
export default Sider;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import * as React from 'react';
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
import * as React from 'react';
|
||||||
import { ConfigContext } from '../config-provider';
|
import { ConfigContext } from '../config-provider';
|
||||||
import useStyle from './style';
|
import useStyle from './style';
|
||||||
|
|
||||||
@ -39,7 +39,9 @@ function generator({ suffixCls, tagName, displayName }: GeneratorProps) {
|
|||||||
|
|
||||||
return <BasicComponent ref={ref} prefixCls={prefixCls} tagName={tagName} {...props} />;
|
return <BasicComponent ref={ref} prefixCls={prefixCls} tagName={tagName} {...props} />;
|
||||||
});
|
});
|
||||||
Adapter.displayName = displayName;
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
Adapter.displayName = displayName;
|
||||||
|
}
|
||||||
return Adapter;
|
return Adapter;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,17 @@
|
|||||||
import * as React from 'react';
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import RcMentions from 'rc-mentions';
|
import RcMentions from 'rc-mentions';
|
||||||
import type { MentionsProps as RcMentionsProps } from 'rc-mentions/lib/Mentions';
|
import type { MentionsProps as RcMentionsProps } from 'rc-mentions/lib/Mentions';
|
||||||
import { composeRef } from 'rc-util/lib/ref';
|
import { composeRef } from 'rc-util/lib/ref';
|
||||||
// eslint-disable-next-line import/no-named-as-default
|
// eslint-disable-next-line import/no-named-as-default
|
||||||
import Spin from '../spin';
|
import * as React from 'react';
|
||||||
import { ConfigContext } from '../config-provider';
|
import { ConfigContext } from '../config-provider';
|
||||||
|
import defaultRenderEmpty from '../config-provider/defaultRenderEmpty';
|
||||||
import { FormItemInputContext } from '../form/context';
|
import { FormItemInputContext } from '../form/context';
|
||||||
import useStyle from './style';
|
import Spin from '../spin';
|
||||||
import type { InputStatus } from '../_util/statusUtils';
|
import type { InputStatus } from '../_util/statusUtils';
|
||||||
import { getMergedStatus, getStatusClassNames } from '../_util/statusUtils';
|
import { getMergedStatus, getStatusClassNames } from '../_util/statusUtils';
|
||||||
import defaultRenderEmpty from '../config-provider/defaultRenderEmpty';
|
|
||||||
|
import useStyle from './style';
|
||||||
|
|
||||||
export const { Option } = RcMentions;
|
export const { Option } = RcMentions;
|
||||||
|
|
||||||
@ -173,7 +174,9 @@ const InternalMentions: React.ForwardRefRenderFunction<unknown, MentionProps> =
|
|||||||
};
|
};
|
||||||
|
|
||||||
const Mentions = React.forwardRef<unknown, MentionProps>(InternalMentions) as CompoundedComponent;
|
const Mentions = React.forwardRef<unknown, MentionProps>(InternalMentions) as CompoundedComponent;
|
||||||
Mentions.displayName = 'Mentions';
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
Mentions.displayName = 'Mentions';
|
||||||
|
}
|
||||||
Mentions.Option = Option;
|
Mentions.Option = Option;
|
||||||
|
|
||||||
Mentions.getMentions = (value: string = '', config: MentionsConfig = {}): MentionsEntity[] => {
|
Mentions.getMentions = (value: string = '', config: MentionsConfig = {}): MentionsEntity[] => {
|
||||||
|
@ -1,16 +0,0 @@
|
|||||||
import * as React from 'react';
|
|
||||||
import type { MenuProps } from '.';
|
|
||||||
|
|
||||||
// Used for Dropdown only
|
|
||||||
export interface OverrideContextProps {
|
|
||||||
prefixCls?: string;
|
|
||||||
expandIcon?: React.ReactNode;
|
|
||||||
mode?: MenuProps['mode'];
|
|
||||||
selectable?: boolean;
|
|
||||||
validator?: (menuProps: Pick<MenuProps, 'mode'>) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @private Internal Usage. Only used for Dropdown component. Do not use this in your production. */
|
|
||||||
const OverrideContext = React.createContext<OverrideContextProps | null>(null);
|
|
||||||
|
|
||||||
export default OverrideContext;
|
|
42
components/menu/OverrideContext.tsx
Normal file
42
components/menu/OverrideContext.tsx
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import type { MenuProps } from '.';
|
||||||
|
|
||||||
|
// Used for Dropdown only
|
||||||
|
export interface OverrideContextProps {
|
||||||
|
prefixCls?: string;
|
||||||
|
expandIcon?: React.ReactNode;
|
||||||
|
mode?: MenuProps['mode'];
|
||||||
|
selectable?: boolean;
|
||||||
|
validator?: (menuProps: Pick<MenuProps, 'mode'>) => void;
|
||||||
|
onClick?: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @private Internal Usage. Only used for Dropdown component. Do not use this in your production. */
|
||||||
|
const OverrideContext = React.createContext<OverrideContextProps | null>(null);
|
||||||
|
|
||||||
|
/** @private Internal Usage. Only used for Dropdown component. Do not use this in your production. */
|
||||||
|
export const OverrideProvider = ({
|
||||||
|
children,
|
||||||
|
...restProps
|
||||||
|
}: OverrideContextProps & { children: React.ReactNode }) => {
|
||||||
|
const override = React.useContext(OverrideContext);
|
||||||
|
|
||||||
|
const context = React.useMemo(
|
||||||
|
() => ({
|
||||||
|
...override,
|
||||||
|
...restProps,
|
||||||
|
}),
|
||||||
|
[
|
||||||
|
override,
|
||||||
|
restProps.prefixCls,
|
||||||
|
// restProps.expandIcon, Not mark as deps since this is a ReactNode
|
||||||
|
restProps.mode,
|
||||||
|
restProps.selectable,
|
||||||
|
// restProps.validator, Not mark as deps since this is a function
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
return <OverrideContext.Provider value={context}>{children}</OverrideContext.Provider>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default OverrideContext;
|
@ -1,28 +1,30 @@
|
|||||||
import * as React from 'react';
|
import EllipsisOutlined from '@ant-design/icons/EllipsisOutlined';
|
||||||
|
import classNames from 'classnames';
|
||||||
import type { MenuProps as RcMenuProps, MenuRef } from 'rc-menu';
|
import type { MenuProps as RcMenuProps, MenuRef } from 'rc-menu';
|
||||||
import RcMenu, { ItemGroup } from 'rc-menu';
|
import RcMenu, { ItemGroup } from 'rc-menu';
|
||||||
import classNames from 'classnames';
|
import useEvent from 'rc-util/lib/hooks/useEvent';
|
||||||
import omit from 'rc-util/lib/omit';
|
import omit from 'rc-util/lib/omit';
|
||||||
import EllipsisOutlined from '@ant-design/icons/EllipsisOutlined';
|
import * as React from 'react';
|
||||||
import { forwardRef } from 'react';
|
import { forwardRef } from 'react';
|
||||||
import SubMenu, { SubMenuProps } from './SubMenu';
|
|
||||||
import Item, { MenuItemProps } from './MenuItem';
|
|
||||||
import { ConfigContext } from '../config-provider';
|
import { ConfigContext } from '../config-provider';
|
||||||
import warning from '../_util/warning';
|
|
||||||
import type { SiderContextProps } from '../layout/Sider';
|
import type { SiderContextProps } from '../layout/Sider';
|
||||||
import { SiderContext } from '../layout/Sider';
|
import { SiderContext } from '../layout/Sider';
|
||||||
import collapseMotion from '../_util/motion';
|
import collapseMotion from '../_util/motion';
|
||||||
import { cloneElement } from '../_util/reactNode';
|
import { cloneElement } from '../_util/reactNode';
|
||||||
import MenuContext, { MenuTheme } from './MenuContext';
|
import warning from '../_util/warning';
|
||||||
import MenuDivider from './MenuDivider';
|
|
||||||
import type { ItemType } from './hooks/useItems';
|
import type { ItemType } from './hooks/useItems';
|
||||||
import useItems from './hooks/useItems';
|
import useItems from './hooks/useItems';
|
||||||
|
import MenuContext, { MenuTheme } from './MenuContext';
|
||||||
|
import MenuDivider from './MenuDivider';
|
||||||
|
import Item, { MenuItemProps } from './MenuItem';
|
||||||
import OverrideContext from './OverrideContext';
|
import OverrideContext from './OverrideContext';
|
||||||
|
import SubMenu, { SubMenuProps } from './SubMenu';
|
||||||
|
|
||||||
import useStyle from './style';
|
import useStyle from './style';
|
||||||
|
|
||||||
export { MenuDividerProps } from './MenuDivider';
|
|
||||||
|
|
||||||
export { MenuItemGroupProps } from 'rc-menu';
|
export { MenuItemGroupProps } from 'rc-menu';
|
||||||
|
export { MenuDividerProps } from './MenuDivider';
|
||||||
|
export { MenuTheme, SubMenuProps, MenuItemProps };
|
||||||
|
|
||||||
export type MenuMode = 'vertical' | 'vertical-left' | 'vertical-right' | 'horizontal' | 'inline';
|
export type MenuMode = 'vertical' | 'vertical-left' | 'vertical-right' | 'horizontal' | 'inline';
|
||||||
|
|
||||||
@ -46,8 +48,9 @@ type InternalMenuProps = MenuProps &
|
|||||||
};
|
};
|
||||||
|
|
||||||
const InternalMenu = forwardRef<MenuRef, InternalMenuProps>((props, ref) => {
|
const InternalMenu = forwardRef<MenuRef, InternalMenuProps>((props, ref) => {
|
||||||
const override = React.useContext(OverrideContext);
|
const override = React.useContext(OverrideContext) || {};
|
||||||
const overrideObj = override || {};
|
const overrideObj = override || {};
|
||||||
|
|
||||||
const { getPrefixCls, getPopupContainer, direction } = React.useContext(ConfigContext);
|
const { getPrefixCls, getPopupContainer, direction } = React.useContext(ConfigContext);
|
||||||
|
|
||||||
const rootPrefixCls = getPrefixCls();
|
const rootPrefixCls = getPrefixCls();
|
||||||
@ -65,6 +68,7 @@ const InternalMenu = forwardRef<MenuRef, InternalMenuProps>((props, ref) => {
|
|||||||
rootClassName,
|
rootClassName,
|
||||||
mode,
|
mode,
|
||||||
selectable,
|
selectable,
|
||||||
|
onClick,
|
||||||
...restProps
|
...restProps
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
@ -94,6 +98,13 @@ const InternalMenu = forwardRef<MenuRef, InternalMenuProps>((props, ref) => {
|
|||||||
|
|
||||||
overrideObj.validator?.({ mode });
|
overrideObj.validator?.({ mode });
|
||||||
|
|
||||||
|
// ========================== Click ==========================
|
||||||
|
// Tell dropdown that item clicked
|
||||||
|
const onItemClick = useEvent<Required<MenuProps>['onClick']>((...args) => {
|
||||||
|
onClick?.(...args);
|
||||||
|
override?.onClick?.();
|
||||||
|
});
|
||||||
|
|
||||||
// ========================== Mode ===========================
|
// ========================== Mode ===========================
|
||||||
const mergedMode = overrideObj.mode || mode;
|
const mergedMode = overrideObj.mode || mode;
|
||||||
|
|
||||||
@ -152,6 +163,7 @@ const InternalMenu = forwardRef<MenuRef, InternalMenuProps>((props, ref) => {
|
|||||||
overflowedIndicatorPopupClassName={`${prefixCls}-${theme}`}
|
overflowedIndicatorPopupClassName={`${prefixCls}-${theme}`}
|
||||||
mode={mergedMode}
|
mode={mergedMode}
|
||||||
selectable={mergedSelectable}
|
selectable={mergedSelectable}
|
||||||
|
onClick={onItemClick}
|
||||||
{...passedProps}
|
{...passedProps}
|
||||||
inlineCollapsed={mergedInlineCollapsed}
|
inlineCollapsed={mergedInlineCollapsed}
|
||||||
className={menuClassName}
|
className={menuClassName}
|
||||||
@ -202,6 +214,4 @@ class Menu extends React.Component<MenuProps, {}> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export { MenuTheme, SubMenuProps, MenuItemProps };
|
|
||||||
|
|
||||||
export default Menu;
|
export default Menu;
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import React from 'react';
|
|
||||||
import { mount } from 'enzyme';
|
import { mount } from 'enzyme';
|
||||||
import { spyElementPrototype } from 'rc-util/lib/test/domHook';
|
import { spyElementPrototype } from 'rc-util/lib/test/domHook';
|
||||||
|
import React from 'react';
|
||||||
import Popconfirm from '..';
|
import Popconfirm from '..';
|
||||||
import mountTest from '../../../tests/shared/mountTest';
|
import mountTest from '../../../tests/shared/mountTest';
|
||||||
import { sleep, render, fireEvent } from '../../../tests/utils';
|
|
||||||
import rtlTest from '../../../tests/shared/rtlTest';
|
import rtlTest from '../../../tests/shared/rtlTest';
|
||||||
|
import { fireEvent, render, sleep } from '../../../tests/utils';
|
||||||
import Button from '../../button';
|
import Button from '../../button';
|
||||||
|
|
||||||
describe('Popconfirm', () => {
|
describe('Popconfirm', () => {
|
||||||
@ -263,7 +263,7 @@ describe('Popconfirm', () => {
|
|||||||
fireEvent.click(container.querySelector('.ant-btn-primary'));
|
fireEvent.click(container.querySelector('.ant-btn-primary'));
|
||||||
|
|
||||||
await sleep(500);
|
await sleep(500);
|
||||||
expect(container.textContent).toEqual('Unmounted');
|
// expect(container.textContent).toEqual('Unmounted');
|
||||||
expect(error).not.toHaveBeenCalled();
|
expect(error).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -53,7 +53,9 @@ const Popover = React.forwardRef<unknown, PopoverProps>(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
Popover.displayName = 'Popover';
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
Popover.displayName = 'Popover';
|
||||||
|
}
|
||||||
|
|
||||||
Popover.defaultProps = {
|
Popover.defaultProps = {
|
||||||
placement: 'top' as TooltipPlacement,
|
placement: 'top' as TooltipPlacement,
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
import * as React from 'react';
|
|
||||||
import RcCheckbox from 'rc-checkbox';
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
import RcCheckbox from 'rc-checkbox';
|
||||||
import { composeRef } from 'rc-util/lib/ref';
|
import { composeRef } from 'rc-util/lib/ref';
|
||||||
|
import * as React from 'react';
|
||||||
import { useContext } from 'react';
|
import { useContext } from 'react';
|
||||||
import { FormItemInputContext } from '../form/context';
|
|
||||||
import type { RadioProps, RadioChangeEvent } from './interface';
|
|
||||||
import { ConfigContext } from '../config-provider';
|
import { ConfigContext } from '../config-provider';
|
||||||
import RadioGroupContext, { RadioOptionTypeContext } from './context';
|
|
||||||
import DisabledContext from '../config-provider/DisabledContext';
|
import DisabledContext from '../config-provider/DisabledContext';
|
||||||
|
import { FormItemInputContext } from '../form/context';
|
||||||
import warning from '../_util/warning';
|
import warning from '../_util/warning';
|
||||||
|
import RadioGroupContext, { RadioOptionTypeContext } from './context';
|
||||||
|
import type { RadioChangeEvent, RadioProps } from './interface';
|
||||||
|
|
||||||
import useStyle from './style';
|
import useStyle from './style';
|
||||||
|
|
||||||
const InternalRadio: React.ForwardRefRenderFunction<HTMLElement, RadioProps> = (props, ref) => {
|
const InternalRadio: React.ForwardRefRenderFunction<HTMLElement, RadioProps> = (props, ref) => {
|
||||||
@ -84,6 +85,8 @@ const InternalRadio: React.ForwardRefRenderFunction<HTMLElement, RadioProps> = (
|
|||||||
|
|
||||||
const Radio = React.forwardRef<unknown, RadioProps>(InternalRadio);
|
const Radio = React.forwardRef<unknown, RadioProps>(InternalRadio);
|
||||||
|
|
||||||
Radio.displayName = 'Radio';
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
Radio.displayName = 'Radio';
|
||||||
|
}
|
||||||
|
|
||||||
export default Radio;
|
export default Radio;
|
||||||
|
@ -39,7 +39,9 @@ const Rate = React.forwardRef<unknown, RateProps>(({ prefixCls, tooltips, ...pro
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
Rate.displayName = 'Rate';
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
Rate.displayName = 'Rate';
|
||||||
|
}
|
||||||
|
|
||||||
Rate.defaultProps = {
|
Rate.defaultProps = {
|
||||||
character: <StarFilled />,
|
character: <StarFilled />,
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import * as React from 'react';
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import RcSegmented from 'rc-segmented';
|
|
||||||
import type {
|
import type {
|
||||||
|
SegmentedLabeledOption as RcSegmentedLabeledOption,
|
||||||
SegmentedProps as RCSegmentedProps,
|
SegmentedProps as RCSegmentedProps,
|
||||||
SegmentedRawOption,
|
SegmentedRawOption,
|
||||||
SegmentedLabeledOption as RcSegmentedLabeledOption,
|
|
||||||
} from 'rc-segmented';
|
} from 'rc-segmented';
|
||||||
|
import RcSegmented from 'rc-segmented';
|
||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
import { ConfigContext } from '../config-provider';
|
import { ConfigContext } from '../config-provider';
|
||||||
import type { SizeType } from '../config-provider/SizeContext';
|
import type { SizeType } from '../config-provider/SizeContext';
|
||||||
@ -103,7 +103,10 @@ const Segmented = React.forwardRef<HTMLDivElement, SegmentedProps>((props, ref)
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
Segmented.displayName = 'Segmented';
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
Segmented.displayName = 'Segmented';
|
||||||
|
}
|
||||||
|
|
||||||
Segmented.defaultProps = {
|
Segmented.defaultProps = {
|
||||||
options: [],
|
options: [],
|
||||||
};
|
};
|
||||||
|
@ -263,7 +263,7 @@
|
|||||||
// .skeleton-color() {
|
// .skeleton-color() {
|
||||||
// position: relative;
|
// position: relative;
|
||||||
// overflow: hidden;
|
// overflow: hidden;
|
||||||
// background: #fff;
|
// background: transparent;
|
||||||
|
|
||||||
// &::after {
|
// &::after {
|
||||||
// position: absolute;
|
// position: absolute;
|
||||||
@ -276,9 +276,9 @@
|
|||||||
// @skeleton-color 25%,
|
// @skeleton-color 25%,
|
||||||
// @skeleton-to-color 37%,
|
// @skeleton-to-color 37%,
|
||||||
// @skeleton-color 63%
|
// @skeleton-color 63%
|
||||||
// );
|
// );
|
||||||
// animation: ~'@{skeleton-prefix-cls}-loading' 1.4s ease infinite;
|
// animation: ~'@{skeleton-prefix-cls}-loading' 1.4s ease infinite;
|
||||||
// content: "";
|
// content: '';
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import * as React from 'react';
|
import classNames from 'classnames';
|
||||||
import type { SliderProps as RcSliderProps } from 'rc-slider';
|
import type { SliderProps as RcSliderProps } from 'rc-slider';
|
||||||
import RcSlider from 'rc-slider';
|
import RcSlider from 'rc-slider';
|
||||||
import classNames from 'classnames';
|
import * as React from 'react';
|
||||||
|
import { ConfigContext } from '../config-provider';
|
||||||
import type { TooltipPlacement } from '../tooltip';
|
import type { TooltipPlacement } from '../tooltip';
|
||||||
import SliderTooltip from './SliderTooltip';
|
import SliderTooltip from './SliderTooltip';
|
||||||
import { ConfigContext } from '../config-provider';
|
|
||||||
import useStyle from './style';
|
import useStyle from './style';
|
||||||
|
|
||||||
export type SliderMarks = RcSliderProps['marks'];
|
export type SliderMarks = RcSliderProps['marks'];
|
||||||
@ -169,7 +170,9 @@ const Slider = React.forwardRef<unknown, SliderSingleProps | SliderRangeProps>(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
Slider.displayName = 'Slider';
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
Slider.displayName = 'Slider';
|
||||||
|
}
|
||||||
|
|
||||||
Slider.defaultProps = {
|
Slider.defaultProps = {
|
||||||
tipFormatter(value: number) {
|
tipFormatter(value: number) {
|
||||||
|
@ -66,6 +66,15 @@
|
|||||||
// &.@{ant-prefix}-tooltip-open {
|
// &.@{ant-prefix}-tooltip-open {
|
||||||
// border-color: @slider-handle-color-tooltip-open;
|
// border-color: @slider-handle-color-tooltip-open;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
// &::after {
|
||||||
|
// position: absolute;
|
||||||
|
// top: -6px;
|
||||||
|
// right: -6px;
|
||||||
|
// bottom: -6px;
|
||||||
|
// left: -6px;
|
||||||
|
// content: "";
|
||||||
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// &:hover {
|
// &:hover {
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
import * as React from 'react';
|
|
||||||
import RcSwitch from 'rc-switch';
|
|
||||||
import classNames from 'classnames';
|
|
||||||
import LoadingOutlined from '@ant-design/icons/LoadingOutlined';
|
import LoadingOutlined from '@ant-design/icons/LoadingOutlined';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
import RcSwitch from 'rc-switch';
|
||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
import Wave from '../_util/wave';
|
|
||||||
import { ConfigContext } from '../config-provider';
|
import { ConfigContext } from '../config-provider';
|
||||||
import SizeContext from '../config-provider/SizeContext';
|
|
||||||
import DisabledContext from '../config-provider/DisabledContext';
|
import DisabledContext from '../config-provider/DisabledContext';
|
||||||
|
import SizeContext from '../config-provider/SizeContext';
|
||||||
import warning from '../_util/warning';
|
import warning from '../_util/warning';
|
||||||
|
import Wave from '../_util/wave';
|
||||||
|
|
||||||
import useStyle from './style';
|
import useStyle from './style';
|
||||||
|
|
||||||
export type SwitchSize = 'small' | 'default';
|
export type SwitchSize = 'small' | 'default';
|
||||||
@ -99,6 +100,8 @@ const Switch = React.forwardRef<unknown, SwitchProps>(
|
|||||||
) as CompoundedComponent;
|
) as CompoundedComponent;
|
||||||
|
|
||||||
Switch.__ANT_SWITCH = true;
|
Switch.__ANT_SWITCH = true;
|
||||||
Switch.displayName = 'Switch';
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
Switch.displayName = 'Switch';
|
||||||
|
}
|
||||||
|
|
||||||
export default Switch;
|
export default Switch;
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
/* eslint-disable react/no-multi-comp */
|
/* eslint-disable react/no-multi-comp */
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { act } from 'react-dom/test-utils';
|
import { act } from 'react-dom/test-utils';
|
||||||
import { render, fireEvent, waitFor } from '../../../tests/utils';
|
|
||||||
import Table from '..';
|
import Table from '..';
|
||||||
import Input from '../../input';
|
import { fireEvent, render, waitFor } from '../../../tests/utils';
|
||||||
import Tooltip from '../../tooltip';
|
|
||||||
import Button from '../../button';
|
import Button from '../../button';
|
||||||
import Select from '../../select';
|
|
||||||
import ConfigProvider from '../../config-provider';
|
import ConfigProvider from '../../config-provider';
|
||||||
|
import Input from '../../input';
|
||||||
|
import Menu from '../../menu';
|
||||||
|
import Select from '../../select';
|
||||||
|
import Tooltip from '../../tooltip';
|
||||||
|
|
||||||
// https://github.com/Semantic-Org/Semantic-UI-React/blob/72c45080e4f20b531fda2e3e430e384083d6766b/test/specs/modules/Dropdown/Dropdown-test.js#L73
|
// https://github.com/Semantic-Org/Semantic-UI-React/blob/72c45080e4f20b531fda2e3e430e384083d6766b/test/specs/modules/Dropdown/Dropdown-test.js#L73
|
||||||
const nativeEvent = { nativeEvent: { stopImmediatePropagation: () => {} } };
|
const nativeEvent = { nativeEvent: { stopImmediatePropagation: () => {} } };
|
||||||
@ -65,6 +66,14 @@ describe('Table.filter', () => {
|
|||||||
return namesList;
|
return namesList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.useFakeTimers();
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
jest.useRealTimers();
|
||||||
|
});
|
||||||
|
|
||||||
it('not show filter icon when undefined', () => {
|
it('not show filter icon when undefined', () => {
|
||||||
const noFilterColumn = { ...column, filters: undefined };
|
const noFilterColumn = { ...column, filters: undefined };
|
||||||
delete noFilterColumn.onFilter;
|
delete noFilterColumn.onFilter;
|
||||||
@ -106,8 +115,6 @@ describe('Table.filter', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('renders empty menu correctly', () => {
|
it('renders empty menu correctly', () => {
|
||||||
jest.useFakeTimers();
|
|
||||||
|
|
||||||
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => undefined);
|
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => undefined);
|
||||||
const { container } = render(
|
const { container } = render(
|
||||||
createTable({
|
createTable({
|
||||||
@ -129,8 +136,6 @@ describe('Table.filter', () => {
|
|||||||
expect(container.querySelector('.ant-empty')).toBeTruthy();
|
expect(container.querySelector('.ant-empty')).toBeTruthy();
|
||||||
expect(errorSpy).not.toHaveBeenCalled();
|
expect(errorSpy).not.toHaveBeenCalled();
|
||||||
errorSpy.mockRestore();
|
errorSpy.mockRestore();
|
||||||
|
|
||||||
jest.useRealTimers();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders radio filter correctly', async () => {
|
it('renders radio filter correctly', async () => {
|
||||||
@ -613,7 +618,6 @@ describe('Table.filter', () => {
|
|||||||
onChange,
|
onChange,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
jest.useFakeTimers();
|
|
||||||
|
|
||||||
expect(renderedNames(container)).toEqual(['Jack', 'Lucy', 'Tom', 'Jerry']);
|
expect(renderedNames(container)).toEqual(['Jack', 'Lucy', 'Tom', 'Jerry']);
|
||||||
|
|
||||||
@ -665,8 +669,6 @@ describe('Table.filter', () => {
|
|||||||
// What's this? Is that a coverage case? Or check a crash?
|
// What's this? Is that a coverage case? Or check a crash?
|
||||||
const latestItems = getFilterMenu().querySelectorAll('li.ant-dropdown-menu-item');
|
const latestItems = getFilterMenu().querySelectorAll('li.ant-dropdown-menu-item');
|
||||||
fireEvent.click(latestItems[latestItems.length - 1]);
|
fireEvent.click(latestItems[latestItems.length - 1]);
|
||||||
|
|
||||||
jest.useRealTimers();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('should support value types', () => {
|
describe('should support value types', () => {
|
||||||
@ -676,7 +678,6 @@ describe('Table.filter', () => {
|
|||||||
['Bamboo', false],
|
['Bamboo', false],
|
||||||
].forEach(([text, value]) => {
|
].forEach(([text, value]) => {
|
||||||
it(`${typeof value} type`, async () => {
|
it(`${typeof value} type`, async () => {
|
||||||
jest.useFakeTimers();
|
|
||||||
const onChange = jest.fn();
|
const onChange = jest.fn();
|
||||||
const filters = [{ text, value }];
|
const filters = [{ text, value }];
|
||||||
const { container } = render(
|
const { container } = render(
|
||||||
@ -698,8 +699,6 @@ describe('Table.filter', () => {
|
|||||||
|
|
||||||
fireEvent.click(container.querySelector('.ant-dropdown-trigger'));
|
fireEvent.click(container.querySelector('.ant-dropdown-trigger'));
|
||||||
|
|
||||||
jest.useFakeTimers();
|
|
||||||
|
|
||||||
fireEvent.click(container.querySelectorAll('.ant-dropdown-menu-item')[0]);
|
fireEvent.click(container.querySelectorAll('.ant-dropdown-menu-item')[0]);
|
||||||
|
|
||||||
// This test can be remove if refactor
|
// This test can be remove if refactor
|
||||||
@ -733,7 +732,6 @@ describe('Table.filter', () => {
|
|||||||
.querySelector('.ant-table-filter-dropdown')
|
.querySelector('.ant-table-filter-dropdown')
|
||||||
.querySelectorAll('.ant-checkbox-input')[0].checked,
|
.querySelectorAll('.ant-checkbox-input')[0].checked,
|
||||||
).toEqual(false);
|
).toEqual(false);
|
||||||
jest.useRealTimers();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -1831,7 +1829,6 @@ describe('Table.filter', () => {
|
|||||||
|
|
||||||
describe('filter tree mode', () => {
|
describe('filter tree mode', () => {
|
||||||
it('supports filter tree', () => {
|
it('supports filter tree', () => {
|
||||||
jest.useFakeTimers();
|
|
||||||
jest.spyOn(console, 'error').mockImplementation(() => undefined);
|
jest.spyOn(console, 'error').mockImplementation(() => undefined);
|
||||||
const { container } = render(
|
const { container } = render(
|
||||||
createTable({
|
createTable({
|
||||||
@ -1852,7 +1849,6 @@ describe('Table.filter', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('supports search input in filter tree', () => {
|
it('supports search input in filter tree', () => {
|
||||||
jest.useFakeTimers();
|
|
||||||
jest.spyOn(console, 'error').mockImplementation(() => undefined);
|
jest.spyOn(console, 'error').mockImplementation(() => undefined);
|
||||||
const { container } = render(
|
const { container } = render(
|
||||||
createTable({
|
createTable({
|
||||||
@ -1875,7 +1871,6 @@ describe('Table.filter', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('supports search input in filter menu', () => {
|
it('supports search input in filter menu', () => {
|
||||||
jest.useFakeTimers();
|
|
||||||
jest.spyOn(console, 'error').mockImplementation(() => undefined);
|
jest.spyOn(console, 'error').mockImplementation(() => undefined);
|
||||||
const { container } = render(
|
const { container } = render(
|
||||||
createTable({
|
createTable({
|
||||||
@ -1897,7 +1892,6 @@ describe('Table.filter', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should skip search when filters[0].text is ReactNode', () => {
|
it('should skip search when filters[0].text is ReactNode', () => {
|
||||||
jest.useFakeTimers();
|
|
||||||
jest.spyOn(console, 'error').mockImplementation(() => undefined);
|
jest.spyOn(console, 'error').mockImplementation(() => undefined);
|
||||||
const { container } = render(
|
const { container } = render(
|
||||||
createTable({
|
createTable({
|
||||||
@ -1936,7 +1930,6 @@ describe('Table.filter', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should supports filterSearch has type of function', () => {
|
it('should supports filterSearch has type of function', () => {
|
||||||
jest.useFakeTimers();
|
|
||||||
jest.spyOn(console, 'error').mockImplementation(() => undefined);
|
jest.spyOn(console, 'error').mockImplementation(() => undefined);
|
||||||
const { container } = render(
|
const { container } = render(
|
||||||
createTable({
|
createTable({
|
||||||
@ -1974,7 +1967,6 @@ describe('Table.filter', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('supports check all items', () => {
|
it('supports check all items', () => {
|
||||||
jest.useFakeTimers();
|
|
||||||
jest.spyOn(console, 'error').mockImplementation(() => undefined);
|
jest.spyOn(console, 'error').mockImplementation(() => undefined);
|
||||||
const { container } = render(
|
const { container } = render(
|
||||||
createTable({
|
createTable({
|
||||||
@ -2007,7 +1999,6 @@ describe('Table.filter', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('supports check item by selecting it', () => {
|
it('supports check item by selecting it', () => {
|
||||||
jest.useFakeTimers();
|
|
||||||
jest.spyOn(console, 'error').mockImplementation(() => undefined);
|
jest.spyOn(console, 'error').mockImplementation(() => undefined);
|
||||||
const { container } = render(
|
const { container } = render(
|
||||||
createTable({
|
createTable({
|
||||||
@ -2043,7 +2034,6 @@ describe('Table.filter', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('select-all checkbox should change when all items are selected', () => {
|
it('select-all checkbox should change when all items are selected', () => {
|
||||||
jest.useFakeTimers();
|
|
||||||
jest.spyOn(console, 'error').mockImplementation(() => undefined);
|
jest.spyOn(console, 'error').mockImplementation(() => undefined);
|
||||||
const { container } = render(
|
const { container } = render(
|
||||||
createTable({
|
createTable({
|
||||||
@ -2075,7 +2065,6 @@ describe('Table.filter', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('filterMultiple is false - check item', () => {
|
it('filterMultiple is false - check item', () => {
|
||||||
jest.useFakeTimers();
|
|
||||||
jest.spyOn(console, 'error').mockImplementation(() => undefined);
|
jest.spyOn(console, 'error').mockImplementation(() => undefined);
|
||||||
const { container } = render(
|
const { container } = render(
|
||||||
createTable({
|
createTable({
|
||||||
@ -2123,7 +2112,6 @@ describe('Table.filter', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('filterMultiple is false - select item', () => {
|
it('filterMultiple is false - select item', () => {
|
||||||
jest.useFakeTimers();
|
|
||||||
jest.spyOn(console, 'error').mockImplementation(() => undefined);
|
jest.spyOn(console, 'error').mockImplementation(() => undefined);
|
||||||
const { container } = render(
|
const { container } = render(
|
||||||
createTable({
|
createTable({
|
||||||
@ -2170,7 +2158,6 @@ describe('Table.filter', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should select children when select parent', () => {
|
it('should select children when select parent', () => {
|
||||||
jest.useFakeTimers();
|
|
||||||
jest.spyOn(console, 'error').mockImplementation(() => undefined);
|
jest.spyOn(console, 'error').mockImplementation(() => undefined);
|
||||||
const { container } = render(
|
const { container } = render(
|
||||||
createTable({
|
createTable({
|
||||||
@ -2299,7 +2286,6 @@ describe('Table.filter', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('filterDropdown should support filterResetToDefaultFilteredValue', () => {
|
it('filterDropdown should support filterResetToDefaultFilteredValue', () => {
|
||||||
jest.useFakeTimers();
|
|
||||||
jest.spyOn(console, 'error').mockImplementation(() => undefined);
|
jest.spyOn(console, 'error').mockImplementation(() => undefined);
|
||||||
|
|
||||||
const columnFilter = {
|
const columnFilter = {
|
||||||
@ -2347,6 +2333,44 @@ describe('Table.filter', () => {
|
|||||||
expect(container.querySelector('.ant-tree-checkbox-checked+span').textContent).toBe('Girl');
|
expect(container.querySelector('.ant-tree-checkbox-checked+span').textContent).toBe('Girl');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('filterDropdown should not override customize Menu selectable', () => {
|
||||||
|
const onSelect = jest.fn();
|
||||||
|
|
||||||
|
const { container } = render(
|
||||||
|
createTable({
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
...column,
|
||||||
|
filterDropdown: (
|
||||||
|
<div className="custom-filter-dropdown">
|
||||||
|
<Menu
|
||||||
|
onSelect={onSelect}
|
||||||
|
items={[
|
||||||
|
{
|
||||||
|
key: '1',
|
||||||
|
label: 'Item 1',
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Open Filter
|
||||||
|
fireEvent.click(container.querySelector('span.ant-dropdown-trigger'));
|
||||||
|
act(() => {
|
||||||
|
jest.runAllTimers();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Click Item
|
||||||
|
fireEvent.click(container.querySelector('.ant-table-filter-dropdown .ant-dropdown-menu-item'));
|
||||||
|
|
||||||
|
expect(onSelect).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
it('filteredKeys should all be controlled or not controlled', () => {
|
it('filteredKeys should all be controlled or not controlled', () => {
|
||||||
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||||
errorSpy.mockReset();
|
errorSpy.mockReset();
|
||||||
|
@ -40,7 +40,12 @@ const VirtualTable = (props: Parameters<typeof Table>[0]) => {
|
|||||||
const [connectObject] = useState<any>(() => {
|
const [connectObject] = useState<any>(() => {
|
||||||
const obj = {};
|
const obj = {};
|
||||||
Object.defineProperty(obj, 'scrollLeft', {
|
Object.defineProperty(obj, 'scrollLeft', {
|
||||||
get: () => null,
|
get: () => {
|
||||||
|
if (gridRef.current) {
|
||||||
|
return gridRef.current?.state?.scrollLeft;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
set: (scrollLeft: number) => {
|
set: (scrollLeft: number) => {
|
||||||
if (gridRef.current) {
|
if (gridRef.current) {
|
||||||
gridRef.current.scrollTo({ scrollLeft });
|
gridRef.current.scrollTo({ scrollLeft });
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import FilterFilled from '@ant-design/icons/FilterFilled';
|
import FilterFilled from '@ant-design/icons/FilterFilled';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import isEqual from 'lodash/isEqual';
|
import isEqual from 'lodash/isEqual';
|
||||||
import * as React from 'react';
|
|
||||||
import type { FieldDataNode } from 'rc-tree';
|
import type { FieldDataNode } from 'rc-tree';
|
||||||
|
import * as React from 'react';
|
||||||
import type { FilterState } from '.';
|
import type { FilterState } from '.';
|
||||||
import { flattenKeys } from '.';
|
import { flattenKeys } from '.';
|
||||||
import Button from '../../../button';
|
import Button from '../../../button';
|
||||||
@ -13,6 +13,7 @@ import Dropdown from '../../../dropdown';
|
|||||||
import Empty from '../../../empty';
|
import Empty from '../../../empty';
|
||||||
import type { MenuProps } from '../../../menu';
|
import type { MenuProps } from '../../../menu';
|
||||||
import Menu from '../../../menu';
|
import Menu from '../../../menu';
|
||||||
|
import { OverrideProvider } from '../../../menu/OverrideContext';
|
||||||
import Radio from '../../../radio';
|
import Radio from '../../../radio';
|
||||||
import type { EventDataNode } from '../../../tree';
|
import type { EventDataNode } from '../../../tree';
|
||||||
import Tree from '../../../tree';
|
import Tree from '../../../tree';
|
||||||
@ -183,21 +184,9 @@ function FilterDropdown<RecordType>(props: FilterDropdownProps<RecordType>) {
|
|||||||
|
|
||||||
// ====================== Open Keys ======================
|
// ====================== Open Keys ======================
|
||||||
const [openKeys, setOpenKeys] = React.useState<string[]>([]);
|
const [openKeys, setOpenKeys] = React.useState<string[]>([]);
|
||||||
const openRef = React.useRef<number>();
|
|
||||||
const onOpenChange = (keys: string[]) => {
|
const onOpenChange = (keys: string[]) => {
|
||||||
openRef.current = window.setTimeout(() => {
|
setOpenKeys(keys);
|
||||||
setOpenKeys(keys);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
const onMenuClick = () => {
|
|
||||||
window.clearTimeout(openRef.current);
|
|
||||||
};
|
|
||||||
React.useEffect(
|
|
||||||
() => () => {
|
|
||||||
window.clearTimeout(openRef.current);
|
|
||||||
},
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
|
|
||||||
// search in tree mode column filter
|
// search in tree mode column filter
|
||||||
const [searchValue, setSearchValue] = React.useState('');
|
const [searchValue, setSearchValue] = React.useState('');
|
||||||
@ -303,6 +292,7 @@ function FilterDropdown<RecordType>(props: FilterDropdownProps<RecordType>) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let dropdownContent: React.ReactNode;
|
let dropdownContent: React.ReactNode;
|
||||||
|
|
||||||
if (typeof column.filterDropdown === 'function') {
|
if (typeof column.filterDropdown === 'function') {
|
||||||
dropdownContent = column.filterDropdown({
|
dropdownContent = column.filterDropdown({
|
||||||
prefixCls: `${dropdownPrefixCls}-custom`,
|
prefixCls: `${dropdownPrefixCls}-custom`,
|
||||||
@ -395,7 +385,6 @@ function FilterDropdown<RecordType>(props: FilterDropdownProps<RecordType>) {
|
|||||||
multiple={filterMultiple}
|
multiple={filterMultiple}
|
||||||
prefixCls={`${dropdownPrefixCls}-menu`}
|
prefixCls={`${dropdownPrefixCls}-menu`}
|
||||||
className={dropdownMenuClass}
|
className={dropdownMenuClass}
|
||||||
onClick={onMenuClick}
|
|
||||||
onSelect={onSelectKeys}
|
onSelect={onSelectKeys}
|
||||||
onDeselect={onSelectKeys}
|
onDeselect={onSelectKeys}
|
||||||
selectedKeys={selectedKeys}
|
selectedKeys={selectedKeys}
|
||||||
@ -441,6 +430,11 @@ function FilterDropdown<RecordType>(props: FilterDropdownProps<RecordType>) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We should not block customize Menu with additional props
|
||||||
|
if (column.filterDropdown) {
|
||||||
|
dropdownContent = <OverrideProvider selectable={undefined}>{dropdownContent}</OverrideProvider>;
|
||||||
|
}
|
||||||
|
|
||||||
const menu = (
|
const menu = (
|
||||||
<FilterDropdownMenuWrapper className={`${prefixCls}-dropdown`}>
|
<FilterDropdownMenuWrapper className={`${prefixCls}-dropdown`}>
|
||||||
{dropdownContent}
|
{dropdownContent}
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
import * as React from 'react';
|
import CloseOutlined from '@ant-design/icons/CloseOutlined';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import omit from 'rc-util/lib/omit';
|
import omit from 'rc-util/lib/omit';
|
||||||
import CloseOutlined from '@ant-design/icons/CloseOutlined';
|
import * as React from 'react';
|
||||||
|
|
||||||
import CheckableTag from './CheckableTag';
|
|
||||||
import { ConfigContext } from '../config-provider';
|
import { ConfigContext } from '../config-provider';
|
||||||
import type { PresetColorType, PresetStatusColorType } from '../_util/colors';
|
import type { PresetColorType, PresetStatusColorType } from '../_util/colors';
|
||||||
import { PresetColorTypes, PresetStatusColorTypes } from '../_util/colors';
|
import { PresetColorTypes, PresetStatusColorTypes } from '../_util/colors';
|
||||||
import Wave from '../_util/wave';
|
|
||||||
import type { LiteralUnion } from '../_util/type';
|
import type { LiteralUnion } from '../_util/type';
|
||||||
|
import Wave from '../_util/wave';
|
||||||
|
import CheckableTag from './CheckableTag';
|
||||||
|
|
||||||
import useStyle from './style';
|
import useStyle from './style';
|
||||||
|
|
||||||
@ -137,7 +137,9 @@ const InternalTag: React.ForwardRefRenderFunction<HTMLSpanElement, TagProps> = (
|
|||||||
|
|
||||||
const Tag = React.forwardRef<unknown, TagProps>(InternalTag) as TagType;
|
const Tag = React.forwardRef<unknown, TagProps>(InternalTag) as TagType;
|
||||||
|
|
||||||
Tag.displayName = 'Tag';
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
Tag.displayName = 'Tag';
|
||||||
|
}
|
||||||
|
|
||||||
Tag.CheckableTag = CheckableTag;
|
Tag.CheckableTag = CheckableTag;
|
||||||
|
|
||||||
|
@ -2,8 +2,8 @@ import type { Dayjs } from 'dayjs';
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import DatePicker from '../date-picker';
|
import DatePicker from '../date-picker';
|
||||||
import type { PickerTimeProps, RangePickerTimeProps } from '../date-picker/generatePicker';
|
import type { PickerTimeProps, RangePickerTimeProps } from '../date-picker/generatePicker';
|
||||||
import warning from '../_util/warning';
|
|
||||||
import type { InputStatus } from '../_util/statusUtils';
|
import type { InputStatus } from '../_util/statusUtils';
|
||||||
|
import warning from '../_util/warning';
|
||||||
|
|
||||||
const { TimePicker: InternalTimePicker, RangePicker: InternalRangePicker } = DatePicker;
|
const { TimePicker: InternalTimePicker, RangePicker: InternalRangePicker } = DatePicker;
|
||||||
|
|
||||||
@ -61,7 +61,9 @@ const TimePicker = React.forwardRef<any, TimePickerProps>(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
TimePicker.displayName = 'TimePicker';
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
TimePicker.displayName = 'TimePicker';
|
||||||
|
}
|
||||||
|
|
||||||
type MergedTimePicker = typeof TimePicker & {
|
type MergedTimePicker = typeof TimePicker & {
|
||||||
RangePicker: typeof RangePicker;
|
RangePicker: typeof RangePicker;
|
||||||
|
@ -11,6 +11,7 @@ import { getTransitionName } from '../_util/motion';
|
|||||||
import getPlacements, { AdjustOverflow, PlacementsConfig } from '../_util/placements';
|
import getPlacements, { AdjustOverflow, PlacementsConfig } from '../_util/placements';
|
||||||
import { cloneElement, isValidElement } from '../_util/reactNode';
|
import { cloneElement, isValidElement } from '../_util/reactNode';
|
||||||
import type { LiteralUnion } from '../_util/type';
|
import type { LiteralUnion } from '../_util/type';
|
||||||
|
|
||||||
import useStyle from './style';
|
import useStyle from './style';
|
||||||
|
|
||||||
export { AdjustOverflow, PlacementsConfig };
|
export { AdjustOverflow, PlacementsConfig };
|
||||||
@ -282,7 +283,9 @@ const Tooltip = React.forwardRef<unknown, TooltipProps>((props, ref) => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
Tooltip.displayName = 'Tooltip';
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
Tooltip.displayName = 'Tooltip';
|
||||||
|
}
|
||||||
|
|
||||||
Tooltip.defaultProps = {
|
Tooltip.defaultProps = {
|
||||||
placement: 'top' as TooltipPlacement,
|
placement: 'top' as TooltipPlacement,
|
||||||
|
@ -1,24 +1,32 @@
|
|||||||
import * as React from 'react';
|
|
||||||
import classNames from 'classnames';
|
|
||||||
import type RcTree from 'rc-tree';
|
|
||||||
import { conductExpandParent } from 'rc-tree/lib/util';
|
|
||||||
import type { EventDataNode, DataNode, Key } from 'rc-tree/lib/interface';
|
|
||||||
import { convertDataToEntities, convertTreeToData } from 'rc-tree/lib/utils/treeUtil';
|
|
||||||
import FileOutlined from '@ant-design/icons/FileOutlined';
|
import FileOutlined from '@ant-design/icons/FileOutlined';
|
||||||
import FolderOpenOutlined from '@ant-design/icons/FolderOpenOutlined';
|
import FolderOpenOutlined from '@ant-design/icons/FolderOpenOutlined';
|
||||||
import FolderOutlined from '@ant-design/icons/FolderOutlined';
|
import FolderOutlined from '@ant-design/icons/FolderOutlined';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
import type RcTree from 'rc-tree';
|
||||||
|
import type { BasicDataNode } from 'rc-tree';
|
||||||
|
import type { DataNode, EventDataNode, Key } from 'rc-tree/lib/interface';
|
||||||
|
import { conductExpandParent } from 'rc-tree/lib/util';
|
||||||
|
import { convertDataToEntities, convertTreeToData } from 'rc-tree/lib/utils/treeUtil';
|
||||||
|
import * as React from 'react';
|
||||||
import { ConfigContext } from '../config-provider';
|
import { ConfigContext } from '../config-provider';
|
||||||
|
|
||||||
import type { TreeProps, AntdTreeNodeAttribute } from './Tree';
|
import type { AntdTreeNodeAttribute, TreeProps } from './Tree';
|
||||||
import Tree from './Tree';
|
import Tree from './Tree';
|
||||||
import { calcRangeKeys, convertDirectoryKeysToNodes } from './utils/dictUtil';
|
import { calcRangeKeys, convertDirectoryKeysToNodes } from './utils/dictUtil';
|
||||||
|
|
||||||
export type ExpandAction = false | 'click' | 'doubleClick';
|
export type ExpandAction = false | 'click' | 'doubleClick';
|
||||||
|
|
||||||
export interface DirectoryTreeProps extends TreeProps {
|
export interface DirectoryTreeProps<T extends BasicDataNode = DataNode> extends TreeProps<T> {
|
||||||
expandAction?: ExpandAction;
|
expandAction?: ExpandAction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type DirectoryTreeCompoundedComponent = (<T extends BasicDataNode | DataNode = DataNode>(
|
||||||
|
props: React.PropsWithChildren<DirectoryTreeProps<T>> & { ref?: React.Ref<RcTree> },
|
||||||
|
) => React.ReactElement) & {
|
||||||
|
defaultProps: Partial<React.PropsWithChildren<DirectoryTreeProps<any>>>;
|
||||||
|
displayName?: string;
|
||||||
|
};
|
||||||
|
|
||||||
export interface DirectoryTreeState {
|
export interface DirectoryTreeState {
|
||||||
expandedKeys?: Key[];
|
expandedKeys?: Key[];
|
||||||
selectedKeys?: Key[];
|
selectedKeys?: Key[];
|
||||||
@ -191,8 +199,13 @@ const DirectoryTree: React.ForwardRefRenderFunction<RcTree, DirectoryTreeProps>
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const ForwardDirectoryTree = React.forwardRef(DirectoryTree);
|
const ForwardDirectoryTree = React.forwardRef(
|
||||||
ForwardDirectoryTree.displayName = 'DirectoryTree';
|
DirectoryTree,
|
||||||
|
) as unknown as DirectoryTreeCompoundedComponent;
|
||||||
|
|
||||||
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
ForwardDirectoryTree.displayName = 'DirectoryTree';
|
||||||
|
}
|
||||||
|
|
||||||
ForwardDirectoryTree.defaultProps = {
|
ForwardDirectoryTree.defaultProps = {
|
||||||
showIcon: true,
|
showIcon: true,
|
||||||
|
@ -3,6 +3,8 @@ import * as React from 'react';
|
|||||||
import { render } from '../../../tests/utils';
|
import { render } from '../../../tests/utils';
|
||||||
import Tree from '../index';
|
import Tree from '../index';
|
||||||
|
|
||||||
|
const { DirectoryTree } = Tree;
|
||||||
|
|
||||||
describe('Tree.TypeScript', () => {
|
describe('Tree.TypeScript', () => {
|
||||||
it('without generic', () => {
|
it('without generic', () => {
|
||||||
const { container } = render(
|
const { container } = render(
|
||||||
@ -48,4 +50,28 @@ describe('Tree.TypeScript', () => {
|
|||||||
|
|
||||||
expect(container).toBeTruthy();
|
expect(container).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('directoryTree support generic', () => {
|
||||||
|
interface MyDataNode extends BasicDataNode {
|
||||||
|
bamboo: string;
|
||||||
|
list?: MyDataNode[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const { container } = render(
|
||||||
|
<DirectoryTree<MyDataNode>
|
||||||
|
treeData={[
|
||||||
|
{
|
||||||
|
bamboo: 'good',
|
||||||
|
list: [
|
||||||
|
{
|
||||||
|
bamboo: 'well',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(container).toBeTruthy();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import * as React from 'react';
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { composeRef } from 'rc-util/lib/ref';
|
import { composeRef } from 'rc-util/lib/ref';
|
||||||
|
import * as React from 'react';
|
||||||
import { ConfigContext } from '../config-provider';
|
import { ConfigContext } from '../config-provider';
|
||||||
import warning from '../_util/warning';
|
import warning from '../_util/warning';
|
||||||
import useStyle from './style';
|
import useStyle from './style';
|
||||||
@ -62,8 +62,9 @@ const Typography: React.ForwardRefRenderFunction<{}, InternalTypographyProps> =
|
|||||||
};
|
};
|
||||||
|
|
||||||
const RefTypography = React.forwardRef(Typography);
|
const RefTypography = React.forwardRef(Typography);
|
||||||
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
RefTypography.displayName = 'Typography';
|
RefTypography.displayName = 'Typography';
|
||||||
|
}
|
||||||
|
|
||||||
// es default export should use const instead of let
|
// es default export should use const instead of let
|
||||||
const ExportTypography = RefTypography as unknown as React.FC<TypographyProps>;
|
const ExportTypography = RefTypography as unknown as React.FC<TypographyProps>;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { LikeOutlined, SmileOutlined } from '@ant-design/icons';
|
import { LikeOutlined, SmileOutlined } from '@ant-design/icons';
|
||||||
|
import { act } from '@testing-library/react';
|
||||||
import * as copyObj from 'copy-to-clipboard';
|
import * as copyObj from 'copy-to-clipboard';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { fireEvent, render, waitFor } from '../../../tests/utils';
|
import { fireEvent, render, waitFor } from '../../../tests/utils';
|
||||||
@ -233,7 +234,8 @@ describe('Typography copy', () => {
|
|||||||
fireEvent.click(wrapper.querySelectorAll('.ant-typography-copy')[0]);
|
fireEvent.click(wrapper.querySelectorAll('.ant-typography-copy')[0]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('copy to clipboard', done => {
|
it('copy to clipboard', () => {
|
||||||
|
jest.useFakeTimers();
|
||||||
const spy = jest.spyOn(copyObj, 'default');
|
const spy = jest.spyOn(copyObj, 'default');
|
||||||
const originText = 'origin text.';
|
const originText = 'origin text.';
|
||||||
const nextText = 'next text.';
|
const nextText = 'next text.';
|
||||||
@ -243,7 +245,7 @@ describe('Typography copy', () => {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setDynamicText(nextText);
|
setDynamicText(nextText);
|
||||||
}, 500);
|
}, 500);
|
||||||
});
|
}, []);
|
||||||
return (
|
return (
|
||||||
<Base component="p" copyable>
|
<Base component="p" copyable>
|
||||||
{dynamicText}
|
{dynamicText}
|
||||||
@ -254,12 +256,13 @@ describe('Typography copy', () => {
|
|||||||
const copyBtn = wrapper.querySelectorAll('.ant-typography-copy')[0];
|
const copyBtn = wrapper.querySelectorAll('.ant-typography-copy')[0];
|
||||||
fireEvent.click(copyBtn);
|
fireEvent.click(copyBtn);
|
||||||
expect(spy.mock.calls[0][0]).toEqual(originText);
|
expect(spy.mock.calls[0][0]).toEqual(originText);
|
||||||
setTimeout(() => {
|
act(() => {
|
||||||
spy.mockReset();
|
jest.runAllTimers();
|
||||||
fireEvent.click(copyBtn);
|
});
|
||||||
expect(spy.mock.calls[0][0]).toEqual(nextText);
|
spy.mockReset();
|
||||||
done();
|
fireEvent.click(copyBtn);
|
||||||
}, 500);
|
expect(spy.mock.calls[0][0]).toEqual(nextText);
|
||||||
|
jest.useRealTimers();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import Upload from './Upload';
|
|
||||||
import type { UploadProps } from './interface';
|
import type { UploadProps } from './interface';
|
||||||
|
import Upload from './Upload';
|
||||||
|
|
||||||
export type DraggerProps = UploadProps & { height?: number };
|
export type DraggerProps = UploadProps & { height?: number };
|
||||||
|
|
||||||
@ -11,6 +11,8 @@ const InternalDragger: React.ForwardRefRenderFunction<unknown, DraggerProps> = (
|
|||||||
|
|
||||||
const Dragger = React.forwardRef(InternalDragger) as React.FC<DraggerProps>;
|
const Dragger = React.forwardRef(InternalDragger) as React.FC<DraggerProps>;
|
||||||
|
|
||||||
Dragger.displayName = 'Dragger';
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
Dragger.displayName = 'Dragger';
|
||||||
|
}
|
||||||
|
|
||||||
export default Dragger;
|
export default Dragger;
|
||||||
|
@ -1,24 +1,25 @@
|
|||||||
import * as React from 'react';
|
import classNames from 'classnames';
|
||||||
import type { UploadProps as RcUploadProps } from 'rc-upload';
|
import type { UploadProps as RcUploadProps } from 'rc-upload';
|
||||||
import RcUpload from 'rc-upload';
|
import RcUpload from 'rc-upload';
|
||||||
import useMergedState from 'rc-util/lib/hooks/useMergedState';
|
import useMergedState from 'rc-util/lib/hooks/useMergedState';
|
||||||
import classNames from 'classnames';
|
import * as React from 'react';
|
||||||
import UploadList from './UploadList';
|
import { ConfigContext } from '../config-provider';
|
||||||
|
import LocaleReceiver from '../locale-provider/LocaleReceiver';
|
||||||
|
import defaultLocale from '../locale/default';
|
||||||
|
import warning from '../_util/warning';
|
||||||
import type {
|
import type {
|
||||||
RcFile,
|
RcFile,
|
||||||
ShowUploadListInterface,
|
ShowUploadListInterface,
|
||||||
UploadFile,
|
|
||||||
UploadLocale,
|
|
||||||
UploadChangeParam,
|
UploadChangeParam,
|
||||||
UploadType,
|
UploadFile,
|
||||||
UploadListType,
|
UploadListType,
|
||||||
|
UploadLocale,
|
||||||
|
UploadType,
|
||||||
} from './interface';
|
} from './interface';
|
||||||
import { UploadProps } from './interface';
|
import { UploadProps } from './interface';
|
||||||
|
import UploadList from './UploadList';
|
||||||
import { file2Obj, getFileItem, removeFileItem, updateFileList } from './utils';
|
import { file2Obj, getFileItem, removeFileItem, updateFileList } from './utils';
|
||||||
import LocaleReceiver from '../locale-provider/LocaleReceiver';
|
|
||||||
import defaultLocale from '../locale/default';
|
|
||||||
import { ConfigContext } from '../config-provider';
|
|
||||||
import warning from '../_util/warning';
|
|
||||||
import useStyle from './style';
|
import useStyle from './style';
|
||||||
|
|
||||||
export const LIST_IGNORE = `__LIST_IGNORE_${Date.now()}__`;
|
export const LIST_IGNORE = `__LIST_IGNORE_${Date.now()}__`;
|
||||||
@ -435,8 +436,9 @@ const InternalUpload: React.ForwardRefRenderFunction<unknown, UploadProps> = (pr
|
|||||||
};
|
};
|
||||||
|
|
||||||
const Upload = React.forwardRef<unknown, UploadProps>(InternalUpload);
|
const Upload = React.forwardRef<unknown, UploadProps>(InternalUpload);
|
||||||
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
Upload.displayName = 'Upload';
|
Upload.displayName = 'Upload';
|
||||||
|
}
|
||||||
|
|
||||||
Upload.defaultProps = {
|
Upload.defaultProps = {
|
||||||
type: 'select' as UploadType,
|
type: 'select' as UploadType,
|
||||||
|
@ -1,20 +1,20 @@
|
|||||||
import * as React from 'react';
|
import FileTwoTone from '@ant-design/icons/FileTwoTone';
|
||||||
import type { CSSMotionListProps } from 'rc-motion';
|
|
||||||
import CSSMotion, { CSSMotionList } from 'rc-motion';
|
|
||||||
import classNames from 'classnames';
|
|
||||||
import LoadingOutlined from '@ant-design/icons/LoadingOutlined';
|
import LoadingOutlined from '@ant-design/icons/LoadingOutlined';
|
||||||
import PaperClipOutlined from '@ant-design/icons/PaperClipOutlined';
|
import PaperClipOutlined from '@ant-design/icons/PaperClipOutlined';
|
||||||
import PictureTwoTone from '@ant-design/icons/PictureTwoTone';
|
import PictureTwoTone from '@ant-design/icons/PictureTwoTone';
|
||||||
import FileTwoTone from '@ant-design/icons/FileTwoTone';
|
import classNames from 'classnames';
|
||||||
import { cloneElement, isValidElement } from '../../_util/reactNode';
|
import type { CSSMotionListProps } from 'rc-motion';
|
||||||
import { previewImage, isImageUrl } from '../utils';
|
import CSSMotion, { CSSMotionList } from 'rc-motion';
|
||||||
import collapseMotion from '../../_util/motion';
|
import * as React from 'react';
|
||||||
import { ConfigContext } from '../../config-provider';
|
|
||||||
import type { ButtonProps } from '../../button';
|
import type { ButtonProps } from '../../button';
|
||||||
import Button from '../../button';
|
import Button from '../../button';
|
||||||
|
import { ConfigContext } from '../../config-provider';
|
||||||
import useForceUpdate from '../../_util/hooks/useForceUpdate';
|
import useForceUpdate from '../../_util/hooks/useForceUpdate';
|
||||||
|
import collapseMotion from '../../_util/motion';
|
||||||
|
import { cloneElement, isValidElement } from '../../_util/reactNode';
|
||||||
|
import type { InternalUploadFile, UploadFile, UploadListProps, UploadListType } from '../interface';
|
||||||
|
import { isImageUrl, previewImage } from '../utils';
|
||||||
import ListItem from './ListItem';
|
import ListItem from './ListItem';
|
||||||
import type { UploadListProps, UploadFile, UploadListType, InternalUploadFile } from '../interface';
|
|
||||||
|
|
||||||
const listItemMotion: Partial<CSSMotionListProps> = {
|
const listItemMotion: Partial<CSSMotionListProps> = {
|
||||||
...collapseMotion,
|
...collapseMotion,
|
||||||
@ -246,8 +246,9 @@ const InternalUploadList: React.ForwardRefRenderFunction<unknown, UploadListProp
|
|||||||
};
|
};
|
||||||
|
|
||||||
const UploadList = React.forwardRef<unknown, UploadListProps>(InternalUploadList);
|
const UploadList = React.forwardRef<unknown, UploadListProps>(InternalUploadList);
|
||||||
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
UploadList.displayName = 'UploadList';
|
UploadList.displayName = 'UploadList';
|
||||||
|
}
|
||||||
|
|
||||||
UploadList.defaultProps = {
|
UploadList.defaultProps = {
|
||||||
listType: 'text' as UploadListType, // or picture
|
listType: 'text' as UploadListType, // or picture
|
||||||
|
@ -28,8 +28,8 @@ exports[`Upload List handle error 1`] = `
|
|||||||
class="ant-upload-list ant-upload-list-text"
|
class="ant-upload-list ant-upload-list-text"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="ant-upload-list-item-container ant-upload-animate-appear ant-upload-animate-appear-active ant-upload-animate"
|
class="ant-upload-list-item-container"
|
||||||
style="height: 0px; opacity: 1;"
|
style=""
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="ant-upload-list-item ant-upload-list-item-error"
|
class="ant-upload-list-item ant-upload-list-item-error"
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
/* eslint-disable react/no-string-refs, react/prefer-es6-class */
|
/* eslint-disable react/no-string-refs, react/prefer-es6-class */
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { mount } from 'enzyme';
|
|
||||||
import { act } from 'react-dom/test-utils';
|
import { act } from 'react-dom/test-utils';
|
||||||
import Upload from '..';
|
import Upload from '..';
|
||||||
import { setup, teardown } from './mock';
|
|
||||||
import mountTest from '../../../tests/shared/mountTest';
|
import mountTest from '../../../tests/shared/mountTest';
|
||||||
|
import { fireEvent, render, waitFor } from '../../../tests/utils';
|
||||||
|
import { setup, teardown } from './mock';
|
||||||
|
|
||||||
describe('Upload.Dragger', () => {
|
describe('Upload.Dragger', () => {
|
||||||
mountTest(Upload.Dragger);
|
mountTest(Upload.Dragger);
|
||||||
@ -12,44 +12,47 @@ describe('Upload.Dragger', () => {
|
|||||||
beforeEach(() => setup());
|
beforeEach(() => setup());
|
||||||
afterEach(() => teardown());
|
afterEach(() => teardown());
|
||||||
|
|
||||||
it('support drag file with over style', () => {
|
it('support drag file with over style', async () => {
|
||||||
jest.useFakeTimers();
|
jest.useFakeTimers();
|
||||||
const wrapper = mount(
|
const { container: wrapper } = render(
|
||||||
<Upload.Dragger action="http://upload.com">
|
<Upload.Dragger action="http://upload.com">
|
||||||
<div />
|
<div />
|
||||||
</Upload.Dragger>,
|
</Upload.Dragger>,
|
||||||
);
|
);
|
||||||
|
|
||||||
wrapper.find('.ant-upload-drag-container').simulate('dragover', {
|
fireEvent.dragOver(wrapper.querySelector('.ant-upload-drag-container'), {
|
||||||
target: {
|
target: {
|
||||||
files: [{ file: 'foo.png' }],
|
files: [{ file: 'foo.png' }],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
act(() => {
|
await act(() => {
|
||||||
jest.runAllTimers();
|
jest.runAllTimers();
|
||||||
});
|
});
|
||||||
wrapper.update();
|
|
||||||
|
|
||||||
expect(wrapper.find('.ant-upload-drag').hasClass('ant-upload-drag-hover')).toBe(true);
|
await waitFor(() => {
|
||||||
|
expect(wrapper.querySelector('.ant-upload-drag')).toHaveClass('ant-upload-drag-hover');
|
||||||
|
});
|
||||||
|
|
||||||
jest.useRealTimers();
|
jest.useRealTimers();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('support onDrop when files are dropped onto upload area', () => {
|
it('support onDrop when files are dropped onto upload area', async () => {
|
||||||
const onDrop = jest.fn();
|
const onDrop = jest.fn();
|
||||||
const wrapper = mount(
|
const { container: wrapper } = render(
|
||||||
<Upload.Dragger onDrop={onDrop}>
|
<Upload.Dragger onDrop={onDrop}>
|
||||||
<div />
|
<div />
|
||||||
</Upload.Dragger>,
|
</Upload.Dragger>,
|
||||||
);
|
);
|
||||||
|
|
||||||
wrapper.find('.ant-upload-drag-container').simulate('drop', {
|
fireEvent.drop(wrapper.querySelector('.ant-upload-drag-container'), {
|
||||||
dataTransfer: {
|
dataTransfer: {
|
||||||
files: [new File(['foo'], 'foo.png', { type: 'image/png' })],
|
files: [new File(['foo'], 'foo.png', { type: 'image/png' })],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(onDrop).toHaveBeenCalled();
|
await waitFor(() => {
|
||||||
|
expect(onDrop).toHaveBeenCalled();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,17 +1,16 @@
|
|||||||
/* eslint-disable react/no-string-refs, react/prefer-es6-class */
|
/* eslint-disable react/no-string-refs, react/prefer-es6-class */
|
||||||
import React from 'react';
|
|
||||||
import { mount } from 'enzyme';
|
|
||||||
import { act } from 'react-dom/test-utils';
|
|
||||||
import produce from 'immer';
|
import produce from 'immer';
|
||||||
import { cloneDeep } from 'lodash';
|
import { cloneDeep } from 'lodash';
|
||||||
|
import React from 'react';
|
||||||
|
import { act } from 'react-dom/test-utils';
|
||||||
import Upload from '..';
|
import Upload from '..';
|
||||||
import Form from '../../form';
|
|
||||||
import { getFileItem, removeFileItem, isImageUrl } from '../utils';
|
|
||||||
import { setup, teardown } from './mock';
|
|
||||||
import { resetWarned } from '../../_util/warning';
|
|
||||||
import mountTest from '../../../tests/shared/mountTest';
|
import mountTest from '../../../tests/shared/mountTest';
|
||||||
import rtlTest from '../../../tests/shared/rtlTest';
|
import rtlTest from '../../../tests/shared/rtlTest';
|
||||||
import { sleep, render, fireEvent } from '../../../tests/utils';
|
import { fireEvent, render, sleep } from '../../../tests/utils';
|
||||||
|
import Form from '../../form';
|
||||||
|
import { resetWarned } from '../../_util/warning';
|
||||||
|
import { getFileItem, isImageUrl, removeFileItem } from '../utils';
|
||||||
|
import { setup, teardown } from './mock';
|
||||||
|
|
||||||
globalThis.IS_REACT_ACT_ENVIRONMENT = true;
|
globalThis.IS_REACT_ACT_ENVIRONMENT = true;
|
||||||
|
|
||||||
@ -46,12 +45,14 @@ describe('Upload', () => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mount(<App />);
|
render(<App />);
|
||||||
expect(ref).toBeDefined();
|
expect(ref).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('return promise in beforeUpload', done => {
|
it('return promise in beforeUpload', async () => {
|
||||||
|
jest.useFakeTimers();
|
||||||
const data = jest.fn();
|
const data = jest.fn();
|
||||||
|
const done = jest.fn();
|
||||||
const props = {
|
const props = {
|
||||||
action: 'http://upload.com',
|
action: 'http://upload.com',
|
||||||
beforeUpload: () =>
|
beforeUpload: () =>
|
||||||
@ -67,19 +68,33 @@ describe('Upload', () => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const wrapper = mount(
|
const { container: wrapper } = render(
|
||||||
<Upload {...props}>
|
<Upload {...props}>
|
||||||
<button type="button">upload</button>
|
<button type="button">upload</button>
|
||||||
</Upload>,
|
</Upload>,
|
||||||
);
|
);
|
||||||
wrapper.find('input').simulate('change', {
|
fireEvent.change(wrapper.querySelector('input'), {
|
||||||
target: {
|
target: {
|
||||||
files: [{ file: 'foo.png' }],
|
files: [{ file: 'foo.png' }],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
act(() => {
|
||||||
|
jest.runAllTimers();
|
||||||
|
});
|
||||||
|
await act(async () => {
|
||||||
|
for (let i = 0; i < 4; i += 1) {
|
||||||
|
// eslint-disable-next-line no-await-in-loop
|
||||||
|
await Promise.resolve();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
expect(done).toHaveBeenCalled();
|
||||||
|
|
||||||
|
jest.useRealTimers();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('beforeUpload can be falsy', done => {
|
it('beforeUpload can be falsy', async () => {
|
||||||
|
jest.useFakeTimers();
|
||||||
|
const done = jest.fn();
|
||||||
const props = {
|
const props = {
|
||||||
action: 'http://upload.com',
|
action: 'http://upload.com',
|
||||||
beforeUpload: false,
|
beforeUpload: false,
|
||||||
@ -90,20 +105,30 @@ describe('Upload', () => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const wrapper = mount(
|
const { container: wrapper } = render(
|
||||||
<Upload {...props}>
|
<Upload {...props}>
|
||||||
<button type="button">upload</button>
|
<button type="button">upload</button>
|
||||||
</Upload>,
|
</Upload>,
|
||||||
);
|
);
|
||||||
|
|
||||||
wrapper.find('input').simulate('change', {
|
fireEvent.change(wrapper.querySelector('input'), {
|
||||||
target: {
|
target: {
|
||||||
files: [{ file: 'foo.png' }],
|
files: [{ file: 'foo.png' }],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
await act(async () => {
|
||||||
|
for (let i = 0; i < 4; i += 1) {
|
||||||
|
// eslint-disable-next-line no-await-in-loop
|
||||||
|
await Promise.resolve();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
expect(done).toHaveBeenCalled();
|
||||||
|
jest.useRealTimers();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('upload promise return file in beforeUpload', done => {
|
it('upload promise return file in beforeUpload', async () => {
|
||||||
|
jest.useFakeTimers();
|
||||||
|
const done = jest.fn();
|
||||||
const data = jest.fn();
|
const data = jest.fn();
|
||||||
const props = {
|
const props = {
|
||||||
action: 'http://upload.com',
|
action: 'http://upload.com',
|
||||||
@ -125,17 +150,29 @@ describe('Upload', () => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const wrapper = mount(
|
const { container: wrapper } = render(
|
||||||
<Upload {...props}>
|
<Upload {...props}>
|
||||||
<button type="button">upload</button>
|
<button type="button">upload</button>
|
||||||
</Upload>,
|
</Upload>,
|
||||||
);
|
);
|
||||||
|
|
||||||
wrapper.find('input').simulate('change', {
|
fireEvent.change(wrapper.querySelector('input'), {
|
||||||
target: {
|
target: {
|
||||||
files: [{ file: 'foo.png' }],
|
files: [{ file: 'foo.png' }],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
act(() => {
|
||||||
|
jest.runAllTimers();
|
||||||
|
});
|
||||||
|
await act(async () => {
|
||||||
|
for (let i = 0; i < 4; i += 1) {
|
||||||
|
// eslint-disable-next-line no-await-in-loop
|
||||||
|
await Promise.resolve();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(done).toHaveBeenCalled();
|
||||||
|
jest.useRealTimers();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not stop upload when return value of beforeUpload is false', done => {
|
it('should not stop upload when return value of beforeUpload is false', done => {
|
||||||
@ -162,13 +199,13 @@ describe('Upload', () => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const wrapper = mount(
|
const { container: wrapper } = render(
|
||||||
<Upload {...props}>
|
<Upload {...props}>
|
||||||
<button type="button">upload</button>
|
<button type="button">upload</button>
|
||||||
</Upload>,
|
</Upload>,
|
||||||
);
|
);
|
||||||
|
|
||||||
wrapper.find('input').simulate('change', {
|
fireEvent.change(wrapper.querySelector('input'), {
|
||||||
target: {
|
target: {
|
||||||
files: [mockFile],
|
files: [mockFile],
|
||||||
},
|
},
|
||||||
@ -187,13 +224,13 @@ describe('Upload', () => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const wrapper = mount(
|
const { container: wrapper } = render(
|
||||||
<Upload {...props}>
|
<Upload {...props}>
|
||||||
<button type="button">upload</button>
|
<button type="button">upload</button>
|
||||||
</Upload>,
|
</Upload>,
|
||||||
);
|
);
|
||||||
|
|
||||||
wrapper.find('input').simulate('change', {
|
fireEvent.change(wrapper.querySelector('input'), {
|
||||||
target: {
|
target: {
|
||||||
files: [{ file: 'foo.png' }],
|
files: [{ file: 'foo.png' }],
|
||||||
},
|
},
|
||||||
@ -247,10 +284,10 @@ describe('Upload', () => {
|
|||||||
</Form>
|
</Form>
|
||||||
);
|
);
|
||||||
|
|
||||||
const wrapper = mount(<Demo />);
|
const { container: wrapper, rerender } = render(<Demo />);
|
||||||
expect(wrapper.find('input#upload').length).toBe(1);
|
expect(wrapper.querySelectorAll('input#upload').length).toBe(1);
|
||||||
wrapper.setProps({ disabled: true });
|
rerender(<Demo disabled />);
|
||||||
expect(wrapper.find('input#upload').length).toBe(0);
|
expect(wrapper.querySelectorAll('input#upload').length).toBe(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
// https://github.com/ant-design/ant-design/issues/24197
|
// https://github.com/ant-design/ant-design/issues/24197
|
||||||
@ -265,10 +302,10 @@ describe('Upload', () => {
|
|||||||
</Form>
|
</Form>
|
||||||
);
|
);
|
||||||
|
|
||||||
const wrapper = mount(<Demo />);
|
const { container: wrapper, rerender } = render(<Demo />);
|
||||||
expect(wrapper.find('input#upload').length).toBe(1);
|
expect(wrapper.querySelectorAll('input#upload').length).toBe(1);
|
||||||
wrapper.setProps({ disabled: true });
|
rerender(<Demo disabled />);
|
||||||
expect(wrapper.find('input#upload').length).toBe(0);
|
expect(wrapper.querySelectorAll('input#upload').length).toBe(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be controlled by fileList', () => {
|
it('should be controlled by fileList', () => {
|
||||||
@ -282,10 +319,9 @@ describe('Upload', () => {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
const ref = React.createRef();
|
const ref = React.createRef();
|
||||||
const wrapper = mount(<Upload ref={ref} />);
|
const { rerender } = render(<Upload ref={ref} />);
|
||||||
expect(ref.current.fileList).toEqual([]);
|
expect(ref.current.fileList).toEqual([]);
|
||||||
|
rerender(<Upload ref={ref} fileList={fileList} />);
|
||||||
wrapper.setProps({ fileList });
|
|
||||||
jest.runAllTimers();
|
jest.runAllTimers();
|
||||||
expect(ref.current.fileList).toEqual(fileList);
|
expect(ref.current.fileList).toEqual(fileList);
|
||||||
jest.useRealTimers();
|
jest.useRealTimers();
|
||||||
@ -299,7 +335,7 @@ describe('Upload', () => {
|
|||||||
url: 'http://www.baidu.com/xxx.png',
|
url: 'http://www.baidu.com/xxx.png',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
mount(<Upload fileList={fileList} />);
|
render(<Upload fileList={fileList} />);
|
||||||
fileList.forEach(file => {
|
fileList.forEach(file => {
|
||||||
expect(file.uid).toBeDefined();
|
expect(file.uid).toBeDefined();
|
||||||
});
|
});
|
||||||
@ -395,10 +431,10 @@ describe('Upload', () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
const wrapper = mount(<Upload fileList={fileList} />);
|
const { container: wrapper } = render(<Upload fileList={fileList} />);
|
||||||
const linkNode = wrapper.find('a.ant-upload-list-item-name');
|
const linkNode = wrapper.querySelector('a.ant-upload-list-item-name');
|
||||||
expect(linkNode.props().download).toBe('image');
|
expect(linkNode.getAttribute('download')).toBe('image');
|
||||||
expect(linkNode.props().rel).toBe('noopener');
|
expect(linkNode.getAttribute('rel')).toBe('noopener');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should support linkProps as json stringify', () => {
|
it('should support linkProps as json stringify', () => {
|
||||||
@ -415,10 +451,10 @@ describe('Upload', () => {
|
|||||||
linkProps: linkPropsString,
|
linkProps: linkPropsString,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
const wrapper = mount(<Upload fileList={fileList} />);
|
const { container: wrapper } = render(<Upload fileList={fileList} />);
|
||||||
const linkNode = wrapper.find('a.ant-upload-list-item-name');
|
const linkNode = wrapper.querySelector('a.ant-upload-list-item-name');
|
||||||
expect(linkNode.props().download).toBe('image');
|
expect(linkNode.getAttribute('download')).toBe('image');
|
||||||
expect(linkNode.props().rel).toBe('noopener');
|
expect(linkNode.getAttribute('rel')).toBe('noopener');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not stop remove when return value of onRemove is false', done => {
|
it('should not stop remove when return value of onRemove is false', done => {
|
||||||
@ -435,13 +471,11 @@ describe('Upload', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
const wrapper = mount(<Upload {...props} />);
|
const { container: wrapper } = render(<Upload {...props} />);
|
||||||
|
|
||||||
wrapper.find('div.ant-upload-list-item .anticon-delete').simulate('click');
|
fireEvent.click(wrapper.querySelector('div.ant-upload-list-item .anticon-delete'));
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
wrapper.update();
|
|
||||||
|
|
||||||
expect(mockRemove).toHaveBeenCalled();
|
expect(mockRemove).toHaveBeenCalled();
|
||||||
expect(props.fileList).toHaveLength(1);
|
expect(props.fileList).toHaveLength(1);
|
||||||
expect(props.fileList[0].status).toBe('done');
|
expect(props.fileList[0].status).toBe('done');
|
||||||
@ -504,13 +538,11 @@ describe('Upload', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
const wrapper = mount(<Upload {...props} onDownload={() => {}} />);
|
const { container: wrapper } = render(<Upload {...props} onDownload={() => {}} />);
|
||||||
|
|
||||||
wrapper.find('div.ant-upload-list-item .anticon-download').simulate('click');
|
fireEvent.click(wrapper.querySelector('div.ant-upload-list-item .anticon-download'));
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
wrapper.update();
|
|
||||||
|
|
||||||
expect(props.fileList).toHaveLength(1);
|
expect(props.fileList).toHaveLength(1);
|
||||||
expect(props.fileList[0].status).toBe('done');
|
expect(props.fileList[0].status).toBe('done');
|
||||||
done();
|
done();
|
||||||
@ -520,7 +552,7 @@ describe('Upload', () => {
|
|||||||
// https://github.com/ant-design/ant-design/issues/14439
|
// https://github.com/ant-design/ant-design/issues/14439
|
||||||
it('should allow call abort function through upload instance', () => {
|
it('should allow call abort function through upload instance', () => {
|
||||||
const ref = React.createRef();
|
const ref = React.createRef();
|
||||||
mount(
|
render(
|
||||||
<Upload ref={ref}>
|
<Upload ref={ref}>
|
||||||
<button type="button">upload</button>
|
<button type="button">upload</button>
|
||||||
</Upload>,
|
</Upload>,
|
||||||
@ -530,18 +562,18 @@ describe('Upload', () => {
|
|||||||
|
|
||||||
it('correct dragCls when type is drag', () => {
|
it('correct dragCls when type is drag', () => {
|
||||||
const fileList = [{ status: 'uploading', uid: 'file' }];
|
const fileList = [{ status: 'uploading', uid: 'file' }];
|
||||||
const wrapper = mount(
|
const { container: wrapper } = render(
|
||||||
<Upload type="drag" fileList={fileList}>
|
<Upload type="drag" fileList={fileList}>
|
||||||
<button type="button">upload</button>
|
<button type="button">upload</button>
|
||||||
</Upload>,
|
</Upload>,
|
||||||
);
|
);
|
||||||
expect(wrapper.find('.ant-upload-drag-uploading').length).toBe(1);
|
expect(wrapper.querySelectorAll('.ant-upload-drag-uploading').length).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('return when targetItem is null', () => {
|
it('return when targetItem is null', () => {
|
||||||
const fileList = [{ uid: 'file' }];
|
const fileList = [{ uid: 'file' }];
|
||||||
const ref = React.createRef();
|
const ref = React.createRef();
|
||||||
mount(
|
render(
|
||||||
<Upload ref={ref} type="drag" fileList={fileList}>
|
<Upload ref={ref} type="drag" fileList={fileList}>
|
||||||
<button type="button">upload</button>
|
<button type="button">upload</button>
|
||||||
</Upload>,
|
</Upload>,
|
||||||
@ -554,7 +586,7 @@ describe('Upload', () => {
|
|||||||
it('should replace file when targetItem already exists', () => {
|
it('should replace file when targetItem already exists', () => {
|
||||||
const fileList = [{ uid: 'file', name: 'file' }];
|
const fileList = [{ uid: 'file', name: 'file' }];
|
||||||
const ref = React.createRef();
|
const ref = React.createRef();
|
||||||
const wrapper = mount(
|
const { unmount } = render(
|
||||||
<Upload ref={ref} defaultFileList={fileList}>
|
<Upload ref={ref} defaultFileList={fileList}>
|
||||||
<button type="button">upload</button>
|
<button type="button">upload</button>
|
||||||
</Upload>,
|
</Upload>,
|
||||||
@ -574,22 +606,20 @@ describe('Upload', () => {
|
|||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
wrapper.update();
|
|
||||||
|
|
||||||
expect(ref.current.fileList.length).toBe(1);
|
expect(ref.current.fileList.length).toBe(1);
|
||||||
expect(ref.current.fileList[0].originFileObj).toEqual({
|
expect(ref.current.fileList[0].originFileObj).toEqual({
|
||||||
name: 'file1',
|
name: 'file1',
|
||||||
uid: 'file',
|
uid: 'file',
|
||||||
});
|
});
|
||||||
|
|
||||||
wrapper.unmount();
|
unmount();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('warning if set `value`', () => {
|
it('warning if set `value`', () => {
|
||||||
resetWarned();
|
resetWarned();
|
||||||
|
|
||||||
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||||
mount(<Upload value={[]} />);
|
render(<Upload value={[]} />);
|
||||||
expect(errorSpy).toHaveBeenCalledWith(
|
expect(errorSpy).toHaveBeenCalledWith(
|
||||||
'Warning: [antd: Upload] `value` is not a valid prop, do you mean `fileList`?',
|
'Warning: [antd: Upload] `value` is not a valid prop, do you mean `fileList`?',
|
||||||
);
|
);
|
||||||
@ -603,8 +633,8 @@ describe('Upload', () => {
|
|||||||
type: 'video/mp4',
|
type: 'video/mp4',
|
||||||
url: 'https://zos.alipayobjects.com/rmsportal/IQKRngzUuFzJzGzRJXUs.png',
|
url: 'https://zos.alipayobjects.com/rmsportal/IQKRngzUuFzJzGzRJXUs.png',
|
||||||
};
|
};
|
||||||
const wrapper = mount(<Upload listType="picture-card" fileList={[file]} />);
|
const { container: wrapper } = render(<Upload listType="picture-card" fileList={[file]} />);
|
||||||
expect(wrapper.find('img').length).toBe(0);
|
expect(wrapper.querySelectorAll('img').length).toBe(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
// https://github.com/ant-design/ant-design/issues/25077
|
// https://github.com/ant-design/ant-design/issues/25077
|
||||||
@ -612,24 +642,29 @@ describe('Upload', () => {
|
|||||||
const onClick = jest.fn();
|
const onClick = jest.fn();
|
||||||
const onMouseEnter = jest.fn();
|
const onMouseEnter = jest.fn();
|
||||||
const onMouseLeave = jest.fn();
|
const onMouseLeave = jest.fn();
|
||||||
const wrapper = mount(
|
const { container: wrapper } = render(
|
||||||
<Upload onClick={onClick} onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave}>
|
<Upload onClick={onClick} onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave}>
|
||||||
<button type="button">upload</button>
|
<button type="button">upload</button>
|
||||||
</Upload>,
|
</Upload>,
|
||||||
);
|
);
|
||||||
wrapper.find('.ant-upload').at(1).simulate('click');
|
fireEvent.click(wrapper.querySelectorAll('.ant-upload')[1]);
|
||||||
expect(onClick).toHaveBeenCalled();
|
expect(onClick).toHaveBeenCalled();
|
||||||
wrapper.find('.ant-upload').at(1).simulate('mouseEnter');
|
fireEvent.mouseEnter(wrapper.querySelectorAll('.ant-upload')[1]);
|
||||||
expect(onMouseEnter).toHaveBeenCalled();
|
expect(onMouseEnter).toHaveBeenCalled();
|
||||||
wrapper.find('.ant-upload').at(1).simulate('mouseLeave');
|
fireEvent.mouseLeave(wrapper.querySelectorAll('.ant-upload')[1]);
|
||||||
expect(onMouseLeave).toHaveBeenCalled();
|
expect(onMouseLeave).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
// https://github.com/ant-design/ant-design/issues/26427
|
// https://github.com/ant-design/ant-design/issues/26427
|
||||||
it('should sync file list with control mode', done => {
|
it('should sync file list with control mode', async () => {
|
||||||
|
jest.useFakeTimers();
|
||||||
|
const done = jest.fn();
|
||||||
let callTimes = 0;
|
let callTimes = 0;
|
||||||
|
|
||||||
const customRequest = jest.fn(async options => {
|
const customRequest = jest.fn(async options => {
|
||||||
|
// stop here to make sure new fileList has been set and passed to Upload
|
||||||
|
// eslint-disable-next-line no-promise-executor-return
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 0));
|
||||||
options.onProgress({ percent: 0 });
|
options.onProgress({ percent: 0 });
|
||||||
const url = Promise.resolve('https://ant.design');
|
const url = Promise.resolve('https://ant.design');
|
||||||
options.onProgress({ percent: 100 });
|
options.onProgress({ percent: 100 });
|
||||||
@ -639,7 +674,7 @@ describe('Upload', () => {
|
|||||||
const Demo = () => {
|
const Demo = () => {
|
||||||
const [fileList, setFileList] = React.useState([]);
|
const [fileList, setFileList] = React.useState([]);
|
||||||
|
|
||||||
const onChange = e => {
|
const onChange = async e => {
|
||||||
const newFileList = Array.isArray(e) ? e : e.fileList;
|
const newFileList = Array.isArray(e) ? e : e.fileList;
|
||||||
setFileList(newFileList);
|
setFileList(newFileList);
|
||||||
const file = newFileList[0];
|
const file = newFileList[0];
|
||||||
@ -676,15 +711,29 @@ describe('Upload', () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const wrapper = mount(<Demo />);
|
const { container: wrapper } = render(<Demo />);
|
||||||
|
|
||||||
act(() => {
|
fireEvent.change(wrapper.querySelector('input'), {
|
||||||
wrapper.find('input').simulate('change', {
|
target: {
|
||||||
target: {
|
files: [{ file: 'foo.png' }],
|
||||||
files: [{ file: 'foo.png' }],
|
},
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await act(async () => {
|
||||||
|
for (let i = 0; i < 3; i += 1) {
|
||||||
|
// eslint-disable-next-line no-await-in-loop
|
||||||
|
await Promise.resolve();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
await act(() => {
|
||||||
|
jest.runAllTimers();
|
||||||
|
});
|
||||||
|
await act(async () => {
|
||||||
|
await Promise.resolve();
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(done).toHaveBeenCalled();
|
||||||
|
jest.useRealTimers();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('maxCount', () => {
|
describe('maxCount', () => {
|
||||||
@ -704,13 +753,13 @@ describe('Upload', () => {
|
|||||||
maxCount: 1,
|
maxCount: 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
const wrapper = mount(
|
const { container: wrapper } = render(
|
||||||
<Upload {...props}>
|
<Upload {...props}>
|
||||||
<button type="button">upload</button>
|
<button type="button">upload</button>
|
||||||
</Upload>,
|
</Upload>,
|
||||||
);
|
);
|
||||||
|
|
||||||
wrapper.find('input').simulate('change', {
|
fireEvent.change(wrapper.querySelector('input'), {
|
||||||
target: {
|
target: {
|
||||||
files: [
|
files: [
|
||||||
new File(['foo'], 'foo.png', {
|
new File(['foo'], 'foo.png', {
|
||||||
@ -746,13 +795,13 @@ describe('Upload', () => {
|
|||||||
maxCount: 2,
|
maxCount: 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
const wrapper = mount(
|
const { container: wrapper } = render(
|
||||||
<Upload {...props}>
|
<Upload {...props}>
|
||||||
<button type="button">upload</button>
|
<button type="button">upload</button>
|
||||||
</Upload>,
|
</Upload>,
|
||||||
);
|
);
|
||||||
|
|
||||||
wrapper.find('input').simulate('change', {
|
fireEvent.change(wrapper.querySelector('input'), {
|
||||||
target: {
|
target: {
|
||||||
files: [
|
files: [
|
||||||
new File(['foo'], 'foo.png', {
|
new File(['foo'], 'foo.png', {
|
||||||
@ -788,7 +837,7 @@ describe('Upload', () => {
|
|||||||
|
|
||||||
expect(fileList[0].uid).toBeFalsy();
|
expect(fileList[0].uid).toBeFalsy();
|
||||||
|
|
||||||
mount(
|
render(
|
||||||
<Upload fileList={fileList}>
|
<Upload fileList={fileList}>
|
||||||
<button type="button">upload</button>
|
<button type="button">upload</button>
|
||||||
</Upload>,
|
</Upload>,
|
||||||
@ -800,13 +849,13 @@ describe('Upload', () => {
|
|||||||
it('Proxy should support deepClone', async () => {
|
it('Proxy should support deepClone', async () => {
|
||||||
const onChange = jest.fn();
|
const onChange = jest.fn();
|
||||||
|
|
||||||
const wrapper = mount(
|
const { container: wrapper } = render(
|
||||||
<Upload onChange={onChange}>
|
<Upload onChange={onChange}>
|
||||||
<button type="button">upload</button>
|
<button type="button">upload</button>
|
||||||
</Upload>,
|
</Upload>,
|
||||||
);
|
);
|
||||||
|
|
||||||
wrapper.find('input').simulate('change', {
|
fireEvent.change(wrapper.querySelector('input'), {
|
||||||
target: {
|
target: {
|
||||||
files: [
|
files: [
|
||||||
new File(['foo'], 'foo.png', {
|
new File(['foo'], 'foo.png', {
|
||||||
@ -843,9 +892,9 @@ describe('Upload', () => {
|
|||||||
|
|
||||||
const frozenFileList = fileList.map(file => Object.freeze(file));
|
const frozenFileList = fileList.map(file => Object.freeze(file));
|
||||||
|
|
||||||
const wrapper = mount(<Upload fileList={frozenFileList} />);
|
const { container: wrapper } = render(<Upload fileList={frozenFileList} />);
|
||||||
const rmBtn = wrapper.find('.ant-upload-list-item-action').last();
|
const rmBtn = wrapper.querySelectorAll('.ant-upload-list-item-card-actions-btn');
|
||||||
rmBtn.simulate('click');
|
fireEvent.click(rmBtn[rmBtn.length - 1]);
|
||||||
|
|
||||||
// Wait for Upload async remove
|
// Wait for Upload async remove
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
@ -893,7 +942,7 @@ describe('Upload', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Motion leave status change: start > active
|
// Motion leave status change: start > active
|
||||||
act(() => {
|
await act(() => {
|
||||||
jest.runAllTimers();
|
jest.runAllTimers();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -907,10 +956,10 @@ describe('Upload', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('<Upload /> should pass <UploadList /> prefixCls', async () => {
|
it('<Upload /> should pass <UploadList /> prefixCls', async () => {
|
||||||
const wrapper1 = mount(<Upload />);
|
const { container: wrapper } = render(<Upload />);
|
||||||
expect(wrapper1.find('.ant-upload-list').exists()).toBeTruthy();
|
expect(wrapper.querySelectorAll('.ant-upload-list').length).toBeGreaterThan(0);
|
||||||
|
|
||||||
const wrapper2 = mount(<Upload prefixCls="custom-upload" />);
|
const { container: wrapper2 } = render(<Upload prefixCls="custom-upload" />);
|
||||||
expect(wrapper2.find('.custom-upload-list').exists()).toBeTruthy();
|
expect(wrapper2.querySelectorAll('.custom-upload-list').length).toBeGreaterThan(0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -2,8 +2,8 @@ import Dragger from './Dragger';
|
|||||||
import type { UploadProps } from './Upload';
|
import type { UploadProps } from './Upload';
|
||||||
import InternalUpload, { LIST_IGNORE } from './Upload';
|
import InternalUpload, { LIST_IGNORE } from './Upload';
|
||||||
|
|
||||||
export { UploadProps, UploadListProps, UploadChangeParam, RcFile } from './interface';
|
|
||||||
export { DraggerProps } from './Dragger';
|
export { DraggerProps } from './Dragger';
|
||||||
|
export { RcFile, UploadChangeParam, UploadFile, UploadListProps, UploadProps } from './interface';
|
||||||
|
|
||||||
type InternalUploadType = typeof InternalUpload;
|
type InternalUploadType = typeof InternalUpload;
|
||||||
interface UploadInterface<T = any> extends InternalUploadType {
|
interface UploadInterface<T = any> extends InternalUploadType {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "antd",
|
"name": "antd",
|
||||||
"version": "4.21.2",
|
"version": "4.21.3",
|
||||||
"description": "An enterprise-class UI design language and React components implementation",
|
"description": "An enterprise-class UI design language and React components implementation",
|
||||||
"title": "Ant Design",
|
"title": "Ant Design",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
@ -157,7 +157,7 @@
|
|||||||
"rc-tree-select": "~5.4.0",
|
"rc-tree-select": "~5.4.0",
|
||||||
"rc-trigger": "^5.2.10",
|
"rc-trigger": "^5.2.10",
|
||||||
"rc-upload": "~4.3.0",
|
"rc-upload": "~4.3.0",
|
||||||
"rc-util": "^5.21.3",
|
"rc-util": "^5.22.3",
|
||||||
"scroll-into-view-if-needed": "^2.2.25",
|
"scroll-into-view-if-needed": "^2.2.25",
|
||||||
"shallowequal": "^1.1.0"
|
"shallowequal": "^1.1.0"
|
||||||
},
|
},
|
||||||
@ -236,7 +236,7 @@
|
|||||||
"identity-obj-proxy": "^3.0.0",
|
"identity-obj-proxy": "^3.0.0",
|
||||||
"immer": "^9.0.1",
|
"immer": "^9.0.1",
|
||||||
"immutability-helper": "^3.0.0",
|
"immutability-helper": "^3.0.0",
|
||||||
"inquirer": "^8.0.0",
|
"inquirer": "^9.0.0",
|
||||||
"intersection-observer": "^0.12.0",
|
"intersection-observer": "^0.12.0",
|
||||||
"isomorphic-fetch": "^3.0.0",
|
"isomorphic-fetch": "^3.0.0",
|
||||||
"jest": "^28.0.3",
|
"jest": "^28.0.3",
|
||||||
@ -246,7 +246,7 @@
|
|||||||
"jest-image-snapshot": "^5.1.0",
|
"jest-image-snapshot": "^5.1.0",
|
||||||
"jest-puppeteer": "^6.0.0",
|
"jest-puppeteer": "^6.0.0",
|
||||||
"jquery": "^3.4.1",
|
"jquery": "^3.4.1",
|
||||||
"jsdom": "^19.0.0",
|
"jsdom": "^20.0.0",
|
||||||
"jsonml.js": "^0.1.0",
|
"jsonml.js": "^0.1.0",
|
||||||
"less-vars-to-js": "^1.3.0",
|
"less-vars-to-js": "^1.3.0",
|
||||||
"lz-string": "^1.4.4",
|
"lz-string": "^1.4.4",
|
||||||
|
Loading…
Reference in New Issue
Block a user