mirror of
https://gitee.com/ant-design/ant-design.git
synced 2024-11-30 02:59:04 +08:00
Merge branch 'feature' into master-merge-feature
This commit is contained in:
commit
e5e2159882
@ -2,6 +2,10 @@ import * as React from 'react';
|
||||
|
||||
export const { isValidElement } = React;
|
||||
|
||||
export function isFragment(child: React.ReactElement): boolean {
|
||||
return child && child.type === React.Fragment;
|
||||
}
|
||||
|
||||
type AnyObject = Record<any, any>;
|
||||
|
||||
type RenderProps = undefined | AnyObject | ((originProps: AnyObject) => AnyObject | undefined);
|
||||
|
@ -98,4 +98,18 @@ describe('AutoComplete', () => {
|
||||
);
|
||||
expect(screen.getByRole('combobox')).toHaveClass('custom');
|
||||
});
|
||||
|
||||
it('should show warning when use dropdownClassName', () => {
|
||||
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
render(
|
||||
<AutoComplete dropdownClassName="myCustomClassName">
|
||||
<AutoComplete.Option value="111">111</AutoComplete.Option>
|
||||
<AutoComplete.Option value="222">222</AutoComplete.Option>
|
||||
</AutoComplete>,
|
||||
);
|
||||
expect(errorSpy).toHaveBeenCalledWith(
|
||||
'Warning: [antd: AutoComplete] `dropdownClassName` is deprecated which will be removed in next major version. Please use `popupClassName` instead.',
|
||||
);
|
||||
errorSpy.mockRestore();
|
||||
});
|
||||
});
|
||||
|
@ -66,7 +66,7 @@ const options = [
|
||||
|
||||
const App: React.FC = () => (
|
||||
<AutoComplete
|
||||
dropdownClassName="certain-category-search-dropdown"
|
||||
popupClassName="certain-category-search-dropdown"
|
||||
dropdownMatchSelectWidth={500}
|
||||
style={{ width: 250 }}
|
||||
options={options}
|
||||
|
@ -31,7 +31,7 @@ The differences with Select are:
|
||||
| defaultOpen | Initial open state of dropdown | boolean | - | |
|
||||
| defaultValue | Initial selected option | string | - | |
|
||||
| disabled | Whether disabled select | boolean | false | |
|
||||
| dropdownClassName | The className of dropdown menu | string | - | |
|
||||
| popupClassName | The className of dropdown menu | string | - | 4.23.0 |
|
||||
| dropdownMatchSelectWidth | Determine whether the dropdown menu and the select input are the same width. Default set `min-width` same as input. Will ignore when value less than select width. `false` will disable virtual scroll | boolean \| number | true | |
|
||||
| filterOption | If true, filter options by input, if function, filter options against it. The function will receive two arguments, `inputValue` and `option`, if the function returns true, the option will be included in the filtered set; Otherwise, it will be excluded | boolean \| function(inputValue, option) | true | |
|
||||
| notFoundContent | Specify content to show when no result matches | string | `Not Found` | |
|
||||
|
@ -41,6 +41,12 @@ export interface AutoCompleteProps<
|
||||
> {
|
||||
dataSource?: DataSourceItemType[];
|
||||
status?: InputStatus;
|
||||
/**
|
||||
* @deprecated `dropdownClassName` is deprecated which will be removed in next major version.
|
||||
* Please use `popupClassName` instead.
|
||||
*/
|
||||
dropdownClassName?: string;
|
||||
popupClassName?: string;
|
||||
}
|
||||
|
||||
function isSelectOptionOrSelectOptGroup(child: any): Boolean {
|
||||
@ -51,7 +57,14 @@ const AutoComplete: React.ForwardRefRenderFunction<RefSelectProps, AutoCompleteP
|
||||
props,
|
||||
ref,
|
||||
) => {
|
||||
const { prefixCls: customizePrefixCls, className, children, dataSource } = props;
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
className,
|
||||
popupClassName,
|
||||
dropdownClassName,
|
||||
children,
|
||||
dataSource,
|
||||
} = props;
|
||||
const childNodes: React.ReactElement[] = toArray(children);
|
||||
|
||||
// ============================= Input =============================
|
||||
@ -112,6 +125,12 @@ const AutoComplete: React.ForwardRefRenderFunction<RefSelectProps, AutoCompleteP
|
||||
'`dataSource` is deprecated, please use `options` instead.',
|
||||
);
|
||||
|
||||
warning(
|
||||
!dropdownClassName,
|
||||
'AutoComplete',
|
||||
'`dropdownClassName` is deprecated which will be removed in next major version. Please use `popupClassName` instead.',
|
||||
);
|
||||
|
||||
warning(
|
||||
!customizeInput || !('size' in props),
|
||||
'AutoComplete',
|
||||
@ -128,6 +147,7 @@ const AutoComplete: React.ForwardRefRenderFunction<RefSelectProps, AutoCompleteP
|
||||
ref={ref}
|
||||
{...omit(props, ['dataSource'])}
|
||||
prefixCls={prefixCls}
|
||||
dropdownClassName={popupClassName || dropdownClassName}
|
||||
className={classNames(`${prefixCls}-auto-complete`, className)}
|
||||
mode={Select.SECRET_COMBOBOX_MODE_DO_NOT_USE as any}
|
||||
{...{
|
||||
|
@ -32,7 +32,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/qtJm4yt45/AutoComplete.svg
|
||||
| defaultOpen | 是否默认展开下拉菜单 | boolean | - | |
|
||||
| defaultValue | 指定默认选中的条目 | string | - | |
|
||||
| disabled | 是否禁用 | boolean | false | |
|
||||
| dropdownClassName | 下拉菜单的 className 属性 | string | - | |
|
||||
| popupClassName | 下拉菜单的 className 属性 | string | - | 4.23.0 |
|
||||
| dropdownMatchSelectWidth | 下拉菜单和选择器同宽。默认将设置 `min-width`,当值小于选择框宽度时会被忽略。false 时会关闭虚拟滚动 | boolean \| number | true | |
|
||||
| filterOption | 是否根据输入项进行筛选。当其为一个函数时,会接收 `inputValue` `option` 两个参数,当 `option` 符合筛选条件时,应返回 true,反之则返回 false | boolean \| function(inputValue, option) | true | |
|
||||
| getPopupContainer | 菜单渲染父节点。默认渲染到 body 上,如果你遇到菜单滚动定位问题,试试修改为滚动的区域,并相对其定位。[示例](https://codesandbox.io/s/4j168r7jw0) | function(triggerNode) | () => document.body | |
|
||||
|
@ -851,13 +851,6 @@ Array [
|
||||
role="tabpanel"
|
||||
tabindex="0"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
tabindex="-1"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -1007,26 +1000,12 @@ Array [
|
||||
<div
|
||||
class="ant-tabs-content ant-tabs-content-top"
|
||||
>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="false"
|
||||
class="ant-tabs-tabpane ant-tabs-tabpane-active"
|
||||
role="tabpanel"
|
||||
tabindex="0"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
tabindex="-1"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -832,13 +832,6 @@ Array [
|
||||
role="tabpanel"
|
||||
tabindex="0"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
tabindex="-1"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -969,26 +962,12 @@ Array [
|
||||
<div
|
||||
class="ant-tabs-content ant-tabs-content-top"
|
||||
>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="false"
|
||||
class="ant-tabs-tabpane ant-tabs-tabpane-active"
|
||||
role="tabpanel"
|
||||
tabindex="0"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
tabindex="-1"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -541,7 +541,7 @@ describe('Cascader', () => {
|
||||
it('popupClassName', () => {
|
||||
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
const { container } = render(
|
||||
<Cascader open popupPlacement="bottomLeft" popupClassName="mock-cls" />,
|
||||
<Cascader open popupPlacement="bottomLeft" dropdownClassName="mock-cls" />,
|
||||
);
|
||||
|
||||
expect(container.querySelector('.mock-cls')).toBeTruthy();
|
||||
@ -550,7 +550,7 @@ describe('Cascader', () => {
|
||||
expect((global as any).triggerProps.popupPlacement).toEqual('bottomLeft');
|
||||
|
||||
expect(errorSpy).toHaveBeenCalledWith(
|
||||
'Warning: [antd: Cascader] `popupClassName` is deprecated. Please use `dropdownClassName` instead.',
|
||||
'Warning: [antd: Cascader] `dropdownClassName` is deprecated which will be removed in next major version. Please use `popupClassName` instead.',
|
||||
);
|
||||
|
||||
errorSpy.mockRestore();
|
||||
|
@ -30,7 +30,7 @@ Cascade selection box.
|
||||
| defaultValue | Initial selected value | string\[] \| number\[] | \[] | |
|
||||
| disabled | Whether disabled select | boolean | false | |
|
||||
| displayRender | The render function of displaying selected options | (label, selectedOptions) => ReactNode | label => label.join(`/`) | `multiple`: 4.18.0 |
|
||||
| dropdownClassName | The additional className of popup overlay | string | - | 4.17.0 |
|
||||
| popupClassName | The additional className of popup overlay | string | - | 4.23.0 |
|
||||
| dropdownRender | Customize dropdown content | (menus: ReactNode) => ReactNode | - | 4.4.0 |
|
||||
| expandIcon | Customize the current item expand icon | ReactNode | - | 4.4.0 |
|
||||
| expandTrigger | expand current item when click or hover, one of `click` `hover` | string | `click` | |
|
||||
|
@ -108,6 +108,11 @@ export type CascaderProps<DataNodeType> = UnionCascaderProps & {
|
||||
suffixIcon?: React.ReactNode;
|
||||
options?: DataNodeType[];
|
||||
status?: InputStatus;
|
||||
/**
|
||||
* @deprecated `dropdownClassName` is deprecated which will be removed in next major
|
||||
* version.Please use `popupClassName` instead.
|
||||
*/
|
||||
dropdownClassName?: string;
|
||||
};
|
||||
|
||||
export interface CascaderRef {
|
||||
@ -164,9 +169,9 @@ const Cascader = React.forwardRef((props: CascaderProps<any>, ref: React.Ref<Cas
|
||||
|
||||
// =================== Warning =====================
|
||||
warning(
|
||||
popupClassName === undefined,
|
||||
!dropdownClassName,
|
||||
'Cascader',
|
||||
'`popupClassName` is deprecated. Please use `dropdownClassName` instead.',
|
||||
'`dropdownClassName` is deprecated which will be removed in next major version. Please use `popupClassName` instead.',
|
||||
);
|
||||
|
||||
warning(
|
||||
@ -185,7 +190,7 @@ const Cascader = React.forwardRef((props: CascaderProps<any>, ref: React.Ref<Cas
|
||||
|
||||
// =================== Dropdown ====================
|
||||
const mergedDropdownClassName = classNames(
|
||||
dropdownClassName || popupClassName,
|
||||
popupClassName || dropdownClassName,
|
||||
`${cascaderPrefixCls}-dropdown`,
|
||||
{
|
||||
[`${cascaderPrefixCls}-dropdown-rtl`]: mergedDirection === 'rtl',
|
||||
|
@ -31,7 +31,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/UdS8y8xyZ/Cascader.svg
|
||||
| defaultValue | 默认的选中项 | string\[] \| number\[] | \[] | |
|
||||
| disabled | 禁用 | boolean | false | |
|
||||
| displayRender | 选择后展示的渲染函数 | (label, selectedOptions) => ReactNode | label => label.join(`/`) | `multiple`: 4.18.0 |
|
||||
| dropdownClassName | 自定义浮层类名 | string | - | 4.17.0 |
|
||||
| popupClassName | 自定义浮层类名 | string | - | 4.23.0 |
|
||||
| dropdownRender | 自定义下拉框内容 | (menus: ReactNode) => ReactNode | - | 4.4.0 |
|
||||
| expandIcon | 自定义次级菜单展开图标 | ReactNode | - | 4.4.0 |
|
||||
| expandTrigger | 次级菜单的展开方式,可选 'click' 和 'hover' | string | `click` | |
|
||||
|
@ -15806,10 +15806,10 @@ exports[`ConfigProvider components Form configProvider 1`] = `
|
||||
>
|
||||
<div
|
||||
class="config-form-item-explain config-show-help-appear config-show-help-appear-start config-show-help config-form-item-explain-connected"
|
||||
role="alert"
|
||||
>
|
||||
<div
|
||||
class="config-show-help-item-appear config-show-help-item-appear-start config-show-help-item config-form-item-explain-error"
|
||||
role="alert"
|
||||
style="height: 0px; opacity: 0;"
|
||||
>
|
||||
Bamboo is Light
|
||||
@ -15854,10 +15854,10 @@ exports[`ConfigProvider components Form configProvider componentDisabled 1`] = `
|
||||
>
|
||||
<div
|
||||
class="config-form-item-explain config-show-help-appear config-show-help-appear-start config-show-help config-form-item-explain-connected"
|
||||
role="alert"
|
||||
>
|
||||
<div
|
||||
class="config-show-help-item-appear config-show-help-item-appear-start config-show-help-item config-form-item-explain-error"
|
||||
role="alert"
|
||||
style="height: 0px; opacity: 0;"
|
||||
>
|
||||
Bamboo is Light
|
||||
@ -15901,10 +15901,10 @@ exports[`ConfigProvider components Form configProvider componentSize large 1`] =
|
||||
>
|
||||
<div
|
||||
class="config-form-item-explain config-show-help-appear config-show-help-appear-start config-show-help config-form-item-explain-connected"
|
||||
role="alert"
|
||||
>
|
||||
<div
|
||||
class="config-show-help-item-appear config-show-help-item-appear-start config-show-help-item config-form-item-explain-error"
|
||||
role="alert"
|
||||
style="height: 0px; opacity: 0;"
|
||||
>
|
||||
Bamboo is Light
|
||||
@ -15948,10 +15948,10 @@ exports[`ConfigProvider components Form configProvider componentSize middle 1`]
|
||||
>
|
||||
<div
|
||||
class="config-form-item-explain config-show-help-appear config-show-help-appear-start config-show-help config-form-item-explain-connected"
|
||||
role="alert"
|
||||
>
|
||||
<div
|
||||
class="config-show-help-item-appear config-show-help-item-appear-start config-show-help-item config-form-item-explain-error"
|
||||
role="alert"
|
||||
style="height: 0px; opacity: 0;"
|
||||
>
|
||||
Bamboo is Light
|
||||
@ -15995,10 +15995,10 @@ exports[`ConfigProvider components Form configProvider virtual and dropdownMatch
|
||||
>
|
||||
<div
|
||||
class="ant-form-item-explain ant-show-help-appear ant-show-help-appear-start ant-show-help ant-form-item-explain-connected"
|
||||
role="alert"
|
||||
>
|
||||
<div
|
||||
class="ant-show-help-item-appear ant-show-help-item-appear-start ant-show-help-item ant-form-item-explain-error"
|
||||
role="alert"
|
||||
style="height: 0px; opacity: 0;"
|
||||
>
|
||||
Bamboo is Light
|
||||
@ -16042,10 +16042,10 @@ exports[`ConfigProvider components Form normal 1`] = `
|
||||
>
|
||||
<div
|
||||
class="ant-form-item-explain ant-show-help-appear ant-show-help-appear-start ant-show-help ant-form-item-explain-connected"
|
||||
role="alert"
|
||||
>
|
||||
<div
|
||||
class="ant-show-help-item-appear ant-show-help-item-appear-start ant-show-help-item ant-form-item-explain-error"
|
||||
role="alert"
|
||||
style="height: 0px; opacity: 0;"
|
||||
>
|
||||
Bamboo is Light
|
||||
@ -16089,10 +16089,10 @@ exports[`ConfigProvider components Form prefixCls 1`] = `
|
||||
>
|
||||
<div
|
||||
class="prefix-Form-item-explain ant-show-help-appear ant-show-help-appear-start ant-show-help prefix-Form-item-explain-connected"
|
||||
role="alert"
|
||||
>
|
||||
<div
|
||||
class="ant-show-help-item-appear ant-show-help-item-appear-start ant-show-help-item prefix-Form-item-explain-error"
|
||||
role="alert"
|
||||
style="height: 0px; opacity: 0;"
|
||||
>
|
||||
Bamboo is Light
|
||||
|
@ -276,7 +276,7 @@ describe('ConfigProvider', () => {
|
||||
testPair('Divider', props => <Divider {...props} />);
|
||||
|
||||
// Drawer
|
||||
testPair('Drawer', props => <Drawer {...props} visible getContainer={false} />);
|
||||
testPair('Drawer', props => <Drawer {...props} open getContainer={false} />);
|
||||
|
||||
// Dropdown
|
||||
testPair('Dropdown', props => {
|
||||
@ -393,7 +393,7 @@ describe('ConfigProvider', () => {
|
||||
// Modal
|
||||
testPair('Modal', props => (
|
||||
<div>
|
||||
<Modal {...props} visible getContainer={false}>
|
||||
<Modal {...props} open getContainer={false}>
|
||||
Bamboo is Little Light
|
||||
</Modal>
|
||||
</div>
|
||||
@ -417,7 +417,7 @@ describe('ConfigProvider', () => {
|
||||
// Popconfirm
|
||||
testPair('Popconfirm', props => (
|
||||
<div>
|
||||
<Popconfirm {...props} visible>
|
||||
<Popconfirm {...props} open>
|
||||
<span>Bamboo</span>
|
||||
</Popconfirm>
|
||||
</div>
|
||||
@ -426,7 +426,7 @@ describe('ConfigProvider', () => {
|
||||
// Popover
|
||||
testPair('Popover', props => (
|
||||
<div>
|
||||
<Popover {...props} visible>
|
||||
<Popover {...props} open>
|
||||
<span>Light</span>
|
||||
</Popover>
|
||||
</div>
|
||||
@ -466,9 +466,14 @@ describe('ConfigProvider', () => {
|
||||
testPair('Slider', props => {
|
||||
const myProps = { ...props };
|
||||
if (myProps.prefixCls) {
|
||||
myProps.tooltipPrefixCls = `${myProps.prefixCls}-tooltip`;
|
||||
return (
|
||||
<Slider
|
||||
tooltip={{ open: true, prefixCls: `${myProps.prefixCls}-tooltip` }}
|
||||
{...myProps}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return <Slider tooltipVisible {...myProps} />;
|
||||
return <Slider tooltip={{ open: true }} {...myProps} />;
|
||||
});
|
||||
|
||||
// Spin
|
||||
@ -507,7 +512,7 @@ describe('ConfigProvider', () => {
|
||||
children: [{ text: 'Green', value: 'Green' }],
|
||||
},
|
||||
],
|
||||
filterDropdownVisible: true,
|
||||
filterDropdownOpen: true,
|
||||
onFilter: (value, record) => record.name.indexOf(value) === 0,
|
||||
sorter: (a, b) => a.name.length - b.name.length,
|
||||
},
|
||||
@ -550,7 +555,7 @@ describe('ConfigProvider', () => {
|
||||
|
||||
// Tooltip
|
||||
testPair('Tooltip', props => (
|
||||
<Tooltip {...props} title="Bamboo" visible>
|
||||
<Tooltip {...props} title="Bamboo" open>
|
||||
<span>Light</span>
|
||||
</Tooltip>
|
||||
));
|
||||
|
@ -30,12 +30,12 @@ describe('ConfigProvider.GetPopupContainer', () => {
|
||||
|
||||
it('Drawer', () => {
|
||||
const getPopupContainer = jest.fn(node => node.parentNode);
|
||||
const Demo: React.FC<{ visible?: boolean }> = ({ visible }) => (
|
||||
const Demo: React.FC<{ open?: boolean }> = ({ open }) => (
|
||||
<ConfigProvider getPopupContainer={getPopupContainer}>
|
||||
<Drawer visible={visible} />
|
||||
<Drawer open={open} />
|
||||
</ConfigProvider>
|
||||
);
|
||||
render(<Demo visible />);
|
||||
render(<Demo open />);
|
||||
expect(getPopupContainer).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
@ -108,7 +108,7 @@ type Placement = 'bottomLeft' | 'bottomRight' | 'topLeft' | 'topRight';
|
||||
|
||||
const Page: React.FC<{ popupPlacement: Placement }> = ({ popupPlacement }) => {
|
||||
const [currentStep, setCurrentStep] = useState(0);
|
||||
const [modalVisible, setModalVisible] = useState(false);
|
||||
const [modalOpen, setModalOpen] = useState(false);
|
||||
const [badgeCount, setBadgeCount] = useState(5);
|
||||
const [showBadge, setShowBadge] = useState(true);
|
||||
|
||||
@ -139,17 +139,17 @@ const Page: React.FC<{ popupPlacement: Placement }> = ({ popupPlacement }) => {
|
||||
|
||||
// ==== Modal ====
|
||||
const showModal = () => {
|
||||
setModalVisible(true);
|
||||
setModalOpen(true);
|
||||
};
|
||||
|
||||
const handleOk = (e: React.MouseEvent<HTMLElement>) => {
|
||||
console.log(e);
|
||||
setModalVisible(false);
|
||||
setModalOpen(false);
|
||||
};
|
||||
|
||||
const handleCancel = (e: React.MouseEvent<HTMLElement>) => {
|
||||
console.log(e);
|
||||
setModalVisible(false);
|
||||
setModalOpen(false);
|
||||
};
|
||||
|
||||
// ==== End Modal ====
|
||||
@ -378,12 +378,7 @@ const Page: React.FC<{ popupPlacement: Placement }> = ({ popupPlacement }) => {
|
||||
<Button type="primary" onClick={showModal}>
|
||||
Open Modal
|
||||
</Button>
|
||||
<Modal
|
||||
title="پنچره ساده"
|
||||
visible={modalVisible}
|
||||
onOk={handleOk}
|
||||
onCancel={handleCancel}
|
||||
>
|
||||
<Modal title="پنچره ساده" open={modalOpen} onOk={handleOk} onCancel={handleCancel}>
|
||||
<p>نگاشتههای خود را اینجا قراردهید</p>
|
||||
<p>نگاشتههای خود را اینجا قراردهید</p>
|
||||
<p>نگاشتههای خود را اینجا قراردهید</p>
|
||||
|
@ -58,14 +58,14 @@ const columns = [
|
||||
];
|
||||
|
||||
const Page = () => {
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const showModal = () => {
|
||||
setVisible(true);
|
||||
setOpen(true);
|
||||
};
|
||||
|
||||
const hideModal = () => {
|
||||
setVisible(false);
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
const info = () => {
|
||||
@ -115,7 +115,7 @@ const Page = () => {
|
||||
<div className="example">
|
||||
<Table dataSource={[]} columns={columns} />
|
||||
</div>
|
||||
<Modal title="Locale Modal" visible={visible} onCancel={hideModal}>
|
||||
<Modal title="Locale Modal" open={open} onCancel={hideModal}>
|
||||
<p>Locale Modal</p>
|
||||
</Modal>
|
||||
</div>
|
||||
|
@ -221,6 +221,20 @@ describe('DatePicker', () => {
|
||||
).toBe(60);
|
||||
});
|
||||
|
||||
it('DatePicker should show warning when use dropdownClassName', () => {
|
||||
render(<DatePicker dropdownClassName="myCustomClassName" />);
|
||||
expect(errorSpy).toHaveBeenCalledWith(
|
||||
'Warning: [antd: DatePicker] `dropdownClassName` is deprecated which will be removed in next major version. Please use `popupClassName` instead.',
|
||||
);
|
||||
});
|
||||
|
||||
it('RangePicker should show warning when use dropdownClassName', () => {
|
||||
render(<DatePicker.RangePicker dropdownClassName="myCustomClassName" />);
|
||||
expect(errorSpy).toHaveBeenCalledWith(
|
||||
'Warning: [antd: RangePicker] `dropdownClassName` is deprecated which will be removed in next major version. Please use `popupClassName` instead.',
|
||||
);
|
||||
});
|
||||
|
||||
it('DatePicker.RangePicker with defaultPickerValue and showTime', () => {
|
||||
const startDate = moment('1982-02-12');
|
||||
const endDate = moment('1982-02-22');
|
||||
|
@ -18,6 +18,7 @@ import { getMergedStatus, getStatusClassNames } from '../../_util/statusUtils';
|
||||
import enUS from '../locale/en_US';
|
||||
import { getRangePlaceholder, transPlacement2DropdownAlign } from '../util';
|
||||
import type { CommonPickerMethods, PickerComponentClass } from './interface';
|
||||
import warning from '../../_util/warning';
|
||||
|
||||
export default function generateRangePicker<DateType>(
|
||||
generateConfig: GenerateConfig<DateType>,
|
||||
@ -26,7 +27,14 @@ export default function generateRangePicker<DateType>(
|
||||
|
||||
const RangePicker = forwardRef<
|
||||
InternalRangePickerProps | CommonPickerMethods,
|
||||
RangePickerProps<DateType>
|
||||
RangePickerProps<DateType> & {
|
||||
/**
|
||||
* @deprecated `dropdownClassName` is deprecated which will be removed in next major
|
||||
* version.Please use `popupClassName` instead.
|
||||
*/
|
||||
dropdownClassName: string;
|
||||
popupClassName?: string;
|
||||
}
|
||||
>((props, ref) => {
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
@ -37,6 +45,8 @@ export default function generateRangePicker<DateType>(
|
||||
disabled: customDisabled,
|
||||
bordered = true,
|
||||
placeholder,
|
||||
popupClassName,
|
||||
dropdownClassName,
|
||||
status: customStatus,
|
||||
...restProps
|
||||
} = props;
|
||||
@ -54,6 +64,12 @@ export default function generateRangePicker<DateType>(
|
||||
...(picker === 'time' ? getTimeProps({ format, ...props, picker }) : {}),
|
||||
};
|
||||
|
||||
warning(
|
||||
!dropdownClassName,
|
||||
'RangePicker',
|
||||
'`dropdownClassName` is deprecated which will be removed in next major version. Please use `popupClassName` instead.',
|
||||
);
|
||||
|
||||
// ===================== Size =====================
|
||||
const size = React.useContext(SizeContext);
|
||||
const mergedSize = customizeSize || size;
|
||||
@ -92,6 +108,7 @@ export default function generateRangePicker<DateType>(
|
||||
}
|
||||
disabled={mergedDisabled}
|
||||
ref={innerRef}
|
||||
dropdownClassName={popupClassName || dropdownClassName}
|
||||
dropdownAlign={transPlacement2DropdownAlign(direction, placement)}
|
||||
placeholder={getRangePlaceholder(picker, locale, placeholder)}
|
||||
suffixIcon={suffixNode}
|
||||
|
@ -24,8 +24,13 @@ import type { CommonPickerMethods, DatePickRef, PickerComponentClass } from './i
|
||||
export default function generatePicker<DateType>(generateConfig: GenerateConfig<DateType>) {
|
||||
type DatePickerProps = PickerProps<DateType> & {
|
||||
status?: InputStatus;
|
||||
/**
|
||||
* @deprecated `dropdownClassName` is deprecated which will be removed in next major
|
||||
* version.Please use `popupClassName` instead.
|
||||
*/
|
||||
dropdownClassName?: string;
|
||||
popupClassName?: string;
|
||||
};
|
||||
|
||||
function getPicker<InnerPickerProps extends DatePickerProps>(
|
||||
picker?: PickerMode,
|
||||
displayName?: string,
|
||||
@ -40,17 +45,13 @@ export default function generatePicker<DateType>(generateConfig: GenerateConfig<
|
||||
bordered = true,
|
||||
placement,
|
||||
placeholder,
|
||||
popupClassName,
|
||||
dropdownClassName,
|
||||
disabled: customDisabled,
|
||||
status: customStatus,
|
||||
...restProps
|
||||
} = props;
|
||||
|
||||
warning(
|
||||
picker !== 'quarter',
|
||||
displayName!,
|
||||
`DatePicker.${displayName} is legacy usage. Please use DatePicker[picker='${picker}'] directly.`,
|
||||
);
|
||||
|
||||
const { getPrefixCls, direction, getPopupContainer } = useContext(ConfigContext);
|
||||
const prefixCls = getPrefixCls('picker', customizePrefixCls);
|
||||
const innerRef = React.useRef<RCPicker<DateType>>(null);
|
||||
@ -80,6 +81,18 @@ export default function generatePicker<DateType>(generateConfig: GenerateConfig<
|
||||
};
|
||||
const rootPrefixCls = getPrefixCls();
|
||||
|
||||
// =================== Warning =====================
|
||||
warning(
|
||||
picker !== 'quarter',
|
||||
displayName!,
|
||||
`DatePicker.${displayName} is legacy usage. Please use DatePicker[picker='${picker}'] directly.`,
|
||||
);
|
||||
|
||||
warning(
|
||||
!dropdownClassName,
|
||||
'DatePicker',
|
||||
'`dropdownClassName` is deprecated which will be removed in next major version. Please use `popupClassName` instead.',
|
||||
);
|
||||
// ===================== Size =====================
|
||||
const size = React.useContext(SizeContext);
|
||||
const mergedSize = customizeSize || size;
|
||||
@ -110,6 +123,7 @@ export default function generatePicker<DateType>(generateConfig: GenerateConfig<
|
||||
placeholder={getPlaceholder(mergedPicker, locale, placeholder)}
|
||||
suffixIcon={suffixNode}
|
||||
dropdownAlign={transPlacement2DropdownAlign(direction, placement)}
|
||||
dropdownClassName={popupClassName || dropdownClassName}
|
||||
clearIcon={<CloseCircleFilled />}
|
||||
prevIcon={<span className={`${prefixCls}-prev-icon`} />}
|
||||
nextIcon={<span className={`${prefixCls}-next-icon`} />}
|
||||
|
@ -59,7 +59,7 @@ The following APIs are shared by DatePicker, RangePicker.
|
||||
| dateRender | Custom rendering function for date cells | function(currentDate: moment, today: moment) => React.ReactNode | - | |
|
||||
| disabled | Determine whether the DatePicker is disabled | boolean | false | |
|
||||
| disabledDate | Specify the date that cannot be selected | (currentDate: moment) => boolean | - | |
|
||||
| dropdownClassName | To customize the className of the popup calendar | string | - | |
|
||||
| popupClassName | To customize the className of the popup calendar | string | - | 4.23.0 |
|
||||
| getPopupContainer | To set the container of the floating layer, while the default is to create a `div` element in `body` | function(trigger) | - | |
|
||||
| inputReadOnly | Set the `readonly` attribute of the input tag (avoids virtual keyboard on touch devices) | boolean | false | |
|
||||
| locale | Localization configuration | object | [default](https://github.com/ant-design/ant-design/blob/master/components/date-picker/locale/example.json) | |
|
||||
|
@ -60,7 +60,7 @@ import locale from 'antd/es/locale/zh_CN';
|
||||
| dateRender | 自定义日期单元格的内容 | function(currentDate: moment, today: moment) => React.ReactNode | - | |
|
||||
| disabled | 禁用 | boolean | false | |
|
||||
| disabledDate | 不可选择的日期 | (currentDate: moment) => boolean | - | |
|
||||
| dropdownClassName | 额外的弹出日历 className | string | - | |
|
||||
| popupClassName | 额外的弹出日历 className | string | - | 4.23.0 |
|
||||
| getPopupContainer | 定义浮层的容器,默认为 body 上新建 div | function(trigger) | - | |
|
||||
| inputReadOnly | 设置输入框为只读(避免在移动设备上打开虚拟键盘) | boolean | false | |
|
||||
| locale | 国际化配置 | object | [默认配置](https://github.com/ant-design/ant-design/blob/master/components/date-picker/locale/example.json) | |
|
||||
|
@ -8,7 +8,7 @@ import ConfigProvider from '../../config-provider';
|
||||
|
||||
const DrawerTest = ({ getContainer }) => (
|
||||
<div>
|
||||
<Drawer visible width={400} getContainer={getContainer}>
|
||||
<Drawer open width={400} getContainer={getContainer}>
|
||||
Here is content of Drawer
|
||||
</Drawer>
|
||||
</div>
|
||||
@ -48,7 +48,7 @@ describe('Drawer', () => {
|
||||
|
||||
it('render correctly', () => {
|
||||
const { container: wrapper } = render(
|
||||
<Drawer visible width={400} getContainer={false}>
|
||||
<Drawer open width={400} getContainer={false}>
|
||||
Here is content of Drawer
|
||||
</Drawer>,
|
||||
);
|
||||
@ -70,7 +70,7 @@ describe('Drawer', () => {
|
||||
|
||||
it('render top drawer', () => {
|
||||
const { container: wrapper } = render(
|
||||
<Drawer visible height={400} placement="top" getContainer={false}>
|
||||
<Drawer open height={400} placement="top" getContainer={false}>
|
||||
Here is content of Drawer
|
||||
</Drawer>,
|
||||
);
|
||||
@ -81,7 +81,7 @@ describe('Drawer', () => {
|
||||
|
||||
it('have a title', () => {
|
||||
const { container: wrapper } = render(
|
||||
<Drawer visible title="Test Title" getContainer={false}>
|
||||
<Drawer open title="Test Title" getContainer={false}>
|
||||
Here is content of Drawer
|
||||
</Drawer>,
|
||||
);
|
||||
@ -92,7 +92,7 @@ describe('Drawer', () => {
|
||||
|
||||
it('closable is false', () => {
|
||||
const { container: wrapper } = render(
|
||||
<Drawer visible closable={false} getContainer={false}>
|
||||
<Drawer open closable={false} getContainer={false}>
|
||||
Here is content of Drawer
|
||||
</Drawer>,
|
||||
);
|
||||
@ -103,7 +103,7 @@ describe('Drawer', () => {
|
||||
|
||||
it('destroyOnClose is true', () => {
|
||||
const { container: wrapper } = render(
|
||||
<Drawer destroyOnClose visible={false} getContainer={false}>
|
||||
<Drawer destroyOnClose open={false} getContainer={false}>
|
||||
Here is content of Drawer
|
||||
</Drawer>,
|
||||
);
|
||||
@ -114,7 +114,7 @@ describe('Drawer', () => {
|
||||
|
||||
it('className is test_drawer', () => {
|
||||
const { container: wrapper } = render(
|
||||
<Drawer destroyOnClose visible className="test_drawer" getContainer={false}>
|
||||
<Drawer destroyOnClose open className="test_drawer" getContainer={false}>
|
||||
Here is content of Drawer
|
||||
</Drawer>,
|
||||
);
|
||||
@ -129,7 +129,7 @@ describe('Drawer', () => {
|
||||
};
|
||||
const { container: wrapper } = render(
|
||||
<Drawer
|
||||
visible
|
||||
open
|
||||
style={style}
|
||||
drawerStyle={style}
|
||||
headerStyle={style}
|
||||
@ -146,7 +146,7 @@ describe('Drawer', () => {
|
||||
|
||||
it('have a footer', () => {
|
||||
const { container: wrapper } = render(
|
||||
<Drawer visible footer="Test Footer" getContainer={false}>
|
||||
<Drawer open footer="Test Footer" getContainer={false}>
|
||||
Here is content of Drawer
|
||||
</Drawer>,
|
||||
);
|
||||
@ -176,7 +176,7 @@ describe('Drawer', () => {
|
||||
|
||||
it('support closeIcon', () => {
|
||||
const { container: wrapper } = render(
|
||||
<Drawer visible closable closeIcon={<span>close</span>} width={400} getContainer={false}>
|
||||
<Drawer open closable closeIcon={<span>close</span>} width={400} getContainer={false}>
|
||||
Here is content of Drawer
|
||||
</Drawer>,
|
||||
);
|
||||
@ -190,7 +190,7 @@ describe('Drawer', () => {
|
||||
|
||||
render(
|
||||
<ConfigProvider virtual>
|
||||
<Drawer visible>Bamboo is Light</Drawer>
|
||||
<Drawer open>Bamboo is Light</Drawer>
|
||||
</ConfigProvider>,
|
||||
);
|
||||
|
||||
@ -200,9 +200,22 @@ describe('Drawer', () => {
|
||||
});
|
||||
|
||||
it('zIndex should work', () => {
|
||||
const { container } = render(<Drawer getContainer={false} visible zIndex={903} />);
|
||||
const { container } = render(<Drawer getContainer={false} open zIndex={903} />);
|
||||
expect(container.querySelector('.ant-drawer')).toHaveStyle({
|
||||
zIndex: 903,
|
||||
});
|
||||
});
|
||||
it('deprecated warning', () => {
|
||||
const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
|
||||
const { rerender } = render(<Drawer visible />);
|
||||
expect(errSpy).toHaveBeenCalledWith(
|
||||
'Warning: [antd: Drawer] `visible` is deprecated which will be removed in next major version, please use `open` instead.',
|
||||
);
|
||||
rerender(<Drawer afterVisibleChange={() => {}} />);
|
||||
expect(errSpy).toHaveBeenCalledWith(
|
||||
'Warning: [antd: Drawer] `afterVisibleChange` is deprecated which will be removed in next major version, please use `afterOpenChange` instead.',
|
||||
);
|
||||
errSpy.mockRestore();
|
||||
});
|
||||
});
|
||||
|
@ -4,7 +4,7 @@ import { act, fireEvent, render } from '../../../tests/utils';
|
||||
|
||||
describe('Drawer', () => {
|
||||
const getDrawer = props => (
|
||||
<Drawer visible getContainer={false} {...props}>
|
||||
<Drawer open getContainer={false} {...props}>
|
||||
Here is content of Drawer
|
||||
</Drawer>
|
||||
);
|
||||
@ -21,7 +21,7 @@ describe('Drawer', () => {
|
||||
const { container, asFragment, rerender } = render(getDrawer());
|
||||
expect(container.querySelector('.ant-drawer-body')).toBeTruthy();
|
||||
|
||||
rerender(getDrawer({ visible: false }));
|
||||
rerender(getDrawer({ open: false }));
|
||||
|
||||
expect(container.querySelector('.ant-drawer-body').textContent).toEqual(
|
||||
'Here is content of Drawer',
|
||||
@ -58,7 +58,7 @@ describe('Drawer', () => {
|
||||
const { container, rerender } = render(getDrawer({ destroyOnClose: true }));
|
||||
expect(container.querySelector('.ant-drawer')).toBeTruthy();
|
||||
|
||||
rerender(getDrawer({ destroyOnClose: true, visible: false }));
|
||||
rerender(getDrawer({ destroyOnClose: true, open: false }));
|
||||
act(() => {
|
||||
jest.runAllTimers();
|
||||
});
|
||||
@ -70,7 +70,7 @@ describe('Drawer', () => {
|
||||
const { container, rerender } = render(getDrawer());
|
||||
expect(container.querySelector('.ant-drawer')).toBeTruthy();
|
||||
|
||||
rerender(getDrawer({ visible: false }));
|
||||
rerender(getDrawer({ open: false }));
|
||||
act(() => {
|
||||
jest.runAllTimers();
|
||||
});
|
||||
@ -80,11 +80,11 @@ describe('Drawer', () => {
|
||||
});
|
||||
|
||||
it('dom should be existed after close twice when getContainer is false', () => {
|
||||
const { container, rerender } = render(getDrawer({ visible: true, getContainer: false }));
|
||||
const { container, rerender } = render(getDrawer({ open: true, getContainer: false }));
|
||||
expect(container.querySelector('.ant-drawer-content')).toBeTruthy();
|
||||
|
||||
// Hide
|
||||
rerender(getDrawer({ visible: false, getContainer: false }));
|
||||
rerender(getDrawer({ open: false, getContainer: false }));
|
||||
act(() => {
|
||||
jest.runAllTimers();
|
||||
});
|
||||
@ -92,12 +92,12 @@ describe('Drawer', () => {
|
||||
expect(container.querySelector('.ant-drawer-content-wrapper-hidden')).toBeTruthy();
|
||||
|
||||
// Show
|
||||
rerender(getDrawer({ visible: true, getContainer: false }));
|
||||
rerender(getDrawer({ open: true, getContainer: false }));
|
||||
expect(container.querySelector('.ant-drawer-content-wrapper')).toBeTruthy();
|
||||
expect(container.querySelector('.ant-drawer-content-wrapper-hidden')).toBeFalsy();
|
||||
|
||||
// Hide
|
||||
rerender(getDrawer({ visible: false, getContainer: false }));
|
||||
rerender(getDrawer({ open: false, getContainer: false }));
|
||||
act(() => {
|
||||
jest.runAllTimers();
|
||||
});
|
||||
@ -107,8 +107,8 @@ describe('Drawer', () => {
|
||||
|
||||
it('test afterVisibleChange', async () => {
|
||||
const afterVisibleChange = jest.fn();
|
||||
const { container, rerender } = render(getDrawer({ afterVisibleChange, visible: true }));
|
||||
rerender(getDrawer({ afterVisibleChange, visible: false }));
|
||||
const { container, rerender } = render(getDrawer({ afterVisibleChange, open: true }));
|
||||
rerender(getDrawer({ afterVisibleChange, open: false }));
|
||||
|
||||
act(() => {
|
||||
jest.runAllTimers();
|
||||
@ -128,18 +128,18 @@ describe('Drawer', () => {
|
||||
|
||||
const RefDemo = () => {
|
||||
const ref = React.useRef();
|
||||
const [visible, setVisible] = React.useState(false);
|
||||
const [open, setOpen] = React.useState(false);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (visible) {
|
||||
if (open) {
|
||||
refCallback(ref.current);
|
||||
}
|
||||
}, [visible]);
|
||||
}, [open]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<a onClick={() => setVisible(true)}>open</a>
|
||||
<Drawer visible={visible}>
|
||||
<a onClick={() => setOpen(true)}>open</a>
|
||||
<Drawer open={open}>
|
||||
<div ref={ref} />
|
||||
</Drawer>
|
||||
</>
|
||||
|
@ -4,18 +4,18 @@ import { fireEvent, render } from '../../../tests/utils';
|
||||
import Button from '../../button';
|
||||
|
||||
class MultiDrawer extends React.Component {
|
||||
state = { visible: false, childrenDrawer: false, hasChildren: true };
|
||||
state = { open: false, childrenDrawer: false, hasChildren: true };
|
||||
|
||||
showDrawer = () => {
|
||||
this.setState({
|
||||
visible: true,
|
||||
open: true,
|
||||
hasChildren: true,
|
||||
});
|
||||
};
|
||||
|
||||
onClose = () => {
|
||||
this.setState({
|
||||
visible: false,
|
||||
open: false,
|
||||
});
|
||||
};
|
||||
|
||||
@ -39,7 +39,7 @@ class MultiDrawer extends React.Component {
|
||||
};
|
||||
|
||||
render() {
|
||||
const { childrenDrawer, visible, hasChildren } = this.state;
|
||||
const { childrenDrawer, open, hasChildren } = this.state;
|
||||
const { placement, push } = this.props;
|
||||
return (
|
||||
<div>
|
||||
@ -56,7 +56,7 @@ class MultiDrawer extends React.Component {
|
||||
onClose={this.onClose}
|
||||
getContainer={false}
|
||||
placement={placement}
|
||||
visible={visible}
|
||||
open={open}
|
||||
push={push}
|
||||
>
|
||||
<Button type="primary" id="open_two_drawer" onClick={this.showChildrenDrawer}>
|
||||
@ -70,7 +70,7 @@ class MultiDrawer extends React.Component {
|
||||
getContainer={false}
|
||||
placement={placement}
|
||||
onClose={this.onChildrenDrawerClose}
|
||||
visible={childrenDrawer}
|
||||
open={childrenDrawer}
|
||||
>
|
||||
<div id="two_drawer_text">This is two-level drawer</div>
|
||||
</Drawer>
|
||||
|
@ -600,6 +600,7 @@ HTMLCollection [
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="name"
|
||||
placeholder="Please enter user name"
|
||||
@ -655,6 +656,7 @@ HTMLCollection [
|
||||
http://
|
||||
</span>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="url"
|
||||
placeholder="Please enter url"
|
||||
@ -710,6 +712,7 @@ HTMLCollection [
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<div
|
||||
aria-required="true"
|
||||
class="ant-select ant-select-in-form-item ant-select-single ant-select-show-arrow"
|
||||
>
|
||||
<div
|
||||
@ -724,6 +727,7 @@ HTMLCollection [
|
||||
aria-controls="owner_list"
|
||||
aria-haspopup="listbox"
|
||||
aria-owns="owner_list"
|
||||
aria-required="true"
|
||||
autocomplete="off"
|
||||
class="ant-select-selection-search-input"
|
||||
id="owner"
|
||||
@ -887,6 +891,7 @@ HTMLCollection [
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<div
|
||||
aria-required="true"
|
||||
class="ant-select ant-select-in-form-item ant-select-single ant-select-show-arrow"
|
||||
>
|
||||
<div
|
||||
@ -901,6 +906,7 @@ HTMLCollection [
|
||||
aria-controls="type_list"
|
||||
aria-haspopup="listbox"
|
||||
aria-owns="type_list"
|
||||
aria-required="true"
|
||||
autocomplete="off"
|
||||
class="ant-select-selection-search-input"
|
||||
id="type"
|
||||
@ -1069,6 +1075,7 @@ HTMLCollection [
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<div
|
||||
aria-required="true"
|
||||
class="ant-select ant-select-in-form-item ant-select-single ant-select-show-arrow"
|
||||
>
|
||||
<div
|
||||
@ -1083,6 +1090,7 @@ HTMLCollection [
|
||||
aria-controls="approver_list"
|
||||
aria-haspopup="listbox"
|
||||
aria-owns="approver_list"
|
||||
aria-required="true"
|
||||
autocomplete="off"
|
||||
class="ant-select-selection-search-input"
|
||||
id="approver"
|
||||
@ -1246,6 +1254,7 @@ HTMLCollection [
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<div
|
||||
aria-required="true"
|
||||
class="ant-picker ant-picker-range"
|
||||
style="width: 100%;"
|
||||
>
|
||||
@ -2470,6 +2479,7 @@ HTMLCollection [
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<textarea
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="description"
|
||||
placeholder="please enter url description"
|
||||
|
@ -10,7 +10,7 @@ describe('Drawer.typescript', () => {
|
||||
placement="right"
|
||||
closable={false}
|
||||
onClose={onClose}
|
||||
visible={false}
|
||||
open={false}
|
||||
contentWrapperStyle={{
|
||||
background: '#f00',
|
||||
}}
|
||||
|
@ -18,14 +18,14 @@ import { Button, Drawer } from 'antd';
|
||||
import React, { useState } from 'react';
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const showDrawer = () => {
|
||||
setVisible(true);
|
||||
setOpen(true);
|
||||
};
|
||||
|
||||
const onClose = () => {
|
||||
setVisible(false);
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
return (
|
||||
@ -33,7 +33,7 @@ const App: React.FC = () => {
|
||||
<Button type="primary" onClick={showDrawer}>
|
||||
Open
|
||||
</Button>
|
||||
<Drawer title="Basic Drawer" placement="right" onClose={onClose} visible={visible}>
|
||||
<Drawer title="Basic Drawer" placement="right" onClose={onClose} open={open}>
|
||||
<p>Some contents...</p>
|
||||
<p>Some contents...</p>
|
||||
<p>Some contents...</p>
|
||||
|
@ -20,14 +20,14 @@ import React, { useRef, useState } from 'react';
|
||||
|
||||
const App: React.FC = () => {
|
||||
const domRef = useRef<HTMLDivElement>(null);
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const showDrawer = () => {
|
||||
setVisible(true);
|
||||
setOpen(true);
|
||||
};
|
||||
|
||||
const onClose = () => {
|
||||
setVisible(false);
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
return (
|
||||
@ -41,7 +41,7 @@ const App: React.FC = () => {
|
||||
title="ConfigProvider"
|
||||
placement="right"
|
||||
onClose={onClose}
|
||||
visible={visible}
|
||||
open={open}
|
||||
>
|
||||
<p>Some contents...</p>
|
||||
<p>Some contents...</p>
|
||||
|
@ -11,7 +11,7 @@ title:
|
||||
|
||||
## en-US
|
||||
|
||||
Extra actions should be placed at corner of drawer in Ant Design, you can using `extra` prop for that.
|
||||
Extra actions should be placed at corner of drawer in Ant Design, you can use `extra` prop for that.
|
||||
|
||||
```tsx
|
||||
import { Button, Drawer, Radio, Space } from 'antd';
|
||||
@ -20,11 +20,11 @@ import type { RadioChangeEvent } from 'antd/es/radio';
|
||||
import React, { useState } from 'react';
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [open, setOpen] = useState(false);
|
||||
const [placement, setPlacement] = useState<DrawerProps['placement']>('right');
|
||||
|
||||
const showDrawer = () => {
|
||||
setVisible(true);
|
||||
setOpen(true);
|
||||
};
|
||||
|
||||
const onChange = (e: RadioChangeEvent) => {
|
||||
@ -32,7 +32,7 @@ const App: React.FC = () => {
|
||||
};
|
||||
|
||||
const onClose = () => {
|
||||
setVisible(false);
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
return (
|
||||
@ -53,7 +53,7 @@ const App: React.FC = () => {
|
||||
placement={placement}
|
||||
width={500}
|
||||
onClose={onClose}
|
||||
visible={visible}
|
||||
open={open}
|
||||
extra={
|
||||
<Space>
|
||||
<Button onClick={onClose}>Cancel</Button>
|
||||
|
@ -21,14 +21,14 @@ import React, { useState } from 'react';
|
||||
const { Option } = Select;
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const showDrawer = () => {
|
||||
setVisible(true);
|
||||
setOpen(true);
|
||||
};
|
||||
|
||||
const onClose = () => {
|
||||
setVisible(false);
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
return (
|
||||
@ -40,7 +40,7 @@ const App: React.FC = () => {
|
||||
title="Create a new account"
|
||||
width={720}
|
||||
onClose={onClose}
|
||||
visible={visible}
|
||||
open={open}
|
||||
bodyStyle={{ paddingBottom: 80 }}
|
||||
extra={
|
||||
<Space>
|
||||
|
@ -18,15 +18,15 @@ import { Button, Drawer } from 'antd';
|
||||
import React, { useState } from 'react';
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [open, setOpen] = useState(false);
|
||||
const [childrenDrawer, setChildrenDrawer] = useState(false);
|
||||
|
||||
const showDrawer = () => {
|
||||
setVisible(true);
|
||||
setOpen(true);
|
||||
};
|
||||
|
||||
const onClose = () => {
|
||||
setVisible(false);
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
const showChildrenDrawer = () => {
|
||||
@ -42,13 +42,7 @@ const App: React.FC = () => {
|
||||
<Button type="primary" onClick={showDrawer}>
|
||||
Open drawer
|
||||
</Button>
|
||||
<Drawer
|
||||
title="Multi-level drawer"
|
||||
width={520}
|
||||
closable={false}
|
||||
onClose={onClose}
|
||||
visible={visible}
|
||||
>
|
||||
<Drawer title="Multi-level drawer" width={520} closable={false} onClose={onClose} open={open}>
|
||||
<Button type="primary" onClick={showChildrenDrawer}>
|
||||
Two-level drawer
|
||||
</Button>
|
||||
@ -57,7 +51,7 @@ const App: React.FC = () => {
|
||||
width={320}
|
||||
closable={false}
|
||||
onClose={onChildrenDrawerClose}
|
||||
visible={childrenDrawer}
|
||||
open={childrenDrawer}
|
||||
>
|
||||
This is two-level drawer
|
||||
</Drawer>
|
||||
|
@ -19,14 +19,14 @@ import { Button, Drawer } from 'antd';
|
||||
import React, { useState } from 'react';
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const showDrawer = () => {
|
||||
setVisible(true);
|
||||
setOpen(true);
|
||||
};
|
||||
|
||||
const onClose = () => {
|
||||
setVisible(false);
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
return (
|
||||
@ -39,7 +39,7 @@ const App: React.FC = () => {
|
||||
placement="right"
|
||||
mask={false}
|
||||
onClose={onClose}
|
||||
visible={visible}
|
||||
open={open}
|
||||
contentWrapperStyle={{
|
||||
width: 333,
|
||||
background: 'red',
|
||||
|
@ -19,15 +19,15 @@ import { Button, Drawer, Radio, Space } from 'antd';
|
||||
import React, { useState } from 'react';
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [open, setOpen] = useState(false);
|
||||
const [placement, setPlacement] = useState<DrawerProps['placement']>('left');
|
||||
|
||||
const showDrawer = () => {
|
||||
setVisible(true);
|
||||
setOpen(true);
|
||||
};
|
||||
|
||||
const onClose = () => {
|
||||
setVisible(false);
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
const onChange = (e: RadioChangeEvent) => {
|
||||
@ -52,7 +52,7 @@ const App: React.FC = () => {
|
||||
placement={placement}
|
||||
closable={false}
|
||||
onClose={onClose}
|
||||
visible={visible}
|
||||
open={open}
|
||||
key={placement}
|
||||
>
|
||||
<p>Some contents...</p>
|
||||
|
@ -18,14 +18,14 @@ import { Button, Drawer } from 'antd';
|
||||
import React, { useState } from 'react';
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const showDrawer = () => {
|
||||
setVisible(true);
|
||||
setOpen(true);
|
||||
};
|
||||
|
||||
const onClose = () => {
|
||||
setVisible(false);
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
return (
|
||||
@ -41,7 +41,7 @@ const App: React.FC = () => {
|
||||
placement="right"
|
||||
closable={false}
|
||||
onClose={onClose}
|
||||
visible={visible}
|
||||
open={open}
|
||||
getContainer={false}
|
||||
style={{ position: 'absolute' }}
|
||||
>
|
||||
|
@ -19,21 +19,21 @@ import type { DrawerProps } from 'antd/es/drawer';
|
||||
import React, { useState } from 'react';
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [open, setOpen] = useState(false);
|
||||
const [size, setSize] = useState<DrawerProps['size']>();
|
||||
|
||||
const showDefaultDrawer = () => {
|
||||
setSize('default');
|
||||
setVisible(true);
|
||||
setOpen(true);
|
||||
};
|
||||
|
||||
const showLargeDrawer = () => {
|
||||
setSize('large');
|
||||
setVisible(true);
|
||||
setOpen(true);
|
||||
};
|
||||
|
||||
const onClose = () => {
|
||||
setVisible(false);
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
return (
|
||||
@ -51,7 +51,7 @@ const App: React.FC = () => {
|
||||
placement="right"
|
||||
size={size}
|
||||
onClose={onClose}
|
||||
visible={visible}
|
||||
open={open}
|
||||
extra={
|
||||
<Space>
|
||||
<Button onClick={onClose}>Cancel</Button>
|
||||
|
@ -30,14 +30,14 @@ const DescriptionItem = ({ title, content }: DescriptionItemProps) => (
|
||||
);
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const showDrawer = () => {
|
||||
setVisible(true);
|
||||
setOpen(true);
|
||||
};
|
||||
|
||||
const onClose = () => {
|
||||
setVisible(false);
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
return (
|
||||
@ -73,7 +73,7 @@ const App: React.FC = () => {
|
||||
</List.Item>
|
||||
)}
|
||||
/>
|
||||
<Drawer width={640} placement="right" closable={false} onClose={onClose} visible={visible}>
|
||||
<Drawer width={640} placement="right" closable={false} onClose={onClose} open={open}>
|
||||
<p className="site-description-item-profile-p" style={{ marginBottom: 24 }}>
|
||||
User Profile
|
||||
</p>
|
||||
|
@ -21,7 +21,7 @@ A Drawer is a panel that is typically overlaid on top of a page and slides in fr
|
||||
| Props | Description | Type | Default | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| autoFocus | Whether Drawer should get focused after open | boolean | true | 4.17.0 |
|
||||
| afterVisibleChange | Callback after the animation ends when switching drawers | function(visible) | - | |
|
||||
| afterOpenChange | Callback after the animation ends when switching drawers | function(open) | - | 4.23.0 |
|
||||
| bodyStyle | Style of the drawer content part | CSSProperties | - | |
|
||||
| className | The class name of the container of the Drawer dialog | string | - | |
|
||||
| closable | Whether a close (x) button is visible on top left of the Drawer dialog or not | boolean | true | |
|
||||
@ -45,7 +45,7 @@ A Drawer is a panel that is typically overlaid on top of a page and slides in fr
|
||||
| style | Style of wrapper element which **contains mask** compare to `drawerStyle` | CSSProperties | - | |
|
||||
| size | presetted size of drawer, default `378px` and large `736px` | 'default' \| 'large' | 'default' | 4.17.0 |
|
||||
| title | The title for Drawer | ReactNode | - | |
|
||||
| visible | Whether the Drawer dialog is visible or not | boolean | false | |
|
||||
| open | Whether the Drawer dialog is visible or not | boolean | false | 4.23.0 |
|
||||
| width | Width of the Drawer dialog | string \| number | 378 | |
|
||||
| zIndex | The `z-index` of the Drawer | number | 1000 | |
|
||||
| onClose | Specify a callback that will be called when a user clicks mask, close button or Cancel button | function(e) | - | |
|
||||
|
@ -8,6 +8,7 @@ import { ConfigContext } from '../config-provider';
|
||||
import { NoFormStyle } from '../form/context';
|
||||
import { getTransitionName } from '../_util/motion';
|
||||
import { tuple } from '../_util/type';
|
||||
import warning from '../_util/warning';
|
||||
|
||||
const SizeTypes = tuple('default', 'large');
|
||||
type sizeType = typeof SizeTypes[number];
|
||||
@ -29,41 +30,55 @@ export interface DrawerProps extends RcDrawerProps {
|
||||
footerStyle?: React.CSSProperties;
|
||||
|
||||
title?: React.ReactNode;
|
||||
/**
|
||||
* @deprecated `visible` is deprecated which will be removed in next major version. Please use
|
||||
* `open` instead.
|
||||
*/
|
||||
visible?: boolean;
|
||||
open?: boolean;
|
||||
|
||||
footer?: React.ReactNode;
|
||||
extra?: React.ReactNode;
|
||||
|
||||
/**
|
||||
* @deprecated `afterVisibleChange` is deprecated which will be removed in next major version.
|
||||
* Please use `afterOpenChange` instead.
|
||||
*/
|
||||
afterVisibleChange?: (visible: boolean) => void;
|
||||
afterOpenChange?: (open: boolean) => void;
|
||||
}
|
||||
|
||||
const defaultPushState: PushState = { distance: 180 };
|
||||
|
||||
function Drawer({
|
||||
width,
|
||||
height,
|
||||
size = 'default',
|
||||
closable = true,
|
||||
mask = true,
|
||||
push = defaultPushState,
|
||||
closeIcon = <CloseOutlined />,
|
||||
bodyStyle,
|
||||
drawerStyle,
|
||||
className,
|
||||
visible,
|
||||
children,
|
||||
style,
|
||||
title,
|
||||
headerStyle,
|
||||
onClose,
|
||||
footer,
|
||||
footerStyle,
|
||||
prefixCls: customizePrefixCls,
|
||||
getContainer: customizeGetContainer,
|
||||
extra,
|
||||
afterVisibleChange,
|
||||
...rest
|
||||
}: DrawerProps) {
|
||||
function Drawer(props: DrawerProps) {
|
||||
const {
|
||||
width,
|
||||
height,
|
||||
size = 'default',
|
||||
closable = true,
|
||||
mask = true,
|
||||
push = defaultPushState,
|
||||
closeIcon = <CloseOutlined />,
|
||||
bodyStyle,
|
||||
drawerStyle,
|
||||
className,
|
||||
visible,
|
||||
open,
|
||||
children,
|
||||
style,
|
||||
title,
|
||||
headerStyle,
|
||||
onClose,
|
||||
footer,
|
||||
footerStyle,
|
||||
prefixCls: customizePrefixCls,
|
||||
getContainer: customizeGetContainer,
|
||||
extra,
|
||||
afterVisibleChange,
|
||||
afterOpenChange,
|
||||
...rest
|
||||
} = props;
|
||||
|
||||
const { getPopupContainer, getPrefixCls, direction } = React.useContext(ConfigContext);
|
||||
const prefixCls = getPrefixCls('drawer', customizePrefixCls);
|
||||
|
||||
@ -79,6 +94,17 @@ function Drawer({
|
||||
</button>
|
||||
);
|
||||
|
||||
[
|
||||
['visible', 'open'],
|
||||
['afterVisibleChange', 'afterOpenChange'],
|
||||
].forEach(([deprecatedName, newName]) => {
|
||||
warning(
|
||||
!(deprecatedName in props),
|
||||
'Drawer',
|
||||
`\`${deprecatedName}\` is deprecated which will be removed in next major version, please use \`${newName}\` instead.`,
|
||||
);
|
||||
});
|
||||
|
||||
function renderHeader() {
|
||||
if (!title && !closable) {
|
||||
return null;
|
||||
@ -152,15 +178,16 @@ function Drawer({
|
||||
prefixCls={prefixCls}
|
||||
onClose={onClose}
|
||||
{...rest}
|
||||
open={visible}
|
||||
open={open || visible}
|
||||
mask={mask}
|
||||
push={push}
|
||||
width={mergedWidth}
|
||||
height={mergedHeight}
|
||||
rootClassName={drawerClassName}
|
||||
getContainer={getContainer}
|
||||
afterOpenChange={open => {
|
||||
afterVisibleChange?.(open);
|
||||
afterOpenChange={isOpen => {
|
||||
afterOpenChange?.(isOpen);
|
||||
afterVisibleChange?.(isOpen);
|
||||
}}
|
||||
maskMotion={maskMotion}
|
||||
motion={panelMotion}
|
||||
|
@ -20,7 +20,7 @@ cover: https://img.alicdn.com/imgextra/i4/O1CN019djdZP1OHwXSRGCOW_!!600000000168
|
||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| autoFocus | 抽屉展开后是否将焦点切换至其 Dom 节点 | boolean | true | 4.17.0 |
|
||||
| afterVisibleChange | 切换抽屉时动画结束后的回调 | function(visible) | - | |
|
||||
| afterOpenChange | 切换抽屉时动画结束后的回调 | function(open) | - | 4.23.0 |
|
||||
| bodyStyle | 可用于设置 Drawer 内容部分的样式 | CSSProperties | - | |
|
||||
| className | 对话框外层容器的类名 | string | - | |
|
||||
| closable | 是否显示左上角的关闭按钮 | boolean | true | |
|
||||
@ -44,7 +44,7 @@ cover: https://img.alicdn.com/imgextra/i4/O1CN019djdZP1OHwXSRGCOW_!!600000000168
|
||||
| size | 预设抽屉宽度(或高度),default `378px` 和 large `736px` | 'default' \| 'large' | 'default' | 4.17.0 |
|
||||
| style | 可用于设置 Drawer 最外层容器的样式,和 `drawerStyle` 的区别是作用节点包括 `mask` | CSSProperties | - | |
|
||||
| title | 标题 | ReactNode | - | |
|
||||
| visible | Drawer 是否可见 | boolean | - | |
|
||||
| open | Drawer 是否可见 | boolean | - | 4.23.0 |
|
||||
| width | 宽度 | string \| number | 378 | |
|
||||
| zIndex | 设置 Drawer 的 `z-index` | number | 1000 | |
|
||||
| onClose | 点击遮罩层或左上角叉或取消按钮的回调 | function(e) | - | |
|
||||
|
@ -4246,7 +4246,7 @@ exports[`renders ./components/dropdown/demo/dropdown-button.md extend context co
|
||||
</div>
|
||||
<div
|
||||
class="ant-space-item"
|
||||
style="padding-bottom:8px"
|
||||
style="margin-right:8px;padding-bottom:8px"
|
||||
>
|
||||
<button
|
||||
class="ant-btn ant-btn-default ant-dropdown-trigger"
|
||||
@ -4528,6 +4528,288 @@ exports[`renders ./components/dropdown/demo/dropdown-button.md extend context co
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-space-item"
|
||||
style="padding-bottom:8px"
|
||||
>
|
||||
<div
|
||||
class="ant-btn-group ant-dropdown-button"
|
||||
>
|
||||
<button
|
||||
class="ant-btn ant-btn-default ant-btn-dangerous"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Danger
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
class="ant-btn ant-btn-default ant-btn-icon-only ant-btn-dangerous ant-dropdown-trigger"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
aria-label="ellipsis"
|
||||
class="anticon anticon-ellipsis"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="ellipsis"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M176 511a56 56 0 10112 0 56 56 0 10-112 0zm280 0a56 56 0 10112 0 56 56 0 10-112 0zm280 0a56 56 0 10112 0 56 56 0 10-112 0z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</button>
|
||||
<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"
|
||||
role="menuitem"
|
||||
tabindex="-1"
|
||||
>
|
||||
<span
|
||||
aria-label="user"
|
||||
class="anticon anticon-user ant-dropdown-menu-item-icon"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="user"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M858.5 763.6a374 374 0 00-80.6-119.5 375.63 375.63 0 00-119.5-80.6c-.4-.2-.8-.3-1.2-.5C719.5 518 760 444.7 760 362c0-137-111-248-248-248S264 225 264 362c0 82.7 40.5 156 102.8 201.1-.4.2-.8.3-1.2.5-44.8 18.9-85 46-119.5 80.6a375.63 375.63 0 00-80.6 119.5A371.7 371.7 0 00136 901.8a8 8 0 008 8.2h60c4.4 0 7.9-3.5 8-7.8 2-77.2 33-149.5 87.8-204.3 56.7-56.7 132-87.9 212.2-87.9s155.5 31.2 212.2 87.9C779 752.7 810 825 812 902.2c.1 4.4 3.6 7.8 8 7.8h60a8 8 0 008-8.2c-1-47.8-10.9-94.3-29.5-138.2zM512 534c-45.9 0-89.1-17.9-121.6-50.4S340 407.9 340 362c0-45.9 17.9-89.1 50.4-121.6S466.1 190 512 190s89.1 17.9 121.6 50.4S684 316.1 684 362c0 45.9-17.9 89.1-50.4 121.6S557.9 534 512 534z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
<span
|
||||
class="ant-dropdown-menu-title-content"
|
||||
>
|
||||
1st menu item
|
||||
</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"
|
||||
role="menuitem"
|
||||
tabindex="-1"
|
||||
>
|
||||
<span
|
||||
aria-label="user"
|
||||
class="anticon anticon-user ant-dropdown-menu-item-icon"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="user"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M858.5 763.6a374 374 0 00-80.6-119.5 375.63 375.63 0 00-119.5-80.6c-.4-.2-.8-.3-1.2-.5C719.5 518 760 444.7 760 362c0-137-111-248-248-248S264 225 264 362c0 82.7 40.5 156 102.8 201.1-.4.2-.8.3-1.2.5-44.8 18.9-85 46-119.5 80.6a375.63 375.63 0 00-80.6 119.5A371.7 371.7 0 00136 901.8a8 8 0 008 8.2h60c4.4 0 7.9-3.5 8-7.8 2-77.2 33-149.5 87.8-204.3 56.7-56.7 132-87.9 212.2-87.9s155.5 31.2 212.2 87.9C779 752.7 810 825 812 902.2c.1 4.4 3.6 7.8 8 7.8h60a8 8 0 008-8.2c-1-47.8-10.9-94.3-29.5-138.2zM512 534c-45.9 0-89.1-17.9-121.6-50.4S340 407.9 340 362c0-45.9 17.9-89.1 50.4-121.6S466.1 190 512 190s89.1 17.9 121.6 50.4S684 316.1 684 362c0 45.9-17.9 89.1-50.4 121.6S557.9 534 512 534z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
<span
|
||||
class="ant-dropdown-menu-title-content"
|
||||
>
|
||||
2nd menu item
|
||||
</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"
|
||||
role="menuitem"
|
||||
tabindex="-1"
|
||||
>
|
||||
<span
|
||||
aria-label="user"
|
||||
class="anticon anticon-user ant-dropdown-menu-item-icon"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="user"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M858.5 763.6a374 374 0 00-80.6-119.5 375.63 375.63 0 00-119.5-80.6c-.4-.2-.8-.3-1.2-.5C719.5 518 760 444.7 760 362c0-137-111-248-248-248S264 225 264 362c0 82.7 40.5 156 102.8 201.1-.4.2-.8.3-1.2.5-44.8 18.9-85 46-119.5 80.6a375.63 375.63 0 00-80.6 119.5A371.7 371.7 0 00136 901.8a8 8 0 008 8.2h60c4.4 0 7.9-3.5 8-7.8 2-77.2 33-149.5 87.8-204.3 56.7-56.7 132-87.9 212.2-87.9s155.5 31.2 212.2 87.9C779 752.7 810 825 812 902.2c.1 4.4 3.6 7.8 8 7.8h60a8 8 0 008-8.2c-1-47.8-10.9-94.3-29.5-138.2zM512 534c-45.9 0-89.1-17.9-121.6-50.4S340 407.9 340 362c0-45.9 17.9-89.1 50.4-121.6S466.1 190 512 190s89.1 17.9 121.6 50.4S684 316.1 684 362c0 45.9-17.9 89.1-50.4 121.6S557.9 534 512 534z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
<span
|
||||
class="ant-dropdown-menu-title-content"
|
||||
>
|
||||
3rd menu item
|
||||
</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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@ -6652,7 +6934,7 @@ Array [
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`renders ./components/dropdown/demo/overlay-visible.md extend context correctly 1`] = `
|
||||
exports[`renders ./components/dropdown/demo/overlay-open.md extend context correctly 1`] = `
|
||||
Array [
|
||||
<a
|
||||
class="ant-dropdown-trigger"
|
||||
|
@ -334,7 +334,7 @@ exports[`renders ./components/dropdown/demo/dropdown-button.md correctly 1`] = `
|
||||
</div>
|
||||
<div
|
||||
class="ant-space-item"
|
||||
style="padding-bottom:8px"
|
||||
style="margin-right:8px;padding-bottom:8px"
|
||||
>
|
||||
<button
|
||||
class="ant-btn ant-btn-default ant-dropdown-trigger"
|
||||
@ -375,6 +375,47 @@ exports[`renders ./components/dropdown/demo/dropdown-button.md correctly 1`] = `
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="ant-space-item"
|
||||
style="padding-bottom:8px"
|
||||
>
|
||||
<div
|
||||
class="ant-btn-group ant-dropdown-button"
|
||||
>
|
||||
<button
|
||||
class="ant-btn ant-btn-default ant-btn-dangerous"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Danger
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
class="ant-btn ant-btn-default ant-btn-icon-only ant-btn-dangerous ant-dropdown-trigger"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
aria-label="ellipsis"
|
||||
class="anticon anticon-ellipsis"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="ellipsis"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M176 511a56 56 0 10112 0 56 56 0 10-112 0zm280 0a56 56 0 10112 0 56 56 0 10-112 0zm280 0a56 56 0 10112 0 56 56 0 10-112 0z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@ -714,7 +755,7 @@ exports[`renders ./components/dropdown/demo/menu-full.md correctly 1`] = `
|
||||
</a>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/dropdown/demo/overlay-visible.md correctly 1`] = `
|
||||
exports[`renders ./components/dropdown/demo/overlay-open.md correctly 1`] = `
|
||||
<a
|
||||
class="ant-dropdown-trigger"
|
||||
>
|
||||
|
@ -43,25 +43,28 @@ describe('DropdownButton', () => {
|
||||
),
|
||||
disabled: false,
|
||||
trigger: ['hover'],
|
||||
visible: true,
|
||||
onVisibleChange: () => {},
|
||||
open: true,
|
||||
onOpenChange: () => {},
|
||||
};
|
||||
|
||||
render(<DropdownButton {...props} />);
|
||||
const { rerender } = render(<DropdownButton {...props} />);
|
||||
|
||||
Object.keys(props).forEach((key: keyof DropdownProps) => {
|
||||
expect(dropdownProps[key]).toBe(props[key]);
|
||||
});
|
||||
|
||||
rerender(<DropdownButton overlay={<div>123</div>} visible />);
|
||||
expect(dropdownProps.open).toBe(true);
|
||||
});
|
||||
|
||||
it("don't pass visible to Dropdown if it's not exits", () => {
|
||||
it("don't pass open to Dropdown if it's not exits", () => {
|
||||
const menu = (
|
||||
<Menu>
|
||||
<Menu.Item key="1">foo</Menu.Item>
|
||||
</Menu>
|
||||
);
|
||||
render(<DropdownButton overlay={menu} />);
|
||||
expect('visible' in dropdownProps).toBe(false);
|
||||
expect('open' in dropdownProps).toBe(false);
|
||||
});
|
||||
|
||||
it('should support href like Button', () => {
|
||||
@ -100,7 +103,7 @@ describe('DropdownButton', () => {
|
||||
overlayClassName="className"
|
||||
overlayStyle={{ color: 'red' }}
|
||||
overlay={menu}
|
||||
visible
|
||||
open
|
||||
/>,
|
||||
);
|
||||
expect(container.querySelector('.ant-dropdown')?.classList).toContain('className');
|
||||
|
@ -38,7 +38,7 @@ describe('Dropdown', () => {
|
||||
|
||||
it('overlay is function and has custom transitionName', () => {
|
||||
const { asFragment } = render(
|
||||
<Dropdown overlay={() => <div>menu</div>} transitionName="move-up" visible>
|
||||
<Dropdown overlay={() => <div>menu</div>} transitionName="move-up" open>
|
||||
<button type="button">button</button>
|
||||
</Dropdown>,
|
||||
);
|
||||
@ -47,7 +47,7 @@ describe('Dropdown', () => {
|
||||
|
||||
it('overlay is string', () => {
|
||||
const { asFragment } = render(
|
||||
<Dropdown overlay={'string' as any} visible>
|
||||
<Dropdown overlay={'string' as any} open>
|
||||
<button type="button">button</button>
|
||||
</Dropdown>,
|
||||
);
|
||||
@ -64,7 +64,7 @@ describe('Dropdown', () => {
|
||||
</Menu.SubMenu>
|
||||
</Menu>
|
||||
),
|
||||
visible: true,
|
||||
open: true,
|
||||
getPopupContainer: node => node,
|
||||
};
|
||||
|
||||
@ -95,12 +95,13 @@ describe('Dropdown', () => {
|
||||
expect(error).toHaveBeenCalledWith(
|
||||
expect.stringContaining("[antd: Dropdown] You are using 'topCenter'"),
|
||||
);
|
||||
error.mockRestore();
|
||||
});
|
||||
|
||||
// zombieJ: when replaced with react test lib, it may be mock fully content
|
||||
it('dropdown should support auto adjust placement', () => {
|
||||
render(
|
||||
<Dropdown overlay={<div>menu</div>} visible>
|
||||
<Dropdown overlay={<div>menu</div>} open>
|
||||
<button type="button">button</button>
|
||||
</Dropdown>,
|
||||
);
|
||||
@ -166,4 +167,27 @@ describe('Dropdown', () => {
|
||||
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
it('deprecated warning', () => {
|
||||
const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
|
||||
const { rerender } = render(
|
||||
<Dropdown visible overlay={<div>menu</div>}>
|
||||
<a />
|
||||
</Dropdown>,
|
||||
);
|
||||
expect(errSpy).toHaveBeenCalledWith(
|
||||
'Warning: [antd: Dropdown] `visible` is deprecated which will be removed in next major version, please use `open` instead.',
|
||||
);
|
||||
rerender(
|
||||
<Dropdown onVisibleChange={() => {}} overlay={<div>menu</div>}>
|
||||
<a />
|
||||
</Dropdown>,
|
||||
);
|
||||
expect(errSpy).toHaveBeenCalledWith(
|
||||
'Warning: [antd: Dropdown] `onVisibleChange` is deprecated which will be removed in next major version, please use `onOpenChange` instead.',
|
||||
);
|
||||
|
||||
errSpy.mockRestore();
|
||||
});
|
||||
});
|
||||
|
@ -82,6 +82,9 @@ const App: React.FC = () => (
|
||||
</Space>
|
||||
</Button>
|
||||
</Dropdown>
|
||||
<Dropdown.Button danger onClick={handleButtonClick} overlay={menu}>
|
||||
Danger
|
||||
</Dropdown.Button>
|
||||
</Space>
|
||||
);
|
||||
|
||||
|
@ -20,16 +20,16 @@ import { Dropdown, Menu, Space } from 'antd';
|
||||
import React, { useState } from 'react';
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const handleMenuClick: MenuProps['onClick'] = e => {
|
||||
if (e.key === '3') {
|
||||
setVisible(false);
|
||||
setOpen(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleVisibleChange = (flag: boolean) => {
|
||||
setVisible(flag);
|
||||
const handleOpenChange = (flag: boolean) => {
|
||||
setOpen(flag);
|
||||
};
|
||||
|
||||
const menu = (
|
||||
@ -53,7 +53,7 @@ const App: React.FC = () => {
|
||||
);
|
||||
|
||||
return (
|
||||
<Dropdown overlay={menu} onVisibleChange={handleVisibleChange} visible={visible}>
|
||||
<Dropdown overlay={menu} onOpenChange={handleOpenChange} open={open}>
|
||||
<a onClick={e => e.preventDefault()}>
|
||||
<Space>
|
||||
Hover me
|
@ -16,6 +16,7 @@ export type DropdownButtonType = 'default' | 'primary' | 'ghost' | 'dashed' | 'l
|
||||
export interface DropdownButtonProps extends ButtonGroupProps, DropdownProps {
|
||||
type?: DropdownButtonType;
|
||||
htmlType?: ButtonHTMLType;
|
||||
danger?: boolean;
|
||||
disabled?: boolean;
|
||||
loading?: ButtonProps['loading'];
|
||||
onClick?: React.MouseEventHandler<HTMLButtonElement>;
|
||||
@ -40,6 +41,7 @@ const DropdownButton: DropdownButtonInterface = props => {
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
type = 'default',
|
||||
danger,
|
||||
disabled,
|
||||
loading,
|
||||
onClick,
|
||||
@ -50,7 +52,9 @@ const DropdownButton: DropdownButtonInterface = props => {
|
||||
trigger,
|
||||
align,
|
||||
visible,
|
||||
open,
|
||||
onVisibleChange,
|
||||
onOpenChange,
|
||||
placement,
|
||||
getPopupContainer,
|
||||
href,
|
||||
@ -71,7 +75,7 @@ const DropdownButton: DropdownButtonInterface = props => {
|
||||
overlay,
|
||||
disabled,
|
||||
trigger: disabled ? [] : trigger,
|
||||
onVisibleChange,
|
||||
onOpenChange: onOpenChange || onVisibleChange,
|
||||
getPopupContainer: getPopupContainer || getContextPopupContainer,
|
||||
mouseEnterDelay,
|
||||
mouseLeaveDelay,
|
||||
@ -80,8 +84,10 @@ const DropdownButton: DropdownButtonInterface = props => {
|
||||
destroyPopupOnHide,
|
||||
} as DropdownProps;
|
||||
|
||||
if ('visible' in props) {
|
||||
dropdownProps.visible = visible;
|
||||
if ('open' in props) {
|
||||
dropdownProps.open = open;
|
||||
} else if ('visible' in props) {
|
||||
dropdownProps.open = visible;
|
||||
}
|
||||
|
||||
if ('placement' in props) {
|
||||
@ -93,6 +99,7 @@ const DropdownButton: DropdownButtonInterface = props => {
|
||||
const leftButton = (
|
||||
<Button
|
||||
type={type}
|
||||
danger={danger}
|
||||
disabled={disabled}
|
||||
loading={loading}
|
||||
onClick={onClick}
|
||||
@ -104,7 +111,7 @@ const DropdownButton: DropdownButtonInterface = props => {
|
||||
</Button>
|
||||
);
|
||||
|
||||
const rightButton = <Button type={type} icon={icon} />;
|
||||
const rightButton = <Button type={type} danger={danger} icon={icon} />;
|
||||
|
||||
const [leftButtonToRender, rightButtonToRender] = buttonsRender!([leftButton, rightButton]);
|
||||
|
||||
|
@ -49,8 +49,18 @@ export interface DropdownProps {
|
||||
arrow?: boolean | DropdownArrowOptions;
|
||||
trigger?: ('click' | 'hover' | 'contextMenu')[];
|
||||
overlay: React.ReactElement | OverlayFunc;
|
||||
/**
|
||||
* @deprecated `onVisibleChange` is deprecated which will be removed in next major version. Please
|
||||
* use `onOpenChange` instead.
|
||||
*/
|
||||
onVisibleChange?: (visible: boolean) => void;
|
||||
onOpenChange?: (open: boolean) => void;
|
||||
/**
|
||||
* @deprecated `visible` is deprecated which will be removed in next major version. Please use
|
||||
* `open` instead.
|
||||
*/
|
||||
visible?: boolean;
|
||||
open?: boolean;
|
||||
disabled?: boolean;
|
||||
destroyPopupOnHide?: boolean;
|
||||
align?: Align;
|
||||
@ -79,6 +89,20 @@ const Dropdown: DropdownInterface = props => {
|
||||
direction,
|
||||
} = React.useContext(ConfigContext);
|
||||
|
||||
// Warning for deprecated usage
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
[
|
||||
['visible', 'open'],
|
||||
['onVisibleChange', 'onOpenChange'],
|
||||
].forEach(([deprecatedName, newName]) => {
|
||||
warning(
|
||||
!(deprecatedName in props),
|
||||
'Dropdown',
|
||||
`\`${deprecatedName}\` is deprecated which will be removed in next major version, please use \`${newName}\` instead.`,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
const getTransitionName = () => {
|
||||
const rootPrefixCls = getPrefixCls();
|
||||
const { placement = '', transitionName } = props;
|
||||
@ -119,7 +143,9 @@ const Dropdown: DropdownInterface = props => {
|
||||
getPopupContainer,
|
||||
overlayClassName,
|
||||
visible,
|
||||
open,
|
||||
onVisibleChange,
|
||||
onOpenChange,
|
||||
} = props;
|
||||
|
||||
const prefixCls = getPrefixCls('dropdown', customizePrefixCls);
|
||||
@ -143,13 +169,14 @@ const Dropdown: DropdownInterface = props => {
|
||||
}
|
||||
|
||||
// =========================== Visible ============================
|
||||
const [mergedVisible, setVisible] = useMergedState(false, {
|
||||
value: visible,
|
||||
const [mergedOpen, setOpen] = useMergedState(false, {
|
||||
value: open !== undefined ? open : visible,
|
||||
});
|
||||
|
||||
const onInnerVisibleChange = useEvent((nextVisible: boolean) => {
|
||||
onVisibleChange?.(nextVisible);
|
||||
setVisible(nextVisible);
|
||||
const onInnerOpenChange = useEvent((nextOpen: boolean) => {
|
||||
onVisibleChange?.(nextOpen);
|
||||
onOpenChange?.(nextOpen);
|
||||
setOpen(nextOpen);
|
||||
});
|
||||
|
||||
// =========================== Overlay ============================
|
||||
@ -163,7 +190,7 @@ const Dropdown: DropdownInterface = props => {
|
||||
});
|
||||
|
||||
const onMenuClick = React.useCallback(() => {
|
||||
setVisible(false);
|
||||
setOpen(false);
|
||||
}, []);
|
||||
|
||||
const renderOverlay = () => {
|
||||
@ -211,7 +238,7 @@ const Dropdown: DropdownInterface = props => {
|
||||
<RcDropdown
|
||||
alignPoint={alignPoint}
|
||||
{...props}
|
||||
visible={mergedVisible}
|
||||
visible={mergedOpen}
|
||||
builtinPlacements={builtinPlacements}
|
||||
arrow={!!arrow}
|
||||
overlayClassName={overlayClassNameCustomized}
|
||||
@ -221,7 +248,7 @@ const Dropdown: DropdownInterface = props => {
|
||||
trigger={triggerActions}
|
||||
overlay={renderOverlay}
|
||||
placement={getPlacement()}
|
||||
onVisibleChange={onInnerVisibleChange}
|
||||
onVisibleChange={onInnerOpenChange}
|
||||
>
|
||||
{dropdownTrigger}
|
||||
</RcDropdown>
|
||||
|
@ -27,8 +27,8 @@ When there are more than a few options to choose from, you can wrap them in a `D
|
||||
| overlayStyle | The style of the dropdown root element | CSSProperties | - | |
|
||||
| placement | Placement of popup menu: `bottom` `bottomLeft` `bottomRight` `top` `topLeft` `topRight` | string | `bottomLeft` | |
|
||||
| trigger | The trigger mode which executes the dropdown action. Note that hover can't be used on touchscreens | Array<`click`\|`hover`\|`contextMenu`> | \[`hover`] | |
|
||||
| visible | Whether the dropdown menu is currently visible | boolean | - | |
|
||||
| onVisibleChange | Called when the visible state is changed. Not trigger when hidden by click item | (visible: boolean) => void | - | |
|
||||
| open | Whether the dropdown menu is currently open | boolean | - | 4.23.0 |
|
||||
| onOpenChange | Called when the open state is changed. Not trigger when hidden by click item | (open: boolean) => void | - | 4.23.0 |
|
||||
|
||||
You should use [Menu](/components/menu/) as `overlay`. The menu items and dividers are also available by using `Menu.Item` and `Menu.Divider`.
|
||||
|
||||
@ -42,6 +42,7 @@ You should use [Menu](/components/menu/) as `overlay`. The menu items and divide
|
||||
| --- | --- | --- | --- | --- |
|
||||
| buttonsRender | Custom buttons inside Dropdown.Button | (buttons: ReactNode\[]) => ReactNode\[] | - | |
|
||||
| loading | Set the loading status of button | boolean \| { delay: number } | false | |
|
||||
| danger | Set the danger status of button | boolean | - | 4.23.0 |
|
||||
| disabled | Whether the dropdown menu is disabled | boolean | - | |
|
||||
| icon | Icon (appears on the right) | ReactNode | - | |
|
||||
| overlay | The dropdown menu | [Menu](/components/menu) | - | |
|
||||
@ -49,6 +50,6 @@ You should use [Menu](/components/menu/) as `overlay`. The menu items and divide
|
||||
| size | Size of the button, the same as [Button](/components/button/#API) | string | `default` | |
|
||||
| trigger | The trigger mode which executes the dropdown action | Array<`click`\|`hover`\|`contextMenu`> | \[`hover`] | |
|
||||
| type | Type of the button, the same as [Button](/components/button/#API) | string | `default` | |
|
||||
| visible | Whether the dropdown menu is currently visible | boolean | - | |
|
||||
| open | Whether the dropdown menu is currently open | boolean | - | 4.23.0 |
|
||||
| onClick | The same as [Button](/components/button/#API): called when you click the button on the left | (event) => void | - | |
|
||||
| onVisibleChange | Called when the visible state is changed | (visible: boolean) => void | - | |
|
||||
| onOpenChange | Called when the open state is changed | (open: boolean) => void | - | 4.23.0 |
|
||||
|
@ -31,8 +31,8 @@ cover: https://gw.alipayobjects.com/zos/alicdn/eedWN59yJ/Dropdown.svg
|
||||
| overlayStyle | 下拉根元素的样式 | CSSProperties | - | |
|
||||
| placement | 菜单弹出位置:`bottom` `bottomLeft` `bottomRight` `top` `topLeft` `topRight` | string | `bottomLeft` | |
|
||||
| trigger | 触发下拉的行为, 移动端不支持 hover | Array<`click`\|`hover`\|`contextMenu`> | \[`hover`] | |
|
||||
| visible | 菜单是否显示 | boolean | - | |
|
||||
| onVisibleChange | 菜单显示状态改变时调用,参数为 `visible`。点击菜单按钮导致的消失不会触发 | (visible: boolean) => void | - | |
|
||||
| open | 菜单是否显示 | boolean | - | 4.23.0 |
|
||||
| onOpenChange | 菜单显示状态改变时调用,参数为 `visible`。点击菜单按钮导致的消失不会触发 | (open: boolean) => void | - | 4.23.0 |
|
||||
|
||||
`overlay` 菜单使用 [Menu](/components/menu/),还包括菜单项 `Menu.Item`,分割线 `Menu.Divider`。
|
||||
|
||||
@ -46,6 +46,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/eedWN59yJ/Dropdown.svg
|
||||
| --- | --- | --- | --- | --- |
|
||||
| buttonsRender | 自定义左右两个按钮 | (buttons: ReactNode\[]) => ReactNode\[] | - | |
|
||||
| loading | 设置按钮载入状态 | boolean \| { delay: number } | false | |
|
||||
| danger | 设置危险按钮 | boolean | - | 4.23.0 |
|
||||
| disabled | 菜单是否禁用 | boolean | - | |
|
||||
| icon | 右侧的 icon | ReactNode | - | |
|
||||
| overlay | 菜单 | [Menu](/components/menu/) | - | |
|
||||
@ -53,6 +54,6 @@ cover: https://gw.alipayobjects.com/zos/alicdn/eedWN59yJ/Dropdown.svg
|
||||
| size | 按钮大小,和 [Button](/components/button/#API) 一致 | string | `default` | |
|
||||
| trigger | 触发下拉的行为 | Array<`click`\|`hover`\|`contextMenu`> | \[`hover`] | |
|
||||
| type | 按钮类型,和 [Button](/components/button/#API) 一致 | string | `default` | |
|
||||
| visible | 菜单是否显示 | boolean | - | |
|
||||
| open | 菜单是否显示 | boolean | - | 4.23.0 |
|
||||
| onClick | 点击左侧按钮的回调,和 [Button](/components/button/#API) 一致 | (event) => void | - | |
|
||||
| onVisibleChange | 菜单显示状态改变时调用,参数为 `visible` | (visible: boolean) => void | - | |
|
||||
| onOpenChange | 菜单显示状态改变时调用,参数为 `visible` | (open: boolean) => void | - | 4.23.0 |
|
||||
|
@ -29,6 +29,7 @@ function toErrorEntity(
|
||||
}
|
||||
|
||||
export interface ErrorListProps {
|
||||
fieldId?: string;
|
||||
help?: React.ReactNode;
|
||||
helpStatus?: ValidateStatus;
|
||||
errors?: React.ReactNode[];
|
||||
@ -43,6 +44,7 @@ export default function ErrorList({
|
||||
errors = EMPTY_LIST,
|
||||
warnings = EMPTY_LIST,
|
||||
className: rootClassName,
|
||||
fieldId,
|
||||
onVisibleChanged,
|
||||
}: ErrorListProps) {
|
||||
const { prefixCls } = React.useContext(FormItemPrefixContext);
|
||||
@ -69,6 +71,12 @@ export default function ErrorList({
|
||||
];
|
||||
}, [help, helpStatus, debounceErrors, debounceWarnings]);
|
||||
|
||||
const helpProps: { id?: string } = {};
|
||||
|
||||
if (fieldId) {
|
||||
helpProps.id = `${fieldId}_help`;
|
||||
}
|
||||
|
||||
return (
|
||||
<CSSMotion
|
||||
motionDeadline={collapseMotion.motionDeadline}
|
||||
@ -81,8 +89,10 @@ export default function ErrorList({
|
||||
|
||||
return (
|
||||
<div
|
||||
{...helpProps}
|
||||
className={classNames(baseClassName, holderClassName, rootClassName)}
|
||||
style={holderStyle}
|
||||
role="alert"
|
||||
>
|
||||
<CSSMotionList
|
||||
keys={fullKeyList}
|
||||
@ -102,7 +112,6 @@ export default function ErrorList({
|
||||
return (
|
||||
<div
|
||||
key={key}
|
||||
role="alert"
|
||||
className={classNames(itemClassName, {
|
||||
[`${baseClassName}-${errorStatus}`]: errorStatus,
|
||||
})}
|
||||
|
@ -37,11 +37,16 @@ interface MemoInputProps {
|
||||
value: any;
|
||||
update: any;
|
||||
children: React.ReactNode;
|
||||
childProps: any[];
|
||||
}
|
||||
|
||||
const MemoInput = React.memo(
|
||||
({ children }: MemoInputProps) => children as JSX.Element,
|
||||
(prev, next) => prev.value === next.value && prev.update === next.update,
|
||||
(prev, next) =>
|
||||
prev.value === next.value &&
|
||||
prev.update === next.update &&
|
||||
prev.childProps.length === next.childProps.length &&
|
||||
prev.childProps.every((value, index) => value === next.childProps[index]),
|
||||
);
|
||||
|
||||
export interface FormItemProps<Values = any>
|
||||
@ -305,6 +310,25 @@ function InternalFormItem<Values = any>(props: FormItemProps<Values>): React.Rea
|
||||
childProps.id = fieldId;
|
||||
}
|
||||
|
||||
if (props.help || mergedErrors.length > 0 || mergedWarnings.length > 0 || props.extra) {
|
||||
const describedbyArr = [];
|
||||
if (props.help || mergedErrors.length > 0) {
|
||||
describedbyArr.push(`${fieldId}_help`);
|
||||
}
|
||||
if (props.extra) {
|
||||
describedbyArr.push(`${fieldId}_extra`);
|
||||
}
|
||||
childProps['aria-describedby'] = describedbyArr.join(' ');
|
||||
}
|
||||
|
||||
if (mergedErrors.length > 0) {
|
||||
childProps['aria-invalid'] = 'true';
|
||||
}
|
||||
|
||||
if (isRequired) {
|
||||
childProps['aria-required'] = 'true';
|
||||
}
|
||||
|
||||
if (supportRef(children)) {
|
||||
childProps.ref = getItemRef(mergedName, children);
|
||||
}
|
||||
@ -322,8 +346,19 @@ function InternalFormItem<Values = any>(props: FormItemProps<Values>): React.Rea
|
||||
};
|
||||
});
|
||||
|
||||
// List of props that need to be watched for changes -> if changes are detected in MemoInput -> rerender
|
||||
const watchingChildProps = [
|
||||
childProps['aria-required'],
|
||||
childProps['aria-invalid'],
|
||||
childProps['aria-describedby'],
|
||||
];
|
||||
|
||||
childNode = (
|
||||
<MemoInput value={mergedControl[props.valuePropName || 'value']} update={children}>
|
||||
<MemoInput
|
||||
value={mergedControl[props.valuePropName || 'value']}
|
||||
update={children}
|
||||
childProps={watchingChildProps}
|
||||
>
|
||||
{cloneElement(children, childProps)}
|
||||
</MemoInput>
|
||||
);
|
||||
|
@ -32,6 +32,7 @@ export interface FormItemInputProps {
|
||||
extra?: React.ReactNode;
|
||||
status?: ValidateStatus;
|
||||
help?: React.ReactNode;
|
||||
fieldId?: string;
|
||||
}
|
||||
|
||||
const FormItemInput: React.FC<FormItemInputProps & FormItemInputMiscProps> = props => {
|
||||
@ -45,6 +46,7 @@ const FormItemInput: React.FC<FormItemInputProps & FormItemInputMiscProps> = pro
|
||||
_internalItemRender: formItemRender,
|
||||
extra,
|
||||
help,
|
||||
fieldId,
|
||||
marginBottom,
|
||||
onErrorVisibleChanged,
|
||||
} = props;
|
||||
@ -72,6 +74,7 @@ const FormItemInput: React.FC<FormItemInputProps & FormItemInputMiscProps> = pro
|
||||
<div style={{ display: 'flex', flexWrap: 'nowrap' }}>
|
||||
<FormItemPrefixContext.Provider value={formItemContext}>
|
||||
<ErrorList
|
||||
fieldId={fieldId}
|
||||
errors={errors}
|
||||
warnings={warnings}
|
||||
help={help}
|
||||
@ -84,9 +87,19 @@ const FormItemInput: React.FC<FormItemInputProps & FormItemInputMiscProps> = pro
|
||||
</div>
|
||||
) : null;
|
||||
|
||||
const extraProps: { id?: string } = {};
|
||||
|
||||
if (fieldId) {
|
||||
extraProps.id = `${fieldId}_extra`;
|
||||
}
|
||||
|
||||
// If extra = 0, && will goes wrong
|
||||
// 0&&error -> 0
|
||||
const extraDom = extra ? <div className={`${baseClassName}-extra`}>{extra}</div> : null;
|
||||
const extraDom = extra ? (
|
||||
<div {...extraProps} className={`${baseClassName}-extra`}>
|
||||
{extra}
|
||||
</div>
|
||||
) : null;
|
||||
|
||||
const dom =
|
||||
formItemRender && formItemRender.mark === 'pro_table_render' && formItemRender.render ? (
|
||||
|
@ -41,6 +41,7 @@ exports[`renders ./components/form/demo/advanced-search.md extend context correc
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="advanced_search_field-0"
|
||||
placeholder="placeholder"
|
||||
@ -84,6 +85,7 @@ exports[`renders ./components/form/demo/advanced-search.md extend context correc
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<div
|
||||
aria-required="true"
|
||||
class="ant-select ant-select-in-form-item ant-select-single ant-select-show-arrow"
|
||||
>
|
||||
<div
|
||||
@ -98,6 +100,7 @@ exports[`renders ./components/form/demo/advanced-search.md extend context correc
|
||||
aria-controls="advanced_search_field-1_list"
|
||||
aria-haspopup="listbox"
|
||||
aria-owns="advanced_search_field-1_list"
|
||||
aria-required="true"
|
||||
autocomplete="off"
|
||||
class="ant-select-selection-search-input"
|
||||
id="advanced_search_field-1"
|
||||
@ -262,6 +265,7 @@ exports[`renders ./components/form/demo/advanced-search.md extend context correc
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="advanced_search_field-2"
|
||||
placeholder="placeholder"
|
||||
@ -305,6 +309,7 @@ exports[`renders ./components/form/demo/advanced-search.md extend context correc
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="advanced_search_field-3"
|
||||
placeholder="placeholder"
|
||||
@ -348,6 +353,7 @@ exports[`renders ./components/form/demo/advanced-search.md extend context correc
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<div
|
||||
aria-required="true"
|
||||
class="ant-select ant-select-in-form-item ant-select-single ant-select-show-arrow"
|
||||
>
|
||||
<div
|
||||
@ -362,6 +368,7 @@ exports[`renders ./components/form/demo/advanced-search.md extend context correc
|
||||
aria-controls="advanced_search_field-4_list"
|
||||
aria-haspopup="listbox"
|
||||
aria-owns="advanced_search_field-4_list"
|
||||
aria-required="true"
|
||||
autocomplete="off"
|
||||
class="ant-select-selection-search-input"
|
||||
id="advanced_search_field-4"
|
||||
@ -526,6 +533,7 @@ exports[`renders ./components/form/demo/advanced-search.md extend context correc
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="advanced_search_field-5"
|
||||
placeholder="placeholder"
|
||||
@ -631,6 +639,7 @@ exports[`renders ./components/form/demo/basic.md extend context correctly 1`] =
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="basic_username"
|
||||
type="text"
|
||||
@ -672,6 +681,7 @@ exports[`renders ./components/form/demo/basic.md extend context correctly 1`] =
|
||||
>
|
||||
<input
|
||||
action="click"
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="basic_password"
|
||||
type="password"
|
||||
@ -815,6 +825,7 @@ Array [
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="basic_username"
|
||||
type="text"
|
||||
@ -856,6 +867,7 @@ Array [
|
||||
>
|
||||
<input
|
||||
action="click"
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="basic_password"
|
||||
type="password"
|
||||
@ -1184,6 +1196,7 @@ Array [
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="responsive_username"
|
||||
type="text"
|
||||
@ -1225,6 +1238,7 @@ Array [
|
||||
>
|
||||
<input
|
||||
action="click"
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="responsive_password"
|
||||
type="password"
|
||||
@ -1601,6 +1615,7 @@ exports[`renders ./components/form/demo/control-hooks.md extend context correctl
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="control-hooks_note"
|
||||
type="text"
|
||||
@ -1638,6 +1653,7 @@ exports[`renders ./components/form/demo/control-hooks.md extend context correctl
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<div
|
||||
aria-required="true"
|
||||
class="ant-select ant-select-in-form-item ant-select-single ant-select-allow-clear ant-select-show-arrow"
|
||||
>
|
||||
<div
|
||||
@ -1652,6 +1668,7 @@ exports[`renders ./components/form/demo/control-hooks.md extend context correctl
|
||||
aria-controls="control-hooks_gender_list"
|
||||
aria-haspopup="listbox"
|
||||
aria-owns="control-hooks_gender_list"
|
||||
aria-required="true"
|
||||
autocomplete="off"
|
||||
class="ant-select-selection-search-input"
|
||||
id="control-hooks_gender"
|
||||
@ -1879,6 +1896,7 @@ exports[`renders ./components/form/demo/control-ref.md extend context correctly
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="control-ref_note"
|
||||
type="text"
|
||||
@ -1916,6 +1934,7 @@ exports[`renders ./components/form/demo/control-ref.md extend context correctly
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<div
|
||||
aria-required="true"
|
||||
class="ant-select ant-select-in-form-item ant-select-single ant-select-allow-clear ant-select-show-arrow"
|
||||
>
|
||||
<div
|
||||
@ -1930,6 +1949,7 @@ exports[`renders ./components/form/demo/control-ref.md extend context correctly
|
||||
aria-controls="control-ref_gender_list"
|
||||
aria-haspopup="listbox"
|
||||
aria-owns="control-ref_gender_list"
|
||||
aria-required="true"
|
||||
autocomplete="off"
|
||||
class="ant-select-selection-search-input"
|
||||
id="control-ref_gender"
|
||||
@ -5972,6 +5992,7 @@ exports[`renders ./components/form/demo/dynamic-form-items-complex.md extend con
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<div
|
||||
aria-required="true"
|
||||
class="ant-select ant-select-in-form-item ant-select-single ant-select-show-arrow"
|
||||
>
|
||||
<div
|
||||
@ -5986,6 +6007,7 @@ exports[`renders ./components/form/demo/dynamic-form-items-complex.md extend con
|
||||
aria-controls="dynamic_form_nest_item_area_list"
|
||||
aria-haspopup="listbox"
|
||||
aria-owns="dynamic_form_nest_item_area_list"
|
||||
aria-required="true"
|
||||
autocomplete="off"
|
||||
class="ant-select-selection-search-input"
|
||||
id="dynamic_form_nest_item_area"
|
||||
@ -6347,6 +6369,7 @@ exports[`renders ./components/form/demo/dynamic-rule.md extend context correctly
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="dynamic_rule_username"
|
||||
placeholder="Please input your name"
|
||||
@ -6497,6 +6520,7 @@ exports[`renders ./components/form/demo/form-context.md extend context correctly
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="basicForm_group"
|
||||
type="text"
|
||||
@ -6648,6 +6672,7 @@ Array [
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="global_state_username"
|
||||
type="text"
|
||||
@ -6721,6 +6746,7 @@ exports[`renders ./components/form/demo/inline-login.md extend context correctly
|
||||
</span>
|
||||
</span>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="horizontal_login_username"
|
||||
placeholder="Username"
|
||||
@ -6775,6 +6801,7 @@ exports[`renders ./components/form/demo/inline-login.md extend context correctly
|
||||
</span>
|
||||
</span>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="horizontal_login_password"
|
||||
placeholder="Password"
|
||||
@ -7209,6 +7236,7 @@ exports[`renders ./components/form/demo/layout-can-wrap.md extend context correc
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="wrap_username"
|
||||
type="text"
|
||||
@ -7248,6 +7276,7 @@ exports[`renders ./components/form/demo/layout-can-wrap.md extend context correc
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="wrap_password"
|
||||
type="text"
|
||||
@ -7333,6 +7362,7 @@ exports[`renders ./components/form/demo/nest-messages.md extend context correctl
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="nest-messages_user_name"
|
||||
type="text"
|
||||
@ -7635,6 +7665,7 @@ exports[`renders ./components/form/demo/normal-login.md extend context correctly
|
||||
</span>
|
||||
</span>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="normal_login_username"
|
||||
placeholder="Username"
|
||||
@ -7689,6 +7720,7 @@ exports[`renders ./components/form/demo/normal-login.md extend context correctly
|
||||
</span>
|
||||
</span>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="normal_login_password"
|
||||
placeholder="Password"
|
||||
@ -7902,6 +7934,7 @@ exports[`renders ./components/form/demo/register.md extend context correctly 1`]
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="register_email"
|
||||
type="text"
|
||||
@ -7943,6 +7976,7 @@ exports[`renders ./components/form/demo/register.md extend context correctly 1`]
|
||||
>
|
||||
<input
|
||||
action="click"
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="register_password"
|
||||
type="password"
|
||||
@ -8012,6 +8046,7 @@ exports[`renders ./components/form/demo/register.md extend context correctly 1`]
|
||||
>
|
||||
<input
|
||||
action="click"
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="register_confirm"
|
||||
type="password"
|
||||
@ -8124,6 +8159,7 @@ exports[`renders ./components/form/demo/register.md extend context correctly 1`]
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="register_nickname"
|
||||
type="text"
|
||||
@ -8161,6 +8197,7 @@ exports[`renders ./components/form/demo/register.md extend context correctly 1`]
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<div
|
||||
aria-required="true"
|
||||
class="ant-select ant-cascader ant-select-in-form-item ant-select-single ant-select-allow-clear ant-select-show-arrow"
|
||||
>
|
||||
<div
|
||||
@ -8174,6 +8211,7 @@ exports[`renders ./components/form/demo/register.md extend context correctly 1`]
|
||||
aria-controls="register_residence_list"
|
||||
aria-haspopup="listbox"
|
||||
aria-owns="register_residence_list"
|
||||
aria-required="true"
|
||||
autocomplete="off"
|
||||
class="ant-select-selection-search-input"
|
||||
id="register_residence"
|
||||
@ -8521,6 +8559,7 @@ exports[`renders ./components/form/demo/register.md extend context correctly 1`]
|
||||
</div>
|
||||
</span>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="register_phone"
|
||||
type="text"
|
||||
@ -8631,6 +8670,7 @@ exports[`renders ./components/form/demo/register.md extend context correctly 1`]
|
||||
class="ant-input-number-input-wrap"
|
||||
>
|
||||
<input
|
||||
aria-required="true"
|
||||
autocomplete="off"
|
||||
class="ant-input-number-input"
|
||||
id="register_donation"
|
||||
@ -8818,6 +8858,7 @@ exports[`renders ./components/form/demo/register.md extend context correctly 1`]
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<div
|
||||
aria-required="true"
|
||||
class="ant-select ant-select-in-form-item ant-select-auto-complete ant-select-single ant-select-customize-input ant-select-show-search"
|
||||
>
|
||||
<div
|
||||
@ -8832,6 +8873,7 @@ exports[`renders ./components/form/demo/register.md extend context correctly 1`]
|
||||
aria-controls="register_website_list"
|
||||
aria-haspopup="listbox"
|
||||
aria-owns="register_website_list"
|
||||
aria-required="true"
|
||||
autocomplete="off"
|
||||
class="ant-input ant-select-selection-search-input"
|
||||
id="register_website"
|
||||
@ -8897,6 +8939,7 @@ exports[`renders ./components/form/demo/register.md extend context correctly 1`]
|
||||
data-count="0 / 100"
|
||||
>
|
||||
<textarea
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="register_intro"
|
||||
/>
|
||||
@ -8933,6 +8976,7 @@ exports[`renders ./components/form/demo/register.md extend context correctly 1`]
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<div
|
||||
aria-required="true"
|
||||
class="ant-select ant-select-in-form-item ant-select-single ant-select-show-arrow"
|
||||
>
|
||||
<div
|
||||
@ -8947,6 +8991,7 @@ exports[`renders ./components/form/demo/register.md extend context correctly 1`]
|
||||
aria-controls="register_gender_list"
|
||||
aria-haspopup="listbox"
|
||||
aria-owns="register_gender_list"
|
||||
aria-required="true"
|
||||
autocomplete="off"
|
||||
class="ant-select-selection-search-input"
|
||||
id="register_gender"
|
||||
@ -9129,6 +9174,7 @@ exports[`renders ./components/form/demo/register.md extend context correctly 1`]
|
||||
style="padding-left:4px;padding-right:4px"
|
||||
>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="register_captcha"
|
||||
type="text"
|
||||
@ -10986,6 +11032,7 @@ exports[`renders ./components/form/demo/time-related-controls.md extend context
|
||||
class="ant-picker-input"
|
||||
>
|
||||
<input
|
||||
aria-required="true"
|
||||
autocomplete="off"
|
||||
id="time_related_controls_date-picker"
|
||||
placeholder="Select date"
|
||||
@ -11611,6 +11658,7 @@ exports[`renders ./components/form/demo/time-related-controls.md extend context
|
||||
class="ant-picker-input"
|
||||
>
|
||||
<input
|
||||
aria-required="true"
|
||||
autocomplete="off"
|
||||
id="time_related_controls_date-time-picker"
|
||||
placeholder="Select date"
|
||||
@ -13589,6 +13637,7 @@ exports[`renders ./components/form/demo/time-related-controls.md extend context
|
||||
class="ant-picker-input"
|
||||
>
|
||||
<input
|
||||
aria-required="true"
|
||||
autocomplete="off"
|
||||
id="time_related_controls_month-picker"
|
||||
placeholder="Select month"
|
||||
@ -13844,6 +13893,7 @@ exports[`renders ./components/form/demo/time-related-controls.md extend context
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<div
|
||||
aria-required="true"
|
||||
class="ant-picker ant-picker-range"
|
||||
>
|
||||
<div
|
||||
@ -15054,6 +15104,7 @@ exports[`renders ./components/form/demo/time-related-controls.md extend context
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<div
|
||||
aria-required="true"
|
||||
class="ant-picker ant-picker-range"
|
||||
>
|
||||
<div
|
||||
@ -17085,6 +17136,7 @@ exports[`renders ./components/form/demo/time-related-controls.md extend context
|
||||
class="ant-picker-input"
|
||||
>
|
||||
<input
|
||||
aria-required="true"
|
||||
autocomplete="off"
|
||||
id="time_related_controls_time-picker"
|
||||
placeholder="Select time"
|
||||
@ -18748,6 +18800,7 @@ exports[`renders ./components/form/demo/validate-other.md extend context correct
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<div
|
||||
aria-required="true"
|
||||
class="ant-select ant-select-in-form-item ant-select-has-feedback ant-select-single ant-select-show-arrow"
|
||||
>
|
||||
<div
|
||||
@ -18762,6 +18815,7 @@ exports[`renders ./components/form/demo/validate-other.md extend context correct
|
||||
aria-controls="validate_other_select_list"
|
||||
aria-haspopup="listbox"
|
||||
aria-owns="validate_other_select_list"
|
||||
aria-required="true"
|
||||
autocomplete="off"
|
||||
class="ant-select-selection-search-input"
|
||||
id="validate_other_select"
|
||||
@ -18920,6 +18974,7 @@ exports[`renders ./components/form/demo/validate-other.md extend context correct
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<div
|
||||
aria-required="true"
|
||||
class="ant-select ant-select-in-form-item ant-select-multiple ant-select-show-search"
|
||||
>
|
||||
<div
|
||||
@ -18942,6 +18997,7 @@ exports[`renders ./components/form/demo/validate-other.md extend context correct
|
||||
aria-controls="validate_other_select-multiple_list"
|
||||
aria-haspopup="listbox"
|
||||
aria-owns="validate_other_select-multiple_list"
|
||||
aria-required="true"
|
||||
autocomplete="off"
|
||||
class="ant-select-selection-search-input"
|
||||
id="validate_other_select-multiple"
|
||||
@ -19475,6 +19531,7 @@ exports[`renders ./components/form/demo/validate-other.md extend context correct
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<div
|
||||
aria-required="true"
|
||||
class="ant-radio-group ant-radio-group-outline"
|
||||
id="validate_other_radio-button"
|
||||
>
|
||||
@ -20094,6 +20151,7 @@ exports[`renders ./components/form/demo/validate-other.md extend context correct
|
||||
>
|
||||
<input
|
||||
accept=""
|
||||
aria-describedby="validate_other_upload_extra"
|
||||
id="validate_other_upload"
|
||||
style="display:none"
|
||||
type="file"
|
||||
@ -20135,6 +20193,7 @@ exports[`renders ./components/form/demo/validate-other.md extend context correct
|
||||
</div>
|
||||
<div
|
||||
class="ant-form-item-extra"
|
||||
id="validate_other_upload_extra"
|
||||
>
|
||||
longgggggggggggggggggggggggggggggggggg
|
||||
</div>
|
||||
@ -26406,6 +26465,7 @@ exports[`renders ./components/form/demo/warning-only.md extend context correctly
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="url"
|
||||
placeholder="input placeholder"
|
||||
|
@ -41,6 +41,7 @@ exports[`renders ./components/form/demo/advanced-search.md correctly 1`] = `
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="advanced_search_field-0"
|
||||
placeholder="placeholder"
|
||||
@ -84,6 +85,7 @@ exports[`renders ./components/form/demo/advanced-search.md correctly 1`] = `
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<div
|
||||
aria-required="true"
|
||||
class="ant-select ant-select-in-form-item ant-select-single ant-select-show-arrow"
|
||||
>
|
||||
<div
|
||||
@ -98,6 +100,7 @@ exports[`renders ./components/form/demo/advanced-search.md correctly 1`] = `
|
||||
aria-controls="advanced_search_field-1_list"
|
||||
aria-haspopup="listbox"
|
||||
aria-owns="advanced_search_field-1_list"
|
||||
aria-required="true"
|
||||
autocomplete="off"
|
||||
class="ant-select-selection-search-input"
|
||||
id="advanced_search_field-1"
|
||||
@ -180,6 +183,7 @@ exports[`renders ./components/form/demo/advanced-search.md correctly 1`] = `
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="advanced_search_field-2"
|
||||
placeholder="placeholder"
|
||||
@ -223,6 +227,7 @@ exports[`renders ./components/form/demo/advanced-search.md correctly 1`] = `
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="advanced_search_field-3"
|
||||
placeholder="placeholder"
|
||||
@ -266,6 +271,7 @@ exports[`renders ./components/form/demo/advanced-search.md correctly 1`] = `
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<div
|
||||
aria-required="true"
|
||||
class="ant-select ant-select-in-form-item ant-select-single ant-select-show-arrow"
|
||||
>
|
||||
<div
|
||||
@ -280,6 +286,7 @@ exports[`renders ./components/form/demo/advanced-search.md correctly 1`] = `
|
||||
aria-controls="advanced_search_field-4_list"
|
||||
aria-haspopup="listbox"
|
||||
aria-owns="advanced_search_field-4_list"
|
||||
aria-required="true"
|
||||
autocomplete="off"
|
||||
class="ant-select-selection-search-input"
|
||||
id="advanced_search_field-4"
|
||||
@ -362,6 +369,7 @@ exports[`renders ./components/form/demo/advanced-search.md correctly 1`] = `
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="advanced_search_field-5"
|
||||
placeholder="placeholder"
|
||||
@ -467,6 +475,7 @@ exports[`renders ./components/form/demo/basic.md correctly 1`] = `
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="basic_username"
|
||||
type="text"
|
||||
@ -508,6 +517,7 @@ exports[`renders ./components/form/demo/basic.md correctly 1`] = `
|
||||
>
|
||||
<input
|
||||
action="click"
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="basic_password"
|
||||
type="password"
|
||||
@ -651,6 +661,7 @@ Array [
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="basic_username"
|
||||
type="text"
|
||||
@ -692,6 +703,7 @@ Array [
|
||||
>
|
||||
<input
|
||||
action="click"
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="basic_password"
|
||||
type="password"
|
||||
@ -913,6 +925,7 @@ Array [
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="responsive_username"
|
||||
type="text"
|
||||
@ -954,6 +967,7 @@ Array [
|
||||
>
|
||||
<input
|
||||
action="click"
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="responsive_password"
|
||||
type="password"
|
||||
@ -1223,6 +1237,7 @@ exports[`renders ./components/form/demo/control-hooks.md correctly 1`] = `
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="control-hooks_note"
|
||||
type="text"
|
||||
@ -1260,6 +1275,7 @@ exports[`renders ./components/form/demo/control-hooks.md correctly 1`] = `
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<div
|
||||
aria-required="true"
|
||||
class="ant-select ant-select-in-form-item ant-select-single ant-select-allow-clear ant-select-show-arrow"
|
||||
>
|
||||
<div
|
||||
@ -1274,6 +1290,7 @@ exports[`renders ./components/form/demo/control-hooks.md correctly 1`] = `
|
||||
aria-controls="control-hooks_gender_list"
|
||||
aria-haspopup="listbox"
|
||||
aria-owns="control-hooks_gender_list"
|
||||
aria-required="true"
|
||||
autocomplete="off"
|
||||
class="ant-select-selection-search-input"
|
||||
id="control-hooks_gender"
|
||||
@ -1402,6 +1419,7 @@ exports[`renders ./components/form/demo/control-ref.md correctly 1`] = `
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="control-ref_note"
|
||||
type="text"
|
||||
@ -1439,6 +1457,7 @@ exports[`renders ./components/form/demo/control-ref.md correctly 1`] = `
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<div
|
||||
aria-required="true"
|
||||
class="ant-select ant-select-in-form-item ant-select-single ant-select-allow-clear ant-select-show-arrow"
|
||||
>
|
||||
<div
|
||||
@ -1453,6 +1472,7 @@ exports[`renders ./components/form/demo/control-ref.md correctly 1`] = `
|
||||
aria-controls="control-ref_gender_list"
|
||||
aria-haspopup="listbox"
|
||||
aria-owns="control-ref_gender_list"
|
||||
aria-required="true"
|
||||
autocomplete="off"
|
||||
class="ant-select-selection-search-input"
|
||||
id="control-ref_gender"
|
||||
@ -3455,6 +3475,7 @@ exports[`renders ./components/form/demo/dynamic-form-items-complex.md correctly
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<div
|
||||
aria-required="true"
|
||||
class="ant-select ant-select-in-form-item ant-select-single ant-select-show-arrow"
|
||||
>
|
||||
<div
|
||||
@ -3469,6 +3490,7 @@ exports[`renders ./components/form/demo/dynamic-form-items-complex.md correctly
|
||||
aria-controls="dynamic_form_nest_item_area_list"
|
||||
aria-haspopup="listbox"
|
||||
aria-owns="dynamic_form_nest_item_area_list"
|
||||
aria-required="true"
|
||||
autocomplete="off"
|
||||
class="ant-select-selection-search-input"
|
||||
id="dynamic_form_nest_item_area"
|
||||
@ -3748,6 +3770,7 @@ exports[`renders ./components/form/demo/dynamic-rule.md correctly 1`] = `
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="dynamic_rule_username"
|
||||
placeholder="Please input your name"
|
||||
@ -3898,6 +3921,7 @@ exports[`renders ./components/form/demo/form-context.md correctly 1`] = `
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="basicForm_group"
|
||||
type="text"
|
||||
@ -4049,6 +4073,7 @@ Array [
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="global_state_username"
|
||||
type="text"
|
||||
@ -4122,6 +4147,7 @@ exports[`renders ./components/form/demo/inline-login.md correctly 1`] = `
|
||||
</span>
|
||||
</span>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="horizontal_login_username"
|
||||
placeholder="Username"
|
||||
@ -4176,6 +4202,7 @@ exports[`renders ./components/form/demo/inline-login.md correctly 1`] = `
|
||||
</span>
|
||||
</span>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="horizontal_login_password"
|
||||
placeholder="Password"
|
||||
@ -4610,6 +4637,7 @@ exports[`renders ./components/form/demo/layout-can-wrap.md correctly 1`] = `
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="wrap_username"
|
||||
type="text"
|
||||
@ -4649,6 +4677,7 @@ exports[`renders ./components/form/demo/layout-can-wrap.md correctly 1`] = `
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="wrap_password"
|
||||
type="text"
|
||||
@ -4734,6 +4763,7 @@ exports[`renders ./components/form/demo/nest-messages.md correctly 1`] = `
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="nest-messages_user_name"
|
||||
type="text"
|
||||
@ -5036,6 +5066,7 @@ exports[`renders ./components/form/demo/normal-login.md correctly 1`] = `
|
||||
</span>
|
||||
</span>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="normal_login_username"
|
||||
placeholder="Username"
|
||||
@ -5090,6 +5121,7 @@ exports[`renders ./components/form/demo/normal-login.md correctly 1`] = `
|
||||
</span>
|
||||
</span>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="normal_login_password"
|
||||
placeholder="Password"
|
||||
@ -5303,6 +5335,7 @@ exports[`renders ./components/form/demo/register.md correctly 1`] = `
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="register_email"
|
||||
type="text"
|
||||
@ -5344,6 +5377,7 @@ exports[`renders ./components/form/demo/register.md correctly 1`] = `
|
||||
>
|
||||
<input
|
||||
action="click"
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="register_password"
|
||||
type="password"
|
||||
@ -5413,6 +5447,7 @@ exports[`renders ./components/form/demo/register.md correctly 1`] = `
|
||||
>
|
||||
<input
|
||||
action="click"
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="register_confirm"
|
||||
type="password"
|
||||
@ -5501,6 +5536,7 @@ exports[`renders ./components/form/demo/register.md correctly 1`] = `
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="register_nickname"
|
||||
type="text"
|
||||
@ -5538,6 +5574,7 @@ exports[`renders ./components/form/demo/register.md correctly 1`] = `
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<div
|
||||
aria-required="true"
|
||||
class="ant-select ant-cascader ant-select-in-form-item ant-select-single ant-select-allow-clear ant-select-show-arrow"
|
||||
>
|
||||
<div
|
||||
@ -5551,6 +5588,7 @@ exports[`renders ./components/form/demo/register.md correctly 1`] = `
|
||||
aria-controls="register_residence_list"
|
||||
aria-haspopup="listbox"
|
||||
aria-owns="register_residence_list"
|
||||
aria-required="true"
|
||||
autocomplete="off"
|
||||
class="ant-select-selection-search-input"
|
||||
id="register_residence"
|
||||
@ -5726,6 +5764,7 @@ exports[`renders ./components/form/demo/register.md correctly 1`] = `
|
||||
</div>
|
||||
</span>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="register_phone"
|
||||
type="text"
|
||||
@ -5836,6 +5875,7 @@ exports[`renders ./components/form/demo/register.md correctly 1`] = `
|
||||
class="ant-input-number-input-wrap"
|
||||
>
|
||||
<input
|
||||
aria-required="true"
|
||||
autocomplete="off"
|
||||
class="ant-input-number-input"
|
||||
id="register_donation"
|
||||
@ -5941,6 +5981,7 @@ exports[`renders ./components/form/demo/register.md correctly 1`] = `
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<div
|
||||
aria-required="true"
|
||||
class="ant-select ant-select-in-form-item ant-select-auto-complete ant-select-single ant-select-customize-input ant-select-show-search"
|
||||
>
|
||||
<div
|
||||
@ -5955,6 +5996,7 @@ exports[`renders ./components/form/demo/register.md correctly 1`] = `
|
||||
aria-controls="register_website_list"
|
||||
aria-haspopup="listbox"
|
||||
aria-owns="register_website_list"
|
||||
aria-required="true"
|
||||
autocomplete="off"
|
||||
class="ant-input ant-select-selection-search-input"
|
||||
id="register_website"
|
||||
@ -6006,6 +6048,7 @@ exports[`renders ./components/form/demo/register.md correctly 1`] = `
|
||||
data-count="0 / 100"
|
||||
>
|
||||
<textarea
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="register_intro"
|
||||
/>
|
||||
@ -6042,6 +6085,7 @@ exports[`renders ./components/form/demo/register.md correctly 1`] = `
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<div
|
||||
aria-required="true"
|
||||
class="ant-select ant-select-in-form-item ant-select-single ant-select-show-arrow"
|
||||
>
|
||||
<div
|
||||
@ -6056,6 +6100,7 @@ exports[`renders ./components/form/demo/register.md correctly 1`] = `
|
||||
aria-controls="register_gender_list"
|
||||
aria-haspopup="listbox"
|
||||
aria-owns="register_gender_list"
|
||||
aria-required="true"
|
||||
autocomplete="off"
|
||||
class="ant-select-selection-search-input"
|
||||
id="register_gender"
|
||||
@ -6139,6 +6184,7 @@ exports[`renders ./components/form/demo/register.md correctly 1`] = `
|
||||
style="padding-left:4px;padding-right:4px"
|
||||
>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="register_captcha"
|
||||
type="text"
|
||||
@ -7186,6 +7232,7 @@ exports[`renders ./components/form/demo/time-related-controls.md correctly 1`] =
|
||||
class="ant-picker-input"
|
||||
>
|
||||
<input
|
||||
aria-required="true"
|
||||
autocomplete="off"
|
||||
id="time_related_controls_date-picker"
|
||||
placeholder="Select date"
|
||||
@ -7257,6 +7304,7 @@ exports[`renders ./components/form/demo/time-related-controls.md correctly 1`] =
|
||||
class="ant-picker-input"
|
||||
>
|
||||
<input
|
||||
aria-required="true"
|
||||
autocomplete="off"
|
||||
id="time_related_controls_date-time-picker"
|
||||
placeholder="Select date"
|
||||
@ -7328,6 +7376,7 @@ exports[`renders ./components/form/demo/time-related-controls.md correctly 1`] =
|
||||
class="ant-picker-input"
|
||||
>
|
||||
<input
|
||||
aria-required="true"
|
||||
autocomplete="off"
|
||||
id="time_related_controls_month-picker"
|
||||
placeholder="Select month"
|
||||
@ -7393,6 +7442,7 @@ exports[`renders ./components/form/demo/time-related-controls.md correctly 1`] =
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<div
|
||||
aria-required="true"
|
||||
class="ant-picker ant-picker-range"
|
||||
>
|
||||
<div
|
||||
@ -7506,6 +7556,7 @@ exports[`renders ./components/form/demo/time-related-controls.md correctly 1`] =
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<div
|
||||
aria-required="true"
|
||||
class="ant-picker ant-picker-range"
|
||||
>
|
||||
<div
|
||||
@ -7625,6 +7676,7 @@ exports[`renders ./components/form/demo/time-related-controls.md correctly 1`] =
|
||||
class="ant-picker-input"
|
||||
>
|
||||
<input
|
||||
aria-required="true"
|
||||
autocomplete="off"
|
||||
id="time_related_controls_time-picker"
|
||||
placeholder="Select time"
|
||||
@ -7923,6 +7975,7 @@ exports[`renders ./components/form/demo/validate-other.md correctly 1`] = `
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<div
|
||||
aria-required="true"
|
||||
class="ant-select ant-select-in-form-item ant-select-has-feedback ant-select-single ant-select-show-arrow"
|
||||
>
|
||||
<div
|
||||
@ -7937,6 +7990,7 @@ exports[`renders ./components/form/demo/validate-other.md correctly 1`] = `
|
||||
aria-controls="validate_other_select_list"
|
||||
aria-haspopup="listbox"
|
||||
aria-owns="validate_other_select_list"
|
||||
aria-required="true"
|
||||
autocomplete="off"
|
||||
class="ant-select-selection-search-input"
|
||||
id="validate_other_select"
|
||||
@ -8013,6 +8067,7 @@ exports[`renders ./components/form/demo/validate-other.md correctly 1`] = `
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<div
|
||||
aria-required="true"
|
||||
class="ant-select ant-select-in-form-item ant-select-multiple ant-select-show-search"
|
||||
>
|
||||
<div
|
||||
@ -8035,6 +8090,7 @@ exports[`renders ./components/form/demo/validate-other.md correctly 1`] = `
|
||||
aria-controls="validate_other_select-multiple_list"
|
||||
aria-haspopup="listbox"
|
||||
aria-owns="validate_other_select-multiple_list"
|
||||
aria-required="true"
|
||||
autocomplete="off"
|
||||
class="ant-select-selection-search-input"
|
||||
id="validate_other_select-multiple"
|
||||
@ -8463,6 +8519,7 @@ exports[`renders ./components/form/demo/validate-other.md correctly 1`] = `
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<div
|
||||
aria-required="true"
|
||||
class="ant-radio-group ant-radio-group-outline"
|
||||
id="validate_other_radio-button"
|
||||
>
|
||||
@ -9082,6 +9139,7 @@ exports[`renders ./components/form/demo/validate-other.md correctly 1`] = `
|
||||
>
|
||||
<input
|
||||
accept=""
|
||||
aria-describedby="validate_other_upload_extra"
|
||||
id="validate_other_upload"
|
||||
style="display:none"
|
||||
type="file"
|
||||
@ -9123,6 +9181,7 @@ exports[`renders ./components/form/demo/validate-other.md correctly 1`] = `
|
||||
</div>
|
||||
<div
|
||||
class="ant-form-item-extra"
|
||||
id="validate_other_upload_extra"
|
||||
>
|
||||
longgggggggggggggggggggggggggggggggggg
|
||||
</div>
|
||||
@ -11063,6 +11122,7 @@ exports[`renders ./components/form/demo/warning-only.md correctly 1`] = `
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<input
|
||||
aria-required="true"
|
||||
class="ant-input"
|
||||
id="url"
|
||||
placeholder="input placeholder"
|
||||
|
@ -203,6 +203,158 @@ describe('Form', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('input element should have the prop aria-describedby pointing to the help id when there is a help message', () => {
|
||||
const wrapper = mount(
|
||||
<Form>
|
||||
<Form.Item name="test" help="This is a help">
|
||||
<input />
|
||||
</Form.Item>
|
||||
</Form>,
|
||||
);
|
||||
|
||||
const input = wrapper.find('input');
|
||||
expect(input.prop('aria-describedby')).toBe('test_help');
|
||||
const help = wrapper.find('.ant-form-item-explain');
|
||||
expect(help.prop('id')).toBe('test_help');
|
||||
});
|
||||
|
||||
it('input element should not have the prop aria-describedby pointing to the help id when there is a help message and name is not defined', () => {
|
||||
const wrapper = mount(
|
||||
<Form>
|
||||
<Form.Item help="This is a help">
|
||||
<input />
|
||||
</Form.Item>
|
||||
</Form>,
|
||||
);
|
||||
|
||||
const input = wrapper.find('input');
|
||||
expect(input.prop('aria-describedby')).toBeUndefined();
|
||||
const help = wrapper.find('.ant-form-item-explain');
|
||||
expect(help.prop('id')).toBeUndefined();
|
||||
});
|
||||
|
||||
it('input element should have the prop aria-describedby concatenated with the form name pointing to the help id when there is a help message', () => {
|
||||
const wrapper = mount(
|
||||
<Form name="form">
|
||||
<Form.Item name="test" help="This is a help">
|
||||
<input />
|
||||
</Form.Item>
|
||||
</Form>,
|
||||
);
|
||||
|
||||
const input = wrapper.find('input');
|
||||
expect(input.prop('aria-describedby')).toBe('form_test_help');
|
||||
const help = wrapper.find('.ant-form-item-explain');
|
||||
expect(help.prop('id')).toBe('form_test_help');
|
||||
});
|
||||
|
||||
it('input element should have the prop aria-describedby pointing to the help id when there are errors', async () => {
|
||||
const wrapper = mount(
|
||||
<Form>
|
||||
<Form.Item name="test" rules={[{ len: 3 }, { type: 'number' }]}>
|
||||
<input />
|
||||
</Form.Item>
|
||||
</Form>,
|
||||
);
|
||||
|
||||
const input = wrapper.find('input');
|
||||
input.simulate('change', { target: { value: 'Invalid number' } });
|
||||
await sleep(800);
|
||||
wrapper.update();
|
||||
|
||||
const inputChanged = wrapper.find('input');
|
||||
expect(inputChanged.prop('aria-describedby')).toBe('test_help');
|
||||
const help = wrapper.find('.ant-form-item-explain');
|
||||
expect(help.prop('id')).toBe('test_help');
|
||||
});
|
||||
|
||||
it('input element should have the prop aria-invalid when there are errors', async () => {
|
||||
const wrapper = mount(
|
||||
<Form>
|
||||
<Form.Item name="test" rules={[{ len: 3 }, { type: 'number' }]}>
|
||||
<input />
|
||||
</Form.Item>
|
||||
</Form>,
|
||||
);
|
||||
|
||||
const input = wrapper.find('input');
|
||||
input.simulate('change', { target: { value: 'Invalid number' } });
|
||||
await sleep(800);
|
||||
wrapper.update();
|
||||
|
||||
const inputChanged = wrapper.find('input');
|
||||
expect(inputChanged.prop('aria-invalid')).toBe('true');
|
||||
});
|
||||
|
||||
it('input element should have the prop aria-required when the prop `required` is true', async () => {
|
||||
const wrapper = mount(
|
||||
<Form>
|
||||
<Form.Item name="test" required>
|
||||
<input />
|
||||
</Form.Item>
|
||||
</Form>,
|
||||
);
|
||||
|
||||
const input = wrapper.find('input');
|
||||
expect(input.prop('aria-required')).toBe('true');
|
||||
});
|
||||
|
||||
it('input element should have the prop aria-required when there is a rule with required', async () => {
|
||||
const wrapper = mount(
|
||||
<Form>
|
||||
<Form.Item name="test" rules={[{ required: true }]}>
|
||||
<input />
|
||||
</Form.Item>
|
||||
</Form>,
|
||||
);
|
||||
|
||||
const input = wrapper.find('input');
|
||||
expect(input.prop('aria-required')).toBe('true');
|
||||
});
|
||||
|
||||
it('input element should have the prop aria-describedby pointing to the extra id when there is a extra message', () => {
|
||||
const wrapper = mount(
|
||||
<Form>
|
||||
<Form.Item name="test" extra="This is a extra message">
|
||||
<input />
|
||||
</Form.Item>
|
||||
</Form>,
|
||||
);
|
||||
|
||||
const input = wrapper.find('input');
|
||||
expect(input.prop('aria-describedby')).toBe('test_extra');
|
||||
const extra = wrapper.find('.ant-form-item-extra');
|
||||
expect(extra.prop('id')).toBe('test_extra');
|
||||
});
|
||||
|
||||
it('input element should not have the prop aria-describedby pointing to the extra id when there is a extra message and name is not defined', () => {
|
||||
const wrapper = mount(
|
||||
<Form>
|
||||
<Form.Item extra="This is a extra message">
|
||||
<input />
|
||||
</Form.Item>
|
||||
</Form>,
|
||||
);
|
||||
|
||||
const input = wrapper.find('input');
|
||||
expect(input.prop('aria-describedby')).toBeUndefined();
|
||||
const extra = wrapper.find('.ant-form-item-extra');
|
||||
expect(extra.prop('id')).toBeUndefined();
|
||||
});
|
||||
|
||||
it('input element should have the prop aria-describedby pointing to the help and extra id when there is a help and extra message', () => {
|
||||
const wrapper = mount(
|
||||
<Form>
|
||||
<Form.Item name="test" help="This is a help" extra="This is a extra message">
|
||||
<input />
|
||||
</Form.Item>
|
||||
</Form>,
|
||||
);
|
||||
|
||||
const input = wrapper.find('input');
|
||||
expect(input.prop('aria-describedby')).toBe('test_help test_extra');
|
||||
});
|
||||
|
||||
describe('scrollToField', () => {
|
||||
function test(name, genForm) {
|
||||
it(name, () => {
|
||||
@ -710,9 +862,7 @@ describe('Form', () => {
|
||||
await sleep(100);
|
||||
wrapper.update();
|
||||
await sleep(100);
|
||||
expect(wrapper.find('.ant-form-item-explain div').getDOMNode().getAttribute('role')).toBe(
|
||||
'alert',
|
||||
);
|
||||
expect(wrapper.find('.ant-form-item-explain').getDOMNode().getAttribute('role')).toBe('alert');
|
||||
});
|
||||
|
||||
it('return same form instance', () => {
|
||||
@ -1232,12 +1382,12 @@ describe('Form', () => {
|
||||
const Demo = () => (
|
||||
<Form>
|
||||
<Form.Item labelCol={4} validateStatus="error">
|
||||
<Modal visible>
|
||||
<Modal open>
|
||||
<Select className="modal-select" />
|
||||
</Modal>
|
||||
</Form.Item>
|
||||
<Form.Item validateStatus="error">
|
||||
<Drawer visible>
|
||||
<Drawer open>
|
||||
<Select className="drawer-select" />
|
||||
</Drawer>
|
||||
</Form.Item>
|
||||
|
@ -33,31 +33,31 @@ interface UserType {
|
||||
}
|
||||
|
||||
interface ModalFormProps {
|
||||
visible: boolean;
|
||||
open: boolean;
|
||||
onCancel: () => void;
|
||||
}
|
||||
|
||||
// reset form fields when modal is form, closed
|
||||
const useResetFormOnCloseModal = ({ form, visible }: { form: FormInstance; visible: boolean }) => {
|
||||
const prevVisibleRef = useRef<boolean>();
|
||||
const useResetFormOnCloseModal = ({ form, open }: { form: FormInstance; open: boolean }) => {
|
||||
const prevOpenRef = useRef<boolean>();
|
||||
useEffect(() => {
|
||||
prevVisibleRef.current = visible;
|
||||
}, [visible]);
|
||||
const prevVisible = prevVisibleRef.current;
|
||||
prevOpenRef.current = open;
|
||||
}, [open]);
|
||||
const prevOpen = prevOpenRef.current;
|
||||
|
||||
useEffect(() => {
|
||||
if (!visible && prevVisible) {
|
||||
if (!open && prevOpen) {
|
||||
form.resetFields();
|
||||
}
|
||||
}, [form, prevVisible, visible]);
|
||||
}, [form, prevOpen, open]);
|
||||
};
|
||||
|
||||
const ModalForm: React.FC<ModalFormProps> = ({ visible, onCancel }) => {
|
||||
const ModalForm: React.FC<ModalFormProps> = ({ open, onCancel }) => {
|
||||
const [form] = Form.useForm();
|
||||
|
||||
useResetFormOnCloseModal({
|
||||
form,
|
||||
visible,
|
||||
open,
|
||||
});
|
||||
|
||||
const onOk = () => {
|
||||
@ -65,7 +65,7 @@ const ModalForm: React.FC<ModalFormProps> = ({ visible, onCancel }) => {
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal title="Basic Drawer" visible={visible} onOk={onOk} onCancel={onCancel}>
|
||||
<Modal title="Basic Drawer" open={open} onOk={onOk} onCancel={onCancel}>
|
||||
<Form form={form} layout="vertical" name="userForm">
|
||||
<Form.Item name="name" label="User Name" rules={[{ required: true }]}>
|
||||
<Input />
|
||||
@ -79,14 +79,14 @@ const ModalForm: React.FC<ModalFormProps> = ({ visible, onCancel }) => {
|
||||
};
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const showUserModal = () => {
|
||||
setVisible(true);
|
||||
setOpen(true);
|
||||
};
|
||||
|
||||
const hideUserModal = () => {
|
||||
setVisible(false);
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
const onFinish = (values: any) => {
|
||||
@ -100,7 +100,7 @@ const App: React.FC = () => {
|
||||
const { basicForm } = forms;
|
||||
const users = basicForm.getFieldValue('users') || [];
|
||||
basicForm.setFieldsValue({ users: [...users, values] });
|
||||
setVisible(false);
|
||||
setOpen(false);
|
||||
}
|
||||
}}
|
||||
>
|
||||
@ -140,7 +140,7 @@ const App: React.FC = () => {
|
||||
</Form.Item>
|
||||
</Form>
|
||||
|
||||
<ModalForm visible={visible} onCancel={hideUserModal} />
|
||||
<ModalForm open={open} onCancel={hideUserModal} />
|
||||
</Form.Provider>
|
||||
);
|
||||
};
|
||||
|
@ -26,20 +26,20 @@ interface Values {
|
||||
}
|
||||
|
||||
interface CollectionCreateFormProps {
|
||||
visible: boolean;
|
||||
open: boolean;
|
||||
onCreate: (values: Values) => void;
|
||||
onCancel: () => void;
|
||||
}
|
||||
|
||||
const CollectionCreateForm: React.FC<CollectionCreateFormProps> = ({
|
||||
visible,
|
||||
open,
|
||||
onCreate,
|
||||
onCancel,
|
||||
}) => {
|
||||
const [form] = Form.useForm();
|
||||
return (
|
||||
<Modal
|
||||
visible={visible}
|
||||
open={open}
|
||||
title="Create a new collection"
|
||||
okText="Create"
|
||||
cancelText="Cancel"
|
||||
@ -84,11 +84,11 @@ const CollectionCreateForm: React.FC<CollectionCreateFormProps> = ({
|
||||
};
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const onCreate = (values: any) => {
|
||||
console.log('Received values of form: ', values);
|
||||
setVisible(false);
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
return (
|
||||
@ -96,16 +96,16 @@ const App: React.FC = () => {
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
setVisible(true);
|
||||
setOpen(true);
|
||||
}}
|
||||
>
|
||||
New Collection
|
||||
</Button>
|
||||
<CollectionCreateForm
|
||||
visible={visible}
|
||||
open={open}
|
||||
onCreate={onCreate}
|
||||
onCancel={() => {
|
||||
setVisible(false);
|
||||
setOpen(false);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
@ -59,7 +59,7 @@ const App: React.FC = () => {
|
||||
onChange={setGutterKey}
|
||||
marks={gutters}
|
||||
step={null}
|
||||
tipFormatter={value => value && gutters[value]}
|
||||
tooltip={{ formatter: value => value && gutters[value] }}
|
||||
/>
|
||||
</div>
|
||||
<span>Vertical Gutter (px): </span>
|
||||
@ -71,7 +71,7 @@ const App: React.FC = () => {
|
||||
onChange={setVgutterKey}
|
||||
marks={vgutters}
|
||||
step={null}
|
||||
tipFormatter={value => value && vgutters[value]}
|
||||
tooltip={{ formatter: value => value && vgutters[value] }}
|
||||
/>
|
||||
</div>
|
||||
<span>Column Count:</span>
|
||||
@ -83,7 +83,7 @@ const App: React.FC = () => {
|
||||
onChange={setColCountKey}
|
||||
marks={colCounts}
|
||||
step={null}
|
||||
tipFormatter={value => value && colCounts[value]}
|
||||
tooltip={{ formatter: value => value && colCounts[value] }}
|
||||
/>
|
||||
</div>
|
||||
<Row gutter={[gutters[gutterKey], vgutters[vgutterKey]]}>
|
||||
|
@ -17,7 +17,7 @@ import type { InputFocusOptions } from './Input';
|
||||
import { fixControlledValue, resolveOnChange, triggerFocus } from './Input';
|
||||
|
||||
interface ShowCountProps {
|
||||
formatter: (args: { count: number; maxLength?: number }) => string;
|
||||
formatter: (args: { value: string; count: number; maxLength?: number }) => string;
|
||||
}
|
||||
|
||||
function fixEmojiLength(value: string, maxLength: number) {
|
||||
@ -233,7 +233,7 @@ const TextArea = React.forwardRef<TextAreaRef, TextAreaProps>(
|
||||
|
||||
let dataCount = '';
|
||||
if (typeof showCount === 'object') {
|
||||
dataCount = showCount.formatter({ count: valueLength, maxLength });
|
||||
dataCount = showCount.formatter({ value: val, count: valueLength, maxLength });
|
||||
} else {
|
||||
dataCount = `${valueLength}${hasMaxLength ? ` / ${maxLength}` : ''}`;
|
||||
}
|
||||
|
@ -272,12 +272,14 @@ describe('should support showCount', () => {
|
||||
const { container } = render(
|
||||
<Input
|
||||
maxLength={5}
|
||||
showCount={{ formatter: ({ count, maxLength }) => `${count}, ${maxLength}` }}
|
||||
showCount={{
|
||||
formatter: ({ value, count, maxLength }) => `${value}, ${count}, ${maxLength}`,
|
||||
}}
|
||||
value="12345"
|
||||
/>,
|
||||
);
|
||||
expect(container.querySelector('input')?.getAttribute('value')).toBe('12345');
|
||||
expect(container.querySelector('.ant-input-show-count-suffix')?.innerHTML).toBe('5, 5');
|
||||
expect(container.querySelector('.ant-input-show-count-suffix')?.innerHTML).toBe('12345, 5, 5');
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -304,13 +304,15 @@ describe('TextArea', () => {
|
||||
const { container } = render(
|
||||
<TextArea
|
||||
maxLength={5}
|
||||
showCount={{ formatter: ({ count, maxLength }) => `${count}, ${maxLength}` }}
|
||||
showCount={{
|
||||
formatter: ({ value, count, maxLength }) => `${value}, ${count}, ${maxLength}`,
|
||||
}}
|
||||
value="12345"
|
||||
/>,
|
||||
);
|
||||
expect(container.querySelector('textarea').value).toBe('12345');
|
||||
expect(container.querySelector('.ant-input-textarea').getAttribute('data-count')).toBe(
|
||||
'5, 5',
|
||||
'12345, 5, 5',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@ -26,7 +26,7 @@ A basic widget for getting the user input is a text field. Keyboard and mouse ca
|
||||
| disabled | Whether the input is disabled | boolean | false | |
|
||||
| id | The ID for input | string | - | |
|
||||
| maxLength | The max length | number | - | |
|
||||
| showCount | Whether show text count | boolean \| { formatter: ({ count: number, maxLength?: number }) => ReactNode } | false | 4.18.0 |
|
||||
| showCount | Whether show text count | boolean \| { formatter: (info: { value: string, count: number, maxLength?: number }) => ReactNode } | false | 4.18.0 info.value: 4.23.0 |
|
||||
| status | Set validation status | 'error' \| 'warning' | - | 4.19.0 |
|
||||
| prefix | The prefix icon for the Input | ReactNode | - | |
|
||||
| size | The size of the input box. Note: in the context of a form, the `middle` size is used | `large` \| `middle` \| `small` | - | |
|
||||
@ -49,7 +49,7 @@ The rest of the props of Input are exactly the same as the original [input](http
|
||||
| bordered | Whether has border style | boolean | true | 4.5.0 |
|
||||
| defaultValue | The initial input content | string | - | |
|
||||
| maxLength | The max length | number | - | 4.7.0 |
|
||||
| showCount | Whether show text count | boolean \| { formatter: ({ count: number, maxLength?: number }) => string } | false | 4.7.0 (formatter: 4.10.0) |
|
||||
| showCount | Whether show text count | boolean \| { formatter: (info: { value: string, count: number, maxLength?: number }) => string } | false | 4.7.0 formatter: 4.10.0 info.value: 4.23.0 |
|
||||
| value | The input content value | string | - | |
|
||||
| onPressEnter | The callback function that is triggered when Enter key is pressed | function(e) | - | |
|
||||
| onResize | The callback function that is triggered when resize | function({ width, height }) | - | |
|
||||
|
@ -27,7 +27,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/xS9YEJhfe/Input.svg
|
||||
| disabled | 是否禁用状态,默认为 false | boolean | false | |
|
||||
| id | 输入框的 id | string | - | |
|
||||
| maxLength | 最大长度 | number | - | |
|
||||
| showCount | 是否展示字数 | boolean \| { formatter: ({ count: number, maxLength?: number }) => ReactNode } | false | 4.18.0 |
|
||||
| showCount | 是否展示字数 | boolean \| { formatter: (info: { value: string, count: number, maxLength?: number }) => ReactNode } | false | 4.18.0 info.value: 4.23.0 |
|
||||
| status | 设置校验状态 | 'error' \| 'warning' | - | 4.19.0 |
|
||||
| prefix | 带有前缀图标的 input | ReactNode | - | |
|
||||
| size | 控件大小。注:标准表单内的输入框大小限制为 `middle` | `large` \| `middle` \| `small` | - | |
|
||||
@ -50,7 +50,7 @@ Input 的其他属性和 React 自带的 [input](https://reactjs.org/docs/dom-el
|
||||
| bordered | 是否有边框 | boolean | true | 4.5.0 |
|
||||
| defaultValue | 输入框默认内容 | string | - | |
|
||||
| maxLength | 内容最大长度 | number | - | 4.7.0 |
|
||||
| showCount | 是否展示字数 | boolean \| { formatter: ({ count: number, maxLength?: number }) => string } | false | 4.7.0 (formatter: 4.10.0) |
|
||||
| showCount | 是否展示字数 | boolean \| { formatter: (info: { value: string, count: number, maxLength?: number }) => string } | false | 4.7.0 formatter: 4.10.0 info.value: 4.23.0 |
|
||||
| value | 输入框内容 | string | - | |
|
||||
| onPressEnter | 按下回车的回调 | function(e) | - | |
|
||||
| onResize | resize 回调 | function({ width, height }) | - | |
|
||||
|
@ -177,13 +177,13 @@ const App: React.FC = () => (
|
||||
<DatePicker open />
|
||||
<TimePicker open defaultOpenValue={moment()} />
|
||||
<RangePicker open style={{ width: 200 }} />
|
||||
<Popconfirm title="Question?" visible>
|
||||
<Popconfirm title="Question?" open>
|
||||
<a>Click to confirm</a>
|
||||
</Popconfirm>
|
||||
<Transfer dataSource={[]} showSearch targetKeys={[]} render={(item: any) => item.title} />
|
||||
<Calendar fullscreen={false} value={moment()} />
|
||||
<Table dataSource={[]} columns={columns} />
|
||||
<Modal title="Locale Modal" visible getContainer={false}>
|
||||
<Modal title="Locale Modal" open getContainer={false}>
|
||||
<p>Locale Modal</p>
|
||||
</Modal>
|
||||
</div>
|
||||
|
@ -112,6 +112,7 @@ exports[`renders ./components/mentions/demo/form.md extend context correctly 1`]
|
||||
class="ant-mentions"
|
||||
>
|
||||
<textarea
|
||||
aria-required="true"
|
||||
class="rc-textarea"
|
||||
id="bio"
|
||||
placeholder="You can use @ to ref user here"
|
||||
|
@ -112,6 +112,7 @@ exports[`renders ./components/mentions/demo/form.md correctly 1`] = `
|
||||
class="ant-mentions"
|
||||
>
|
||||
<textarea
|
||||
aria-required="true"
|
||||
class="rc-textarea"
|
||||
id="bio"
|
||||
placeholder="You can use @ to ref user here"
|
||||
|
@ -55,9 +55,9 @@ export default class MenuItem extends React.Component<MenuItemProps> {
|
||||
|
||||
if (!siderCollapsed && !inlineCollapsed) {
|
||||
tooltipProps.title = null;
|
||||
// Reset `visible` to fix control mode tooltip display not correct
|
||||
// Reset `open` to fix control mode tooltip display not correct
|
||||
// ref: https://github.com/ant-design/ant-design/issues/16742
|
||||
tooltipProps.visible = false;
|
||||
tooltipProps.open = false;
|
||||
}
|
||||
const childrenLength = toArray(children).length;
|
||||
|
||||
|
@ -120,7 +120,7 @@ return <Menu items={items} />;
|
||||
#### SubMenuType
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| children | 子菜单的菜单项 | [ItemType\[\]](#ItemType) | - | |
|
||||
| disabled | 是否禁用 | boolean | false | |
|
||||
| icon | 菜单图标 | ReactNode | - | |
|
||||
|
@ -24,6 +24,7 @@ const ConfirmDialog = (props: ConfirmDialogProps) => {
|
||||
zIndex,
|
||||
afterClose,
|
||||
visible,
|
||||
open,
|
||||
keyboard,
|
||||
centered,
|
||||
getContainer,
|
||||
@ -90,8 +91,8 @@ const ConfirmDialog = (props: ConfirmDialogProps) => {
|
||||
{ [`${contentPrefixCls}-centered`]: !!props.centered },
|
||||
wrapClassName,
|
||||
)}
|
||||
onCancel={() => close({ triggerCancel: true })}
|
||||
visible={visible}
|
||||
onCancel={() => close?.({ triggerCancel: true })}
|
||||
open={open || visible}
|
||||
title=""
|
||||
footer=""
|
||||
transitionName={getTransitionName(rootPrefixCls, 'zoom', props.transitionName)}
|
||||
|
@ -12,6 +12,7 @@ import { NoFormStyle } from '../form/context';
|
||||
import LocaleReceiver from '../locale-provider/LocaleReceiver';
|
||||
import { getTransitionName } from '../_util/motion';
|
||||
import { canUseDocElement } from '../_util/styleChecker';
|
||||
import warning from '../_util/warning';
|
||||
import { getConfirmLocale } from './locale';
|
||||
|
||||
let mousePosition: { x: number; y: number } | null;
|
||||
@ -37,7 +38,12 @@ if (canUseDocElement()) {
|
||||
|
||||
export interface ModalProps {
|
||||
/** 对话框是否可见 */
|
||||
/**
|
||||
* @deprecated `visible` is deprecated which will be removed in next major version. Please use
|
||||
* `open` instead.
|
||||
*/
|
||||
visible?: boolean;
|
||||
open?: boolean;
|
||||
/** 确定按钮 loading */
|
||||
confirmLoading?: boolean;
|
||||
/** 标题 */
|
||||
@ -92,7 +98,12 @@ type getContainerFunc = () => HTMLElement;
|
||||
export interface ModalFuncProps {
|
||||
prefixCls?: string;
|
||||
className?: string;
|
||||
/**
|
||||
* @deprecated `visible` is deprecated which will be removed in next major version. Please use
|
||||
* `open` instead.
|
||||
*/
|
||||
visible?: boolean;
|
||||
open?: boolean;
|
||||
title?: React.ReactNode;
|
||||
closable?: boolean;
|
||||
content?: React.ReactNode;
|
||||
@ -151,6 +162,12 @@ const Modal: React.FC<ModalProps> = props => {
|
||||
onOk?.(e);
|
||||
};
|
||||
|
||||
warning(
|
||||
!('visible' in props),
|
||||
'Modal',
|
||||
`\`visible\` will be removed in next major version, please use \`open\` instead.`,
|
||||
);
|
||||
|
||||
const renderFooter = (locale: ModalLocale) => {
|
||||
const { okText, okType, cancelText, confirmLoading } = props;
|
||||
return (
|
||||
@ -174,6 +191,7 @@ const Modal: React.FC<ModalProps> = props => {
|
||||
prefixCls: customizePrefixCls,
|
||||
footer,
|
||||
visible,
|
||||
open,
|
||||
wrapClassName,
|
||||
centered,
|
||||
getContainer,
|
||||
@ -211,7 +229,7 @@ const Modal: React.FC<ModalProps> = props => {
|
||||
prefixCls={prefixCls}
|
||||
wrapClassName={wrapClassNameExtended}
|
||||
footer={footer === undefined ? defaultFooter : footer}
|
||||
visible={visible}
|
||||
visible={open || visible}
|
||||
mousePosition={mousePosition}
|
||||
onClose={handleCancel}
|
||||
closeIcon={closeIconToRender}
|
||||
@ -226,7 +244,7 @@ const Modal: React.FC<ModalProps> = props => {
|
||||
Modal.defaultProps = {
|
||||
width: 520,
|
||||
confirmLoading: false,
|
||||
visible: false,
|
||||
open: false,
|
||||
okType: 'primary' as LegacyButtonType,
|
||||
};
|
||||
|
||||
|
@ -4,14 +4,15 @@ import Modal from '..';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
import { fireEvent, render } from '../../../tests/utils';
|
||||
import { resetWarned } from '../../_util/warning';
|
||||
|
||||
jest.mock('rc-util/lib/Portal');
|
||||
|
||||
class ModalTester extends React.Component<ModalProps, { visible: boolean }> {
|
||||
state = { visible: false };
|
||||
class ModalTester extends React.Component<ModalProps, { open: boolean }> {
|
||||
state = { open: false };
|
||||
|
||||
componentDidMount() {
|
||||
this.setState({ visible: true }); // eslint-disable-line react/no-did-mount-set-state
|
||||
this.setState({ open: true }); // eslint-disable-line react/no-did-mount-set-state
|
||||
}
|
||||
|
||||
container = React.createRef<HTMLDivElement>();
|
||||
@ -19,11 +20,11 @@ class ModalTester extends React.Component<ModalProps, { visible: boolean }> {
|
||||
getContainer = () => this.container?.current!;
|
||||
|
||||
render() {
|
||||
const { visible } = this.state;
|
||||
const { open } = this.state;
|
||||
return (
|
||||
<div>
|
||||
<div ref={this.container} />
|
||||
<Modal {...this.props} visible={visible} getContainer={this.getContainer}>
|
||||
<Modal {...this.props} open={open} getContainer={this.getContainer}>
|
||||
Here is content of Modal
|
||||
</Modal>
|
||||
</div>
|
||||
@ -36,7 +37,7 @@ describe('Modal', () => {
|
||||
rtlTest(Modal);
|
||||
|
||||
it('support closeIcon', () => {
|
||||
render(<Modal closeIcon={<a>closeIcon</a>} visible />);
|
||||
render(<Modal closeIcon={<a>closeIcon</a>} open />);
|
||||
expect(document.body.querySelectorAll('.ant-modal-root')[0]).toMatchSnapshot();
|
||||
});
|
||||
|
||||
@ -52,35 +53,35 @@ describe('Modal', () => {
|
||||
|
||||
it('onCancel should be called', () => {
|
||||
const onCancel = jest.fn();
|
||||
render(<Modal visible onCancel={onCancel} />);
|
||||
render(<Modal open onCancel={onCancel} />);
|
||||
fireEvent.click(document.body.querySelectorAll('.ant-btn')[0]);
|
||||
expect(onCancel).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('onOk should be called', () => {
|
||||
const onOk = jest.fn();
|
||||
render(<Modal visible onOk={onOk} />);
|
||||
render(<Modal open onOk={onOk} />);
|
||||
const btns = document.body.querySelectorAll('.ant-btn');
|
||||
fireEvent.click(btns[btns.length - 1]);
|
||||
expect(onOk).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('danger type', () => {
|
||||
render(<Modal okType="danger" okText="123" visible />);
|
||||
render(<Modal okType="danger" okText="123" open />);
|
||||
const btns = document.body.querySelectorAll('.ant-btn');
|
||||
expect(btns[btns.length - 1].classList.contains('ant-btn-dangerous')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('mouse position', () => {
|
||||
const Demo = () => {
|
||||
const [visible, setVisible] = React.useState(false);
|
||||
const [open, setOpen] = React.useState(false);
|
||||
const containerRef = React.useRef<HTMLDivElement>(null);
|
||||
return (
|
||||
<div ref={containerRef}>
|
||||
<div id="trigger" onClick={() => setVisible(true)}>
|
||||
<div id="trigger" onClick={() => setOpen(true)}>
|
||||
click me
|
||||
</div>
|
||||
<Modal visible={visible} getContainer={() => containerRef.current!} />
|
||||
<Modal open={open} getContainer={() => containerRef.current!} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@ -90,4 +91,18 @@ describe('Modal', () => {
|
||||
(container.querySelectorAll('.ant-modal')[0] as HTMLDivElement).style.transformOrigin,
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
it('deprecated warning', () => {
|
||||
resetWarned();
|
||||
const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
|
||||
render(<Modal visible />);
|
||||
expect(errSpy).toHaveBeenCalledWith(
|
||||
'Warning: [antd: Modal] `visible` will be removed in next major version, please use `open` instead.',
|
||||
);
|
||||
|
||||
expect(document.querySelector('.ant-modal')).toBeTruthy();
|
||||
|
||||
errSpy.mockRestore();
|
||||
});
|
||||
});
|
||||
|
@ -29,7 +29,7 @@ export type ModalStaticFunctions = Record<NonNullable<ModalFuncProps['type']>, M
|
||||
export default function confirm(config: ModalFuncProps) {
|
||||
const container = document.createDocumentFragment();
|
||||
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
||||
let currentConfig = { ...config, close, visible: true } as any;
|
||||
let currentConfig = { ...config, close, open: true } as any;
|
||||
|
||||
function destroy(...args: any[]) {
|
||||
const triggerCancel = args.some(param => param && param.triggerCancel);
|
||||
@ -79,7 +79,7 @@ export default function confirm(config: ModalFuncProps) {
|
||||
function close(...args: any[]) {
|
||||
currentConfig = {
|
||||
...currentConfig,
|
||||
visible: false,
|
||||
open: false,
|
||||
afterClose: () => {
|
||||
if (typeof config.afterClose === 'function') {
|
||||
config.afterClose();
|
||||
|
@ -18,26 +18,26 @@ import { Button, Modal } from 'antd';
|
||||
import React, { useState } from 'react';
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [open, setOpen] = useState(false);
|
||||
const [confirmLoading, setConfirmLoading] = useState(false);
|
||||
const [modalText, setModalText] = useState('Content of the modal');
|
||||
|
||||
const showModal = () => {
|
||||
setVisible(true);
|
||||
setOpen(true);
|
||||
};
|
||||
|
||||
const handleOk = () => {
|
||||
setModalText('The modal will be closed after two seconds');
|
||||
setConfirmLoading(true);
|
||||
setTimeout(() => {
|
||||
setVisible(false);
|
||||
setOpen(false);
|
||||
setConfirmLoading(false);
|
||||
}, 2000);
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
console.log('Clicked cancel button');
|
||||
setVisible(false);
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
return (
|
||||
@ -47,7 +47,7 @@ const App: React.FC = () => {
|
||||
</Button>
|
||||
<Modal
|
||||
title="Title"
|
||||
visible={visible}
|
||||
open={open}
|
||||
onOk={handleOk}
|
||||
confirmLoading={confirmLoading}
|
||||
onCancel={handleCancel}
|
||||
|
@ -18,18 +18,18 @@ import { Button, Modal } from 'antd';
|
||||
import React, { useState } from 'react';
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [isModalVisible, setIsModalVisible] = useState(false);
|
||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||
|
||||
const showModal = () => {
|
||||
setIsModalVisible(true);
|
||||
setIsModalOpen(true);
|
||||
};
|
||||
|
||||
const handleOk = () => {
|
||||
setIsModalVisible(false);
|
||||
setIsModalOpen(false);
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
setIsModalVisible(false);
|
||||
setIsModalOpen(false);
|
||||
};
|
||||
|
||||
return (
|
||||
@ -37,7 +37,7 @@ const App: React.FC = () => {
|
||||
<Button type="primary" onClick={showModal}>
|
||||
Open Modal
|
||||
</Button>
|
||||
<Modal title="Basic Modal" visible={isModalVisible} onOk={handleOk} onCancel={handleCancel}>
|
||||
<Modal title="Basic Modal" open={isModalOpen} onOk={handleOk} onCancel={handleCancel}>
|
||||
<p>Some contents...</p>
|
||||
<p>Some contents...</p>
|
||||
<p>Some contents...</p>
|
||||
|
@ -18,20 +18,20 @@ import { Button, Modal } from 'antd';
|
||||
import React, { useState } from 'react';
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const showModal = () => {
|
||||
setVisible(true);
|
||||
setOpen(true);
|
||||
};
|
||||
|
||||
const handleOk = (e: React.MouseEvent<HTMLElement>) => {
|
||||
console.log(e);
|
||||
setVisible(false);
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
const handleCancel = (e: React.MouseEvent<HTMLElement>) => {
|
||||
console.log(e);
|
||||
setVisible(false);
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
return (
|
||||
@ -41,7 +41,7 @@ const App: React.FC = () => {
|
||||
</Button>
|
||||
<Modal
|
||||
title="Basic Modal"
|
||||
visible={visible}
|
||||
open={open}
|
||||
onOk={handleOk}
|
||||
onCancel={handleCancel}
|
||||
okButtonProps={{ disabled: true }}
|
||||
|
@ -298,7 +298,7 @@ const TableTransfer = ({ leftColumns, rightColumns, ...restProps }) => (
|
||||
);
|
||||
|
||||
export default () => {
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [open, setOpen] = useState(false);
|
||||
const [targetKeys, setTargetKeys] = useState(oriTargetKeys);
|
||||
const [selectedKeys, setSelectedKeys] = useState([]);
|
||||
const [disabled, setDisabled] = useState(false);
|
||||
@ -329,17 +329,17 @@ export default () => {
|
||||
};
|
||||
|
||||
const showModal = () => {
|
||||
setVisible(true);
|
||||
setOpen(true);
|
||||
};
|
||||
|
||||
const handleOk = e => {
|
||||
console.log(e);
|
||||
setVisible(false);
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
const handleCancel = e => {
|
||||
console.log(e);
|
||||
setVisible(false);
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
const columns = [
|
||||
@ -385,7 +385,7 @@ export default () => {
|
||||
<Button type="primary" onClick={showModal}>
|
||||
Open Modal
|
||||
</Button>
|
||||
<Modal title="Basic Modal" visible={visible} onOk={handleOk} onCancel={handleCancel}>
|
||||
<Modal title="Basic Modal" open={open} onOk={handleOk} onCancel={handleCancel}>
|
||||
<Switch
|
||||
unCheckedChildren="disabled"
|
||||
checkedChildren="disabled"
|
||||
|
@ -23,22 +23,22 @@ import React, { useState } from 'react';
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const showModal = () => {
|
||||
setVisible(true);
|
||||
setOpen(true);
|
||||
};
|
||||
|
||||
const handleOk = () => {
|
||||
setLoading(true);
|
||||
setTimeout(() => {
|
||||
setLoading(false);
|
||||
setVisible(false);
|
||||
setOpen(false);
|
||||
}, 3000);
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
setVisible(false);
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
return (
|
||||
@ -47,7 +47,7 @@ const App: React.FC = () => {
|
||||
Open Modal with customized footer
|
||||
</Button>
|
||||
<Modal
|
||||
visible={visible}
|
||||
open={open}
|
||||
title="Title"
|
||||
onOk={handleOk}
|
||||
onCancel={handleCancel}
|
||||
|
@ -19,14 +19,14 @@ import { Button, Modal, Space } from 'antd';
|
||||
import React, { useState } from 'react';
|
||||
|
||||
const LocalizedModal = () => {
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const showModal = () => {
|
||||
setVisible(true);
|
||||
setOpen(true);
|
||||
};
|
||||
|
||||
const hideModal = () => {
|
||||
setVisible(false);
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
return (
|
||||
@ -36,7 +36,7 @@ const LocalizedModal = () => {
|
||||
</Button>
|
||||
<Modal
|
||||
title="Modal"
|
||||
visible={visible}
|
||||
open={open}
|
||||
onOk={hideModal}
|
||||
onCancel={hideModal}
|
||||
okText="确认"
|
||||
|
@ -20,23 +20,23 @@ import type { DraggableData, DraggableEvent } from 'react-draggable';
|
||||
import Draggable from 'react-draggable';
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [open, setOpen] = useState(false);
|
||||
const [disabled, setDisabled] = useState(false);
|
||||
const [bounds, setBounds] = useState({ left: 0, top: 0, bottom: 0, right: 0 });
|
||||
const draggleRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const showModal = () => {
|
||||
setVisible(true);
|
||||
setOpen(true);
|
||||
};
|
||||
|
||||
const handleOk = (e: React.MouseEvent<HTMLElement>) => {
|
||||
console.log(e);
|
||||
setVisible(false);
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
const handleCancel = (e: React.MouseEvent<HTMLElement>) => {
|
||||
console.log(e);
|
||||
setVisible(false);
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
const onStart = (_event: DraggableEvent, uiData: DraggableData) => {
|
||||
@ -80,7 +80,7 @@ const App: React.FC = () => {
|
||||
Draggable Modal
|
||||
</div>
|
||||
}
|
||||
visible={visible}
|
||||
open={open}
|
||||
onOk={handleOk}
|
||||
onCancel={handleCancel}
|
||||
modalRender={modal => (
|
||||
|
@ -18,20 +18,20 @@ import { Button, Modal } from 'antd';
|
||||
import React, { useState } from 'react';
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [modal1Visible, setModal1Visible] = useState(false);
|
||||
const [modal2Visible, setModal2Visible] = useState(false);
|
||||
const [modal1Open, setModal1Open] = useState(false);
|
||||
const [modal2Open, setModal2Open] = useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button type="primary" onClick={() => setModal1Visible(true)}>
|
||||
<Button type="primary" onClick={() => setModal1Open(true)}>
|
||||
Display a modal dialog at 20px to Top
|
||||
</Button>
|
||||
<Modal
|
||||
title="20px to Top"
|
||||
style={{ top: 20 }}
|
||||
visible={modal1Visible}
|
||||
onOk={() => setModal1Visible(false)}
|
||||
onCancel={() => setModal1Visible(false)}
|
||||
visible={modal1Open}
|
||||
onOk={() => setModal1Open(false)}
|
||||
onCancel={() => setModal1Open(false)}
|
||||
>
|
||||
<p>some contents...</p>
|
||||
<p>some contents...</p>
|
||||
@ -39,15 +39,15 @@ const App: React.FC = () => {
|
||||
</Modal>
|
||||
<br />
|
||||
<br />
|
||||
<Button type="primary" onClick={() => setModal2Visible(true)}>
|
||||
<Button type="primary" onClick={() => setModal2Open(true)}>
|
||||
Vertically centered modal dialog
|
||||
</Button>
|
||||
<Modal
|
||||
title="Vertically centered modal dialog"
|
||||
centered
|
||||
visible={modal2Visible}
|
||||
onOk={() => setModal2Visible(false)}
|
||||
onCancel={() => setModal2Visible(false)}
|
||||
visible={modal2Open}
|
||||
onOk={() => setModal2Open(false)}
|
||||
onCancel={() => setModal2Open(false)}
|
||||
>
|
||||
<p>some contents...</p>
|
||||
<p>some contents...</p>
|
||||
|
@ -18,19 +18,19 @@ import { Button, Modal } from 'antd';
|
||||
import React, { useState } from 'react';
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button type="primary" onClick={() => setVisible(true)}>
|
||||
<Button type="primary" onClick={() => setOpen(true)}>
|
||||
Open Modal of 1000px width
|
||||
</Button>
|
||||
<Modal
|
||||
title="Modal 1000px width"
|
||||
centered
|
||||
visible={visible}
|
||||
onOk={() => setVisible(false)}
|
||||
onCancel={() => setVisible(false)}
|
||||
open={open}
|
||||
onOk={() => setOpen(false)}
|
||||
onCancel={() => setOpen(false)}
|
||||
width={1000}
|
||||
>
|
||||
<p>some contents...</p>
|
||||
|
@ -38,7 +38,7 @@ When requiring users to interact with the application, but without jumping to a
|
||||
| okType | Button `type` of the OK button | string | `primary` | |
|
||||
| style | Style of floating layer, typically used at least for adjusting the position | CSSProperties | - | |
|
||||
| title | The modal dialog's title | ReactNode | - | |
|
||||
| visible | Whether the modal dialog is visible or not | boolean | false | |
|
||||
| open | Whether the modal dialog is visible or not | boolean | false | 4.23.0 |
|
||||
| width | Width of the modal dialog | string \| number | 520 | |
|
||||
| wrapClassName | The class name of the container of the modal dialog | string | - | |
|
||||
| zIndex | The `z-index` of the Modal | number | 1000 | |
|
||||
|
@ -41,7 +41,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/3StSdUlSH/Modal.svg
|
||||
| okType | 确认按钮类型 | string | `primary` | |
|
||||
| style | 可用于设置浮层的样式,调整浮层位置等 | CSSProperties | - | |
|
||||
| title | 标题 | ReactNode | - | |
|
||||
| visible | 对话框是否可见 | boolean | - | |
|
||||
| open | 对话框是否可见 | boolean | - | 4.23.0 |
|
||||
| width | 宽度 | string \| number | 520 | |
|
||||
| wrapClassName | 对话框外层容器的类名 | string | - | |
|
||||
| zIndex | 设置 Modal 的 `z-index` | number | 1000 | |
|
||||
|
@ -25,7 +25,7 @@ const HookModal: React.ForwardRefRenderFunction<HookModalRef, HookModalProps> =
|
||||
{ afterClose, config },
|
||||
ref,
|
||||
) => {
|
||||
const [visible, setVisible] = React.useState(true);
|
||||
const [open, setOpen] = React.useState(true);
|
||||
const [innerConfig, setInnerConfig] = React.useState(config);
|
||||
const { direction, getPrefixCls } = React.useContext(ConfigContext);
|
||||
|
||||
@ -33,7 +33,7 @@ const HookModal: React.ForwardRefRenderFunction<HookModalRef, HookModalProps> =
|
||||
const rootPrefixCls = getPrefixCls();
|
||||
|
||||
const close = (...args: any[]) => {
|
||||
setVisible(false);
|
||||
setOpen(false);
|
||||
const triggerCancel = args.some(param => param && param.triggerCancel);
|
||||
if (innerConfig.onCancel && triggerCancel) {
|
||||
innerConfig.onCancel(() => {}, ...args.slice(1));
|
||||
@ -58,7 +58,7 @@ const HookModal: React.ForwardRefRenderFunction<HookModalRef, HookModalProps> =
|
||||
rootPrefixCls={rootPrefixCls}
|
||||
{...innerConfig}
|
||||
close={close}
|
||||
visible={visible}
|
||||
open={open}
|
||||
afterClose={afterClose}
|
||||
okText={
|
||||
innerConfig.okText ||
|
||||
|
@ -1637,13 +1637,6 @@ exports[`renders ./components/page-header/demo/responsive.md extend context corr
|
||||
role="tabpanel"
|
||||
tabindex="0"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
tabindex="-1"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1416,13 +1416,6 @@ exports[`renders ./components/page-header/demo/responsive.md correctly 1`] = `
|
||||
role="tabpanel"
|
||||
tabindex="0"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-tabpane"
|
||||
role="tabpanel"
|
||||
style="display:none"
|
||||
tabindex="-1"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -23,7 +23,7 @@ describe('Popconfirm', () => {
|
||||
});
|
||||
|
||||
it('should popup Popconfirm dialog', () => {
|
||||
const onVisibleChange = jest.fn();
|
||||
const onOpenChange = jest.fn();
|
||||
|
||||
const wrapper = mount(
|
||||
<Popconfirm
|
||||
@ -32,7 +32,7 @@ describe('Popconfirm', () => {
|
||||
cancelText="No"
|
||||
mouseEnterDelay={0}
|
||||
mouseLeaveDelay={0}
|
||||
onVisibleChange={onVisibleChange}
|
||||
onOpenChange={onOpenChange}
|
||||
>
|
||||
<span>Delete</span>
|
||||
</Popconfirm>,
|
||||
@ -40,11 +40,11 @@ describe('Popconfirm', () => {
|
||||
|
||||
const triggerNode = wrapper.find('span').at(0);
|
||||
triggerNode.simulate('click');
|
||||
expect(onVisibleChange).toHaveBeenLastCalledWith(true, undefined);
|
||||
expect(onOpenChange).toHaveBeenLastCalledWith(true, undefined);
|
||||
expect(wrapper.find('.popconfirm-test').length).toBe(1);
|
||||
|
||||
triggerNode.simulate('click');
|
||||
expect(onVisibleChange).toHaveBeenLastCalledWith(false, undefined);
|
||||
expect(onOpenChange).toHaveBeenLastCalledWith(false, undefined);
|
||||
});
|
||||
|
||||
it('should show overlay when trigger is clicked', async () => {
|
||||
@ -88,7 +88,7 @@ describe('Popconfirm', () => {
|
||||
expect(popup.innerHTML).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should be controlled by visible', () => {
|
||||
it('should be controlled by open', () => {
|
||||
const ref = React.createRef();
|
||||
jest.useFakeTimers();
|
||||
const popconfirm = mount(
|
||||
@ -97,10 +97,10 @@ describe('Popconfirm', () => {
|
||||
</Popconfirm>,
|
||||
);
|
||||
expect(ref.current.getPopupDomNode()).toBeFalsy();
|
||||
popconfirm.setProps({ visible: true });
|
||||
popconfirm.setProps({ open: true });
|
||||
expect(ref.current.getPopupDomNode()).toBeTruthy();
|
||||
expect(ref.current.getPopupDomNode().className).not.toContain('ant-popover-hidden');
|
||||
popconfirm.setProps({ visible: false });
|
||||
popconfirm.setProps({ open: false });
|
||||
popconfirm.update(); // https://github.com/enzymejs/enzyme/issues/2305
|
||||
act(() => {
|
||||
jest.runAllTimers();
|
||||
@ -112,14 +112,9 @@ describe('Popconfirm', () => {
|
||||
it('should trigger onConfirm and onCancel', () => {
|
||||
const confirm = jest.fn();
|
||||
const cancel = jest.fn();
|
||||
const onVisibleChange = jest.fn();
|
||||
const onOpenChange = jest.fn();
|
||||
const popconfirm = mount(
|
||||
<Popconfirm
|
||||
title="code"
|
||||
onConfirm={confirm}
|
||||
onCancel={cancel}
|
||||
onVisibleChange={onVisibleChange}
|
||||
>
|
||||
<Popconfirm title="code" onConfirm={confirm} onCancel={cancel} onOpenChange={onOpenChange}>
|
||||
<span>show me your code</span>
|
||||
</Popconfirm>,
|
||||
);
|
||||
@ -127,11 +122,11 @@ describe('Popconfirm', () => {
|
||||
triggerNode.simulate('click');
|
||||
popconfirm.find('.ant-btn-primary').simulate('click');
|
||||
expect(confirm).toHaveBeenCalled();
|
||||
expect(onVisibleChange).toHaveBeenLastCalledWith(false, eventObject);
|
||||
expect(onOpenChange).toHaveBeenLastCalledWith(false, eventObject);
|
||||
triggerNode.simulate('click');
|
||||
popconfirm.find('.ant-btn').at(0).simulate('click');
|
||||
expect(cancel).toHaveBeenCalled();
|
||||
expect(onVisibleChange).toHaveBeenLastCalledWith(false, eventObject);
|
||||
expect(onOpenChange).toHaveBeenLastCalledWith(false, eventObject);
|
||||
});
|
||||
|
||||
it('should support onConfirm to return Promise', async () => {
|
||||
@ -139,20 +134,20 @@ describe('Popconfirm', () => {
|
||||
new Promise(res => {
|
||||
setTimeout(res, 300);
|
||||
});
|
||||
const onVisibleChange = jest.fn();
|
||||
const onOpenChange = jest.fn();
|
||||
const popconfirm = mount(
|
||||
<Popconfirm title="code" onConfirm={confirm} onVisibleChange={onVisibleChange}>
|
||||
<Popconfirm title="code" onConfirm={confirm} onOpenChange={onOpenChange}>
|
||||
<span>show me your code</span>
|
||||
</Popconfirm>,
|
||||
);
|
||||
|
||||
const triggerNode = popconfirm.find('span').at(0);
|
||||
triggerNode.simulate('click');
|
||||
expect(onVisibleChange).toHaveBeenCalledTimes(1);
|
||||
expect(onOpenChange).toHaveBeenCalledTimes(1);
|
||||
|
||||
popconfirm.find('.ant-btn').at(0).simulate('click');
|
||||
await sleep(400);
|
||||
expect(onVisibleChange).toHaveBeenCalledWith(false, eventObject);
|
||||
expect(onOpenChange).toHaveBeenCalledWith(false, eventObject);
|
||||
});
|
||||
|
||||
it('should support customize icon', () => {
|
||||
@ -171,7 +166,7 @@ describe('Popconfirm', () => {
|
||||
const btnPrefixCls = 'custom-btn';
|
||||
const wrapper = mount(
|
||||
<Popconfirm
|
||||
visible
|
||||
open
|
||||
title="x"
|
||||
prefixCls="custom-popconfirm"
|
||||
okButtonProps={{ prefixCls: btnPrefixCls }}
|
||||
@ -185,10 +180,10 @@ describe('Popconfirm', () => {
|
||||
expect(wrapper.find('.custom-btn').length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('should support defaultVisible', () => {
|
||||
it('should support defaultOpen', () => {
|
||||
const ref = React.createRef();
|
||||
mount(
|
||||
<Popconfirm ref={ref} title="code" defaultVisible>
|
||||
<Popconfirm ref={ref} title="code" defaultOpen>
|
||||
<span>show me your code</span>
|
||||
</Popconfirm>,
|
||||
);
|
||||
@ -209,22 +204,17 @@ describe('Popconfirm', () => {
|
||||
});
|
||||
|
||||
it('should be closed by pressing ESC', () => {
|
||||
const onVisibleChange = jest.fn();
|
||||
const onOpenChange = jest.fn();
|
||||
const wrapper = mount(
|
||||
<Popconfirm
|
||||
title="title"
|
||||
mouseEnterDelay={0}
|
||||
mouseLeaveDelay={0}
|
||||
onVisibleChange={onVisibleChange}
|
||||
>
|
||||
<Popconfirm title="title" mouseEnterDelay={0} mouseLeaveDelay={0} onOpenChange={onOpenChange}>
|
||||
<span>Delete</span>
|
||||
</Popconfirm>,
|
||||
);
|
||||
const triggerNode = wrapper.find('span').at(0);
|
||||
triggerNode.simulate('click');
|
||||
expect(onVisibleChange).toHaveBeenLastCalledWith(true, undefined);
|
||||
expect(onOpenChange).toHaveBeenLastCalledWith(true, undefined);
|
||||
triggerNode.simulate('keydown', { key: 'Escape', keyCode: 27 });
|
||||
expect(onVisibleChange).toHaveBeenLastCalledWith(false, eventObject);
|
||||
expect(onOpenChange).toHaveBeenLastCalledWith(false, eventObject);
|
||||
});
|
||||
|
||||
it('should not warn memory leaking if setState in async callback', async () => {
|
||||
|
@ -18,31 +18,31 @@ import { Button, Popconfirm } from 'antd';
|
||||
import React, { useState } from 'react';
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [open, setOpen] = useState(false);
|
||||
const [confirmLoading, setConfirmLoading] = useState(false);
|
||||
|
||||
const showPopconfirm = () => {
|
||||
setVisible(true);
|
||||
setOpen(true);
|
||||
};
|
||||
|
||||
const handleOk = () => {
|
||||
setConfirmLoading(true);
|
||||
|
||||
setTimeout(() => {
|
||||
setVisible(false);
|
||||
setOpen(false);
|
||||
setConfirmLoading(false);
|
||||
}, 2000);
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
console.log('Clicked cancel button');
|
||||
setVisible(false);
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<Popconfirm
|
||||
title="Title"
|
||||
visible={visible}
|
||||
open={open}
|
||||
onConfirm={handleOk}
|
||||
okButtonProps={{ loading: confirmLoading }}
|
||||
onCancel={handleCancel}
|
||||
|
@ -18,7 +18,7 @@ import { message, Popconfirm, Switch } from 'antd';
|
||||
import React, { useState } from 'react';
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [open, setOpen] = useState(false);
|
||||
const [condition, setCondition] = useState(true);
|
||||
|
||||
const changeCondition = (checked: boolean) => {
|
||||
@ -26,18 +26,18 @@ const App: React.FC = () => {
|
||||
};
|
||||
|
||||
const confirm = () => {
|
||||
setVisible(false);
|
||||
setOpen(false);
|
||||
message.success('Next step.');
|
||||
};
|
||||
|
||||
const cancel = () => {
|
||||
setVisible(false);
|
||||
setOpen(false);
|
||||
message.error('Click on cancel.');
|
||||
};
|
||||
|
||||
const handleVisibleChange = (newVisible: boolean) => {
|
||||
if (!newVisible) {
|
||||
setVisible(newVisible);
|
||||
const handleOpenChange = (newOpen: boolean) => {
|
||||
if (!newOpen) {
|
||||
setOpen(newOpen);
|
||||
return;
|
||||
}
|
||||
// Determining condition before show the popconfirm.
|
||||
@ -45,7 +45,7 @@ const App: React.FC = () => {
|
||||
if (condition) {
|
||||
confirm(); // next step
|
||||
} else {
|
||||
setVisible(newVisible);
|
||||
setOpen(newOpen);
|
||||
}
|
||||
};
|
||||
|
||||
@ -53,8 +53,8 @@ const App: React.FC = () => {
|
||||
<div>
|
||||
<Popconfirm
|
||||
title="Are you sure delete this task?"
|
||||
visible={visible}
|
||||
onVisibleChange={handleVisibleChange}
|
||||
open={open}
|
||||
onOpenChange={handleOpenChange}
|
||||
onConfirm={confirm}
|
||||
onCancel={cancel}
|
||||
okText="Yes"
|
||||
|
@ -25,11 +25,7 @@ const App: React.FC = () => {
|
||||
});
|
||||
|
||||
return (
|
||||
<Popconfirm
|
||||
title="Title"
|
||||
onConfirm={confirm}
|
||||
onVisibleChange={() => console.log('visible change')}
|
||||
>
|
||||
<Popconfirm title="Title" onConfirm={confirm} onOpenChange={() => console.log('open change')}>
|
||||
<Button type="primary">Open Popconfirm with Promise</Button>
|
||||
</Popconfirm>
|
||||
);
|
||||
|
@ -23,56 +23,65 @@ export interface PopconfirmProps extends AbstractTooltipProps {
|
||||
cancelButtonProps?: ButtonProps;
|
||||
showCancel?: boolean;
|
||||
icon?: React.ReactNode;
|
||||
/**
|
||||
* @deprecated `onVisibleChange` is deprecated which will be removed in next major version. Please
|
||||
* use `onOpenChange` instead.
|
||||
*/
|
||||
onVisibleChange?: (
|
||||
visible: boolean,
|
||||
e?: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLDivElement>,
|
||||
) => void;
|
||||
onOpenChange?: (
|
||||
open: boolean,
|
||||
e?: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLDivElement>,
|
||||
) => void;
|
||||
}
|
||||
|
||||
export interface PopconfirmState {
|
||||
visible?: boolean;
|
||||
open?: boolean;
|
||||
}
|
||||
|
||||
const Popconfirm = React.forwardRef<unknown, PopconfirmProps>((props, ref) => {
|
||||
const { getPrefixCls } = React.useContext(ConfigContext);
|
||||
const [visible, setVisible] = useMergedState(false, {
|
||||
value: props.visible,
|
||||
defaultValue: props.defaultVisible,
|
||||
const [open, setOpen] = useMergedState(false, {
|
||||
value: props.open !== undefined ? props.open : props.visible,
|
||||
defaultValue: props.defaultOpen !== undefined ? props.defaultOpen : props.defaultVisible,
|
||||
});
|
||||
|
||||
// const isDestroyed = useDestroyed();
|
||||
|
||||
const settingVisible = (
|
||||
const settingOpen = (
|
||||
value: boolean,
|
||||
e?: React.MouseEvent<HTMLButtonElement> | React.KeyboardEvent<HTMLDivElement>,
|
||||
) => {
|
||||
setVisible(value, true);
|
||||
setOpen(value, true);
|
||||
props.onVisibleChange?.(value, e);
|
||||
props.onOpenChange?.(value, e);
|
||||
};
|
||||
|
||||
const close = (e: React.MouseEvent<HTMLButtonElement>) => {
|
||||
settingVisible(false, e);
|
||||
settingOpen(false, e);
|
||||
};
|
||||
|
||||
const onConfirm = (e: React.MouseEvent<HTMLButtonElement>) => props.onConfirm?.call(this, e);
|
||||
|
||||
const onCancel = (e: React.MouseEvent<HTMLButtonElement>) => {
|
||||
settingVisible(false, e);
|
||||
settingOpen(false, e);
|
||||
props.onCancel?.call(this, e);
|
||||
};
|
||||
|
||||
const onKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {
|
||||
if (e.keyCode === KeyCode.ESC && visible) {
|
||||
settingVisible(false, e);
|
||||
if (e.keyCode === KeyCode.ESC && open) {
|
||||
settingOpen(false, e);
|
||||
}
|
||||
};
|
||||
|
||||
const onVisibleChange = (value: boolean) => {
|
||||
const onOpenChange = (value: boolean) => {
|
||||
const { disabled } = props;
|
||||
if (disabled) {
|
||||
return;
|
||||
}
|
||||
settingVisible(value);
|
||||
settingOpen(value);
|
||||
};
|
||||
|
||||
const {
|
||||
@ -91,8 +100,8 @@ const Popconfirm = React.forwardRef<unknown, PopconfirmProps>((props, ref) => {
|
||||
{...restProps}
|
||||
prefixCls={prefixCls}
|
||||
placement={placement}
|
||||
onVisibleChange={onVisibleChange}
|
||||
visible={visible}
|
||||
onOpenChange={onOpenChange}
|
||||
open={open}
|
||||
_overlay={
|
||||
<Overlay
|
||||
{...props}
|
||||
|
@ -90,7 +90,7 @@ describe('Popover', () => {
|
||||
it(`should be rendered correctly in RTL direction`, () => {
|
||||
const wrapper = render(
|
||||
<ConfigProvider direction="rtl">
|
||||
<Popover title="RTL" visible>
|
||||
<Popover title="RTL" open>
|
||||
<span>show me your Rtl demo</span>
|
||||
</Popover>
|
||||
</ConfigProvider>,
|
||||
|
@ -7,25 +7,25 @@ title:
|
||||
|
||||
## zh-CN
|
||||
|
||||
使用 `visible` 属性控制浮层显示。
|
||||
使用 `open` 属性控制浮层显示。
|
||||
|
||||
## en-US
|
||||
|
||||
Use `visible` prop to control the display of the card.
|
||||
Use `open` prop to control the display of the card.
|
||||
|
||||
```tsx
|
||||
import { Button, Popover } from 'antd';
|
||||
import React, { useState } from 'react';
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const hide = () => {
|
||||
setVisible(false);
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
const handleVisibleChange = (newVisible: boolean) => {
|
||||
setVisible(newVisible);
|
||||
const handleOpenChange = (newOpen: boolean) => {
|
||||
setOpen(newOpen);
|
||||
};
|
||||
|
||||
return (
|
||||
@ -33,8 +33,8 @@ const App: React.FC = () => {
|
||||
content={<a onClick={hide}>Close</a>}
|
||||
title="Title"
|
||||
trigger="click"
|
||||
visible={visible}
|
||||
onVisibleChange={handleVisibleChange}
|
||||
open={open}
|
||||
onOpenChange={handleOpenChange}
|
||||
>
|
||||
<Button type="primary">Click me</Button>
|
||||
</Popover>
|
||||
|
@ -26,14 +26,14 @@ const App: React.FC = () => {
|
||||
setHovered(false);
|
||||
};
|
||||
|
||||
const handleHoverChange = (visible: boolean) => {
|
||||
setHovered(visible);
|
||||
const handleHoverChange = (open: boolean) => {
|
||||
setHovered(open);
|
||||
setClicked(false);
|
||||
};
|
||||
|
||||
const handleClickChange = (visible: boolean) => {
|
||||
const handleClickChange = (open: boolean) => {
|
||||
setHovered(false);
|
||||
setClicked(visible);
|
||||
setClicked(open);
|
||||
};
|
||||
|
||||
const hoverContent = <div>This is hover content.</div>;
|
||||
@ -44,8 +44,8 @@ const App: React.FC = () => {
|
||||
content={hoverContent}
|
||||
title="Hover title"
|
||||
trigger="hover"
|
||||
visible={hovered}
|
||||
onVisibleChange={handleHoverChange}
|
||||
open={hovered}
|
||||
onOpenChange={handleHoverChange}
|
||||
>
|
||||
<Popover
|
||||
content={
|
||||
@ -56,8 +56,8 @@ const App: React.FC = () => {
|
||||
}
|
||||
title="Click title"
|
||||
trigger="click"
|
||||
visible={clicked}
|
||||
onVisibleChange={handleClickChange}
|
||||
open={clicked}
|
||||
onOpenChange={handleClickChange}
|
||||
>
|
||||
<Button>Hover and click / 悬停并单击</Button>
|
||||
</Popover>
|
||||
|
@ -90,6 +90,16 @@ describe('Select', () => {
|
||||
expect(container.querySelectorAll('.anticon-down').length).toBe(0);
|
||||
expect(container.querySelectorAll('.anticon-search').length).toBe(1);
|
||||
});
|
||||
|
||||
it('should show warning when use dropdownClassName', () => {
|
||||
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
render(<Select dropdownClassName="myCustomClassName" />);
|
||||
expect(errorSpy).toHaveBeenCalledWith(
|
||||
'Warning: [antd: Select] `dropdownClassName` is deprecated which will be removed in next major version. Please use `popupClassName` instead.',
|
||||
);
|
||||
errorSpy.mockRestore();
|
||||
});
|
||||
|
||||
//
|
||||
describe('Select Custom Icons', () => {
|
||||
it('should support customized icons', () => {
|
||||
|
@ -33,7 +33,7 @@ Select component to select value from options.
|
||||
| defaultOpen | Initial open state of dropdown | boolean | - | |
|
||||
| defaultValue | Initial selected option | string \| string\[]<br />number \| number\[]<br />LabeledValue \| LabeledValue\[] | - | |
|
||||
| disabled | Whether disabled select | boolean | false | |
|
||||
| dropdownClassName | The className of dropdown menu | string | - | |
|
||||
| popupClassName | The className of dropdown menu | string | - | 4.23.0 |
|
||||
| dropdownMatchSelectWidth | Determine whether the dropdown menu and the select input are the same width. Default set `min-width` same as input. Will ignore when value less than select width. `false` will disable virtual scroll | boolean \| number | true | |
|
||||
| dropdownRender | Customize dropdown content | (originNode: ReactNode) => ReactNode | - | |
|
||||
| dropdownStyle | The style of dropdown menu | CSSProperties | - | |
|
||||
|
@ -19,6 +19,7 @@ import { getTransitionDirection, getTransitionName } from '../_util/motion';
|
||||
import type { InputStatus } from '../_util/statusUtils';
|
||||
import { getMergedStatus, getStatusClassNames } from '../_util/statusUtils';
|
||||
import getIcons from './utils/iconUtil';
|
||||
import warning from '../_util/warning';
|
||||
|
||||
type RawValue = string | number;
|
||||
|
||||
@ -53,6 +54,12 @@ export interface SelectProps<
|
||||
placement?: SelectCommonPlacement;
|
||||
mode?: 'multiple' | 'tags';
|
||||
status?: InputStatus;
|
||||
/**
|
||||
* @deprecated `dropdownClassName` is deprecated which will be removed in next major
|
||||
* version.Please use `popupClassName` instead.
|
||||
*/
|
||||
dropdownClassName?: string;
|
||||
popupClassName?: string;
|
||||
}
|
||||
|
||||
const SECRET_COMBOBOX_MODE_DO_NOT_USE = 'SECRET_COMBOBOX_MODE_DO_NOT_USE';
|
||||
@ -64,6 +71,7 @@ const InternalSelect = <OptionType extends BaseOptionType | DefaultOptionType =
|
||||
className,
|
||||
getPopupContainer,
|
||||
dropdownClassName,
|
||||
popupClassName,
|
||||
listHeight = 256,
|
||||
placement,
|
||||
listItemHeight = 24,
|
||||
@ -107,6 +115,13 @@ const InternalSelect = <OptionType extends BaseOptionType | DefaultOptionType =
|
||||
const mergedShowArrow =
|
||||
showArrow !== undefined ? showArrow : props.loading || !(isMultiple || mode === 'combobox');
|
||||
|
||||
// =================== Warning =====================
|
||||
warning(
|
||||
!dropdownClassName,
|
||||
'Select',
|
||||
'`dropdownClassName` is deprecated which will be removed in next major version. Please use `popupClassName` instead.',
|
||||
);
|
||||
|
||||
// ===================== Form Status =====================
|
||||
const {
|
||||
status: contextStatus,
|
||||
@ -138,7 +153,7 @@ const InternalSelect = <OptionType extends BaseOptionType | DefaultOptionType =
|
||||
|
||||
const selectProps = omit(props as typeof props & { itemIcon: any }, ['suffixIcon', 'itemIcon']);
|
||||
|
||||
const rcSelectRtlDropdownClassName = classNames(dropdownClassName, {
|
||||
const rcSelectRtlDropdownClassName = classNames(popupClassName || dropdownClassName, {
|
||||
[`${prefixCls}-dropdown-${direction}`]: direction === 'rtl',
|
||||
});
|
||||
|
||||
|
@ -34,7 +34,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/_0XzgOis7/Select.svg
|
||||
| defaultOpen | 是否默认展开下拉菜单 | boolean | - | |
|
||||
| defaultValue | 指定默认选中的条目 | string \| string\[]<br />number \| number\[]<br />LabeledValue \| LabeledValue\[] | - | |
|
||||
| disabled | 是否禁用 | boolean | false | |
|
||||
| dropdownClassName | 下拉菜单的 className 属性 | string | - | |
|
||||
| popupClassName | 下拉菜单的 className 属性 | string | - | 4.23.0 |
|
||||
| dropdownMatchSelectWidth | 下拉菜单和选择器同宽。默认将设置 `min-width`,当值小于选择框宽度时会被忽略。false 时会关闭虚拟滚动 | boolean \| number | true | |
|
||||
| dropdownRender | 自定义下拉框内容 | (originNode: ReactNode) => ReactNode | - | |
|
||||
| dropdownStyle | 下拉菜单的 style 属性 | CSSProperties | - | |
|
||||
|
@ -6,7 +6,7 @@ import type { TooltipProps } from '../tooltip';
|
||||
import Tooltip from '../tooltip';
|
||||
|
||||
const SliderTooltip = React.forwardRef<unknown, TooltipProps>((props, ref) => {
|
||||
const { visible } = props;
|
||||
const { open } = props;
|
||||
const innerRef = useRef<any>(null);
|
||||
|
||||
const rafRef = useRef<number | null>(null);
|
||||
@ -24,14 +24,14 @@ const SliderTooltip = React.forwardRef<unknown, TooltipProps>((props, ref) => {
|
||||
}
|
||||
|
||||
React.useEffect(() => {
|
||||
if (visible) {
|
||||
if (open) {
|
||||
keepAlign();
|
||||
} else {
|
||||
cancelKeepAlign();
|
||||
}
|
||||
|
||||
return cancelKeepAlign;
|
||||
}, [visible, props.title]);
|
||||
}, [open, props.title]);
|
||||
|
||||
return <Tooltip ref={composeRef(innerRef, ref)} {...props} />;
|
||||
});
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user