mirror of
https://github.com/ant-design/ant-design.git
synced 2025-06-07 09:26:06 +08:00
Revert "revert: Revert "Merge branch 'feature' into master" (#33903)"
This reverts commit 6b1a48d5ed
.
This commit is contained in:
parent
6b1a48d5ed
commit
222ee1f3ad
@ -1,5 +1,6 @@
|
|||||||
import { CSSMotionProps, MotionEventHandler, MotionEndEventHandler } from 'rc-motion';
|
import { CSSMotionProps, MotionEventHandler, MotionEndEventHandler } from 'rc-motion';
|
||||||
import { MotionEvent } from 'rc-motion/lib/interface';
|
import { MotionEvent } from 'rc-motion/lib/interface';
|
||||||
|
import { tuple } from './type';
|
||||||
|
|
||||||
// ================== Collapse Motion ==================
|
// ================== Collapse Motion ==================
|
||||||
const getCollapsedHeight: MotionEventHandler = () => ({ height: 0, opacity: 0 });
|
const getCollapsedHeight: MotionEventHandler = () => ({ height: 0, opacity: 0 });
|
||||||
@ -25,11 +26,21 @@ const collapseMotion: CSSMotionProps = {
|
|||||||
motionDeadline: 500,
|
motionDeadline: 500,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const SelectPlacements = tuple('bottomLeft', 'bottomRight', 'topLeft', 'topRight');
|
||||||
|
export type SelectCommonPlacement = typeof SelectPlacements[number];
|
||||||
|
|
||||||
|
const getTransitionDirection = (placement: SelectCommonPlacement | undefined) => {
|
||||||
|
if (placement !== undefined && (placement === 'topLeft' || placement === 'topRight')) {
|
||||||
|
return `slide-down`;
|
||||||
|
}
|
||||||
|
return `slide-up`;
|
||||||
|
};
|
||||||
|
|
||||||
const getTransitionName = (rootPrefixCls: string, motion: string, transitionName?: string) => {
|
const getTransitionName = (rootPrefixCls: string, motion: string, transitionName?: string) => {
|
||||||
if (transitionName !== undefined) {
|
if (transitionName !== undefined) {
|
||||||
return transitionName;
|
return transitionName;
|
||||||
}
|
}
|
||||||
return `${rootPrefixCls}-${motion}`;
|
return `${rootPrefixCls}-${motion}`;
|
||||||
};
|
};
|
||||||
export { getTransitionName };
|
export { getTransitionName, getTransitionDirection };
|
||||||
export default collapseMotion;
|
export default collapseMotion;
|
||||||
|
@ -42,6 +42,7 @@ export default function getPlacements(config: PlacementsConfig) {
|
|||||||
horizontalArrowShift = 16,
|
horizontalArrowShift = 16,
|
||||||
verticalArrowShift = 8,
|
verticalArrowShift = 8,
|
||||||
autoAdjustOverflow,
|
autoAdjustOverflow,
|
||||||
|
arrowPointAtCenter,
|
||||||
} = config;
|
} = config;
|
||||||
const placementMap: BuildInPlacements = {
|
const placementMap: BuildInPlacements = {
|
||||||
left: {
|
left: {
|
||||||
@ -94,7 +95,7 @@ export default function getPlacements(config: PlacementsConfig) {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
Object.keys(placementMap).forEach(key => {
|
Object.keys(placementMap).forEach(key => {
|
||||||
placementMap[key] = config.arrowPointAtCenter
|
placementMap[key] = arrowPointAtCenter
|
||||||
? {
|
? {
|
||||||
...placementMap[key],
|
...placementMap[key],
|
||||||
overflow: getOverflowOptions(autoAdjustOverflow),
|
overflow: getOverflowOptions(autoAdjustOverflow),
|
@ -30,7 +30,7 @@ const BreadcrumbItem: BreadcrumbItemInterface = ({
|
|||||||
const renderBreadcrumbNode = (breadcrumbItem: React.ReactNode) => {
|
const renderBreadcrumbNode = (breadcrumbItem: React.ReactNode) => {
|
||||||
if (overlay) {
|
if (overlay) {
|
||||||
return (
|
return (
|
||||||
<DropDown overlay={overlay} placement="bottomCenter" {...dropdownProps}>
|
<DropDown overlay={overlay} placement="bottom" {...dropdownProps}>
|
||||||
<span className={`${prefixCls}-overlay-link`}>
|
<span className={`${prefixCls}-overlay-link`}>
|
||||||
{breadcrumbItem}
|
{breadcrumbItem}
|
||||||
<DownOutlined />
|
<DownOutlined />
|
||||||
@ -62,9 +62,7 @@ const BreadcrumbItem: BreadcrumbItemInterface = ({
|
|||||||
return (
|
return (
|
||||||
<span>
|
<span>
|
||||||
{link}
|
{link}
|
||||||
{separator && (
|
{separator && <span className={`${prefixCls}-separator`}>{separator}</span>}
|
||||||
<span className={`${prefixCls}-separator`}>{separator}</span>
|
|
||||||
)}
|
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1674,6 +1674,241 @@ exports[`renders ./components/cascader/demo/multiple.md extend context correctly
|
|||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`renders ./components/cascader/demo/placement.md extend context correctly 1`] = `
|
||||||
|
Array [
|
||||||
|
<div
|
||||||
|
class="ant-radio-group ant-radio-group-outline"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
class="ant-radio-button-wrapper ant-radio-button-wrapper-checked"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button ant-radio-button-checked"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
checked=""
|
||||||
|
class="ant-radio-button-input"
|
||||||
|
type="radio"
|
||||||
|
value="topLeft"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button-inner"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
topLeft
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<label
|
||||||
|
class="ant-radio-button-wrapper"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
class="ant-radio-button-input"
|
||||||
|
type="radio"
|
||||||
|
value="topRight"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button-inner"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
topRight
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<label
|
||||||
|
class="ant-radio-button-wrapper"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
class="ant-radio-button-input"
|
||||||
|
type="radio"
|
||||||
|
value="bottomLeft"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button-inner"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
bottomLeft
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<label
|
||||||
|
class="ant-radio-button-wrapper"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
class="ant-radio-button-input"
|
||||||
|
type="radio"
|
||||||
|
value="bottomRight"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button-inner"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
bottomRight
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</div>,
|
||||||
|
<br />,
|
||||||
|
<br />,
|
||||||
|
<div
|
||||||
|
class="ant-select ant-cascader ant-select-single ant-select-allow-clear ant-select-show-arrow"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="ant-select-selector"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-select-selection-search"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
aria-autocomplete="list"
|
||||||
|
aria-controls="undefined_list"
|
||||||
|
aria-haspopup="listbox"
|
||||||
|
aria-owns="undefined_list"
|
||||||
|
autocomplete="off"
|
||||||
|
class="ant-select-selection-search-input"
|
||||||
|
readonly=""
|
||||||
|
role="combobox"
|
||||||
|
style="opacity:0"
|
||||||
|
type="search"
|
||||||
|
unselectable="on"
|
||||||
|
value=""
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="ant-select-selection-placeholder"
|
||||||
|
>
|
||||||
|
Please select
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="ant-select-dropdown ant-cascader-dropdown"
|
||||||
|
style="opacity:0;pointer-events:none;min-width:auto"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="ant-cascader-menus"
|
||||||
|
>
|
||||||
|
<ul
|
||||||
|
class="ant-cascader-menu"
|
||||||
|
role="menu"
|
||||||
|
>
|
||||||
|
<li
|
||||||
|
aria-checked="false"
|
||||||
|
class="ant-cascader-menu-item ant-cascader-menu-item-expand"
|
||||||
|
data-path-key="zhejiang"
|
||||||
|
role="menuitemcheckbox"
|
||||||
|
title="Zhejiang"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="ant-cascader-menu-item-content"
|
||||||
|
>
|
||||||
|
Zhejiang
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="ant-cascader-menu-item-expand-icon"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
aria-label="right"
|
||||||
|
class="anticon anticon-right"
|
||||||
|
role="img"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
data-icon="right"
|
||||||
|
fill="currentColor"
|
||||||
|
focusable="false"
|
||||||
|
height="1em"
|
||||||
|
viewBox="64 64 896 896"
|
||||||
|
width="1em"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M765.7 486.8L314.9 134.7A7.97 7.97 0 00302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 000-50.4z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li
|
||||||
|
aria-checked="false"
|
||||||
|
class="ant-cascader-menu-item ant-cascader-menu-item-expand"
|
||||||
|
data-path-key="jiangsu"
|
||||||
|
role="menuitemcheckbox"
|
||||||
|
title="Jiangsu"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="ant-cascader-menu-item-content"
|
||||||
|
>
|
||||||
|
Jiangsu
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="ant-cascader-menu-item-expand-icon"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
aria-label="right"
|
||||||
|
class="anticon anticon-right"
|
||||||
|
role="img"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
data-icon="right"
|
||||||
|
fill="currentColor"
|
||||||
|
focusable="false"
|
||||||
|
height="1em"
|
||||||
|
viewBox="64 64 896 896"
|
||||||
|
width="1em"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M765.7 486.8L314.9 134.7A7.97 7.97 0 00302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 000-50.4z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
aria-hidden="true"
|
||||||
|
class="ant-select-arrow"
|
||||||
|
style="user-select:none;-webkit-user-select:none"
|
||||||
|
unselectable="on"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
aria-label="down"
|
||||||
|
class="anticon anticon-down ant-select-suffix"
|
||||||
|
role="img"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
data-icon="down"
|
||||||
|
fill="currentColor"
|
||||||
|
focusable="false"
|
||||||
|
height="1em"
|
||||||
|
viewBox="64 64 896 896"
|
||||||
|
width="1em"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</div>,
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`renders ./components/cascader/demo/search.md extend context correctly 1`] = `
|
exports[`renders ./components/cascader/demo/search.md extend context correctly 1`] = `
|
||||||
<div
|
<div
|
||||||
class="ant-select ant-cascader ant-select-single ant-select-allow-clear ant-select-show-arrow ant-select-show-search"
|
class="ant-select ant-cascader ant-select-single ant-select-allow-clear ant-select-show-arrow ant-select-show-search"
|
||||||
|
@ -658,6 +658,151 @@ exports[`renders ./components/cascader/demo/multiple.md correctly 1`] = `
|
|||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`renders ./components/cascader/demo/placement.md correctly 1`] = `
|
||||||
|
Array [
|
||||||
|
<div
|
||||||
|
class="ant-radio-group ant-radio-group-outline"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
class="ant-radio-button-wrapper ant-radio-button-wrapper-checked"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button ant-radio-button-checked"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
checked=""
|
||||||
|
class="ant-radio-button-input"
|
||||||
|
type="radio"
|
||||||
|
value="topLeft"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button-inner"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
topLeft
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<label
|
||||||
|
class="ant-radio-button-wrapper"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
class="ant-radio-button-input"
|
||||||
|
type="radio"
|
||||||
|
value="topRight"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button-inner"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
topRight
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<label
|
||||||
|
class="ant-radio-button-wrapper"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
class="ant-radio-button-input"
|
||||||
|
type="radio"
|
||||||
|
value="bottomLeft"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button-inner"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
bottomLeft
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<label
|
||||||
|
class="ant-radio-button-wrapper"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
class="ant-radio-button-input"
|
||||||
|
type="radio"
|
||||||
|
value="bottomRight"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button-inner"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
bottomRight
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</div>,
|
||||||
|
<br />,
|
||||||
|
<br />,
|
||||||
|
<div
|
||||||
|
class="ant-select ant-cascader ant-select-single ant-select-allow-clear ant-select-show-arrow"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="ant-select-selector"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-select-selection-search"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
aria-autocomplete="list"
|
||||||
|
aria-controls="undefined_list"
|
||||||
|
aria-haspopup="listbox"
|
||||||
|
aria-owns="undefined_list"
|
||||||
|
autocomplete="off"
|
||||||
|
class="ant-select-selection-search-input"
|
||||||
|
readonly=""
|
||||||
|
role="combobox"
|
||||||
|
style="opacity:0"
|
||||||
|
type="search"
|
||||||
|
unselectable="on"
|
||||||
|
value=""
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="ant-select-selection-placeholder"
|
||||||
|
>
|
||||||
|
Please select
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
aria-hidden="true"
|
||||||
|
class="ant-select-arrow"
|
||||||
|
style="user-select:none;-webkit-user-select:none"
|
||||||
|
unselectable="on"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
aria-label="down"
|
||||||
|
class="anticon anticon-down ant-select-suffix"
|
||||||
|
role="img"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
data-icon="down"
|
||||||
|
fill="currentColor"
|
||||||
|
focusable="false"
|
||||||
|
height="1em"
|
||||||
|
viewBox="64 64 896 896"
|
||||||
|
width="1em"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</div>,
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`renders ./components/cascader/demo/search.md correctly 1`] = `
|
exports[`renders ./components/cascader/demo/search.md correctly 1`] = `
|
||||||
<div
|
<div
|
||||||
class="ant-select ant-cascader ant-select-single ant-select-allow-clear ant-select-show-arrow ant-select-show-search"
|
class="ant-select ant-cascader ant-select-single ant-select-allow-clear ant-select-show-arrow ant-select-show-search"
|
||||||
|
@ -368,6 +368,23 @@ describe('Cascader', () => {
|
|||||||
expect(wrapper.find('.ant-select-selection-placeholder').text()).toEqual(customPlaceholder);
|
expect(wrapper.find('.ant-select-selection-placeholder').text()).toEqual(customPlaceholder);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('placement work correctly', () => {
|
||||||
|
const customerOptions = [
|
||||||
|
{
|
||||||
|
value: 'zhejiang',
|
||||||
|
label: 'Zhejiang',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
value: 'hangzhou',
|
||||||
|
label: 'Hangzhou',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const wrapper = mount(<Cascader options={customerOptions} placement="topRight" />);
|
||||||
|
expect(wrapper.find('Trigger').prop('popupPlacement')).toEqual('topRight');
|
||||||
|
});
|
||||||
|
|
||||||
it('popup correctly with defaultValue RTL', () => {
|
it('popup correctly with defaultValue RTL', () => {
|
||||||
const wrapper = mount(
|
const wrapper = mount(
|
||||||
<ConfigProvider direction="rtl">
|
<ConfigProvider direction="rtl">
|
||||||
@ -484,10 +501,12 @@ describe('Cascader', () => {
|
|||||||
describe('legacy props', () => {
|
describe('legacy props', () => {
|
||||||
it('popupClassName', () => {
|
it('popupClassName', () => {
|
||||||
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||||
const wrapper = mount(<Cascader open popupPlacement="topRight" popupClassName="mock-cls" />);
|
const wrapper = mount(
|
||||||
|
<Cascader open popupPlacement="bottomLeft" popupClassName="mock-cls" />,
|
||||||
|
);
|
||||||
|
|
||||||
expect(wrapper.exists('.mock-cls')).toBeTruthy();
|
expect(wrapper.exists('.mock-cls')).toBeTruthy();
|
||||||
expect(wrapper.find('Trigger').prop('popupPlacement')).toEqual('topRight');
|
expect(wrapper.find('Trigger').prop('popupPlacement')).toEqual('bottomLeft');
|
||||||
|
|
||||||
expect(errorSpy).toHaveBeenCalledWith(
|
expect(errorSpy).toHaveBeenCalledWith(
|
||||||
'Warning: [antd: Cascader] `popupClassName` is deprecated. Please use `dropdownClassName` instead.',
|
'Warning: [antd: Cascader] `popupClassName` is deprecated. Please use `dropdownClassName` instead.',
|
||||||
|
77
components/cascader/demo/placement.md
Normal file
77
components/cascader/demo/placement.md
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
---
|
||||||
|
order: 13
|
||||||
|
title:
|
||||||
|
zh-CN: 弹出位置
|
||||||
|
en-US: Placement
|
||||||
|
---
|
||||||
|
|
||||||
|
## zh-CN
|
||||||
|
|
||||||
|
可以通过 `placement` 手动指定弹出的位置。
|
||||||
|
|
||||||
|
## en-US
|
||||||
|
|
||||||
|
You can manually specify the position of the popup via `placement`.
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
import { Cascader, Radio } from 'antd';
|
||||||
|
|
||||||
|
const options = [
|
||||||
|
{
|
||||||
|
value: 'zhejiang',
|
||||||
|
label: 'Zhejiang',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
value: 'hangzhou',
|
||||||
|
label: 'Hangzhou',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
value: 'xihu',
|
||||||
|
label: 'West Lake',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'jiangsu',
|
||||||
|
label: 'Jiangsu',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
value: 'nanjing',
|
||||||
|
label: 'Nanjing',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
value: 'zhonghuamen',
|
||||||
|
label: 'Zhong Hua Men',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const SetPlacementDemo = () => {
|
||||||
|
const [placement, SetPlacement] = React.useState('topLeft');
|
||||||
|
|
||||||
|
const placementChange = e => {
|
||||||
|
SetPlacement(e.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Radio.Group value={placement} onChange={placementChange}>
|
||||||
|
<Radio.Button value="topLeft">topLeft</Radio.Button>
|
||||||
|
<Radio.Button value="topRight">topRight</Radio.Button>
|
||||||
|
<Radio.Button value="bottomLeft">bottomLeft</Radio.Button>
|
||||||
|
<Radio.Button value="bottomRight">bottomRight</Radio.Button>
|
||||||
|
</Radio.Group>
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<Cascader options={options} placeholder="Please select" placement={placement} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
ReactDOM.render(<SetPlacementDemo />, mountNode);
|
||||||
|
```
|
@ -42,7 +42,7 @@ Cascade selection box.
|
|||||||
| open | Set visible of cascader popup | boolean | - | 4.17.0 |
|
| open | Set visible of cascader popup | boolean | - | 4.17.0 |
|
||||||
| options | The data options of cascade | [Option](#Option)\[] | - | |
|
| options | The data options of cascade | [Option](#Option)\[] | - | |
|
||||||
| placeholder | The input placeholder | string | `Please select` | |
|
| placeholder | The input placeholder | string | `Please select` | |
|
||||||
| placement | Use preset popup align config from builtinPlacements:`bottomLeft` `bottomRight` `topLeft` `topRight` | string | `bottomLeft` | 4.17.0 |
|
| placement | Use preset popup align config from builtinPlacements | `bottomLeft` `bottomRight` `topLeft` `topRight` | `bottomLeft` | 4.17.0 |
|
||||||
| showSearch | Whether show search input in single mode | boolean \| [Object](#showSearch) | false | |
|
| showSearch | Whether show search input in single mode | boolean \| [Object](#showSearch) | false | |
|
||||||
| size | The input size | `large` \| `middle` \| `small` | - | |
|
| size | The input size | `large` \| `middle` \| `small` | - | |
|
||||||
| style | The additional style | CSSProperties | - | |
|
| style | The additional style | CSSProperties | - | |
|
||||||
|
@ -17,7 +17,7 @@ import { ConfigContext } from '../config-provider';
|
|||||||
import type { SizeType } from '../config-provider/SizeContext';
|
import type { SizeType } from '../config-provider/SizeContext';
|
||||||
import SizeContext from '../config-provider/SizeContext';
|
import SizeContext from '../config-provider/SizeContext';
|
||||||
import getIcons from '../select/utils/iconUtil';
|
import getIcons from '../select/utils/iconUtil';
|
||||||
import { getTransitionName } from '../_util/motion';
|
import { getTransitionName, getTransitionDirection, SelectCommonPlacement } from '../_util/motion';
|
||||||
|
|
||||||
// Align the design since we use `rc-select` in root. This help:
|
// Align the design since we use `rc-select` in root. This help:
|
||||||
// - List search content will show all content
|
// - List search content will show all content
|
||||||
@ -85,7 +85,7 @@ export interface CascaderProps<DataNodeType>
|
|||||||
multiple?: boolean;
|
multiple?: boolean;
|
||||||
size?: SizeType;
|
size?: SizeType;
|
||||||
bordered?: boolean;
|
bordered?: boolean;
|
||||||
|
placement?: SelectCommonPlacement;
|
||||||
suffixIcon?: React.ReactNode;
|
suffixIcon?: React.ReactNode;
|
||||||
options?: DataNodeType[];
|
options?: DataNodeType[];
|
||||||
}
|
}
|
||||||
@ -107,6 +107,7 @@ const Cascader = React.forwardRef((props: CascaderProps<any>, ref: React.Ref<Cas
|
|||||||
popupClassName,
|
popupClassName,
|
||||||
dropdownClassName,
|
dropdownClassName,
|
||||||
expandIcon,
|
expandIcon,
|
||||||
|
placement,
|
||||||
showSearch,
|
showSearch,
|
||||||
allowClear = true,
|
allowClear = true,
|
||||||
notFoundContent,
|
notFoundContent,
|
||||||
@ -210,6 +211,16 @@ const Cascader = React.forwardRef((props: CascaderProps<any>, ref: React.Ref<Cas
|
|||||||
prefixCls,
|
prefixCls,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ===================== Placement =====================
|
||||||
|
const getPlacement = () => {
|
||||||
|
if (placement !== undefined) {
|
||||||
|
return placement;
|
||||||
|
}
|
||||||
|
return direction === 'rtl'
|
||||||
|
? ('bottomRight' as SelectCommonPlacement)
|
||||||
|
: ('bottomLeft' as SelectCommonPlacement);
|
||||||
|
};
|
||||||
|
|
||||||
// ==================== Render =====================
|
// ==================== Render =====================
|
||||||
return (
|
return (
|
||||||
<RcCascader
|
<RcCascader
|
||||||
@ -226,6 +237,7 @@ const Cascader = React.forwardRef((props: CascaderProps<any>, ref: React.Ref<Cas
|
|||||||
)}
|
)}
|
||||||
{...(restProps as any)}
|
{...(restProps as any)}
|
||||||
direction={mergedDirection}
|
direction={mergedDirection}
|
||||||
|
placement={getPlacement()}
|
||||||
notFoundContent={mergedNotFoundContent}
|
notFoundContent={mergedNotFoundContent}
|
||||||
allowClear={allowClear}
|
allowClear={allowClear}
|
||||||
showSearch={mergedShowSearch}
|
showSearch={mergedShowSearch}
|
||||||
@ -238,7 +250,11 @@ const Cascader = React.forwardRef((props: CascaderProps<any>, ref: React.Ref<Cas
|
|||||||
dropdownClassName={mergedDropdownClassName}
|
dropdownClassName={mergedDropdownClassName}
|
||||||
dropdownPrefixCls={customizePrefixCls || cascaderPrefixCls}
|
dropdownPrefixCls={customizePrefixCls || cascaderPrefixCls}
|
||||||
choiceTransitionName={getTransitionName(rootPrefixCls, '', choiceTransitionName)}
|
choiceTransitionName={getTransitionName(rootPrefixCls, '', choiceTransitionName)}
|
||||||
transitionName={getTransitionName(rootPrefixCls, 'slide-up', transitionName)}
|
transitionName={getTransitionName(
|
||||||
|
rootPrefixCls,
|
||||||
|
getTransitionDirection(placement),
|
||||||
|
transitionName,
|
||||||
|
)}
|
||||||
getPopupContainer={getPopupContainer || getContextPopupContainer}
|
getPopupContainer={getPopupContainer || getContextPopupContainer}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
/>
|
/>
|
||||||
|
@ -43,7 +43,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/UdS8y8xyZ/Cascader.svg
|
|||||||
| open | 控制浮层显隐 | boolean | - | 4.17.0 |
|
| open | 控制浮层显隐 | boolean | - | 4.17.0 |
|
||||||
| options | 可选项数据源 | [Option](#Option)\[] | - | |
|
| options | 可选项数据源 | [Option](#Option)\[] | - | |
|
||||||
| placeholder | 输入框占位文本 | string | `请选择` | |
|
| placeholder | 输入框占位文本 | string | `请选择` | |
|
||||||
| placement | 浮层预设位置:`bottomLeft` `bottomRight` `topLeft` `topRight` | string | `bottomLeft` | 4.17.0 |
|
| placement | 浮层预设位置 | `bottomLeft` `bottomRight` `topLeft` `topRight` | `bottomLeft` | 4.17.0 |
|
||||||
| showSearch | 在选择框中显示搜索框 | boolean \| [Object](#showSearch) | false | |
|
| showSearch | 在选择框中显示搜索框 | boolean \| [Object](#showSearch) | false | |
|
||||||
| size | 输入框大小 | `large` \| `middle` \| `small` | - | |
|
| size | 输入框大小 | `large` \| `middle` \| `small` | - | |
|
||||||
| style | 自定义样式 | CSSProperties | - | |
|
| style | 自定义样式 | CSSProperties | - | |
|
||||||
|
@ -199,4 +199,36 @@ describe('DatePicker', () => {
|
|||||||
expect(year).toBe(startDate.format('YYYY'));
|
expect(year).toBe(startDate.format('YYYY'));
|
||||||
expect(wrapper.find('.ant-picker-time-panel').length).toBe(1);
|
expect(wrapper.find('.ant-picker-time-panel').length).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('placement api work correctly ', () => {
|
||||||
|
const popupAlignDefault = (points = ['tl', 'bl'], offset = [0, 4]) => ({
|
||||||
|
points,
|
||||||
|
offset,
|
||||||
|
overflow: {
|
||||||
|
adjustX: 1,
|
||||||
|
adjustY: 1,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const wrapper = mount(
|
||||||
|
<DatePicker.RangePicker defaultValue={moment()} placement="bottomLeft" />,
|
||||||
|
);
|
||||||
|
expect(wrapper.find('Trigger').prop('popupAlign')).toEqual(popupAlignDefault(['tl', 'bl']));
|
||||||
|
wrapper.setProps({
|
||||||
|
placement: 'bottomRight',
|
||||||
|
});
|
||||||
|
expect(wrapper.find('Trigger').prop('popupAlign')).toEqual(popupAlignDefault(['tr', 'br']));
|
||||||
|
wrapper.setProps({
|
||||||
|
placement: 'topLeft',
|
||||||
|
});
|
||||||
|
expect(wrapper.find('Trigger').prop('popupAlign')).toEqual(
|
||||||
|
popupAlignDefault(['bl', 'tl'], [0, -4]),
|
||||||
|
);
|
||||||
|
wrapper.setProps({
|
||||||
|
placement: 'topRight',
|
||||||
|
});
|
||||||
|
expect(wrapper.find('Trigger').prop('popupAlign')).toEqual(
|
||||||
|
popupAlignDefault(['br', 'tr'], [0, -4]),
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -2349,6 +2349,216 @@ exports[`renders ./components/date-picker/demo/mode.md correctly 1`] = `
|
|||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`renders ./components/date-picker/demo/placement.md correctly 1`] = `
|
||||||
|
Array [
|
||||||
|
<div
|
||||||
|
class="ant-radio-group ant-radio-group-outline"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
class="ant-radio-button-wrapper ant-radio-button-wrapper-checked"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button ant-radio-button-checked"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
checked=""
|
||||||
|
class="ant-radio-button-input"
|
||||||
|
type="radio"
|
||||||
|
value="topLeft"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button-inner"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
topLeft
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<label
|
||||||
|
class="ant-radio-button-wrapper"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
class="ant-radio-button-input"
|
||||||
|
type="radio"
|
||||||
|
value="topRight"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button-inner"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
topRight
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<label
|
||||||
|
class="ant-radio-button-wrapper"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
class="ant-radio-button-input"
|
||||||
|
type="radio"
|
||||||
|
value="bottomLeft"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button-inner"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
bottomLeft
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<label
|
||||||
|
class="ant-radio-button-wrapper"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
class="ant-radio-button-input"
|
||||||
|
type="radio"
|
||||||
|
value="bottomRight"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button-inner"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
bottomRight
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</div>,
|
||||||
|
<br />,
|
||||||
|
<br />,
|
||||||
|
<div
|
||||||
|
class="ant-picker"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="ant-picker-input"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
autocomplete="off"
|
||||||
|
placeholder="Select date"
|
||||||
|
readonly=""
|
||||||
|
size="12"
|
||||||
|
title=""
|
||||||
|
value=""
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="ant-picker-suffix"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
aria-label="calendar"
|
||||||
|
class="anticon anticon-calendar"
|
||||||
|
role="img"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
data-icon="calendar"
|
||||||
|
fill="currentColor"
|
||||||
|
focusable="false"
|
||||||
|
height="1em"
|
||||||
|
viewBox="64 64 896 896"
|
||||||
|
width="1em"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M880 184H712v-64c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v64H384v-64c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v64H144c-17.7 0-32 14.3-32 32v664c0 17.7 14.3 32 32 32h736c17.7 0 32-14.3 32-32V216c0-17.7-14.3-32-32-32zm-40 656H184V460h656v380zM184 392V256h128v48c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-48h256v48c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-48h128v136H184z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>,
|
||||||
|
<br />,
|
||||||
|
<br />,
|
||||||
|
<div
|
||||||
|
class="ant-picker ant-picker-range"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="ant-picker-input ant-picker-input-active"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
autocomplete="off"
|
||||||
|
placeholder="Start date"
|
||||||
|
readonly=""
|
||||||
|
size="12"
|
||||||
|
value=""
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="ant-picker-range-separator"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
aria-label="to"
|
||||||
|
class="ant-picker-separator"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
aria-label="swap-right"
|
||||||
|
class="anticon anticon-swap-right"
|
||||||
|
role="img"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
data-icon="swap-right"
|
||||||
|
fill="currentColor"
|
||||||
|
focusable="false"
|
||||||
|
height="1em"
|
||||||
|
viewBox="0 0 1024 1024"
|
||||||
|
width="1em"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M873.1 596.2l-164-208A32 32 0 00684 376h-64.8c-6.7 0-10.4 7.7-6.3 13l144.3 183H152c-4.4 0-8 3.6-8 8v60c0 4.4 3.6 8 8 8h695.9c26.8 0 41.7-30.8 25.2-51.8z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="ant-picker-input"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
autocomplete="off"
|
||||||
|
placeholder="End date"
|
||||||
|
readonly=""
|
||||||
|
size="12"
|
||||||
|
value=""
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="ant-picker-active-bar"
|
||||||
|
style="left:0;width:0;position:absolute"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="ant-picker-suffix"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
aria-label="calendar"
|
||||||
|
class="anticon anticon-calendar"
|
||||||
|
role="img"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
data-icon="calendar"
|
||||||
|
fill="currentColor"
|
||||||
|
focusable="false"
|
||||||
|
height="1em"
|
||||||
|
viewBox="64 64 896 896"
|
||||||
|
width="1em"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M880 184H712v-64c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v64H384v-64c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v64H144c-17.7 0-32 14.3-32 32v664c0 17.7 14.3 32 32 32h736c17.7 0 32-14.3 32-32V216c0-17.7-14.3-32-32-32zm-40 656H184V460h656v380zM184 392V256h128v48c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-48h256v48c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-48h128v136H184z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</div>,
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`renders ./components/date-picker/demo/presetted-ranges.md correctly 1`] = `
|
exports[`renders ./components/date-picker/demo/presetted-ranges.md correctly 1`] = `
|
||||||
<div
|
<div
|
||||||
class="ant-space ant-space-vertical"
|
class="ant-space ant-space-vertical"
|
||||||
|
47
components/date-picker/demo/placement.md
Normal file
47
components/date-picker/demo/placement.md
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
---
|
||||||
|
order: 28
|
||||||
|
title:
|
||||||
|
zh-CN: 基本
|
||||||
|
en-US: Basic
|
||||||
|
---
|
||||||
|
|
||||||
|
## zh-CN
|
||||||
|
|
||||||
|
可以通过 `placement` 手动指定弹出的位置。
|
||||||
|
|
||||||
|
## en-US
|
||||||
|
|
||||||
|
You can manually specify the position of the popup via `placement`.
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
import { DatePicker, Space, Radio } from 'antd';
|
||||||
|
|
||||||
|
const { RangePicker } = DatePicker;
|
||||||
|
|
||||||
|
const SetPlacementDemo = () => {
|
||||||
|
const [placement, SetPlacement] = React.useState('topLeft');
|
||||||
|
|
||||||
|
const placementChange = e => {
|
||||||
|
SetPlacement(e.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Radio.Group value={placement} onChange={placementChange}>
|
||||||
|
<Radio.Button value="topLeft">topLeft</Radio.Button>
|
||||||
|
<Radio.Button value="topRight">topRight</Radio.Button>
|
||||||
|
<Radio.Button value="bottomLeft">bottomLeft</Radio.Button>
|
||||||
|
<Radio.Button value="bottomRight">bottomRight</Radio.Button>
|
||||||
|
</Radio.Group>
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<DatePicker placement={placement} />
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<RangePicker placement={placement} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
ReactDOM.render(<SetPlacementDemo />, mountNode);
|
||||||
|
```
|
@ -10,7 +10,7 @@ import enUS from '../locale/en_US';
|
|||||||
import { ConfigContext, ConfigConsumerProps } from '../../config-provider';
|
import { ConfigContext, ConfigConsumerProps } from '../../config-provider';
|
||||||
import SizeContext from '../../config-provider/SizeContext';
|
import SizeContext from '../../config-provider/SizeContext';
|
||||||
import LocaleReceiver from '../../locale-provider/LocaleReceiver';
|
import LocaleReceiver from '../../locale-provider/LocaleReceiver';
|
||||||
import { getRangePlaceholder } from '../util';
|
import { getRangePlaceholder, transPlacement2DropdownAlign } from '../util';
|
||||||
import { RangePickerProps, PickerLocale, getTimeProps, Components } from '.';
|
import { RangePickerProps, PickerLocale, getTimeProps, Components } from '.';
|
||||||
import { PickerComponentClass } from './interface';
|
import { PickerComponentClass } from './interface';
|
||||||
|
|
||||||
@ -43,6 +43,7 @@ export default function generateRangePicker<DateType>(
|
|||||||
prefixCls: customizePrefixCls,
|
prefixCls: customizePrefixCls,
|
||||||
getPopupContainer: customGetPopupContainer,
|
getPopupContainer: customGetPopupContainer,
|
||||||
className,
|
className,
|
||||||
|
placement,
|
||||||
size: customizeSize,
|
size: customizeSize,
|
||||||
bordered = true,
|
bordered = true,
|
||||||
placeholder,
|
placeholder,
|
||||||
@ -73,6 +74,7 @@ export default function generateRangePicker<DateType>(
|
|||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
ref={this.pickerRef}
|
ref={this.pickerRef}
|
||||||
|
dropdownAlign={transPlacement2DropdownAlign(direction, placement)}
|
||||||
placeholder={getRangePlaceholder(picker, locale, placeholder)}
|
placeholder={getRangePlaceholder(picker, locale, placeholder)}
|
||||||
suffixIcon={picker === 'time' ? <ClockCircleOutlined /> : <CalendarOutlined />}
|
suffixIcon={picker === 'time' ? <ClockCircleOutlined /> : <CalendarOutlined />}
|
||||||
clearIcon={<CloseCircleFilled />}
|
clearIcon={<CloseCircleFilled />}
|
||||||
|
@ -7,7 +7,7 @@ import RCPicker from 'rc-picker';
|
|||||||
import { PickerMode } from 'rc-picker/lib/interface';
|
import { PickerMode } from 'rc-picker/lib/interface';
|
||||||
import { GenerateConfig } from 'rc-picker/lib/generate/index';
|
import { GenerateConfig } from 'rc-picker/lib/generate/index';
|
||||||
import enUS from '../locale/en_US';
|
import enUS from '../locale/en_US';
|
||||||
import { getPlaceholder } from '../util';
|
import { getPlaceholder, transPlacement2DropdownAlign } from '../util';
|
||||||
import devWarning from '../../_util/devWarning';
|
import devWarning from '../../_util/devWarning';
|
||||||
import { ConfigContext, ConfigConsumerProps } from '../../config-provider';
|
import { ConfigContext, ConfigConsumerProps } from '../../config-provider';
|
||||||
import LocaleReceiver from '../../locale-provider/LocaleReceiver';
|
import LocaleReceiver from '../../locale-provider/LocaleReceiver';
|
||||||
@ -68,6 +68,7 @@ export default function generatePicker<DateType>(generateConfig: GenerateConfig<
|
|||||||
className,
|
className,
|
||||||
size: customizeSize,
|
size: customizeSize,
|
||||||
bordered = true,
|
bordered = true,
|
||||||
|
placement,
|
||||||
placeholder,
|
placeholder,
|
||||||
...restProps
|
...restProps
|
||||||
} = this.props;
|
} = this.props;
|
||||||
@ -105,6 +106,7 @@ export default function generatePicker<DateType>(generateConfig: GenerateConfig<
|
|||||||
suffixIcon={
|
suffixIcon={
|
||||||
mergedPicker === 'time' ? <ClockCircleOutlined /> : <CalendarOutlined />
|
mergedPicker === 'time' ? <ClockCircleOutlined /> : <CalendarOutlined />
|
||||||
}
|
}
|
||||||
|
dropdownAlign={transPlacement2DropdownAlign(direction, placement)}
|
||||||
clearIcon={<CloseCircleFilled />}
|
clearIcon={<CloseCircleFilled />}
|
||||||
prevIcon={<span className={`${prefixCls}-prev-icon`} />}
|
prevIcon={<span className={`${prefixCls}-prev-icon`} />}
|
||||||
nextIcon={<span className={`${prefixCls}-next-icon`} />}
|
nextIcon={<span className={`${prefixCls}-next-icon`} />}
|
||||||
|
@ -17,6 +17,7 @@ import PickerTag from '../PickerTag';
|
|||||||
import { TimePickerLocale } from '../../time-picker';
|
import { TimePickerLocale } from '../../time-picker';
|
||||||
import generateSinglePicker from './generateSinglePicker';
|
import generateSinglePicker from './generateSinglePicker';
|
||||||
import generateRangePicker from './generateRangePicker';
|
import generateRangePicker from './generateRangePicker';
|
||||||
|
import { tuple } from '../../_util/type';
|
||||||
|
|
||||||
export const Components = { button: PickerButton, rangeItem: PickerTag };
|
export const Components = { button: PickerButton, rangeItem: PickerTag };
|
||||||
|
|
||||||
@ -27,13 +28,18 @@ function toArray<T>(list: T | T[]): T[] {
|
|||||||
return Array.isArray(list) ? list : [list];
|
return Array.isArray(list) ? list : [list];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getTimeProps<DateType>(
|
export function getTimeProps<DateType, DisabledTime>(
|
||||||
props: { format?: string; picker?: PickerMode } & SharedTimeProps<DateType>,
|
props: { format?: string; picker?: PickerMode } & Omit<
|
||||||
|
SharedTimeProps<DateType>,
|
||||||
|
'disabledTime'
|
||||||
|
> & {
|
||||||
|
disabledTime?: DisabledTime;
|
||||||
|
},
|
||||||
) {
|
) {
|
||||||
const { format, picker, showHour, showMinute, showSecond, use12Hours } = props;
|
const { format, picker, showHour, showMinute, showSecond, use12Hours } = props;
|
||||||
|
|
||||||
const firstFormat = toArray(format)[0];
|
const firstFormat = toArray(format)[0];
|
||||||
const showTimeObj: SharedTimeProps<DateType> = { ...props };
|
const showTimeObj = { ...props };
|
||||||
|
|
||||||
if (firstFormat && typeof firstFormat === 'string') {
|
if (firstFormat && typeof firstFormat === 'string') {
|
||||||
if (!firstFormat.includes('s') && showSecond === undefined) {
|
if (!firstFormat.includes('s') && showSecond === undefined) {
|
||||||
@ -64,16 +70,16 @@ export function getTimeProps<DateType>(
|
|||||||
showTime: showTimeObj,
|
showTime: showTimeObj,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
const DataPickerPlacements = tuple('bottomLeft', 'bottomRight', 'topLeft', 'topRight');
|
||||||
|
type DataPickerPlacement = typeof DataPickerPlacements[number];
|
||||||
|
|
||||||
type InjectDefaultProps<Props> = Omit<
|
type InjectDefaultProps<Props> = Omit<
|
||||||
Props,
|
Props,
|
||||||
| 'locale'
|
'locale' | 'generateConfig' | 'hideHeader' | 'components'
|
||||||
| 'generateConfig'
|
|
||||||
| 'hideHeader'
|
|
||||||
| 'components'
|
|
||||||
> & {
|
> & {
|
||||||
locale?: PickerLocale;
|
locale?: PickerLocale;
|
||||||
size?: SizeType;
|
size?: SizeType;
|
||||||
|
placement?: DataPickerPlacement;
|
||||||
bordered?: boolean;
|
bordered?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -69,6 +69,7 @@ The following APIs are shared by DatePicker, RangePicker.
|
|||||||
| panelRender | Customize panel render | (panelNode) => ReactNode | - | 4.5.0 |
|
| panelRender | Customize panel render | (panelNode) => ReactNode | - | 4.5.0 |
|
||||||
| picker | Set picker type | `date` \| `week` \| `month` \| `quarter` \| `year` | `date` | `quarter`: 4.1.0 |
|
| picker | Set picker type | `date` \| `week` \| `month` \| `quarter` \| `year` | `date` | `quarter`: 4.1.0 |
|
||||||
| placeholder | The placeholder of date input | string \| \[string,string] | - | |
|
| placeholder | The placeholder of date input | string \| \[string,string] | - | |
|
||||||
|
| placement | The position where the selection box pops up | `bottomLeft` `bottomRight` `topLeft` `topRight` | bottomLeft | |
|
||||||
| popupStyle | To customize the style of the popup calendar | CSSProperties | {} | |
|
| popupStyle | To customize the style of the popup calendar | CSSProperties | {} | |
|
||||||
| prevIcon | The custom prev icon | ReactNode | - | 4.17.0 |
|
| prevIcon | The custom prev icon | ReactNode | - | 4.17.0 |
|
||||||
| size | To determine the size of the input box, the height of `large` and `small`, are 40px and 24px respectively, while default size is 32px | `large` \| `middle` \| `small` | - | |
|
| size | To determine the size of the input box, the height of `large` and `small`, are 40px and 24px respectively, while default size is 32px | `large` \| `middle` \| `small` | - | |
|
||||||
|
@ -70,6 +70,7 @@ import locale from 'antd/lib/locale/zh_CN';
|
|||||||
| panelRender | 自定义渲染面板 | (panelNode) => ReactNode | - | 4.5.0 |
|
| panelRender | 自定义渲染面板 | (panelNode) => ReactNode | - | 4.5.0 |
|
||||||
| picker | 设置选择器类型 | `date` \| `week` \| `month` \| `quarter` \| `year` | `date` | `quarter`: 4.1.0 |
|
| picker | 设置选择器类型 | `date` \| `week` \| `month` \| `quarter` \| `year` | `date` | `quarter`: 4.1.0 |
|
||||||
| placeholder | 输入框提示文字 | string \| \[string, string] | - | |
|
| placeholder | 输入框提示文字 | string \| \[string, string] | - | |
|
||||||
|
| placement | 选择框弹出的位置 | `bottomLeft` `bottomRight` `topLeft` `topRight` | bottomLeft | |
|
||||||
| popupStyle | 额外的弹出日历样式 | CSSProperties | {} | |
|
| popupStyle | 额外的弹出日历样式 | CSSProperties | {} | |
|
||||||
| prevIcon | 自定义上一个图标 | ReactNode | - | 4.17.0 |
|
| prevIcon | 自定义上一个图标 | ReactNode | - | 4.17.0 |
|
||||||
| size | 输入框大小,`large` 高度为 40px,`small` 为 24px,默认是 32px | `large` \| `middle` \| `small` | - | |
|
| size | 输入框大小,`large` 高度为 40px,`small` 为 24px,默认是 32px | `large` \| `middle` \| `small` | - | |
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
import { PickerMode } from 'rc-picker/lib/interface';
|
import { PickerMode } from 'rc-picker/lib/interface';
|
||||||
|
import { DirectionType } from '../config-provider';
|
||||||
|
import { SelectCommonPlacement } from '../_util/motion';
|
||||||
import { PickerLocale } from './generatePicker';
|
import { PickerLocale } from './generatePicker';
|
||||||
|
|
||||||
export function getPlaceholder(
|
export function getPlaceholder(
|
||||||
@ -51,3 +53,56 @@ export function getRangePlaceholder(
|
|||||||
}
|
}
|
||||||
return locale.lang.rangePlaceholder;
|
return locale.lang.rangePlaceholder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function transPlacement2DropdownAlign(
|
||||||
|
direction: DirectionType,
|
||||||
|
placement?: SelectCommonPlacement,
|
||||||
|
) {
|
||||||
|
const overflow = {
|
||||||
|
adjustX: 1,
|
||||||
|
adjustY: 1,
|
||||||
|
};
|
||||||
|
switch (placement) {
|
||||||
|
case 'bottomLeft': {
|
||||||
|
return {
|
||||||
|
points: ['tl', 'bl'],
|
||||||
|
offset: [0, 4],
|
||||||
|
overflow,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
case 'bottomRight': {
|
||||||
|
return {
|
||||||
|
points: ['tr', 'br'],
|
||||||
|
offset: [0, 4],
|
||||||
|
overflow,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
case 'topLeft': {
|
||||||
|
return {
|
||||||
|
points: ['bl', 'tl'],
|
||||||
|
offset: [0, -4],
|
||||||
|
overflow,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
case 'topRight': {
|
||||||
|
return {
|
||||||
|
points: ['br', 'tr'],
|
||||||
|
offset: [0, -4],
|
||||||
|
overflow,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
return direction === 'rtl'
|
||||||
|
? {
|
||||||
|
points: ['tr', 'br'],
|
||||||
|
offset: [0, 4],
|
||||||
|
overflow,
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
points: ['tl', 'bl'],
|
||||||
|
offset: [0, 4],
|
||||||
|
overflow,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -15,7 +15,7 @@ Array [
|
|||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
<span>
|
<span>
|
||||||
bottomCenter
|
bottom
|
||||||
</span>
|
</span>
|
||||||
</button>,
|
</button>,
|
||||||
<button
|
<button
|
||||||
@ -40,7 +40,61 @@ Array [
|
|||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
<span>
|
<span>
|
||||||
topCenter
|
top
|
||||||
|
</span>
|
||||||
|
</button>,
|
||||||
|
<button
|
||||||
|
class="ant-btn ant-dropdown-trigger"
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
topRight
|
||||||
|
</span>
|
||||||
|
</button>,
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`renders ./components/dropdown/demo/arrow-center.md correctly 1`] = `
|
||||||
|
Array [
|
||||||
|
<button
|
||||||
|
class="ant-btn ant-dropdown-trigger"
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
bottomLeft
|
||||||
|
</span>
|
||||||
|
</button>,
|
||||||
|
<button
|
||||||
|
class="ant-btn ant-dropdown-trigger"
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
bottom
|
||||||
|
</span>
|
||||||
|
</button>,
|
||||||
|
<button
|
||||||
|
class="ant-btn ant-dropdown-trigger"
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
bottomRight
|
||||||
|
</span>
|
||||||
|
</button>,
|
||||||
|
<br />,
|
||||||
|
<button
|
||||||
|
class="ant-btn ant-dropdown-trigger"
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
topLeft
|
||||||
|
</span>
|
||||||
|
</button>,
|
||||||
|
<button
|
||||||
|
class="ant-btn ant-dropdown-trigger"
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
top
|
||||||
</span>
|
</span>
|
||||||
</button>,
|
</button>,
|
||||||
<button
|
<button
|
||||||
@ -658,7 +712,7 @@ exports[`renders ./components/dropdown/demo/placement.md correctly 1`] = `
|
|||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
<span>
|
<span>
|
||||||
bottomCenter
|
bottom
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@ -706,7 +760,7 @@ exports[`renders ./components/dropdown/demo/placement.md correctly 1`] = `
|
|||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
<span>
|
<span>
|
||||||
topCenter
|
top
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -59,4 +59,24 @@ describe('Dropdown', () => {
|
|||||||
await sleep(500);
|
await sleep(500);
|
||||||
expect(wrapper.find(Dropdown).find('#customExpandIcon').length).toBe(1);
|
expect(wrapper.find(Dropdown).find('#customExpandIcon').length).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should warn if use topCenter or bottomCenter', () => {
|
||||||
|
const error = jest.spyOn(console, 'error');
|
||||||
|
mount(
|
||||||
|
<div>
|
||||||
|
<Dropdown overlay="123" placement="bottomCenter">
|
||||||
|
<button type="button">bottomCenter</button>
|
||||||
|
</Dropdown>
|
||||||
|
<Dropdown overlay="123" placement="topCenter">
|
||||||
|
<button type="button">topCenter</button>
|
||||||
|
</Dropdown>
|
||||||
|
</div>,
|
||||||
|
);
|
||||||
|
expect(error).toHaveBeenCalledWith(
|
||||||
|
expect.stringContaining("[antd: Dropdown] You are using 'bottomCenter'"),
|
||||||
|
);
|
||||||
|
expect(error).toHaveBeenCalledWith(
|
||||||
|
expect.stringContaining("[antd: Dropdown] You are using 'topCenter'"),
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
75
components/dropdown/demo/arrow-center.md
Normal file
75
components/dropdown/demo/arrow-center.md
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
---
|
||||||
|
order: 3
|
||||||
|
title:
|
||||||
|
zh-CN: 箭头指向
|
||||||
|
en-US: Arrow pointing at the center
|
||||||
|
---
|
||||||
|
|
||||||
|
## zh-CN
|
||||||
|
|
||||||
|
设置 `arrow` 为 `{ pointAtCenter: true }` 后,箭头将指向目标元素的中心。
|
||||||
|
|
||||||
|
## en-US
|
||||||
|
|
||||||
|
By specifying `arrow` prop with `{ pointAtCenter: true }`, the arrow will point to the center of the target element.
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
import { Menu, Dropdown, Button } from 'antd';
|
||||||
|
|
||||||
|
const menu = (
|
||||||
|
<Menu>
|
||||||
|
<Menu.Item>
|
||||||
|
<a target="_blank" rel="noopener noreferrer" href="https://www.antgroup.com">
|
||||||
|
1st menu item
|
||||||
|
</a>
|
||||||
|
</Menu.Item>
|
||||||
|
<Menu.Item>
|
||||||
|
<a target="_blank" rel="noopener noreferrer" href="https://www.aliyun.com">
|
||||||
|
2nd menu item
|
||||||
|
</a>
|
||||||
|
</Menu.Item>
|
||||||
|
<Menu.Item>
|
||||||
|
<a target="_blank" rel="noopener noreferrer" href="https://www.luohanacademy.com">
|
||||||
|
3rd menu item
|
||||||
|
</a>
|
||||||
|
</Menu.Item>
|
||||||
|
</Menu>
|
||||||
|
);
|
||||||
|
|
||||||
|
ReactDOM.render(
|
||||||
|
<>
|
||||||
|
<Dropdown overlay={menu} placement="bottomLeft" arrow={{ pointAtCenter: true }}>
|
||||||
|
<Button>bottomLeft</Button>
|
||||||
|
</Dropdown>
|
||||||
|
<Dropdown overlay={menu} placement="bottom" arrow={{ pointAtCenter: true }}>
|
||||||
|
<Button>bottom</Button>
|
||||||
|
</Dropdown>
|
||||||
|
<Dropdown overlay={menu} placement="bottomRight" arrow={{ pointAtCenter: true }}>
|
||||||
|
<Button>bottomRight</Button>
|
||||||
|
</Dropdown>
|
||||||
|
<br />
|
||||||
|
<Dropdown overlay={menu} placement="topLeft" arrow={{ pointAtCenter: true }}>
|
||||||
|
<Button>topLeft</Button>
|
||||||
|
</Dropdown>
|
||||||
|
<Dropdown overlay={menu} placement="top" arrow={{ pointAtCenter: true }}>
|
||||||
|
<Button>top</Button>
|
||||||
|
</Dropdown>
|
||||||
|
<Dropdown overlay={menu} placement="topRight" arrow={{ pointAtCenter: true }}>
|
||||||
|
<Button>topRight</Button>
|
||||||
|
</Dropdown>
|
||||||
|
</>,
|
||||||
|
mountNode,
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
```css
|
||||||
|
#components-dropdown-demo-arrow-center .ant-btn {
|
||||||
|
margin-right: 8px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
.ant-row-rtl #components-dropdown-demo-arrow-center .ant-btn {
|
||||||
|
margin-right: 0;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
```
|
@ -41,8 +41,8 @@ ReactDOM.render(
|
|||||||
<Dropdown overlay={menu} placement="bottomLeft" arrow>
|
<Dropdown overlay={menu} placement="bottomLeft" arrow>
|
||||||
<Button>bottomLeft</Button>
|
<Button>bottomLeft</Button>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
<Dropdown overlay={menu} placement="bottomCenter" arrow>
|
<Dropdown overlay={menu} placement="bottom" arrow>
|
||||||
<Button>bottomCenter</Button>
|
<Button>bottom</Button>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
<Dropdown overlay={menu} placement="bottomRight" arrow>
|
<Dropdown overlay={menu} placement="bottomRight" arrow>
|
||||||
<Button>bottomRight</Button>
|
<Button>bottomRight</Button>
|
||||||
@ -51,8 +51,8 @@ ReactDOM.render(
|
|||||||
<Dropdown overlay={menu} placement="topLeft" arrow>
|
<Dropdown overlay={menu} placement="topLeft" arrow>
|
||||||
<Button>topLeft</Button>
|
<Button>topLeft</Button>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
<Dropdown overlay={menu} placement="topCenter" arrow>
|
<Dropdown overlay={menu} placement="top" arrow>
|
||||||
<Button>topCenter</Button>
|
<Button>top</Button>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
<Dropdown overlay={menu} placement="topRight" arrow>
|
<Dropdown overlay={menu} placement="topRight" arrow>
|
||||||
<Button>topRight</Button>
|
<Button>topRight</Button>
|
||||||
|
@ -46,7 +46,7 @@ ReactDOM.render(
|
|||||||
<Dropdown.Button onClick={handleButtonClick} overlay={menu}>
|
<Dropdown.Button onClick={handleButtonClick} overlay={menu}>
|
||||||
Dropdown
|
Dropdown
|
||||||
</Dropdown.Button>
|
</Dropdown.Button>
|
||||||
<Dropdown.Button overlay={menu} placement="bottomCenter" icon={<UserOutlined />}>
|
<Dropdown.Button overlay={menu} placement="bottom" icon={<UserOutlined />}>
|
||||||
Dropdown
|
Dropdown
|
||||||
</Dropdown.Button>
|
</Dropdown.Button>
|
||||||
<Dropdown.Button onClick={handleButtonClick} overlay={menu} disabled>
|
<Dropdown.Button onClick={handleButtonClick} overlay={menu} disabled>
|
||||||
|
@ -42,8 +42,8 @@ ReactDOM.render(
|
|||||||
<Dropdown overlay={menu} placement="bottomLeft">
|
<Dropdown overlay={menu} placement="bottomLeft">
|
||||||
<Button>bottomLeft</Button>
|
<Button>bottomLeft</Button>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
<Dropdown overlay={menu} placement="bottomCenter">
|
<Dropdown overlay={menu} placement="bottom">
|
||||||
<Button>bottomCenter</Button>
|
<Button>bottom</Button>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
<Dropdown overlay={menu} placement="bottomRight">
|
<Dropdown overlay={menu} placement="bottomRight">
|
||||||
<Button>bottomRight</Button>
|
<Button>bottomRight</Button>
|
||||||
@ -53,8 +53,8 @@ ReactDOM.render(
|
|||||||
<Dropdown overlay={menu} placement="topLeft">
|
<Dropdown overlay={menu} placement="topLeft">
|
||||||
<Button>topLeft</Button>
|
<Button>topLeft</Button>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
<Dropdown overlay={menu} placement="topCenter">
|
<Dropdown overlay={menu} placement="top">
|
||||||
<Button>topCenter</Button>
|
<Button>top</Button>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
<Dropdown overlay={menu} placement="topRight">
|
<Dropdown overlay={menu} placement="topRight">
|
||||||
<Button>topRight</Button>
|
<Button>topRight</Button>
|
||||||
|
@ -7,6 +7,7 @@ import { ConfigContext } from '../config-provider';
|
|||||||
import devWarning from '../_util/devWarning';
|
import devWarning from '../_util/devWarning';
|
||||||
import { tuple } from '../_util/type';
|
import { tuple } from '../_util/type';
|
||||||
import { cloneElement } from '../_util/reactNode';
|
import { cloneElement } from '../_util/reactNode';
|
||||||
|
import getPlacements from '../_util/placements';
|
||||||
|
|
||||||
const Placements = tuple(
|
const Placements = tuple(
|
||||||
'topLeft',
|
'topLeft',
|
||||||
@ -15,6 +16,8 @@ const Placements = tuple(
|
|||||||
'bottomLeft',
|
'bottomLeft',
|
||||||
'bottomCenter',
|
'bottomCenter',
|
||||||
'bottomRight',
|
'bottomRight',
|
||||||
|
'top',
|
||||||
|
'bottom',
|
||||||
);
|
);
|
||||||
|
|
||||||
type Placement = typeof Placements[number];
|
type Placement = typeof Placements[number];
|
||||||
@ -34,8 +37,12 @@ type Align = {
|
|||||||
useCssTransform?: boolean;
|
useCssTransform?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type DropdownArrowOptions = {
|
||||||
|
pointAtCenter?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
export interface DropDownProps {
|
export interface DropDownProps {
|
||||||
arrow?: boolean;
|
arrow?: boolean | DropdownArrowOptions;
|
||||||
trigger?: ('click' | 'hover' | 'contextMenu')[];
|
trigger?: ('click' | 'hover' | 'contextMenu')[];
|
||||||
overlay: React.ReactElement | OverlayFunc;
|
overlay: React.ReactElement | OverlayFunc;
|
||||||
onVisibleChange?: (visible: boolean) => void;
|
onVisibleChange?: (visible: boolean) => void;
|
||||||
@ -129,10 +136,21 @@ const Dropdown: DropdownInterface = props => {
|
|||||||
|
|
||||||
const getPlacement = () => {
|
const getPlacement = () => {
|
||||||
const { placement } = props;
|
const { placement } = props;
|
||||||
if (placement !== undefined) {
|
if (!placement) {
|
||||||
return placement;
|
return direction === 'rtl' ? ('bottomRight' as Placement) : ('bottomLeft' as Placement);
|
||||||
}
|
}
|
||||||
return direction === 'rtl' ? ('bottomRight' as Placement) : ('bottomLeft' as Placement);
|
|
||||||
|
if (placement.includes('Center')) {
|
||||||
|
const newPlacement = placement.slice(0, placement.indexOf('Center'));
|
||||||
|
devWarning(
|
||||||
|
!placement.includes('Center'),
|
||||||
|
'Dropdown',
|
||||||
|
`You are using '${placement}' placement in Dropdown, which is deprecated. Try to use '${newPlacement}' instead.`,
|
||||||
|
);
|
||||||
|
return newPlacement;
|
||||||
|
}
|
||||||
|
|
||||||
|
return placement;
|
||||||
};
|
};
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@ -169,11 +187,16 @@ const Dropdown: DropdownInterface = props => {
|
|||||||
alignPoint = true;
|
alignPoint = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const builtinPlacements = getPlacements({
|
||||||
|
arrowPointAtCenter: typeof arrow === 'object' && arrow.pointAtCenter,
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RcDropdown
|
<RcDropdown
|
||||||
arrow={arrow}
|
|
||||||
alignPoint={alignPoint}
|
alignPoint={alignPoint}
|
||||||
{...props}
|
{...props}
|
||||||
|
builtinPlacements={builtinPlacements}
|
||||||
|
arrow={!!arrow}
|
||||||
overlayClassName={overlayClassNameCustomized}
|
overlayClassName={overlayClassNameCustomized}
|
||||||
prefixCls={prefixCls}
|
prefixCls={prefixCls}
|
||||||
getPopupContainer={getPopupContainer || getContextPopupContainer}
|
getPopupContainer={getPopupContainer || getContextPopupContainer}
|
||||||
|
@ -17,14 +17,14 @@ When there are more than a few options to choose from, you can wrap them in a `D
|
|||||||
|
|
||||||
| Property | Description | Type | Default | Version |
|
| Property | Description | Type | Default | Version |
|
||||||
| --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- |
|
||||||
| arrow | Whether the dropdown arrow should be visible | boolean | false | |
|
| arrow | Whether the dropdown arrow should be visible | boolean \| { pointAtCenter: boolean } | false | |
|
||||||
| disabled | Whether the dropdown menu is disabled | boolean | - | |
|
| disabled | Whether the dropdown menu is disabled | boolean | - | |
|
||||||
| destroyPopupOnHide | Whether destroy dropdown when hidden | boolean | false | |
|
| destroyPopupOnHide | Whether destroy dropdown when hidden | boolean | false | |
|
||||||
| getPopupContainer | To set the container of the dropdown menu. The default is to create a div element in body, but you can reset it to the scrolling area and make a relative reposition. [Example on CodePen](https://codepen.io/afc163/pen/zEjNOy?editors=0010) | (triggerNode: HTMLElement) => HTMLElement | () => document.body | |
|
| getPopupContainer | To set the container of the dropdown menu. The default is to create a div element in body, but you can reset it to the scrolling area and make a relative reposition. [Example on CodePen](https://codepen.io/afc163/pen/zEjNOy?editors=0010) | (triggerNode: HTMLElement) => HTMLElement | () => document.body | |
|
||||||
| overlay | The dropdown menu | [Menu](/components/menu) \| () => Menu | - | |
|
| overlay | The dropdown menu | [Menu](/components/menu) \| () => Menu | - | |
|
||||||
| overlayClassName | The class name of the dropdown root element | string | - | |
|
| overlayClassName | The class name of the dropdown root element | string | - | |
|
||||||
| overlayStyle | The style of the dropdown root element | CSSProperties | - | |
|
| overlayStyle | The style of the dropdown root element | CSSProperties | - | |
|
||||||
| placement | Placement of popup menu: `bottomLeft`, `bottomCenter`, `bottomRight`, `topLeft`, `topCenter` or `topRight` | string | `bottomLeft` | |
|
| 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`] | |
|
| 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 | - | |
|
| 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 | - | |
|
| onVisibleChange | Called when the visible state is changed. Not trigger when hidden by click item | (visible: boolean) => void | - | |
|
||||||
@ -44,7 +44,7 @@ You should use [Menu](/components/menu/) as `overlay`. The menu items and divide
|
|||||||
| disabled | Whether the dropdown menu is disabled | boolean | - | |
|
| disabled | Whether the dropdown menu is disabled | boolean | - | |
|
||||||
| icon | Icon (appears on the right) | ReactNode | - | |
|
| icon | Icon (appears on the right) | ReactNode | - | |
|
||||||
| overlay | The dropdown menu | [Menu](/components/menu) | - | |
|
| overlay | The dropdown menu | [Menu](/components/menu) | - | |
|
||||||
| placement | Placement of popup menu: `bottomLeft` `bottomCenter` `bottomRight` `topLeft` `topCenter` `topRight` | string | `bottomLeft` | |
|
| placement | Placement of popup menu: `bottom` `bottomLeft` `bottomRight` `top` `topLeft` `topRight` | string | `bottomLeft` | |
|
||||||
| size | Size of the button, the same as [Button](/components/button/#API) | string | `default` | |
|
| 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`] | |
|
| 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` | |
|
| type | Type of the button, the same as [Button](/components/button/#API) | string | `default` | |
|
||||||
|
@ -21,14 +21,14 @@ cover: https://gw.alipayobjects.com/zos/alicdn/eedWN59yJ/Dropdown.svg
|
|||||||
|
|
||||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||||
| --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- |
|
||||||
| arrow | 下拉框箭头是否显示 | boolean | false | |
|
| arrow | 下拉框箭头是否显示 | boolean \| { pointAtCenter: boolean } | false | |
|
||||||
| disabled | 菜单是否禁用 | boolean | - | |
|
| disabled | 菜单是否禁用 | boolean | - | |
|
||||||
| destroyPopupOnHide | 关闭后是否销毁 Dropdown | boolean | false | |
|
| destroyPopupOnHide | 关闭后是否销毁 Dropdown | boolean | false | |
|
||||||
| getPopupContainer | 菜单渲染父节点。默认渲染到 body 上,如果你遇到菜单滚动定位问题,试试修改为滚动的区域,并相对其定位。[示例](https://codepen.io/afc163/pen/zEjNOy?editors=0010) | (triggerNode: HTMLElement) => HTMLElement | () => document.body | |
|
| getPopupContainer | 菜单渲染父节点。默认渲染到 body 上,如果你遇到菜单滚动定位问题,试试修改为滚动的区域,并相对其定位。[示例](https://codepen.io/afc163/pen/zEjNOy?editors=0010) | (triggerNode: HTMLElement) => HTMLElement | () => document.body | |
|
||||||
| overlay | 菜单 | [Menu](/components/menu) \| () => Menu | - | |
|
| overlay | 菜单 | [Menu](/components/menu) \| () => Menu | - | |
|
||||||
| overlayClassName | 下拉根元素的类名称 | string | - | |
|
| overlayClassName | 下拉根元素的类名称 | string | - | |
|
||||||
| overlayStyle | 下拉根元素的样式 | CSSProperties | - | |
|
| overlayStyle | 下拉根元素的样式 | CSSProperties | - | |
|
||||||
| placement | 菜单弹出位置:`bottomLeft` `bottomCenter` `bottomRight` `topLeft` `topCenter` `topRight` | string | `bottomLeft` | |
|
| placement | 菜单弹出位置:`bottom` `bottomLeft` `bottomRight` `top` `topLeft` `topRight` | string | `bottomLeft` | |
|
||||||
| trigger | 触发下拉的行为, 移动端不支持 hover | Array<`click`\|`hover`\|`contextMenu`> | \[`hover`] | |
|
| trigger | 触发下拉的行为, 移动端不支持 hover | Array<`click`\|`hover`\|`contextMenu`> | \[`hover`] | |
|
||||||
| visible | 菜单是否显示 | boolean | - | |
|
| visible | 菜单是否显示 | boolean | - | |
|
||||||
| onVisibleChange | 菜单显示状态改变时调用,参数为 `visible`。点击菜单按钮导致的消失不会触发 | (visible: boolean) => void | - | |
|
| onVisibleChange | 菜单显示状态改变时调用,参数为 `visible`。点击菜单按钮导致的消失不会触发 | (visible: boolean) => void | - | |
|
||||||
@ -48,7 +48,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/eedWN59yJ/Dropdown.svg
|
|||||||
| disabled | 菜单是否禁用 | boolean | - | |
|
| disabled | 菜单是否禁用 | boolean | - | |
|
||||||
| icon | 右侧的 icon | ReactNode | - | |
|
| icon | 右侧的 icon | ReactNode | - | |
|
||||||
| overlay | 菜单 | [Menu](/components/menu/) | - | |
|
| overlay | 菜单 | [Menu](/components/menu/) | - | |
|
||||||
| placement | 菜单弹出位置:`bottomLeft` `bottomCenter` `bottomRight` `topLeft` `topCenter` `topRight` | string | `bottomLeft` | |
|
| placement | 菜单弹出位置:`bottom` `bottomLeft` `bottomRight` `top` `topLeft` `topRight` | string | `bottomLeft` | |
|
||||||
| size | 按钮大小,和 [Button](/components/button/#API) 一致 | string | `default` | |
|
| size | 按钮大小,和 [Button](/components/button/#API) 一致 | string | `default` | |
|
||||||
| trigger | 触发下拉的行为 | Array<`click`\|`hover`\|`contextMenu`> | \[`hover`] | |
|
| trigger | 触发下拉的行为 | Array<`click`\|`hover`\|`contextMenu`> | \[`hover`] | |
|
||||||
| type | 按钮类型,和 [Button](/components/button/#API) 一致 | string | `default` | |
|
| type | 按钮类型,和 [Button](/components/button/#API) 一致 | string | `default` | |
|
||||||
|
@ -49,14 +49,14 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Offset the popover to account for the dropdown arrow
|
// Offset the popover to account for the dropdown arrow
|
||||||
&-show-arrow&-placement-topCenter,
|
|
||||||
&-show-arrow&-placement-topLeft,
|
&-show-arrow&-placement-topLeft,
|
||||||
|
&-show-arrow&-placement-top,
|
||||||
&-show-arrow&-placement-topRight {
|
&-show-arrow&-placement-topRight {
|
||||||
padding-bottom: @popover-distance;
|
padding-bottom: @popover-distance;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-show-arrow&-placement-bottomCenter,
|
|
||||||
&-show-arrow&-placement-bottomLeft,
|
&-show-arrow&-placement-bottomLeft,
|
||||||
|
&-show-arrow&-placement-bottom,
|
||||||
&-show-arrow&-placement-bottomRight {
|
&-show-arrow&-placement-bottomRight {
|
||||||
padding-top: @popover-distance;
|
padding-top: @popover-distance;
|
||||||
}
|
}
|
||||||
@ -76,7 +76,7 @@
|
|||||||
transform: rotate(45deg);
|
transform: rotate(45deg);
|
||||||
}
|
}
|
||||||
|
|
||||||
&-placement-topCenter > &-arrow,
|
&-placement-top > &-arrow,
|
||||||
&-placement-topLeft > &-arrow,
|
&-placement-topLeft > &-arrow,
|
||||||
&-placement-topRight > &-arrow {
|
&-placement-topRight > &-arrow {
|
||||||
bottom: @popover-distance - @popover-arrow-width + 2.2px;
|
bottom: @popover-distance - @popover-arrow-width + 2.2px;
|
||||||
@ -84,7 +84,7 @@
|
|||||||
box-shadow: 3px 3px 7px fade(@black, 7%);
|
box-shadow: 3px 3px 7px fade(@black, 7%);
|
||||||
}
|
}
|
||||||
|
|
||||||
&-placement-topCenter > &-arrow {
|
&-placement-top > &-arrow {
|
||||||
left: 50%;
|
left: 50%;
|
||||||
transform: translateX(-50%) rotate(45deg);
|
transform: translateX(-50%) rotate(45deg);
|
||||||
}
|
}
|
||||||
@ -97,7 +97,7 @@
|
|||||||
right: 16px;
|
right: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-placement-bottomCenter > &-arrow,
|
&-placement-bottom > &-arrow,
|
||||||
&-placement-bottomLeft > &-arrow,
|
&-placement-bottomLeft > &-arrow,
|
||||||
&-placement-bottomRight > &-arrow {
|
&-placement-bottomRight > &-arrow {
|
||||||
top: @popover-distance - @popover-arrow-width + 2px;
|
top: @popover-distance - @popover-arrow-width + 2px;
|
||||||
@ -105,7 +105,7 @@
|
|||||||
box-shadow: -2px -2px 5px fade(@black, 6%);
|
box-shadow: -2px -2px 5px fade(@black, 6%);
|
||||||
}
|
}
|
||||||
|
|
||||||
&-placement-bottomCenter > &-arrow {
|
&-placement-bottom > &-arrow {
|
||||||
left: 50%;
|
left: 50%;
|
||||||
transform: translateX(-50%) rotate(45deg);
|
transform: translateX(-50%) rotate(45deg);
|
||||||
}
|
}
|
||||||
@ -300,8 +300,8 @@
|
|||||||
|
|
||||||
&.@{ant-prefix}-slide-down-enter.@{ant-prefix}-slide-down-enter-active&-placement-bottomLeft,
|
&.@{ant-prefix}-slide-down-enter.@{ant-prefix}-slide-down-enter-active&-placement-bottomLeft,
|
||||||
&.@{ant-prefix}-slide-down-appear.@{ant-prefix}-slide-down-appear-active&-placement-bottomLeft,
|
&.@{ant-prefix}-slide-down-appear.@{ant-prefix}-slide-down-appear-active&-placement-bottomLeft,
|
||||||
&.@{ant-prefix}-slide-down-enter.@{ant-prefix}-slide-down-enter-active&-placement-bottomCenter,
|
&.@{ant-prefix}-slide-down-enter.@{ant-prefix}-slide-down-enter-active&-placement-bottom,
|
||||||
&.@{ant-prefix}-slide-down-appear.@{ant-prefix}-slide-down-appear-active&-placement-bottomCenter,
|
&.@{ant-prefix}-slide-down-appear.@{ant-prefix}-slide-down-appear-active&-placement-bottom,
|
||||||
&.@{ant-prefix}-slide-down-enter.@{ant-prefix}-slide-down-enter-active&-placement-bottomRight,
|
&.@{ant-prefix}-slide-down-enter.@{ant-prefix}-slide-down-enter-active&-placement-bottomRight,
|
||||||
&.@{ant-prefix}-slide-down-appear.@{ant-prefix}-slide-down-appear-active&-placement-bottomRight {
|
&.@{ant-prefix}-slide-down-appear.@{ant-prefix}-slide-down-appear-active&-placement-bottomRight {
|
||||||
animation-name: antSlideUpIn;
|
animation-name: antSlideUpIn;
|
||||||
@ -309,21 +309,21 @@
|
|||||||
|
|
||||||
&.@{ant-prefix}-slide-up-enter.@{ant-prefix}-slide-up-enter-active&-placement-topLeft,
|
&.@{ant-prefix}-slide-up-enter.@{ant-prefix}-slide-up-enter-active&-placement-topLeft,
|
||||||
&.@{ant-prefix}-slide-up-appear.@{ant-prefix}-slide-up-appear-active&-placement-topLeft,
|
&.@{ant-prefix}-slide-up-appear.@{ant-prefix}-slide-up-appear-active&-placement-topLeft,
|
||||||
&.@{ant-prefix}-slide-up-enter.@{ant-prefix}-slide-up-enter-active&-placement-topCenter,
|
&.@{ant-prefix}-slide-up-enter.@{ant-prefix}-slide-up-enter-active&-placement-top,
|
||||||
&.@{ant-prefix}-slide-up-appear.@{ant-prefix}-slide-up-appear-active&-placement-topCenter,
|
&.@{ant-prefix}-slide-up-appear.@{ant-prefix}-slide-up-appear-active&-placement-top,
|
||||||
&.@{ant-prefix}-slide-up-enter.@{ant-prefix}-slide-up-enter-active&-placement-topRight,
|
&.@{ant-prefix}-slide-up-enter.@{ant-prefix}-slide-up-enter-active&-placement-topRight,
|
||||||
&.@{ant-prefix}-slide-up-appear.@{ant-prefix}-slide-up-appear-active&-placement-topRight {
|
&.@{ant-prefix}-slide-up-appear.@{ant-prefix}-slide-up-appear-active&-placement-topRight {
|
||||||
animation-name: antSlideDownIn;
|
animation-name: antSlideDownIn;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.@{ant-prefix}-slide-down-leave.@{ant-prefix}-slide-down-leave-active&-placement-bottomLeft,
|
&.@{ant-prefix}-slide-down-leave.@{ant-prefix}-slide-down-leave-active&-placement-bottomLeft,
|
||||||
&.@{ant-prefix}-slide-down-leave.@{ant-prefix}-slide-down-leave-active&-placement-bottomCenter,
|
&.@{ant-prefix}-slide-down-leave.@{ant-prefix}-slide-down-leave-active&-placement-bottom,
|
||||||
&.@{ant-prefix}-slide-down-leave.@{ant-prefix}-slide-down-leave-active&-placement-bottomRight {
|
&.@{ant-prefix}-slide-down-leave.@{ant-prefix}-slide-down-leave-active&-placement-bottomRight {
|
||||||
animation-name: antSlideUpOut;
|
animation-name: antSlideUpOut;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.@{ant-prefix}-slide-up-leave.@{ant-prefix}-slide-up-leave-active&-placement-topLeft,
|
&.@{ant-prefix}-slide-up-leave.@{ant-prefix}-slide-up-leave-active&-placement-topLeft,
|
||||||
&.@{ant-prefix}-slide-up-leave.@{ant-prefix}-slide-up-leave-active&-placement-topCenter,
|
&.@{ant-prefix}-slide-up-leave.@{ant-prefix}-slide-up-leave-active&-placement-top,
|
||||||
&.@{ant-prefix}-slide-up-leave.@{ant-prefix}-slide-up-leave-active&-placement-topRight {
|
&.@{ant-prefix}-slide-up-leave.@{ant-prefix}-slide-up-leave-active&-placement-topRight {
|
||||||
animation-name: antSlideDownOut;
|
animation-name: antSlideDownOut;
|
||||||
}
|
}
|
||||||
|
@ -189,6 +189,77 @@ Array [
|
|||||||
|
|
||||||
exports[`renders ./components/notification/demo/placement.md extend context correctly 1`] = `
|
exports[`renders ./components/notification/demo/placement.md extend context correctly 1`] = `
|
||||||
<div>
|
<div>
|
||||||
|
<div
|
||||||
|
class="ant-space ant-space-horizontal ant-space-align-center"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="ant-space-item"
|
||||||
|
style="margin-right:8px"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
class="ant-btn ant-btn-primary"
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
aria-label="border-top"
|
||||||
|
class="anticon anticon-border-top"
|
||||||
|
role="img"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
data-icon="border-top"
|
||||||
|
fill="currentColor"
|
||||||
|
focusable="false"
|
||||||
|
height="1em"
|
||||||
|
viewBox="64 64 896 896"
|
||||||
|
width="1em"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M872 144H152c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h720c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM208 310h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 498h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0-332h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 166h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm166-166h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 332h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm332 0h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0-332h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm166 0h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm-332 0h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm332 332h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm-332 0h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm332-498h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm-332 0h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm332 332h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm-332 0h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
top
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="ant-space-item"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
class="ant-btn ant-btn-primary"
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
aria-label="border-bottom"
|
||||||
|
class="anticon anticon-border-bottom"
|
||||||
|
role="img"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
data-icon="border-bottom"
|
||||||
|
fill="currentColor"
|
||||||
|
focusable="false"
|
||||||
|
height="1em"
|
||||||
|
viewBox="64 64 896 896"
|
||||||
|
width="1em"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M872 808H152c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h720c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm-720-94h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm0-498h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm0 332h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm0-166h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm166 166h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm0-332h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm332 0h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm0 332h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm222-72h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm-388 72h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm388-404h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm-388 72h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm388 426h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm-388 72h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm388-404h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm-388 72h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
bottom
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="ant-divider ant-divider-horizontal"
|
||||||
|
role="separator"
|
||||||
|
/>
|
||||||
<div
|
<div
|
||||||
class="ant-space ant-space-horizontal ant-space-align-center"
|
class="ant-space ant-space-horizontal ant-space-align-center"
|
||||||
>
|
>
|
||||||
|
@ -189,6 +189,77 @@ Array [
|
|||||||
|
|
||||||
exports[`renders ./components/notification/demo/placement.md correctly 1`] = `
|
exports[`renders ./components/notification/demo/placement.md correctly 1`] = `
|
||||||
<div>
|
<div>
|
||||||
|
<div
|
||||||
|
class="ant-space ant-space-horizontal ant-space-align-center"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="ant-space-item"
|
||||||
|
style="margin-right:8px"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
class="ant-btn ant-btn-primary"
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
aria-label="border-top"
|
||||||
|
class="anticon anticon-border-top"
|
||||||
|
role="img"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
data-icon="border-top"
|
||||||
|
fill="currentColor"
|
||||||
|
focusable="false"
|
||||||
|
height="1em"
|
||||||
|
viewBox="64 64 896 896"
|
||||||
|
width="1em"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M872 144H152c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h720c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM208 310h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 498h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0-332h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 166h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm166-166h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 332h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm332 0h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0-332h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm166 0h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm-332 0h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm332 332h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm-332 0h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm332-498h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm-332 0h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm332 332h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm-332 0h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
top
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="ant-space-item"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
class="ant-btn ant-btn-primary"
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
aria-label="border-bottom"
|
||||||
|
class="anticon anticon-border-bottom"
|
||||||
|
role="img"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
data-icon="border-bottom"
|
||||||
|
fill="currentColor"
|
||||||
|
focusable="false"
|
||||||
|
height="1em"
|
||||||
|
viewBox="64 64 896 896"
|
||||||
|
width="1em"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M872 808H152c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h720c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm-720-94h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm0-498h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm0 332h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm0-166h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm166 166h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm0-332h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm332 0h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm0 332h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm222-72h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm-388 72h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm388-404h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm-388 72h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm388 426h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm-388 72h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm388-404h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm-388 72h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
bottom
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="ant-divider ant-divider-horizontal"
|
||||||
|
role="separator"
|
||||||
|
/>
|
||||||
<div
|
<div
|
||||||
class="ant-space ant-space-horizontal ant-space-align-center"
|
class="ant-space ant-space-horizontal ant-space-align-center"
|
||||||
>
|
>
|
||||||
|
@ -34,6 +34,22 @@ describe('Notification.placement', () => {
|
|||||||
const defaultBottom = '24px';
|
const defaultBottom = '24px';
|
||||||
let style;
|
let style;
|
||||||
|
|
||||||
|
// top
|
||||||
|
open({
|
||||||
|
placement: 'top',
|
||||||
|
top: 50,
|
||||||
|
});
|
||||||
|
style = getStyle($$('.ant-notification-top')[0]);
|
||||||
|
expect(style.top).toBe('50px');
|
||||||
|
expect(style.left).toBe('0px');
|
||||||
|
expect(style.right).toBe('0px');
|
||||||
|
expect(style.bottom).toBe('');
|
||||||
|
|
||||||
|
open({
|
||||||
|
placement: 'top',
|
||||||
|
});
|
||||||
|
expect($$('.ant-notification-top').length).toBe(1);
|
||||||
|
|
||||||
// topLeft
|
// topLeft
|
||||||
open({
|
open({
|
||||||
placement: 'topLeft',
|
placement: 'topLeft',
|
||||||
@ -63,6 +79,22 @@ describe('Notification.placement', () => {
|
|||||||
});
|
});
|
||||||
expect($$('.ant-notification-topRight').length).toBe(1);
|
expect($$('.ant-notification-topRight').length).toBe(1);
|
||||||
|
|
||||||
|
// bottom
|
||||||
|
open({
|
||||||
|
placement: 'bottom',
|
||||||
|
bottom: 100,
|
||||||
|
});
|
||||||
|
style = getStyle($$('.ant-notification-bottom')[0]);
|
||||||
|
expect(style.top).toBe('');
|
||||||
|
expect(style.left).toBe('0px');
|
||||||
|
expect(style.right).toBe('0px');
|
||||||
|
expect(style.bottom).toBe('100px');
|
||||||
|
|
||||||
|
open({
|
||||||
|
placement: 'bottom',
|
||||||
|
});
|
||||||
|
expect($$('.ant-notification-bottom').length).toBe(1);
|
||||||
|
|
||||||
// bottomRight
|
// bottomRight
|
||||||
open({
|
open({
|
||||||
placement: 'bottomRight',
|
placement: 'bottomRight',
|
||||||
|
@ -20,6 +20,8 @@ import {
|
|||||||
RadiusUprightOutlined,
|
RadiusUprightOutlined,
|
||||||
RadiusBottomleftOutlined,
|
RadiusBottomleftOutlined,
|
||||||
RadiusBottomrightOutlined,
|
RadiusBottomrightOutlined,
|
||||||
|
BorderTopOutlined,
|
||||||
|
BorderBottomOutlined,
|
||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
|
|
||||||
const openNotification = placement => {
|
const openNotification = placement => {
|
||||||
@ -33,6 +35,17 @@ const openNotification = placement => {
|
|||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<div>
|
<div>
|
||||||
|
<Space>
|
||||||
|
<Button type="primary" onClick={() => openNotification('top')}>
|
||||||
|
<BorderTopOutlined />
|
||||||
|
top
|
||||||
|
</Button>
|
||||||
|
<Button type="primary" onClick={() => openNotification('bottom')}>
|
||||||
|
<BorderBottomOutlined />
|
||||||
|
bottom
|
||||||
|
</Button>
|
||||||
|
</Space>
|
||||||
|
<Divider />
|
||||||
<Space>
|
<Space>
|
||||||
<Button type="primary" onClick={() => openNotification('topLeft')}>
|
<Button type="primary" onClick={() => openNotification('topLeft')}>
|
||||||
<RadiusUpleftOutlined />
|
<RadiusUpleftOutlined />
|
||||||
|
@ -10,7 +10,13 @@ import InfoCircleOutlined from '@ant-design/icons/InfoCircleOutlined';
|
|||||||
import createUseNotification from './hooks/useNotification';
|
import createUseNotification from './hooks/useNotification';
|
||||||
import ConfigProvider, { globalConfig } from '../config-provider';
|
import ConfigProvider, { globalConfig } from '../config-provider';
|
||||||
|
|
||||||
export type NotificationPlacement = 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight';
|
export type NotificationPlacement =
|
||||||
|
| 'top'
|
||||||
|
| 'topLeft'
|
||||||
|
| 'topRight'
|
||||||
|
| 'bottom'
|
||||||
|
| 'bottomLeft'
|
||||||
|
| 'bottomRight';
|
||||||
|
|
||||||
export type IconType = 'success' | 'info' | 'error' | 'warning';
|
export type IconType = 'success' | 'info' | 'error' | 'warning';
|
||||||
|
|
||||||
@ -79,6 +85,14 @@ function getPlacementStyle(
|
|||||||
) {
|
) {
|
||||||
let style;
|
let style;
|
||||||
switch (placement) {
|
switch (placement) {
|
||||||
|
case 'top':
|
||||||
|
style = {
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
top,
|
||||||
|
bottom: 'auto',
|
||||||
|
};
|
||||||
|
break;
|
||||||
case 'topLeft':
|
case 'topLeft':
|
||||||
style = {
|
style = {
|
||||||
left: 0,
|
left: 0,
|
||||||
@ -93,6 +107,14 @@ function getPlacementStyle(
|
|||||||
bottom: 'auto',
|
bottom: 'auto',
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
|
case 'bottom':
|
||||||
|
style = {
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
top: 'auto',
|
||||||
|
bottom,
|
||||||
|
};
|
||||||
|
break;
|
||||||
case 'bottomLeft':
|
case 'bottomLeft':
|
||||||
style = {
|
style = {
|
||||||
left: 0,
|
left: 0,
|
||||||
|
@ -71,7 +71,7 @@ notification.config({
|
|||||||
| closeIcon | 自定义关闭图标 | ReactNode | - | |
|
| closeIcon | 自定义关闭图标 | ReactNode | - | |
|
||||||
| duration | 默认自动关闭延时,单位秒 | number | 4.5 | |
|
| duration | 默认自动关闭延时,单位秒 | number | 4.5 | |
|
||||||
| getContainer | 配置渲染节点的输出位置 | () => HTMLNode | () => document.body | |
|
| getContainer | 配置渲染节点的输出位置 | () => HTMLNode | () => document.body | |
|
||||||
| placement | 弹出位置,可选 `topLeft` `topRight` `bottomLeft` `bottomRight` | string | `topRight` | |
|
| placement | 弹出位置,可选 `top` `topLeft` `topRight` `bottom` `bottomLeft` `bottomRight` | string | `topRight` | |
|
||||||
| rtl | 是否开启 RTL 模式 | boolean | false | |
|
| rtl | 是否开启 RTL 模式 | boolean | false | |
|
||||||
| top | 消息从顶部弹出时,距离顶部的位置,单位像素 | number | 24 | |
|
| top | 消息从顶部弹出时,距离顶部的位置,单位像素 | number | 24 | |
|
||||||
| maxCount | 最大显示数, 超过限制时,最早的消息会被自动关闭 | number | - | 4.17.0 |
|
| maxCount | 最大显示数, 超过限制时,最早的消息会被自动关闭 | number | - | 4.17.0 |
|
||||||
|
@ -16,6 +16,8 @@
|
|||||||
z-index: @zindex-notification;
|
z-index: @zindex-notification;
|
||||||
margin-right: @notification-margin-edge;
|
margin-right: @notification-margin-edge;
|
||||||
|
|
||||||
|
&-top,
|
||||||
|
&-bottom,
|
||||||
&-topLeft,
|
&-topLeft,
|
||||||
&-bottomLeft {
|
&-bottomLeft {
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
@ -27,6 +29,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&-top,
|
||||||
|
&-bottom {
|
||||||
|
margin-right: auto;
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
|
||||||
&-close-icon {
|
&-close-icon {
|
||||||
font-size: @font-size-base;
|
font-size: @font-size-base;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@ -50,6 +58,12 @@
|
|||||||
border-radius: @border-radius-base;
|
border-radius: @border-radius-base;
|
||||||
box-shadow: @shadow-2;
|
box-shadow: @shadow-2;
|
||||||
|
|
||||||
|
.@{notification-prefix-cls}-top &,
|
||||||
|
.@{notification-prefix-cls}-bottom & {
|
||||||
|
margin-right: auto;
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
|
||||||
.@{notification-prefix-cls}-topLeft &,
|
.@{notification-prefix-cls}-topLeft &,
|
||||||
.@{notification-prefix-cls}-bottomLeft & {
|
.@{notification-prefix-cls}-bottomLeft & {
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
|
@ -4145,6 +4145,253 @@ exports[`renders ./components/select/demo/option-label-prop.md extend context co
|
|||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`renders ./components/select/demo/placement.md extend context correctly 1`] = `
|
||||||
|
Array [
|
||||||
|
<div
|
||||||
|
class="ant-radio-group ant-radio-group-outline"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
class="ant-radio-button-wrapper ant-radio-button-wrapper-checked"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button ant-radio-button-checked"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
checked=""
|
||||||
|
class="ant-radio-button-input"
|
||||||
|
type="radio"
|
||||||
|
value="topLeft"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button-inner"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
topLeft
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<label
|
||||||
|
class="ant-radio-button-wrapper"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
class="ant-radio-button-input"
|
||||||
|
type="radio"
|
||||||
|
value="topRight"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button-inner"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
topRight
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<label
|
||||||
|
class="ant-radio-button-wrapper"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
class="ant-radio-button-input"
|
||||||
|
type="radio"
|
||||||
|
value="bottomLeft"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button-inner"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
bottomLeft
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<label
|
||||||
|
class="ant-radio-button-wrapper"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
class="ant-radio-button-input"
|
||||||
|
type="radio"
|
||||||
|
value="bottomRight"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button-inner"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
bottomRight
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</div>,
|
||||||
|
<br />,
|
||||||
|
<br />,
|
||||||
|
<div
|
||||||
|
class="ant-select ant-select-single ant-select-show-arrow"
|
||||||
|
style="width:120px"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="ant-select-selector"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-select-selection-search"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
aria-activedescendant="undefined_list_0"
|
||||||
|
aria-autocomplete="list"
|
||||||
|
aria-controls="undefined_list"
|
||||||
|
aria-haspopup="listbox"
|
||||||
|
aria-owns="undefined_list"
|
||||||
|
autocomplete="off"
|
||||||
|
class="ant-select-selection-search-input"
|
||||||
|
readonly=""
|
||||||
|
role="combobox"
|
||||||
|
style="opacity:0"
|
||||||
|
type="search"
|
||||||
|
unselectable="on"
|
||||||
|
value=""
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="ant-select-selection-item"
|
||||||
|
title="HangZhou #310000"
|
||||||
|
>
|
||||||
|
HangZhou #310000
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="ant-select-dropdown"
|
||||||
|
style="opacity:0;pointer-events:none"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
id="undefined_list"
|
||||||
|
role="listbox"
|
||||||
|
style="height:0;width:0;overflow:hidden"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
aria-label="HangZhou #310000"
|
||||||
|
aria-selected="true"
|
||||||
|
id="undefined_list_0"
|
||||||
|
role="option"
|
||||||
|
>
|
||||||
|
HangZhou
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
aria-label="NingBo #315000"
|
||||||
|
aria-selected="false"
|
||||||
|
id="undefined_list_1"
|
||||||
|
role="option"
|
||||||
|
>
|
||||||
|
NingBo
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="rc-virtual-list"
|
||||||
|
style="position:relative"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="rc-virtual-list-holder"
|
||||||
|
style="max-height:256px;overflow-y:auto;overflow-anchor:none"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="rc-virtual-list-holder-inner"
|
||||||
|
style="display:flex;flex-direction:column"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
aria-selected="true"
|
||||||
|
class="ant-select-item ant-select-item-option ant-select-item-option-active ant-select-item-option-selected"
|
||||||
|
title="HangZhou #310000"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="ant-select-item-option-content"
|
||||||
|
>
|
||||||
|
HangZhou #310000
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
aria-hidden="true"
|
||||||
|
class="ant-select-item-option-state"
|
||||||
|
style="user-select:none;-webkit-user-select:none"
|
||||||
|
unselectable="on"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
aria-selected="false"
|
||||||
|
class="ant-select-item ant-select-item-option"
|
||||||
|
title="NingBo #315000"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="ant-select-item-option-content"
|
||||||
|
>
|
||||||
|
NingBo #315000
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
aria-hidden="true"
|
||||||
|
class="ant-select-item-option-state"
|
||||||
|
style="user-select:none;-webkit-user-select:none"
|
||||||
|
unselectable="on"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
aria-selected="false"
|
||||||
|
class="ant-select-item ant-select-item-option"
|
||||||
|
title="WenZhou #325000"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="ant-select-item-option-content"
|
||||||
|
>
|
||||||
|
WenZhou #325000
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
aria-hidden="true"
|
||||||
|
class="ant-select-item-option-state"
|
||||||
|
style="user-select:none;-webkit-user-select:none"
|
||||||
|
unselectable="on"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
aria-hidden="true"
|
||||||
|
class="ant-select-arrow"
|
||||||
|
style="user-select:none;-webkit-user-select:none"
|
||||||
|
unselectable="on"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
aria-label="down"
|
||||||
|
class="anticon anticon-down ant-select-suffix"
|
||||||
|
role="img"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
data-icon="down"
|
||||||
|
fill="currentColor"
|
||||||
|
focusable="false"
|
||||||
|
height="1em"
|
||||||
|
viewBox="64 64 896 896"
|
||||||
|
width="1em"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</div>,
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`renders ./components/select/demo/responsive.md extend context correctly 1`] = `
|
exports[`renders ./components/select/demo/responsive.md extend context correctly 1`] = `
|
||||||
<div
|
<div
|
||||||
class="ant-space ant-space-vertical"
|
class="ant-space ant-space-vertical"
|
||||||
|
@ -1569,6 +1569,154 @@ exports[`renders ./components/select/demo/option-label-prop.md correctly 1`] = `
|
|||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`renders ./components/select/demo/placement.md correctly 1`] = `
|
||||||
|
Array [
|
||||||
|
<div
|
||||||
|
class="ant-radio-group ant-radio-group-outline"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
class="ant-radio-button-wrapper ant-radio-button-wrapper-checked"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button ant-radio-button-checked"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
checked=""
|
||||||
|
class="ant-radio-button-input"
|
||||||
|
type="radio"
|
||||||
|
value="topLeft"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button-inner"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
topLeft
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<label
|
||||||
|
class="ant-radio-button-wrapper"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
class="ant-radio-button-input"
|
||||||
|
type="radio"
|
||||||
|
value="topRight"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button-inner"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
topRight
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<label
|
||||||
|
class="ant-radio-button-wrapper"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
class="ant-radio-button-input"
|
||||||
|
type="radio"
|
||||||
|
value="bottomLeft"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button-inner"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
bottomLeft
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<label
|
||||||
|
class="ant-radio-button-wrapper"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
class="ant-radio-button-input"
|
||||||
|
type="radio"
|
||||||
|
value="bottomRight"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button-inner"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
bottomRight
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</div>,
|
||||||
|
<br />,
|
||||||
|
<br />,
|
||||||
|
<div
|
||||||
|
class="ant-select ant-select-single ant-select-show-arrow"
|
||||||
|
style="width:120px"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="ant-select-selector"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-select-selection-search"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
aria-activedescendant="undefined_list_0"
|
||||||
|
aria-autocomplete="list"
|
||||||
|
aria-controls="undefined_list"
|
||||||
|
aria-haspopup="listbox"
|
||||||
|
aria-owns="undefined_list"
|
||||||
|
autocomplete="off"
|
||||||
|
class="ant-select-selection-search-input"
|
||||||
|
readonly=""
|
||||||
|
role="combobox"
|
||||||
|
style="opacity:0"
|
||||||
|
type="search"
|
||||||
|
unselectable="on"
|
||||||
|
value=""
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="ant-select-selection-item"
|
||||||
|
title="HangZhou #310000"
|
||||||
|
>
|
||||||
|
HangZhou #310000
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
aria-hidden="true"
|
||||||
|
class="ant-select-arrow"
|
||||||
|
style="user-select:none;-webkit-user-select:none"
|
||||||
|
unselectable="on"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
aria-label="down"
|
||||||
|
class="anticon anticon-down ant-select-suffix"
|
||||||
|
role="img"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
data-icon="down"
|
||||||
|
fill="currentColor"
|
||||||
|
focusable="false"
|
||||||
|
height="1em"
|
||||||
|
viewBox="64 64 896 896"
|
||||||
|
width="1em"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</div>,
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`renders ./components/select/demo/responsive.md correctly 1`] = `
|
exports[`renders ./components/select/demo/responsive.md correctly 1`] = `
|
||||||
<div
|
<div
|
||||||
class="ant-space ant-space-vertical"
|
class="ant-space ant-space-vertical"
|
||||||
|
53
components/select/demo/placement.md
Normal file
53
components/select/demo/placement.md
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
---
|
||||||
|
order: 38
|
||||||
|
title:
|
||||||
|
zh-CN: 弹出位置
|
||||||
|
en-US: Placement
|
||||||
|
---
|
||||||
|
|
||||||
|
## zh-CN
|
||||||
|
|
||||||
|
可以通过 `placement` 手动指定弹出的位置。
|
||||||
|
|
||||||
|
## en-US
|
||||||
|
|
||||||
|
You can manually specify the position of the popup via `placement`.
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
import { Select, Radio } from 'antd';
|
||||||
|
|
||||||
|
const { Option } = Select;
|
||||||
|
|
||||||
|
const SetPlacementDemo = () => {
|
||||||
|
const [placement, SetPlacement] = React.useState('topLeft');
|
||||||
|
|
||||||
|
const placementChange = e => {
|
||||||
|
SetPlacement(e.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Radio.Group value={placement} onChange={placementChange}>
|
||||||
|
<Radio.Button value="topLeft">topLeft</Radio.Button>
|
||||||
|
<Radio.Button value="topRight">topRight</Radio.Button>
|
||||||
|
<Radio.Button value="bottomLeft">bottomLeft</Radio.Button>
|
||||||
|
<Radio.Button value="bottomRight">bottomRight</Radio.Button>
|
||||||
|
</Radio.Group>
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<Select
|
||||||
|
defaultValue="HangZhou"
|
||||||
|
style={{ width: 120 }}
|
||||||
|
dropdownMatchSelectWidth={false}
|
||||||
|
placement={placement}
|
||||||
|
>
|
||||||
|
<Option value="HangZhou">HangZhou #310000</Option>
|
||||||
|
<Option value="NingBo">NingBo #315000</Option>
|
||||||
|
<Option value="WenZhou">WenZhou #325000</Option>
|
||||||
|
</Select>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
ReactDOM.render(<SetPlacementDemo />, mountNode);
|
||||||
|
```
|
@ -37,7 +37,7 @@ Select component to select value from options.
|
|||||||
| 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 | |
|
| 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 | - | |
|
| dropdownRender | Customize dropdown content | (originNode: ReactNode) => ReactNode | - | |
|
||||||
| dropdownStyle | The style of dropdown menu | CSSProperties | - | |
|
| dropdownStyle | The style of dropdown menu | CSSProperties | - | |
|
||||||
| fieldNames | Customize node label, value, options field name | object | { label: `label`, value: `value`, options: `options` } | 4.17.0 |
|
| fieldNames | Customize node title, key, options field name | object | { label: `label`, key: `key`, options: `options` } | 4.17.0 |
|
||||||
| 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 | |
|
| 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 | |
|
||||||
| filterSort | Sort function for search options sorting, see [Array.sort](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort)'s compareFunction | (optionA: Option, optionB: Option) => number | - | 4.9.0 |
|
| filterSort | Sort function for search options sorting, see [Array.sort](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort)'s compareFunction | (optionA: Option, optionB: Option) => number | - | 4.9.0 |
|
||||||
| getPopupContainer | Parent Node which the selector should be rendered to. Default to `body`. When position issues happen, try to modify it into scrollable content and position it relative. [Example](https://codesandbox.io/s/4j168r7jw0) | function(triggerNode) | () => document.body | |
|
| getPopupContainer | Parent Node which the selector should be rendered to. Default to `body`. When position issues happen, try to modify it into scrollable content and position it relative. [Example](https://codesandbox.io/s/4j168r7jw0) | function(triggerNode) | () => document.body | |
|
||||||
@ -55,6 +55,7 @@ Select component to select value from options.
|
|||||||
| optionLabelProp | Which prop value of option will render as content of select. [Example](https://codesandbox.io/s/antd-reproduction-template-tk678) | string | `children` | |
|
| optionLabelProp | Which prop value of option will render as content of select. [Example](https://codesandbox.io/s/antd-reproduction-template-tk678) | string | `children` | |
|
||||||
| options | Select options. Will get better perf than jsx definition | { label, value }\[] | - | |
|
| options | Select options. Will get better perf than jsx definition | { label, value }\[] | - | |
|
||||||
| placeholder | Placeholder of select | ReactNode | - | |
|
| placeholder | Placeholder of select | ReactNode | - | |
|
||||||
|
| placement | The position where the selection box pops up | `bottomLeft` `bottomRight` `topLeft` `topRight` | bottomLeft | |
|
||||||
| removeIcon | The custom remove icon | ReactNode | - | |
|
| removeIcon | The custom remove icon | ReactNode | - | |
|
||||||
| searchValue | The current input "search" text | string | - | |
|
| searchValue | The current input "search" text | string | - | |
|
||||||
| showArrow | Whether to show the drop-down arrow | boolean | true(for single select), false(for multiple select) | |
|
| showArrow | Whether to show the drop-down arrow | boolean | true(for single select), false(for multiple select) | |
|
||||||
|
@ -9,7 +9,7 @@ import { OptionProps } from 'rc-select/lib/Option';
|
|||||||
import { ConfigContext } from '../config-provider';
|
import { ConfigContext } from '../config-provider';
|
||||||
import getIcons from './utils/iconUtil';
|
import getIcons from './utils/iconUtil';
|
||||||
import SizeContext, { SizeType } from '../config-provider/SizeContext';
|
import SizeContext, { SizeType } from '../config-provider/SizeContext';
|
||||||
import { getTransitionName } from '../_util/motion';
|
import { getTransitionName, getTransitionDirection, SelectCommonPlacement } from '../_util/motion';
|
||||||
|
|
||||||
type RawValue = string | number;
|
type RawValue = string | number;
|
||||||
|
|
||||||
@ -38,8 +38,9 @@ export interface SelectProps<
|
|||||||
OptionType extends BaseOptionType | DefaultOptionType = DefaultOptionType,
|
OptionType extends BaseOptionType | DefaultOptionType = DefaultOptionType,
|
||||||
> extends Omit<
|
> extends Omit<
|
||||||
InternalSelectProps<ValueType, OptionType>,
|
InternalSelectProps<ValueType, OptionType>,
|
||||||
'inputIcon' | 'mode' | 'getInputElement' | 'getRawInputElement' | 'backfill'
|
'inputIcon' | 'mode' | 'getInputElement' | 'getRawInputElement' | 'backfill' | 'placement'
|
||||||
> {
|
> {
|
||||||
|
placement?: SelectCommonPlacement;
|
||||||
mode?: 'multiple' | 'tags';
|
mode?: 'multiple' | 'tags';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,6 +54,7 @@ const InternalSelect = <OptionType extends BaseOptionType | DefaultOptionType =
|
|||||||
getPopupContainer,
|
getPopupContainer,
|
||||||
dropdownClassName,
|
dropdownClassName,
|
||||||
listHeight = 256,
|
listHeight = 256,
|
||||||
|
placement,
|
||||||
listItemHeight = 24,
|
listItemHeight = 24,
|
||||||
size: customizeSize,
|
size: customizeSize,
|
||||||
notFoundContent,
|
notFoundContent,
|
||||||
@ -123,17 +125,32 @@ const InternalSelect = <OptionType extends BaseOptionType | DefaultOptionType =
|
|||||||
className,
|
className,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// ===================== Placement =====================
|
||||||
|
const getPlacement = () => {
|
||||||
|
if (placement !== undefined) {
|
||||||
|
return placement;
|
||||||
|
}
|
||||||
|
return direction === 'rtl'
|
||||||
|
? ('bottomRight' as SelectCommonPlacement)
|
||||||
|
: ('bottomLeft' as SelectCommonPlacement);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RcSelect<any, any>
|
<RcSelect<any, any>
|
||||||
ref={ref as any}
|
ref={ref as any}
|
||||||
virtual={virtual}
|
virtual={virtual}
|
||||||
dropdownMatchSelectWidth={dropdownMatchSelectWidth}
|
dropdownMatchSelectWidth={dropdownMatchSelectWidth}
|
||||||
{...selectProps}
|
{...selectProps}
|
||||||
transitionName={getTransitionName(rootPrefixCls, 'slide-up', props.transitionName)}
|
transitionName={getTransitionName(
|
||||||
|
rootPrefixCls,
|
||||||
|
getTransitionDirection(placement),
|
||||||
|
props.transitionName,
|
||||||
|
)}
|
||||||
listHeight={listHeight}
|
listHeight={listHeight}
|
||||||
listItemHeight={listItemHeight}
|
listItemHeight={listItemHeight}
|
||||||
mode={mode as any}
|
mode={mode as any}
|
||||||
prefixCls={prefixCls}
|
prefixCls={prefixCls}
|
||||||
|
placement={getPlacement()}
|
||||||
direction={direction}
|
direction={direction}
|
||||||
inputIcon={suffixIcon}
|
inputIcon={suffixIcon}
|
||||||
menuItemSelectedIcon={itemIcon}
|
menuItemSelectedIcon={itemIcon}
|
||||||
|
@ -38,7 +38,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/_0XzgOis7/Select.svg
|
|||||||
| dropdownMatchSelectWidth | 下拉菜单和选择器同宽。默认将设置 `min-width`,当值小于选择框宽度时会被忽略。false 时会关闭虚拟滚动 | boolean \| number | true | |
|
| dropdownMatchSelectWidth | 下拉菜单和选择器同宽。默认将设置 `min-width`,当值小于选择框宽度时会被忽略。false 时会关闭虚拟滚动 | boolean \| number | true | |
|
||||||
| dropdownRender | 自定义下拉框内容 | (originNode: ReactNode) => ReactNode | - | |
|
| dropdownRender | 自定义下拉框内容 | (originNode: ReactNode) => ReactNode | - | |
|
||||||
| dropdownStyle | 下拉菜单的 style 属性 | CSSProperties | - | |
|
| dropdownStyle | 下拉菜单的 style 属性 | CSSProperties | - | |
|
||||||
| fieldNames | 自定义节点 label、value、options 的字段 | object | { label: `label`, value: `value`, options: `options` } | 4.17.0 |
|
| fieldNames | 自定义节点 label、key、options 的字段 | object | { label: `label`, key: `key`, options: `options` } | 4.17.0 |
|
||||||
| filterOption | 是否根据输入项进行筛选。当其为一个函数时,会接收 `inputValue` `option` 两个参数,当 `option` 符合筛选条件时,应返回 true,反之则返回 false | boolean \| function(inputValue, option) | true | |
|
| filterOption | 是否根据输入项进行筛选。当其为一个函数时,会接收 `inputValue` `option` 两个参数,当 `option` 符合筛选条件时,应返回 true,反之则返回 false | boolean \| function(inputValue, option) | true | |
|
||||||
| filterSort | 搜索时对筛选结果项的排序函数, 类似[Array.sort](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort)里的 compareFunction | (optionA: Option, optionB: Option) => number | - | 4.9.0 |
|
| filterSort | 搜索时对筛选结果项的排序函数, 类似[Array.sort](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort)里的 compareFunction | (optionA: Option, optionB: Option) => number | - | 4.9.0 |
|
||||||
| getPopupContainer | 菜单渲染父节点。默认渲染到 body 上,如果你遇到菜单滚动定位问题,试试修改为滚动的区域,并相对其定位。[示例](https://codesandbox.io/s/4j168r7jw0) | function(triggerNode) | () => document.body | |
|
| getPopupContainer | 菜单渲染父节点。默认渲染到 body 上,如果你遇到菜单滚动定位问题,试试修改为滚动的区域,并相对其定位。[示例](https://codesandbox.io/s/4j168r7jw0) | function(triggerNode) | () => document.body | |
|
||||||
@ -56,6 +56,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/_0XzgOis7/Select.svg
|
|||||||
| optionLabelProp | 回填到选择框的 Option 的属性值,默认是 Option 的子元素。比如在子元素需要高亮效果时,此值可以设为 `value`。[示例](https://codesandbox.io/s/antd-reproduction-template-tk678) | string | `children` | |
|
| optionLabelProp | 回填到选择框的 Option 的属性值,默认是 Option 的子元素。比如在子元素需要高亮效果时,此值可以设为 `value`。[示例](https://codesandbox.io/s/antd-reproduction-template-tk678) | string | `children` | |
|
||||||
| options | 数据化配置选项内容,相比 jsx 定义会获得更好的渲染性能 | { label, value }\[] | - | |
|
| options | 数据化配置选项内容,相比 jsx 定义会获得更好的渲染性能 | { label, value }\[] | - | |
|
||||||
| placeholder | 选择框默认文本 | string | - | |
|
| placeholder | 选择框默认文本 | string | - | |
|
||||||
|
| placement | 选择框弹出的位置 | `bottomLeft` `bottomRight` `topLeft` `topRight` | bottomLeft | |
|
||||||
| removeIcon | 自定义的多选框清除图标 | ReactNode | - | |
|
| removeIcon | 自定义的多选框清除图标 | ReactNode | - | |
|
||||||
| searchValue | 控制搜索文本 | string | - | |
|
| searchValue | 控制搜索文本 | string | - | |
|
||||||
| showArrow | 是否显示下拉小箭头 | boolean | 单选为 true,多选为 false | |
|
| showArrow | 是否显示下拉小箭头 | boolean | 单选为 true,多选为 false | |
|
||||||
|
@ -6,11 +6,12 @@ import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
|||||||
|
|
||||||
export interface SkeletonInputProps extends Omit<SkeletonElementProps, 'size' | 'shape'> {
|
export interface SkeletonInputProps extends Omit<SkeletonElementProps, 'size' | 'shape'> {
|
||||||
size?: 'large' | 'small' | 'default';
|
size?: 'large' | 'small' | 'default';
|
||||||
|
block?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SkeletonInput = (props: SkeletonInputProps) => {
|
const SkeletonInput = (props: SkeletonInputProps) => {
|
||||||
const renderSkeletonInput = ({ getPrefixCls }: ConfigConsumerProps) => {
|
const renderSkeletonInput = ({ getPrefixCls }: ConfigConsumerProps) => {
|
||||||
const { prefixCls: customizePrefixCls, className, active } = props;
|
const { prefixCls: customizePrefixCls, className, active, block } = props;
|
||||||
const prefixCls = getPrefixCls('skeleton', customizePrefixCls);
|
const prefixCls = getPrefixCls('skeleton', customizePrefixCls);
|
||||||
const otherProps = omit(props, ['prefixCls']);
|
const otherProps = omit(props, ['prefixCls']);
|
||||||
const cls = classNames(
|
const cls = classNames(
|
||||||
@ -18,6 +19,7 @@ const SkeletonInput = (props: SkeletonInputProps) => {
|
|||||||
`${prefixCls}-element`,
|
`${prefixCls}-element`,
|
||||||
{
|
{
|
||||||
[`${prefixCls}-active`]: active,
|
[`${prefixCls}-active`]: active,
|
||||||
|
[`${prefixCls}-block`]: block,
|
||||||
},
|
},
|
||||||
className,
|
className,
|
||||||
);
|
);
|
||||||
|
@ -138,7 +138,6 @@ Array [
|
|||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
class="ant-skeleton-input"
|
class="ant-skeleton-input"
|
||||||
style="width:200px"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -154,6 +153,15 @@ Array [
|
|||||||
</div>,
|
</div>,
|
||||||
<br />,
|
<br />,
|
||||||
<br />,
|
<br />,
|
||||||
|
<div
|
||||||
|
class="ant-skeleton ant-skeleton-element"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-skeleton-input"
|
||||||
|
/>
|
||||||
|
</div>,
|
||||||
|
<br />,
|
||||||
|
<br />,
|
||||||
<div
|
<div
|
||||||
class="ant-skeleton ant-skeleton-element"
|
class="ant-skeleton ant-skeleton-element"
|
||||||
>
|
>
|
||||||
@ -227,9 +235,9 @@ Array [
|
|||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
class=""
|
class=""
|
||||||
title="Button Block"
|
title="Button and Input Block"
|
||||||
>
|
>
|
||||||
Button Block
|
Button and Input Block
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
@ -138,7 +138,6 @@ Array [
|
|||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
class="ant-skeleton-input"
|
class="ant-skeleton-input"
|
||||||
style="width:200px"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -154,6 +153,15 @@ Array [
|
|||||||
</div>,
|
</div>,
|
||||||
<br />,
|
<br />,
|
||||||
<br />,
|
<br />,
|
||||||
|
<div
|
||||||
|
class="ant-skeleton ant-skeleton-element"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-skeleton-input"
|
||||||
|
/>
|
||||||
|
</div>,
|
||||||
|
<br />,
|
||||||
|
<br />,
|
||||||
<div
|
<div
|
||||||
class="ant-skeleton ant-skeleton-element"
|
class="ant-skeleton ant-skeleton-element"
|
||||||
>
|
>
|
||||||
@ -227,9 +235,9 @@ Array [
|
|||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
class=""
|
class=""
|
||||||
title="Button Block"
|
title="Button and Input Block"
|
||||||
>
|
>
|
||||||
Button Block
|
Button and Input Block
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
@ -14,7 +14,7 @@ title:
|
|||||||
Skeleton Button, Avatar, Input and Image.
|
Skeleton Button, Avatar, Input and Image.
|
||||||
|
|
||||||
```jsx
|
```jsx
|
||||||
import { Skeleton, Space, Divider, Switch, Form, Radio } from 'antd';
|
import { Skeleton, Space, Divider, Switch, Form, Radio, Button, Input } from 'antd';
|
||||||
|
|
||||||
class Demo extends React.Component {
|
class Demo extends React.Component {
|
||||||
state = {
|
state = {
|
||||||
@ -48,20 +48,23 @@ class Demo extends React.Component {
|
|||||||
<Space>
|
<Space>
|
||||||
<Skeleton.Button active={active} size={size} shape={buttonShape} block={block} />
|
<Skeleton.Button active={active} size={size} shape={buttonShape} block={block} />
|
||||||
<Skeleton.Avatar active={active} size={size} shape={avatarShape} />
|
<Skeleton.Avatar active={active} size={size} shape={avatarShape} />
|
||||||
<Skeleton.Input style={{ width: 200 }} active={active} size={size} />
|
<Skeleton.Input active={active} size={size} />
|
||||||
</Space>
|
</Space>
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
<Skeleton.Button active={active} size={size} shape={buttonShape} block={block} />
|
<Skeleton.Button active={active} size={size} shape={buttonShape} block={block} />
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
|
<Skeleton.Input active={active} size={size} block={block} />
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
<Skeleton.Image />
|
<Skeleton.Image />
|
||||||
<Divider />
|
<Divider />
|
||||||
<Form layout="inline" style={{ margin: '16px 0' }}>
|
<Form layout="inline" style={{ margin: '16px 0' }}>
|
||||||
<Form.Item label="Active">
|
<Form.Item label="Active">
|
||||||
<Switch checked={active} onChange={this.handleActiveChange} />
|
<Switch checked={active} onChange={this.handleActiveChange} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label="Button Block">
|
<Form.Item label="Button and Input Block">
|
||||||
<Switch checked={block} onChange={this.handleBlockChange} />
|
<Switch checked={block} onChange={this.handleBlockChange} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label="Size">
|
<Form.Item label="Size">
|
||||||
|
@ -109,13 +109,17 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skeleton Block Button
|
// Skeleton Block Button, Input
|
||||||
&.@{skeleton-prefix-cls}-block {
|
&.@{skeleton-prefix-cls}-block {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
.@{skeleton-button-prefix-cls} {
|
.@{skeleton-button-prefix-cls} {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.@{skeleton-input-prefix-cls} {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skeleton element
|
// Skeleton element
|
||||||
@ -238,7 +242,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.skeleton-element-input-size(@size) {
|
.skeleton-element-input-size(@size) {
|
||||||
width: 100%;
|
width: @size * 5;
|
||||||
|
min-width: @size * 5;
|
||||||
.skeleton-element-common-size(@size);
|
.skeleton-element-common-size(@size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,11 +88,12 @@ const Space: React.FC<SpaceProps> = props => {
|
|||||||
latestIndex = i;
|
latestIndex = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* eslint-disable react/no-array-index-key */
|
const keyOfChild = child && child.key;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Item
|
<Item
|
||||||
className={itemClassName}
|
className={itemClassName}
|
||||||
key={`${itemClassName}-${i}`}
|
key={`${itemClassName}-${keyOfChild || i}`}
|
||||||
direction={direction}
|
direction={direction}
|
||||||
index={i}
|
index={i}
|
||||||
marginDirection={marginDirection}
|
marginDirection={marginDirection}
|
||||||
@ -102,7 +103,6 @@ const Space: React.FC<SpaceProps> = props => {
|
|||||||
{child}
|
{child}
|
||||||
</Item>
|
</Item>
|
||||||
);
|
);
|
||||||
/* eslint-enable */
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const spaceContext = React.useMemo(
|
const spaceContext = React.useMemo(
|
||||||
|
@ -221,7 +221,7 @@ html {
|
|||||||
|
|
||||||
// Border color
|
// Border color
|
||||||
@border-color-base: hsv(0, 0, 85%); // base border outline a component
|
@border-color-base: hsv(0, 0, 85%); // base border outline a component
|
||||||
@border-color-split: hsv(0, 0, 94%); // split border inside a component
|
@border-color-split: rgba(0, 0, 0, 0.06); // split border inside a component
|
||||||
@border-color-inverse: @white;
|
@border-color-inverse: @white;
|
||||||
@border-width-base: 1px; // width of the border for a component
|
@border-width-base: 1px; // width of the border for a component
|
||||||
@border-style-base: solid; // style of a components border
|
@border-style-base: solid; // style of a components border
|
||||||
@ -622,7 +622,7 @@ html {
|
|||||||
// Progress
|
// Progress
|
||||||
// --
|
// --
|
||||||
@progress-default-color: @processing-color;
|
@progress-default-color: @processing-color;
|
||||||
@progress-remaining-color: @background-color-base;
|
@progress-remaining-color: rgba(0, 0, 0, 0.04);
|
||||||
@progress-info-text-color: @progress-text-color;
|
@progress-info-text-color: @progress-text-color;
|
||||||
@progress-radius: 100px;
|
@progress-radius: 100px;
|
||||||
@progress-steps-item-bg: #f3f3f3;
|
@progress-steps-item-bg: #f3f3f3;
|
||||||
|
@ -68,19 +68,55 @@ describe('Table.sorter', () => {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const getNameColumn = () => wrapper.find('th').at(0);
|
||||||
|
|
||||||
expect(renderedNames(wrapper)).toEqual(['Tom', 'Lucy', 'Jack', 'Jerry']);
|
expect(renderedNames(wrapper)).toEqual(['Tom', 'Lucy', 'Jack', 'Jerry']);
|
||||||
|
expect(getNameColumn().prop('aria-sort')).toEqual('descending');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should change aria-sort when default sort order is set to descend', () => {
|
||||||
|
const wrapper = mount(
|
||||||
|
createTable(
|
||||||
|
{
|
||||||
|
sortDirections: ['descend', 'ascend'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
defaultSortOrder: 'descend',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
const getNameColumn = () => wrapper.find('th').at(0);
|
||||||
|
|
||||||
|
// Test that it cycles through the order of sortDirections
|
||||||
|
expect(renderedNames(wrapper)).toEqual(['Tom', 'Lucy', 'Jack', 'Jerry']);
|
||||||
|
expect(getNameColumn().prop('aria-sort')).toEqual('descending');
|
||||||
|
|
||||||
|
wrapper.find('.ant-table-column-sorters').simulate('click');
|
||||||
|
expect(getNameColumn().prop('aria-sort')).toEqual('ascending');
|
||||||
|
|
||||||
|
wrapper.find('.ant-table-column-sorters').simulate('click');
|
||||||
|
expect(getNameColumn().prop('aria-sort')).toEqual(undefined);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sort records', () => {
|
it('sort records', () => {
|
||||||
const wrapper = mount(createTable());
|
const wrapper = mount(createTable());
|
||||||
|
|
||||||
|
const getNameColumn = () => wrapper.find('th').at(0);
|
||||||
|
|
||||||
|
// first assert default state
|
||||||
|
expect(renderedNames(wrapper)).toEqual(['Jack', 'Lucy', 'Tom', 'Jerry']);
|
||||||
|
expect(getNameColumn().prop('aria-sort')).toEqual(undefined);
|
||||||
|
|
||||||
// ascend
|
// ascend
|
||||||
wrapper.find('.ant-table-column-sorters').simulate('click');
|
wrapper.find('.ant-table-column-sorters').simulate('click');
|
||||||
expect(renderedNames(wrapper)).toEqual(['Jack', 'Jerry', 'Lucy', 'Tom']);
|
expect(renderedNames(wrapper)).toEqual(['Jack', 'Jerry', 'Lucy', 'Tom']);
|
||||||
|
expect(getNameColumn().prop('aria-sort')).toEqual('ascending');
|
||||||
|
|
||||||
// descend
|
// descend
|
||||||
wrapper.find('.ant-table-column-sorters').simulate('click');
|
wrapper.find('.ant-table-column-sorters').simulate('click');
|
||||||
expect(renderedNames(wrapper)).toEqual(['Tom', 'Lucy', 'Jack', 'Jerry']);
|
expect(renderedNames(wrapper)).toEqual(['Tom', 'Lucy', 'Jack', 'Jerry']);
|
||||||
|
expect(getNameColumn().prop('aria-sort')).toEqual('descending');
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('can be controlled by sortOrder', () => {
|
describe('can be controlled by sortOrder', () => {
|
||||||
@ -333,12 +369,16 @@ describe('Table.sorter', () => {
|
|||||||
// sort name
|
// sort name
|
||||||
getNameColumn().simulate('click');
|
getNameColumn().simulate('click');
|
||||||
expect(getNameIcon('up').hasClass('active')).toBeTruthy();
|
expect(getNameIcon('up').hasClass('active')).toBeTruthy();
|
||||||
|
expect(getNameColumn().prop('aria-sort')).toEqual('ascending');
|
||||||
expect(getAgeIcon('up').hasClass('active')).toBeFalsy();
|
expect(getAgeIcon('up').hasClass('active')).toBeFalsy();
|
||||||
|
expect(getAgeColumn().prop('aria-sort')).toEqual(undefined);
|
||||||
|
|
||||||
// sort age
|
// sort age
|
||||||
getAgeColumn().simulate('click');
|
getAgeColumn().simulate('click');
|
||||||
expect(getNameIcon('up').hasClass('active')).toBeFalsy();
|
expect(getNameIcon('up').hasClass('active')).toBeFalsy();
|
||||||
|
expect(getNameColumn().prop('aria-sort')).toEqual(undefined);
|
||||||
expect(getAgeIcon('up').hasClass('active')).toBeTruthy();
|
expect(getAgeIcon('up').hasClass('active')).toBeTruthy();
|
||||||
|
expect(getAgeColumn().prop('aria-sort')).toEqual('ascending');
|
||||||
});
|
});
|
||||||
|
|
||||||
// https://github.com/ant-design/ant-design/issues/12571
|
// https://github.com/ant-design/ant-design/issues/12571
|
||||||
@ -380,7 +420,7 @@ describe('Table.sorter', () => {
|
|||||||
|
|
||||||
const wrapper = mount(<TableTest />);
|
const wrapper = mount(<TableTest />);
|
||||||
|
|
||||||
const getNameColumn = () => wrapper.find('.ant-table-column-has-sorters').at(0);
|
const getNameColumn = () => wrapper.find('th').at(0);
|
||||||
const getIcon = name => getNameColumn().find(`.ant-table-column-sorter-${name}`).first();
|
const getIcon = name => getNameColumn().find(`.ant-table-column-sorter-${name}`).first();
|
||||||
|
|
||||||
expect(getIcon('up').hasClass('active')).toBeFalsy();
|
expect(getIcon('up').hasClass('active')).toBeFalsy();
|
||||||
@ -390,16 +430,19 @@ describe('Table.sorter', () => {
|
|||||||
getNameColumn().simulate('click');
|
getNameColumn().simulate('click');
|
||||||
expect(getIcon('up').hasClass('active')).toBeTruthy();
|
expect(getIcon('up').hasClass('active')).toBeTruthy();
|
||||||
expect(getIcon('down').hasClass('active')).toBeFalsy();
|
expect(getIcon('down').hasClass('active')).toBeFalsy();
|
||||||
|
expect(getNameColumn().prop('aria-sort')).toEqual('ascending');
|
||||||
|
|
||||||
// sort name
|
// sort name
|
||||||
getNameColumn().simulate('click');
|
getNameColumn().simulate('click');
|
||||||
expect(getIcon('up').hasClass('active')).toBeFalsy();
|
expect(getIcon('up').hasClass('active')).toBeFalsy();
|
||||||
expect(getIcon('down').hasClass('active')).toBeTruthy();
|
expect(getIcon('down').hasClass('active')).toBeTruthy();
|
||||||
|
expect(getNameColumn().prop('aria-sort')).toEqual('descending');
|
||||||
|
|
||||||
// sort name
|
// sort name
|
||||||
getNameColumn().simulate('click');
|
getNameColumn().simulate('click');
|
||||||
expect(getIcon('up').hasClass('active')).toBeFalsy();
|
expect(getIcon('up').hasClass('active')).toBeFalsy();
|
||||||
expect(getIcon('down').hasClass('active')).toBeFalsy();
|
expect(getIcon('down').hasClass('active')).toBeFalsy();
|
||||||
|
expect(getNameColumn().prop('aria-sort')).toEqual(undefined);
|
||||||
});
|
});
|
||||||
|
|
||||||
// https://github.com/ant-design/ant-design/issues/12737
|
// https://github.com/ant-design/ant-design/issues/12737
|
||||||
@ -444,7 +487,7 @@ describe('Table.sorter', () => {
|
|||||||
|
|
||||||
const wrapper = mount(<TableTest />);
|
const wrapper = mount(<TableTest />);
|
||||||
|
|
||||||
const getNameColumn = () => wrapper.find('.ant-table-column-has-sorters').at(0);
|
const getNameColumn = () => wrapper.find('th').at(0);
|
||||||
const getIcon = name => getNameColumn().find(`.ant-table-column-sorter-${name}`).first();
|
const getIcon = name => getNameColumn().find(`.ant-table-column-sorter-${name}`).first();
|
||||||
|
|
||||||
expect(getIcon('up').hasClass('active')).toBeFalsy();
|
expect(getIcon('up').hasClass('active')).toBeFalsy();
|
||||||
@ -454,16 +497,19 @@ describe('Table.sorter', () => {
|
|||||||
getNameColumn().simulate('click');
|
getNameColumn().simulate('click');
|
||||||
expect(getIcon('up').hasClass('active')).toBeTruthy();
|
expect(getIcon('up').hasClass('active')).toBeTruthy();
|
||||||
expect(getIcon('down').hasClass('active')).toBeFalsy();
|
expect(getIcon('down').hasClass('active')).toBeFalsy();
|
||||||
|
expect(getNameColumn().prop('aria-sort')).toEqual('ascending');
|
||||||
|
|
||||||
// sort name
|
// sort name
|
||||||
getNameColumn().simulate('click');
|
getNameColumn().simulate('click');
|
||||||
expect(getIcon('up').hasClass('active')).toBeFalsy();
|
expect(getIcon('up').hasClass('active')).toBeFalsy();
|
||||||
expect(getIcon('down').hasClass('active')).toBeTruthy();
|
expect(getIcon('down').hasClass('active')).toBeTruthy();
|
||||||
|
expect(getNameColumn().prop('aria-sort')).toEqual('descending');
|
||||||
|
|
||||||
// sort name
|
// sort name
|
||||||
getNameColumn().simulate('click');
|
getNameColumn().simulate('click');
|
||||||
expect(getIcon('up').hasClass('active')).toBeFalsy();
|
expect(getIcon('up').hasClass('active')).toBeFalsy();
|
||||||
expect(getIcon('down').hasClass('active')).toBeFalsy();
|
expect(getIcon('down').hasClass('active')).toBeFalsy();
|
||||||
|
expect(getNameColumn().prop('aria-sort')).toEqual(undefined);
|
||||||
});
|
});
|
||||||
|
|
||||||
// https://github.com/ant-design/ant-design/issues/12870
|
// https://github.com/ant-design/ant-design/issues/12870
|
||||||
@ -508,13 +554,14 @@ describe('Table.sorter', () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const wrapper = mount(<TableTest />);
|
const wrapper = mount(<TableTest />);
|
||||||
const getNameColumn = () => wrapper.find('.ant-table-column-has-sorters').at(0);
|
const getNameColumn = () => wrapper.find('th').at(0);
|
||||||
expect(
|
expect(
|
||||||
getNameColumn().find('.ant-table-column-sorter-up').at(0).hasClass('active'),
|
getNameColumn().find('.ant-table-column-sorter-up').at(0).hasClass('active'),
|
||||||
).toBeFalsy();
|
).toBeFalsy();
|
||||||
expect(
|
expect(
|
||||||
getNameColumn().find('.ant-table-column-sorter-down').at(0).hasClass('active'),
|
getNameColumn().find('.ant-table-column-sorter-down').at(0).hasClass('active'),
|
||||||
).toBeFalsy();
|
).toBeFalsy();
|
||||||
|
expect(getNameColumn().prop('aria-sort')).toEqual(undefined);
|
||||||
|
|
||||||
// sort name
|
// sort name
|
||||||
getNameColumn().simulate('click');
|
getNameColumn().simulate('click');
|
||||||
@ -524,6 +571,7 @@ describe('Table.sorter', () => {
|
|||||||
expect(
|
expect(
|
||||||
getNameColumn().find('.ant-table-column-sorter-down').at(0).hasClass('active'),
|
getNameColumn().find('.ant-table-column-sorter-down').at(0).hasClass('active'),
|
||||||
).toBeFalsy();
|
).toBeFalsy();
|
||||||
|
expect(getNameColumn().prop('aria-sort')).toEqual('ascending');
|
||||||
|
|
||||||
// sort name
|
// sort name
|
||||||
getNameColumn().simulate('click');
|
getNameColumn().simulate('click');
|
||||||
@ -533,6 +581,7 @@ describe('Table.sorter', () => {
|
|||||||
expect(
|
expect(
|
||||||
getNameColumn().find('.ant-table-column-sorter-down').at(0).hasClass('active'),
|
getNameColumn().find('.ant-table-column-sorter-down').at(0).hasClass('active'),
|
||||||
).toBeTruthy();
|
).toBeTruthy();
|
||||||
|
expect(getNameColumn().prop('aria-sort')).toEqual('descending');
|
||||||
|
|
||||||
// sort name
|
// sort name
|
||||||
getNameColumn().simulate('click');
|
getNameColumn().simulate('click');
|
||||||
@ -542,6 +591,7 @@ describe('Table.sorter', () => {
|
|||||||
expect(
|
expect(
|
||||||
getNameColumn().find('.ant-table-column-sorter-down').at(0).hasClass('active'),
|
getNameColumn().find('.ant-table-column-sorter-down').at(0).hasClass('active'),
|
||||||
).toBeFalsy();
|
).toBeFalsy();
|
||||||
|
expect(getNameColumn().prop('aria-sort')).toEqual(undefined);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should first sort by descend, then ascend, then cancel sort', () => {
|
it('should first sort by descend, then ascend, then cancel sort', () => {
|
||||||
@ -550,18 +600,22 @@ describe('Table.sorter', () => {
|
|||||||
sortDirections: ['descend', 'ascend'],
|
sortDirections: ['descend', 'ascend'],
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
const getNameColumn = () => wrapper.find('th').at(0);
|
||||||
|
|
||||||
// descend
|
// descend
|
||||||
wrapper.find('.ant-table-column-sorters').simulate('click');
|
getNameColumn().simulate('click');
|
||||||
expect(renderedNames(wrapper)).toEqual(['Tom', 'Lucy', 'Jack', 'Jerry']);
|
expect(renderedNames(wrapper)).toEqual(['Tom', 'Lucy', 'Jack', 'Jerry']);
|
||||||
|
expect(getNameColumn().prop('aria-sort')).toEqual('descending');
|
||||||
|
|
||||||
// ascend
|
// ascend
|
||||||
wrapper.find('.ant-table-column-sorters').simulate('click');
|
getNameColumn().simulate('click');
|
||||||
expect(renderedNames(wrapper)).toEqual(['Jack', 'Jerry', 'Lucy', 'Tom']);
|
expect(renderedNames(wrapper)).toEqual(['Jack', 'Jerry', 'Lucy', 'Tom']);
|
||||||
|
expect(getNameColumn().prop('aria-sort')).toEqual('ascending');
|
||||||
|
|
||||||
// cancel sort
|
// cancel sort
|
||||||
wrapper.find('.ant-table-column-sorters').simulate('click');
|
getNameColumn().simulate('click');
|
||||||
expect(renderedNames(wrapper)).toEqual(['Jack', 'Lucy', 'Tom', 'Jerry']);
|
expect(renderedNames(wrapper)).toEqual(['Jack', 'Lucy', 'Tom', 'Jerry']);
|
||||||
|
expect(getNameColumn().prop('aria-sort')).toEqual(undefined);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should first sort by descend, then cancel sort', () => {
|
it('should first sort by descend, then cancel sort', () => {
|
||||||
@ -571,13 +625,20 @@ describe('Table.sorter', () => {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const getNameColumn = () => wrapper.find('th').at(0);
|
||||||
|
|
||||||
|
// default
|
||||||
|
expect(getNameColumn().prop('aria-sort')).toEqual(undefined);
|
||||||
|
|
||||||
// descend
|
// descend
|
||||||
wrapper.find('.ant-table-column-sorters').simulate('click');
|
getNameColumn().simulate('click');
|
||||||
expect(renderedNames(wrapper)).toEqual(['Tom', 'Lucy', 'Jack', 'Jerry']);
|
expect(renderedNames(wrapper)).toEqual(['Tom', 'Lucy', 'Jack', 'Jerry']);
|
||||||
|
expect(getNameColumn().prop('aria-sort')).toEqual('descending');
|
||||||
|
|
||||||
// cancel sort
|
// cancel sort
|
||||||
wrapper.find('.ant-table-column-sorters').simulate('click');
|
getNameColumn().simulate('click');
|
||||||
expect(renderedNames(wrapper)).toEqual(['Jack', 'Lucy', 'Tom', 'Jerry']);
|
expect(renderedNames(wrapper)).toEqual(['Jack', 'Lucy', 'Tom', 'Jerry']);
|
||||||
|
expect(getNameColumn().prop('aria-sort')).toEqual(undefined);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should first sort by descend, then cancel sort. (column prop)', () => {
|
it('should first sort by descend, then cancel sort. (column prop)', () => {
|
||||||
@ -590,13 +651,20 @@ describe('Table.sorter', () => {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const getNameColumn = () => wrapper.find('th').at(0);
|
||||||
|
|
||||||
|
// default
|
||||||
|
expect(getNameColumn().prop('aria-sort')).toEqual(undefined);
|
||||||
|
|
||||||
// descend
|
// descend
|
||||||
wrapper.find('.ant-table-column-sorters').simulate('click');
|
getNameColumn().simulate('click');
|
||||||
expect(renderedNames(wrapper)).toEqual(['Tom', 'Lucy', 'Jack', 'Jerry']);
|
expect(renderedNames(wrapper)).toEqual(['Tom', 'Lucy', 'Jack', 'Jerry']);
|
||||||
|
expect(getNameColumn().prop('aria-sort')).toEqual('descending');
|
||||||
|
|
||||||
// cancel sort
|
// cancel sort
|
||||||
wrapper.find('.ant-table-column-sorters').simulate('click');
|
getNameColumn().simulate('click');
|
||||||
expect(renderedNames(wrapper)).toEqual(['Jack', 'Lucy', 'Tom', 'Jerry']);
|
expect(renderedNames(wrapper)).toEqual(['Jack', 'Lucy', 'Tom', 'Jerry']);
|
||||||
|
expect(getNameColumn().prop('aria-sort')).toEqual(undefined);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('pagination back', () => {
|
it('pagination back', () => {
|
||||||
@ -614,9 +682,14 @@ describe('Table.sorter', () => {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
wrapper.find('.ant-table-column-sorters').simulate('click');
|
const getNameColumn = () => wrapper.find('th').at(0);
|
||||||
|
|
||||||
|
expect(getNameColumn().prop('aria-sort')).toEqual(undefined);
|
||||||
|
|
||||||
|
getNameColumn().simulate('click');
|
||||||
expect(onChange.mock.calls[0][0].current).toBe(2);
|
expect(onChange.mock.calls[0][0].current).toBe(2);
|
||||||
expect(onPageChange).not.toHaveBeenCalled();
|
expect(onPageChange).not.toHaveBeenCalled();
|
||||||
|
expect(getNameColumn().prop('aria-sort')).toEqual('ascending');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should support onHeaderCell in sort column', () => {
|
it('should support onHeaderCell in sort column', () => {
|
||||||
|
@ -96,6 +96,7 @@ exports[`Table.sorter should support defaultOrder in Column 1`] = `
|
|||||||
>
|
>
|
||||||
<tr>
|
<tr>
|
||||||
<th
|
<th
|
||||||
|
aria-sort="ascending"
|
||||||
class="ant-table-cell ant-table-column-sort ant-table-column-has-sorters"
|
class="ant-table-cell ant-table-column-sort ant-table-column-has-sorters"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
|
@ -12778,6 +12778,7 @@ exports[`renders ./components/table/demo/head.md extend context correctly 1`] =
|
|||||||
</div>
|
</div>
|
||||||
</th>
|
</th>
|
||||||
<th
|
<th
|
||||||
|
aria-sort="descending"
|
||||||
class="ant-table-cell ant-table-column-sort ant-table-column-has-sorters"
|
class="ant-table-cell ant-table-column-sort ant-table-column-has-sorters"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
|
@ -9898,6 +9898,7 @@ exports[`renders ./components/table/demo/head.md correctly 1`] = `
|
|||||||
</div>
|
</div>
|
||||||
</th>
|
</th>
|
||||||
<th
|
<th
|
||||||
|
aria-sort="descending"
|
||||||
class="ant-table-cell ant-table-column-sort ant-table-column-has-sorters"
|
class="ant-table-cell ant-table-column-sort ant-table-column-has-sorters"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
|
@ -192,6 +192,15 @@ function injectSorter<RecordType>(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Inform the screen-reader so it can tell the visually impaired user which column is sorted
|
||||||
|
if (sorterOrder) {
|
||||||
|
if (sorterOrder === 'ascend') {
|
||||||
|
cell['aria-sort'] = 'ascending';
|
||||||
|
} else {
|
||||||
|
cell['aria-sort'] = 'descending';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cell.className = classNames(cell.className, `${prefixCls}-column-has-sorters`);
|
cell.className = classNames(cell.className, `${prefixCls}-column-has-sorters`);
|
||||||
|
|
||||||
return cell;
|
return cell;
|
||||||
|
@ -33,9 +33,7 @@ import moment from 'moment';
|
|||||||
| clearText | The clear tooltip of icon | string | clear | |
|
| clearText | The clear tooltip of icon | string | clear | |
|
||||||
| defaultValue | To set default time | [moment](http://momentjs.com/) | - | |
|
| defaultValue | To set default time | [moment](http://momentjs.com/) | - | |
|
||||||
| disabled | Determine whether the TimePicker is disabled | boolean | false | |
|
| disabled | Determine whether the TimePicker is disabled | boolean | false | |
|
||||||
| disabledHours | To specify the hours that cannot be selected | function() | - | |
|
| disabledTime | To specify the time that cannot be selected | [DisabledTime](#DisabledTime) | - | 4.19.0 |
|
||||||
| disabledMinutes | To specify the minutes that cannot be selected | function(selectedHour) | - | |
|
|
||||||
| disabledSeconds | To specify the seconds that cannot be selected | function(selectedHour, selectedMinute) | - | |
|
|
||||||
| format | To set the time format | string | `HH:mm:ss` | |
|
| format | To set the time format | string | `HH:mm:ss` | |
|
||||||
| getPopupContainer | To set the container of the floating layer, while the default is to create a div element in body | function(trigger) | - | |
|
| getPopupContainer | To set the container of the floating layer, while the default is to create a div element in body | function(trigger) | - | |
|
||||||
| hideDisabledOptions | Whether hide the options that can not be selected | boolean | false | |
|
| hideDisabledOptions | Whether hide the options that can not be selected | boolean | false | |
|
||||||
@ -44,6 +42,7 @@ import moment from 'moment';
|
|||||||
| minuteStep | Interval between minutes in picker | number | 1 | |
|
| minuteStep | Interval between minutes in picker | number | 1 | |
|
||||||
| open | Whether to popup panel | boolean | false | |
|
| open | Whether to popup panel | boolean | false | |
|
||||||
| placeholder | Display when there's no value | string \| \[string, string] | `Select a time` | |
|
| placeholder | Display when there's no value | string \| \[string, string] | `Select a time` | |
|
||||||
|
| placement | The position where the selection box pops up | `bottomLeft` `bottomRight` `topLeft` `topRight` | bottomLeft | |
|
||||||
| popupClassName | The className of panel | string | - | |
|
| popupClassName | The className of panel | string | - | |
|
||||||
| popupStyle | The style of panel | CSSProperties | - | |
|
| popupStyle | The style of panel | CSSProperties | - | |
|
||||||
| renderExtraFooter | Called from time picker panel to render some addon to its bottom | () => ReactNode | - | |
|
| renderExtraFooter | Called from time picker panel to render some addon to its bottom | () => ReactNode | - | |
|
||||||
@ -56,12 +55,22 @@ import moment from 'moment';
|
|||||||
| onOpenChange | A callback function which will be called while panel opening/closing | (open: boolean) => void | - | |
|
| onOpenChange | A callback function which will be called while panel opening/closing | (open: boolean) => void | - | |
|
||||||
| onSelect | A callback function, executes when a value is selected | function(time: moment): void | - | |
|
| onSelect | A callback function, executes when a value is selected | function(time: moment): void | - | |
|
||||||
|
|
||||||
|
#### DisabledTime
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
type DisabledTime = (now: Moment) => {
|
||||||
|
disabledHours?: () => number[];
|
||||||
|
disabledMinutes?: (selectedHour: number) => number[];
|
||||||
|
disabledSeconds?: (selectedHour: number, selectedMinute: number) => number[];
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
## Methods
|
## Methods
|
||||||
|
|
||||||
| Name | Description | Version |
|
| Name | Description | Version |
|
||||||
| --- | --- | --- |
|
| ------- | ------------ | ------- |
|
||||||
| blur() | Remove focus | |
|
| blur() | Remove focus | |
|
||||||
| focus() | Get focus | |
|
| focus() | Get focus | |
|
||||||
|
|
||||||
### RangePicker
|
### RangePicker
|
||||||
|
|
||||||
@ -69,8 +78,22 @@ Same props from [RangePicker](/components/date-picker/#RangePicker) of DatePicke
|
|||||||
|
|
||||||
| Property | Description | Type | Default | Version |
|
| Property | Description | Type | Default | Version |
|
||||||
| --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- |
|
||||||
|
| disabledTime | To specify the time that cannot be selected | [RangeDisabledTime](#RangeDisabledTime) | - | 4.19.0 |
|
||||||
| order | Order start and end time | boolean | true | 4.1.0 |
|
| order | Order start and end time | boolean | true | 4.1.0 |
|
||||||
|
|
||||||
|
### RangeDisabledTime
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
type RangeDisabledTime = (
|
||||||
|
now: Moment,
|
||||||
|
type = 'start' | 'end',
|
||||||
|
) => {
|
||||||
|
disabledHours?: () => number[];
|
||||||
|
disabledMinutes?: (selectedHour: number) => number[];
|
||||||
|
disabledSeconds?: (selectedHour: number, selectedMinute: number) => number[];
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.code-box-demo .ant-picker { margin: 0 8px 12px 0; }
|
.code-box-demo .ant-picker { margin: 0 8px 12px 0; }
|
||||||
.ant-row-rtl .code-box-demo .ant-picker { margin: 0 0 12px 8px; }
|
.ant-row-rtl .code-box-demo .ant-picker { margin: 0 0 12px 8px; }
|
||||||
|
@ -33,9 +33,7 @@ import moment from 'moment';
|
|||||||
| clearText | 清除按钮的提示文案 | string | clear | |
|
| clearText | 清除按钮的提示文案 | string | clear | |
|
||||||
| defaultValue | 默认时间 | [moment](http://momentjs.com/) | - | |
|
| defaultValue | 默认时间 | [moment](http://momentjs.com/) | - | |
|
||||||
| disabled | 禁用全部操作 | boolean | false | |
|
| disabled | 禁用全部操作 | boolean | false | |
|
||||||
| disabledHours | 禁止选择部分小时选项 | function() | - | |
|
| disabledTime | 不可选择的时间 | [DisabledTime](#DisabledTime) | - | 4.19.0 |
|
||||||
| disabledMinutes | 禁止选择部分分钟选项 | function(selectedHour) | - | |
|
|
||||||
| disabledSeconds | 禁止选择部分秒选项 | function(selectedHour, selectedMinute) | - | |
|
|
||||||
| format | 展示的时间格式 | string | `HH:mm:ss` | |
|
| format | 展示的时间格式 | string | `HH:mm:ss` | |
|
||||||
| getPopupContainer | 定义浮层的容器,默认为 body 上新建 div | function(trigger) | - | |
|
| getPopupContainer | 定义浮层的容器,默认为 body 上新建 div | function(trigger) | - | |
|
||||||
| hideDisabledOptions | 隐藏禁止选择的选项 | boolean | false | |
|
| hideDisabledOptions | 隐藏禁止选择的选项 | boolean | false | |
|
||||||
@ -44,6 +42,7 @@ import moment from 'moment';
|
|||||||
| minuteStep | 分钟选项间隔 | number | 1 | |
|
| minuteStep | 分钟选项间隔 | number | 1 | |
|
||||||
| open | 面板是否打开 | boolean | false | |
|
| open | 面板是否打开 | boolean | false | |
|
||||||
| placeholder | 没有值的时候显示的内容 | string \| \[string, string] | `请选择时间` | |
|
| placeholder | 没有值的时候显示的内容 | string \| \[string, string] | `请选择时间` | |
|
||||||
|
| placement | 选择框弹出的位置 | `bottomLeft` `bottomRight` `topLeft` `topRight` | bottomLeft | |
|
||||||
| popupClassName | 弹出层类名 | string | - | |
|
| popupClassName | 弹出层类名 | string | - | |
|
||||||
| popupStyle | 弹出层样式对象 | object | - | |
|
| popupStyle | 弹出层样式对象 | object | - | |
|
||||||
| renderExtraFooter | 选择框底部显示自定义的内容 | () => ReactNode | - | |
|
| renderExtraFooter | 选择框底部显示自定义的内容 | () => ReactNode | - | |
|
||||||
@ -55,20 +54,44 @@ import moment from 'moment';
|
|||||||
| onChange | 时间发生变化的回调 | function(time: moment, timeString: string): void | - | |
|
| onChange | 时间发生变化的回调 | function(time: moment, timeString: string): void | - | |
|
||||||
| onOpenChange | 面板打开/关闭时的回调 | (open: boolean) => void | - | |
|
| onOpenChange | 面板打开/关闭时的回调 | (open: boolean) => void | - | |
|
||||||
|
|
||||||
|
#### DisabledTime
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
type DisabledTime = (now: Moment) => {
|
||||||
|
disabledHours?: () => number[];
|
||||||
|
disabledMinutes?: (selectedHour: number) => number[];
|
||||||
|
disabledSeconds?: (selectedHour: number, selectedMinute: number) => number[];
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
## 方法
|
## 方法
|
||||||
|
|
||||||
| 名称 | 描述 | 版本 |
|
| 名称 | 描述 | 版本 |
|
||||||
| --- | --- | --- |
|
| ------- | -------- | ---- |
|
||||||
| blur() | 移除焦点 | |
|
| blur() | 移除焦点 | |
|
||||||
| focus() | 获取焦点 | |
|
| focus() | 获取焦点 | |
|
||||||
|
|
||||||
### RangePicker
|
## RangePicker
|
||||||
|
|
||||||
属性与 DatePicker 的 [RangePicker](/components/date-picker/#RangePicker) 相同。还包含以下属性:
|
属性与 DatePicker 的 [RangePicker](/components/date-picker/#RangePicker) 相同。还包含以下属性:
|
||||||
|
|
||||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||||
| --- | --- | --- | --- | --- |
|
| ------------ | -------------------- | --------------------------------------- | ------ | ------ |
|
||||||
| order | 始末时间是否自动排序 | boolean | true | 4.1.0 |
|
| disabledTime | 不可选择的时间 | [RangeDisabledTime](#RangeDisabledTime) | - | 4.19.0 |
|
||||||
|
| order | 始末时间是否自动排序 | boolean | true | 4.1.0 |
|
||||||
|
|
||||||
|
### RangeDisabledTime
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
type RangeDisabledTime = (
|
||||||
|
now: Moment,
|
||||||
|
type = 'start' | 'end',
|
||||||
|
) => {
|
||||||
|
disabledHours?: () => number[];
|
||||||
|
disabledMinutes?: (selectedHour: number) => number[];
|
||||||
|
disabledSeconds?: (selectedHour: number, selectedMinute: number) => number[];
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.code-box-demo .ant-picker { margin: 0 8px 12px 0; }
|
.code-box-demo .ant-picker { margin: 0 8px 12px 0; }
|
||||||
|
@ -4,7 +4,7 @@ import useMergedState from 'rc-util/lib/hooks/useMergedState';
|
|||||||
import { TooltipProps as RcTooltipProps } from 'rc-tooltip/lib/Tooltip';
|
import { TooltipProps as RcTooltipProps } from 'rc-tooltip/lib/Tooltip';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { placements as Placements } from 'rc-tooltip/lib/placements';
|
import { placements as Placements } from 'rc-tooltip/lib/placements';
|
||||||
import getPlacements, { AdjustOverflow, PlacementsConfig } from './placements';
|
import getPlacements, { AdjustOverflow, PlacementsConfig } from '../_util/placements';
|
||||||
import { cloneElement, isValidElement } from '../_util/reactNode';
|
import { cloneElement, isValidElement } from '../_util/reactNode';
|
||||||
import { ConfigContext } from '../config-provider';
|
import { ConfigContext } from '../config-provider';
|
||||||
import { PresetColorType, PresetColorTypes } from '../_util/colors';
|
import { PresetColorType, PresetColorTypes } from '../_util/colors';
|
||||||
@ -166,11 +166,11 @@ const Tooltip = React.forwardRef<unknown, TooltipProps>((props, ref) => {
|
|||||||
const onPopupAlign = (domNode: HTMLElement, align: any) => {
|
const onPopupAlign = (domNode: HTMLElement, align: any) => {
|
||||||
const placements: any = getTooltipPlacements();
|
const placements: any = getTooltipPlacements();
|
||||||
// 当前返回的位置
|
// 当前返回的位置
|
||||||
const placement = Object.keys(placements).filter(
|
const placement = Object.keys(placements).find(
|
||||||
key =>
|
key =>
|
||||||
placements[key].points[0] === align.points[0] &&
|
placements[key].points[0] === align.points[0] &&
|
||||||
placements[key].points[1] === align.points[1],
|
placements[key].points[1] === align.points[1],
|
||||||
)[0];
|
);
|
||||||
if (!placement) {
|
if (!placement) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1144,6 +1144,433 @@ exports[`renders ./components/tree-select/demo/multiple.md extend context correc
|
|||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`renders ./components/tree-select/demo/placement.md extend context correctly 1`] = `
|
||||||
|
Array [
|
||||||
|
<div
|
||||||
|
class="ant-radio-group ant-radio-group-outline"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
class="ant-radio-button-wrapper ant-radio-button-wrapper-checked"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button ant-radio-button-checked"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
checked=""
|
||||||
|
class="ant-radio-button-input"
|
||||||
|
type="radio"
|
||||||
|
value="topLeft"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button-inner"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
topLeft
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<label
|
||||||
|
class="ant-radio-button-wrapper"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
class="ant-radio-button-input"
|
||||||
|
type="radio"
|
||||||
|
value="topRight"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button-inner"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
topRight
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<label
|
||||||
|
class="ant-radio-button-wrapper"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
class="ant-radio-button-input"
|
||||||
|
type="radio"
|
||||||
|
value="bottomLeft"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button-inner"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
bottomLeft
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<label
|
||||||
|
class="ant-radio-button-wrapper"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
class="ant-radio-button-input"
|
||||||
|
type="radio"
|
||||||
|
value="bottomRight"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button-inner"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
bottomRight
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</div>,
|
||||||
|
<br />,
|
||||||
|
<br />,
|
||||||
|
<div
|
||||||
|
class="ant-select ant-tree-select ant-select-single ant-select-allow-clear ant-select-show-arrow ant-select-show-search"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="ant-select-selector"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-select-selection-search"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
aria-autocomplete="list"
|
||||||
|
aria-controls="undefined_list"
|
||||||
|
aria-haspopup="listbox"
|
||||||
|
aria-owns="undefined_list"
|
||||||
|
autocomplete="off"
|
||||||
|
class="ant-select-selection-search-input"
|
||||||
|
role="combobox"
|
||||||
|
type="search"
|
||||||
|
value=""
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="ant-select-selection-placeholder"
|
||||||
|
>
|
||||||
|
Please select
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="ant-select-dropdown ant-tree-select-dropdown"
|
||||||
|
style="opacity:0;pointer-events:none;min-width:300px;max-height:400px;overflow:auto"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="ant-select-tree"
|
||||||
|
role="tree"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<input
|
||||||
|
aria-label="for screen reader"
|
||||||
|
disabled=""
|
||||||
|
style="width:0;height:0;display:flex;overflow:hidden;opacity:0;border:0;padding:0;margin:0"
|
||||||
|
value=""
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
aria-hidden="true"
|
||||||
|
class="ant-select-tree-treenode"
|
||||||
|
style="position:absolute;pointer-events:none;visibility:hidden;height:0;overflow:hidden"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="ant-select-tree-indent"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="ant-select-tree-indent-unit"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="ant-select-tree-list"
|
||||||
|
style="position:relative"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="ant-select-tree-list-holder"
|
||||||
|
style="max-height:256px;overflow-y:auto;overflow-anchor:none"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="ant-select-tree-list-holder-inner"
|
||||||
|
style="display:flex;flex-direction:column"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
aria-grabbed="false"
|
||||||
|
class="ant-select-tree-treenode ant-select-tree-treenode-switcher-open ant-select-tree-treenode-leaf-last"
|
||||||
|
draggable="false"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
aria-hidden="true"
|
||||||
|
class="ant-select-tree-indent"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="ant-select-tree-switcher ant-select-tree-switcher_open"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
aria-label="caret-down"
|
||||||
|
class="anticon anticon-caret-down ant-select-tree-switcher-icon"
|
||||||
|
role="img"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
data-icon="caret-down"
|
||||||
|
fill="currentColor"
|
||||||
|
focusable="false"
|
||||||
|
height="1em"
|
||||||
|
viewBox="0 0 1024 1024"
|
||||||
|
width="1em"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M840.4 300H183.6c-19.7 0-30.7 20.8-18.5 35l328.4 380.8c9.4 10.9 27.5 10.9 37 0L858.9 335c12.2-14.2 1.2-35-18.5-35z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="ant-select-tree-node-content-wrapper ant-select-tree-node-content-wrapper-open"
|
||||||
|
title="parent 1"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-select-tree-title"
|
||||||
|
>
|
||||||
|
parent 1
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
aria-grabbed="false"
|
||||||
|
class="ant-select-tree-treenode ant-select-tree-treenode-switcher-open"
|
||||||
|
draggable="false"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
aria-hidden="true"
|
||||||
|
class="ant-select-tree-indent"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-select-tree-indent-unit ant-select-tree-indent-unit-start ant-select-tree-indent-unit-end"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="ant-select-tree-switcher ant-select-tree-switcher_open"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
aria-label="caret-down"
|
||||||
|
class="anticon anticon-caret-down ant-select-tree-switcher-icon"
|
||||||
|
role="img"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
data-icon="caret-down"
|
||||||
|
fill="currentColor"
|
||||||
|
focusable="false"
|
||||||
|
height="1em"
|
||||||
|
viewBox="0 0 1024 1024"
|
||||||
|
width="1em"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M840.4 300H183.6c-19.7 0-30.7 20.8-18.5 35l328.4 380.8c9.4 10.9 27.5 10.9 37 0L858.9 335c12.2-14.2 1.2-35-18.5-35z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="ant-select-tree-node-content-wrapper ant-select-tree-node-content-wrapper-open"
|
||||||
|
title="parent 1-0"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-select-tree-title"
|
||||||
|
>
|
||||||
|
parent 1-0
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
aria-grabbed="false"
|
||||||
|
class="ant-select-tree-treenode ant-select-tree-treenode-switcher-open"
|
||||||
|
draggable="false"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
aria-hidden="true"
|
||||||
|
class="ant-select-tree-indent"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-select-tree-indent-unit ant-select-tree-indent-unit-start ant-select-tree-indent-unit-end"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="ant-select-tree-indent-unit ant-select-tree-indent-unit-start"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="ant-select-tree-switcher ant-select-tree-switcher-noop"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="ant-select-tree-node-content-wrapper ant-select-tree-node-content-wrapper-normal"
|
||||||
|
title="leaf1"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-select-tree-title"
|
||||||
|
>
|
||||||
|
leaf1
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
aria-grabbed="false"
|
||||||
|
class="ant-select-tree-treenode ant-select-tree-treenode-switcher-open ant-select-tree-treenode-leaf-last"
|
||||||
|
draggable="false"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
aria-hidden="true"
|
||||||
|
class="ant-select-tree-indent"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-select-tree-indent-unit ant-select-tree-indent-unit-start ant-select-tree-indent-unit-end"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="ant-select-tree-indent-unit ant-select-tree-indent-unit-start"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="ant-select-tree-switcher ant-select-tree-switcher-noop"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="ant-select-tree-node-content-wrapper ant-select-tree-node-content-wrapper-normal"
|
||||||
|
title="leaf2"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-select-tree-title"
|
||||||
|
>
|
||||||
|
leaf2
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
aria-grabbed="false"
|
||||||
|
class="ant-select-tree-treenode ant-select-tree-treenode-switcher-open ant-select-tree-treenode-leaf-last"
|
||||||
|
draggable="false"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
aria-hidden="true"
|
||||||
|
class="ant-select-tree-indent"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-select-tree-indent-unit ant-select-tree-indent-unit-start ant-select-tree-indent-unit-end"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="ant-select-tree-switcher ant-select-tree-switcher_open"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
aria-label="caret-down"
|
||||||
|
class="anticon anticon-caret-down ant-select-tree-switcher-icon"
|
||||||
|
role="img"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
data-icon="caret-down"
|
||||||
|
fill="currentColor"
|
||||||
|
focusable="false"
|
||||||
|
height="1em"
|
||||||
|
viewBox="0 0 1024 1024"
|
||||||
|
width="1em"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M840.4 300H183.6c-19.7 0-30.7 20.8-18.5 35l328.4 380.8c9.4 10.9 27.5 10.9 37 0L858.9 335c12.2-14.2 1.2-35-18.5-35z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="ant-select-tree-node-content-wrapper ant-select-tree-node-content-wrapper-open"
|
||||||
|
title="parent 1-1"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-select-tree-title"
|
||||||
|
>
|
||||||
|
parent 1-1
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
aria-grabbed="false"
|
||||||
|
class="ant-select-tree-treenode ant-select-tree-treenode-switcher-open ant-select-tree-treenode-leaf-last"
|
||||||
|
draggable="false"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
aria-hidden="true"
|
||||||
|
class="ant-select-tree-indent"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-select-tree-indent-unit ant-select-tree-indent-unit-start ant-select-tree-indent-unit-end"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="ant-select-tree-indent-unit ant-select-tree-indent-unit-end"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="ant-select-tree-switcher ant-select-tree-switcher-noop"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="ant-select-tree-node-content-wrapper ant-select-tree-node-content-wrapper-normal"
|
||||||
|
title=""
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-select-tree-title"
|
||||||
|
>
|
||||||
|
<b
|
||||||
|
style="color:#08c"
|
||||||
|
>
|
||||||
|
leaf3
|
||||||
|
</b>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
aria-hidden="true"
|
||||||
|
class="ant-select-arrow"
|
||||||
|
style="user-select:none;-webkit-user-select:none"
|
||||||
|
unselectable="on"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
aria-label="down"
|
||||||
|
class="anticon anticon-down ant-select-suffix"
|
||||||
|
role="img"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
data-icon="down"
|
||||||
|
fill="currentColor"
|
||||||
|
focusable="false"
|
||||||
|
height="1em"
|
||||||
|
viewBox="64 64 896 896"
|
||||||
|
width="1em"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</div>,
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`renders ./components/tree-select/demo/suffix.md extend context correctly 1`] = `
|
exports[`renders ./components/tree-select/demo/suffix.md extend context correctly 1`] = `
|
||||||
<div
|
<div
|
||||||
class="ant-select ant-tree-select ant-select-single ant-select-allow-clear ant-select-show-arrow ant-select-show-search"
|
class="ant-select ant-tree-select ant-select-single ant-select-allow-clear ant-select-show-arrow ant-select-show-search"
|
||||||
|
@ -257,6 +257,148 @@ exports[`renders ./components/tree-select/demo/multiple.md correctly 1`] = `
|
|||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`renders ./components/tree-select/demo/placement.md correctly 1`] = `
|
||||||
|
Array [
|
||||||
|
<div
|
||||||
|
class="ant-radio-group ant-radio-group-outline"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
class="ant-radio-button-wrapper ant-radio-button-wrapper-checked"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button ant-radio-button-checked"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
checked=""
|
||||||
|
class="ant-radio-button-input"
|
||||||
|
type="radio"
|
||||||
|
value="topLeft"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button-inner"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
topLeft
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<label
|
||||||
|
class="ant-radio-button-wrapper"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
class="ant-radio-button-input"
|
||||||
|
type="radio"
|
||||||
|
value="topRight"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button-inner"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
topRight
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<label
|
||||||
|
class="ant-radio-button-wrapper"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
class="ant-radio-button-input"
|
||||||
|
type="radio"
|
||||||
|
value="bottomLeft"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button-inner"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
bottomLeft
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<label
|
||||||
|
class="ant-radio-button-wrapper"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
class="ant-radio-button-input"
|
||||||
|
type="radio"
|
||||||
|
value="bottomRight"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="ant-radio-button-inner"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
bottomRight
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</div>,
|
||||||
|
<br />,
|
||||||
|
<br />,
|
||||||
|
<div
|
||||||
|
class="ant-select ant-tree-select ant-select-single ant-select-allow-clear ant-select-show-arrow ant-select-show-search"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="ant-select-selector"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-select-selection-search"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
aria-autocomplete="list"
|
||||||
|
aria-controls="undefined_list"
|
||||||
|
aria-haspopup="listbox"
|
||||||
|
aria-owns="undefined_list"
|
||||||
|
autocomplete="off"
|
||||||
|
class="ant-select-selection-search-input"
|
||||||
|
role="combobox"
|
||||||
|
type="search"
|
||||||
|
value=""
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="ant-select-selection-placeholder"
|
||||||
|
>
|
||||||
|
Please select
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
aria-hidden="true"
|
||||||
|
class="ant-select-arrow"
|
||||||
|
style="user-select:none;-webkit-user-select:none"
|
||||||
|
unselectable="on"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
aria-label="down"
|
||||||
|
class="anticon anticon-down ant-select-suffix"
|
||||||
|
role="img"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
data-icon="down"
|
||||||
|
fill="currentColor"
|
||||||
|
focusable="false"
|
||||||
|
height="1em"
|
||||||
|
viewBox="64 64 896 896"
|
||||||
|
width="1em"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</div>,
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`renders ./components/tree-select/demo/suffix.md correctly 1`] = `
|
exports[`renders ./components/tree-select/demo/suffix.md correctly 1`] = `
|
||||||
<div
|
<div
|
||||||
class="ant-select ant-tree-select ant-select-single ant-select-allow-clear ant-select-show-arrow ant-select-show-search"
|
class="ant-select ant-tree-select ant-select-single ant-select-allow-clear ant-select-show-arrow ant-select-show-search"
|
||||||
|
64
components/tree-select/demo/placement.md
Normal file
64
components/tree-select/demo/placement.md
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
---
|
||||||
|
order: 8
|
||||||
|
title:
|
||||||
|
zh-CN: 弹出位置
|
||||||
|
en-US: Placement
|
||||||
|
---
|
||||||
|
|
||||||
|
## zh-CN
|
||||||
|
|
||||||
|
可以通过 `placement` 手动指定弹出的位置。
|
||||||
|
|
||||||
|
## en-US
|
||||||
|
|
||||||
|
You can manually specify the position of the popup via `placement`.
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
import { TreeSelect, Radio } from 'antd';
|
||||||
|
|
||||||
|
const { TreeNode } = TreeSelect;
|
||||||
|
|
||||||
|
const Demo = () => {
|
||||||
|
const [placement, SetPlacement] = useState('topLeft');
|
||||||
|
|
||||||
|
const placementChange = e => {
|
||||||
|
SetPlacement(e.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Radio.Group value={placement} onChange={placementChange}>
|
||||||
|
<Radio.Button value="topLeft">topLeft</Radio.Button>
|
||||||
|
<Radio.Button value="topRight">topRight</Radio.Button>
|
||||||
|
<Radio.Button value="bottomLeft">bottomLeft</Radio.Button>
|
||||||
|
<Radio.Button value="bottomRight">bottomRight</Radio.Button>
|
||||||
|
</Radio.Group>
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<TreeSelect
|
||||||
|
showSearch
|
||||||
|
dropdownStyle={{ maxHeight: 400, overflow: 'auto', minWidth: 300 }}
|
||||||
|
placeholder="Please select"
|
||||||
|
dropdownMatchSelectWidth={false}
|
||||||
|
placement={placement}
|
||||||
|
allowClear
|
||||||
|
treeDefaultExpandAll
|
||||||
|
>
|
||||||
|
<TreeNode value="parent 1" title="parent 1">
|
||||||
|
<TreeNode value="parent 1-0" title="parent 1-0">
|
||||||
|
<TreeNode value="leaf1" title="leaf1" />
|
||||||
|
<TreeNode value="leaf2" title="leaf2" />
|
||||||
|
</TreeNode>
|
||||||
|
<TreeNode value="parent 1-1" title="parent 1-1">
|
||||||
|
<TreeNode value="leaf3" title={<b style={{ color: '#08c' }}>leaf3</b>} />
|
||||||
|
</TreeNode>
|
||||||
|
</TreeNode>
|
||||||
|
</TreeSelect>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
ReactDOM.render(<Demo />, mountNode);
|
||||||
|
```
|
@ -37,6 +37,7 @@ Tree selection control.
|
|||||||
| multiple | Support multiple or not, will be `true` when enable `treeCheckable` | boolean | false | |
|
| multiple | Support multiple or not, will be `true` when enable `treeCheckable` | boolean | false | |
|
||||||
| notFoundContent | Specify content to show when no result matches | ReactNode | `Not Found` | |
|
| notFoundContent | Specify content to show when no result matches | ReactNode | `Not Found` | |
|
||||||
| placeholder | Placeholder of the select input | string | - | |
|
| placeholder | Placeholder of the select input | string | - | |
|
||||||
|
| placement | The position where the selection box pops up | `bottomLeft` `bottomRight` `topLeft` `topRight` | bottomLeft | |
|
||||||
| searchValue | Work with `onSearch` to make search value controlled | string | - | |
|
| searchValue | Work with `onSearch` to make search value controlled | string | - | |
|
||||||
| showArrow | Whether to show the `suffixIcon`,when single selection mode, default `true` | boolean | - | |
|
| showArrow | Whether to show the `suffixIcon`,when single selection mode, default `true` | boolean | - | |
|
||||||
| showCheckedStrategy | The way show selected item in box when `treeCheckable` set. **Default:** just show child nodes. **`TreeSelect.SHOW_ALL`:** show all checked treeNodes (include parent treeNode). **`TreeSelect.SHOW_PARENT`:** show checked treeNodes (just show parent treeNode) | `TreeSelect.SHOW_ALL` \| `TreeSelect.SHOW_PARENT` \| `TreeSelect.SHOW_CHILD` | `TreeSelect.SHOW_CHILD` | |
|
| showCheckedStrategy | The way show selected item in box when `treeCheckable` set. **Default:** just show child nodes. **`TreeSelect.SHOW_ALL`:** show all checked treeNodes (include parent treeNode). **`TreeSelect.SHOW_PARENT`:** show checked treeNodes (just show parent treeNode) | `TreeSelect.SHOW_ALL` \| `TreeSelect.SHOW_PARENT` \| `TreeSelect.SHOW_CHILD` | `TreeSelect.SHOW_CHILD` | |
|
||||||
|
@ -16,7 +16,7 @@ import { AntTreeNodeProps, TreeProps } from '../tree';
|
|||||||
import getIcons from '../select/utils/iconUtil';
|
import getIcons from '../select/utils/iconUtil';
|
||||||
import renderSwitcherIcon from '../tree/utils/iconUtil';
|
import renderSwitcherIcon from '../tree/utils/iconUtil';
|
||||||
import SizeContext, { SizeType } from '../config-provider/SizeContext';
|
import SizeContext, { SizeType } from '../config-provider/SizeContext';
|
||||||
import { getTransitionName } from '../_util/motion';
|
import { getTransitionName, getTransitionDirection, SelectCommonPlacement } from '../_util/motion';
|
||||||
|
|
||||||
type RawValue = string | number;
|
type RawValue = string | number;
|
||||||
|
|
||||||
@ -43,6 +43,7 @@ export interface TreeSelectProps<
|
|||||||
> {
|
> {
|
||||||
suffixIcon?: React.ReactNode;
|
suffixIcon?: React.ReactNode;
|
||||||
size?: SizeType;
|
size?: SizeType;
|
||||||
|
placement?: SelectCommonPlacement;
|
||||||
bordered?: boolean;
|
bordered?: boolean;
|
||||||
treeLine?: TreeProps['showLine'];
|
treeLine?: TreeProps['showLine'];
|
||||||
}
|
}
|
||||||
@ -57,6 +58,7 @@ const InternalTreeSelect = <OptionType extends BaseOptionType | DefaultOptionTyp
|
|||||||
multiple,
|
multiple,
|
||||||
listHeight = 256,
|
listHeight = 256,
|
||||||
listItemHeight = 26,
|
listItemHeight = 26,
|
||||||
|
placement,
|
||||||
notFoundContent,
|
notFoundContent,
|
||||||
switcherIcon,
|
switcherIcon,
|
||||||
treeLine,
|
treeLine,
|
||||||
@ -119,6 +121,16 @@ const InternalTreeSelect = <OptionType extends BaseOptionType | DefaultOptionTyp
|
|||||||
'switcherIcon',
|
'switcherIcon',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// ===================== Placement =====================
|
||||||
|
const getPlacement = () => {
|
||||||
|
if (placement !== undefined) {
|
||||||
|
return placement;
|
||||||
|
}
|
||||||
|
return direction === 'rtl'
|
||||||
|
? ('bottomRight' as SelectCommonPlacement)
|
||||||
|
: ('bottomLeft' as SelectCommonPlacement);
|
||||||
|
};
|
||||||
|
|
||||||
const mergedSize = customizeSize || size;
|
const mergedSize = customizeSize || size;
|
||||||
const mergedClassName = classNames(
|
const mergedClassName = classNames(
|
||||||
!customizePrefixCls && treeSelectPrefixCls,
|
!customizePrefixCls && treeSelectPrefixCls,
|
||||||
@ -148,6 +160,7 @@ const InternalTreeSelect = <OptionType extends BaseOptionType | DefaultOptionTyp
|
|||||||
treeLine={!!treeLine}
|
treeLine={!!treeLine}
|
||||||
inputIcon={suffixIcon}
|
inputIcon={suffixIcon}
|
||||||
multiple={multiple}
|
multiple={multiple}
|
||||||
|
placement={getPlacement()}
|
||||||
removeIcon={removeIcon}
|
removeIcon={removeIcon}
|
||||||
clearIcon={clearIcon}
|
clearIcon={clearIcon}
|
||||||
switcherIcon={(nodeProps: AntTreeNodeProps) =>
|
switcherIcon={(nodeProps: AntTreeNodeProps) =>
|
||||||
@ -159,7 +172,11 @@ const InternalTreeSelect = <OptionType extends BaseOptionType | DefaultOptionTyp
|
|||||||
treeMotion={null}
|
treeMotion={null}
|
||||||
dropdownClassName={mergedDropdownClassName}
|
dropdownClassName={mergedDropdownClassName}
|
||||||
choiceTransitionName={getTransitionName(rootPrefixCls, '', choiceTransitionName)}
|
choiceTransitionName={getTransitionName(rootPrefixCls, '', choiceTransitionName)}
|
||||||
transitionName={getTransitionName(rootPrefixCls, 'slide-up', transitionName)}
|
transitionName={getTransitionName(
|
||||||
|
rootPrefixCls,
|
||||||
|
getTransitionDirection(placement),
|
||||||
|
transitionName,
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -38,6 +38,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/Ax4DA0njr/TreeSelect.svg
|
|||||||
| multiple | 支持多选(当设置 treeCheckable 时自动变为 true) | boolean | false | |
|
| multiple | 支持多选(当设置 treeCheckable 时自动变为 true) | boolean | false | |
|
||||||
| notFoundContent | 当下拉列表为空时显示的内容 | ReactNode | `Not Found` | |
|
| notFoundContent | 当下拉列表为空时显示的内容 | ReactNode | `Not Found` | |
|
||||||
| placeholder | 选择框默认文字 | string | - | |
|
| placeholder | 选择框默认文字 | string | - | |
|
||||||
|
| placement | 选择框弹出的位置 | `bottomLeft` `bottomRight` `topLeft` `topRight` | bottomLeft | |
|
||||||
| searchValue | 搜索框的值,可以通过 `onSearch` 获取用户输入 | string | - | |
|
| searchValue | 搜索框的值,可以通过 `onSearch` 获取用户输入 | string | - | |
|
||||||
| showArrow | 是否显示 `suffixIcon`,单选模式下默认 `true` | boolean | - | |
|
| showArrow | 是否显示 `suffixIcon`,单选模式下默认 `true` | boolean | - | |
|
||||||
| showCheckedStrategy | 配置 `treeCheckable` 时,定义选中项回填的方式。`TreeSelect.SHOW_ALL`: 显示所有选中节点(包括父节点)。`TreeSelect.SHOW_PARENT`: 只显示父节点(当父节点下所有子节点都选中时)。 默认只显示子节点 | `TreeSelect.SHOW_ALL` \| `TreeSelect.SHOW_PARENT` \| `TreeSelect.SHOW_CHILD` | `TreeSelect.SHOW_CHILD` | |
|
| showCheckedStrategy | 配置 `treeCheckable` 时,定义选中项回填的方式。`TreeSelect.SHOW_ALL`: 显示所有选中节点(包括父节点)。`TreeSelect.SHOW_PARENT`: 只显示父节点(当父节点下所有子节点都选中时)。 默认只显示子节点 | `TreeSelect.SHOW_ALL` \| `TreeSelect.SHOW_PARENT` \| `TreeSelect.SHOW_CHILD` | `TreeSelect.SHOW_CHILD` | |
|
||||||
|
@ -135,7 +135,7 @@
|
|||||||
"rc-motion": "^2.4.4",
|
"rc-motion": "^2.4.4",
|
||||||
"rc-notification": "~4.5.7",
|
"rc-notification": "~4.5.7",
|
||||||
"rc-pagination": "~3.1.9",
|
"rc-pagination": "~3.1.9",
|
||||||
"rc-picker": "~2.5.17",
|
"rc-picker": "~2.6.0",
|
||||||
"rc-progress": "~3.2.1",
|
"rc-progress": "~3.2.1",
|
||||||
"rc-rate": "~2.9.0",
|
"rc-rate": "~2.9.0",
|
||||||
"rc-resize-observer": "^1.2.0",
|
"rc-resize-observer": "^1.2.0",
|
||||||
|
@ -523,7 +523,7 @@ class MainContent extends Component {
|
|||||||
</section>
|
</section>
|
||||||
{componentPage && (
|
{componentPage && (
|
||||||
<div className="fixed-widgets">
|
<div className="fixed-widgets">
|
||||||
<Dropdown overlay={this.getThemeSwitchMenu()} placement="topCenter">
|
<Dropdown overlay={this.getThemeSwitchMenu()} placement="top">
|
||||||
<Avatar className="fixed-widgets-avatar" size={44} icon={<ThemeIcon />} />
|
<Avatar className="fixed-widgets-avatar" size={44} icon={<ThemeIcon />} />
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user