mirror of
https://gitee.com/ant-design/ant-design.git
synced 2024-11-30 02:59:04 +08:00
resolve merge confilct
This commit is contained in:
commit
e6b4708f04
@ -186,7 +186,7 @@
|
||||
}
|
||||
|
||||
a:not(.@{ant-prefix}-btn),
|
||||
> .anticon {
|
||||
> .@{iconfont-css-prefix} {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
color: @text-color-secondary;
|
||||
@ -198,7 +198,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
> .anticon {
|
||||
> .@{iconfont-css-prefix} {
|
||||
font-size: @card-action-icon-size;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import { SmileOutlined } from '@ant-design/icons';
|
||||
import ConfigProvider, { ConfigContext } from '..';
|
||||
import Button from '../../button';
|
||||
import Table from '../../table';
|
||||
@ -56,6 +57,17 @@ describe('ConfigProvider', () => {
|
||||
expect(wrapper.find('button').props().className).toEqual('bamboo-btn');
|
||||
});
|
||||
|
||||
it('iconPrefixCls', () => {
|
||||
const wrapper = mount(
|
||||
<ConfigProvider iconPrefixCls="bamboo">
|
||||
<SmileOutlined />
|
||||
</ConfigProvider>,
|
||||
);
|
||||
|
||||
expect(wrapper.find('[role="img"]').hasClass('bamboo')).toBeTruthy();
|
||||
expect(wrapper.find('[role="img"]').hasClass('bamboo-smile')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('input autoComplete', () => {
|
||||
const wrapper = mount(
|
||||
<ConfigProvider input={{ autoComplete: 'off' }}>
|
||||
|
@ -14,6 +14,7 @@ export interface ConfigConsumerProps {
|
||||
getTargetContainer?: () => HTMLElement;
|
||||
getPopupContainer?: (triggerNode: HTMLElement) => HTMLElement;
|
||||
rootPrefixCls?: string;
|
||||
iconPrefixCls?: string;
|
||||
getPrefixCls: (suffixCls?: string, customizePrefixCls?: string) => string;
|
||||
renderEmpty: RenderEmptyHandler;
|
||||
csp?: CSPConfig;
|
||||
|
32
components/config-provider/demo/prefixCls.md
Normal file
32
components/config-provider/demo/prefixCls.md
Normal file
@ -0,0 +1,32 @@
|
||||
---
|
||||
order: 99
|
||||
title:
|
||||
zh-CN: 前缀
|
||||
en-US: prefixCls
|
||||
debug: true
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
修改组件和图标前缀。
|
||||
|
||||
## en-US
|
||||
|
||||
Config component and icon prefixCls.
|
||||
|
||||
```jsx
|
||||
import { ConfigProvider, Select } from 'antd';
|
||||
import { SmileOutlined } from '@ant-design/icons';
|
||||
|
||||
// Ant Design site use `es` module for view
|
||||
// but do not replace related lib `lib` with `es`
|
||||
// which do not show correct in site.
|
||||
// We may need do convert in site also.
|
||||
const FormSizeDemo = () => (
|
||||
<ConfigProvider prefixCls="light" iconPrefixCls="bamboo">
|
||||
<SmileOutlined />
|
||||
<Select />
|
||||
</ConfigProvider>
|
||||
);
|
||||
ReactDOM.render(<FormSizeDemo />, mountNode);
|
||||
```
|
@ -46,6 +46,7 @@ Some components use dynamic style to support wave effect. You can config `csp` p
|
||||
| form | Set Form common props | { validateMessages?: [ValidateMessages](/components/form/#validateMessages), requiredMark?: boolean \| `optional` } | - | requiredMark: 4.8.0 |
|
||||
| getPopupContainer | To set the container of the popup element. The default is to create a `div` element in `body` | function(triggerNode) | () => document.body | |
|
||||
| getTargetContainer | Config Affix, Anchor scroll target container | () => HTMLElement | () => window | 4.2.0 |
|
||||
| iconPrefixCls | Set icon prefix className (cooperated with [@iconfont-css-prefix](https://github.com/ant-design/ant-design/blob/d943b85a523bdf181dabc12c928226f3b4b893de/components/style/themes/default.less#L106)) | string | `anticon` | 4.11.0 |
|
||||
| input | Set Input common props | { autoComplete?: string } | - | 4.2.0 |
|
||||
| locale | Language package setting, you can find the packages in [antd/lib/locale](http://unpkg.com/antd/lib/locale/) | object | - | |
|
||||
| pageHeader | Unify the ghost of PageHeader, ref [PageHeader](/components/page-header) | { ghost: boolean } | true | |
|
||||
|
@ -1,4 +1,5 @@
|
||||
import * as React from 'react';
|
||||
import { IconProvider } from '@ant-design/icons/lib/'; // keep last '/' since antd-tools need this
|
||||
import { FormProvider as RcFormProvider } from 'rc-field-form';
|
||||
import { ValidateMessages } from 'rc-field-form/lib/interface';
|
||||
import useMemo from 'rc-util/lib/hooks/useMemo';
|
||||
@ -38,10 +39,21 @@ export const configConsumerProps = [
|
||||
'pageHeader',
|
||||
];
|
||||
|
||||
// These props is used by `useContext` directly in sub component
|
||||
const PASSED_PROPS: Exclude<keyof ConfigConsumerProps, 'rootPrefixCls' | 'getPrefixCls'>[] = [
|
||||
'getTargetContainer',
|
||||
'getPopupContainer',
|
||||
'renderEmpty',
|
||||
'pageHeader',
|
||||
'input',
|
||||
'form',
|
||||
];
|
||||
|
||||
export interface ConfigProviderProps {
|
||||
getTargetContainer?: () => HTMLElement;
|
||||
getPopupContainer?: (triggerNode: HTMLElement) => HTMLElement;
|
||||
prefixCls?: string;
|
||||
iconPrefixCls?: string;
|
||||
children?: React.ReactNode;
|
||||
renderEmpty?: RenderEmptyHandler;
|
||||
csp?: CSPConfig;
|
||||
@ -74,15 +86,10 @@ interface ProviderChildrenProps extends ConfigProviderProps {
|
||||
const ProviderChildren: React.FC<ProviderChildrenProps> = props => {
|
||||
const {
|
||||
children,
|
||||
getTargetContainer,
|
||||
getPopupContainer,
|
||||
renderEmpty,
|
||||
csp,
|
||||
autoInsertSpaceInButton,
|
||||
form,
|
||||
input,
|
||||
locale,
|
||||
pageHeader,
|
||||
componentSize,
|
||||
direction,
|
||||
space,
|
||||
@ -90,6 +97,7 @@ const ProviderChildren: React.FC<ProviderChildrenProps> = props => {
|
||||
dropdownMatchSelectWidth,
|
||||
legacyLocale,
|
||||
parentContext,
|
||||
iconPrefixCls,
|
||||
} = props;
|
||||
|
||||
const getPrefixCls = React.useCallback(
|
||||
@ -116,29 +124,15 @@ const ProviderChildren: React.FC<ProviderChildrenProps> = props => {
|
||||
dropdownMatchSelectWidth,
|
||||
getPrefixCls,
|
||||
};
|
||||
if (getTargetContainer) {
|
||||
config.getTargetContainer = getTargetContainer;
|
||||
}
|
||||
|
||||
if (getPopupContainer) {
|
||||
config.getPopupContainer = getPopupContainer;
|
||||
}
|
||||
|
||||
if (renderEmpty) {
|
||||
config.renderEmpty = renderEmpty;
|
||||
}
|
||||
|
||||
if (pageHeader) {
|
||||
config.pageHeader = pageHeader;
|
||||
}
|
||||
|
||||
if (input) {
|
||||
config.input = input;
|
||||
}
|
||||
|
||||
if (form) {
|
||||
config.form = form;
|
||||
}
|
||||
// Pass the props used by `useContext` directly with child component.
|
||||
// These props should merged into `config`.
|
||||
PASSED_PROPS.forEach(propName => {
|
||||
const propValue: any = props[propName];
|
||||
if (propValue) {
|
||||
(config as any)[propName] = propValue;
|
||||
}
|
||||
});
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/27617
|
||||
const memoedConfig = useMemo(
|
||||
@ -169,20 +163,23 @@ const ProviderChildren: React.FC<ProviderChildrenProps> = props => {
|
||||
childNode = <RcFormProvider validateMessages={validateMessages}>{children}</RcFormProvider>;
|
||||
}
|
||||
|
||||
const childrenWithLocale =
|
||||
locale === undefined ? (
|
||||
childNode
|
||||
) : (
|
||||
if (locale) {
|
||||
childNode = (
|
||||
<LocaleProvider locale={locale} _ANT_MARK__={ANT_MARK}>
|
||||
{childNode}
|
||||
</LocaleProvider>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<SizeContextProvider size={componentSize}>
|
||||
<ConfigContext.Provider value={memoedConfig}>{childrenWithLocale}</ConfigContext.Provider>
|
||||
</SizeContextProvider>
|
||||
);
|
||||
if (iconPrefixCls) {
|
||||
childNode = <IconProvider value={{ prefixCls: iconPrefixCls }}>{childNode}</IconProvider>;
|
||||
}
|
||||
|
||||
if (componentSize) {
|
||||
childNode = <SizeContextProvider size={componentSize}>{childNode}</SizeContextProvider>;
|
||||
}
|
||||
|
||||
return <ConfigContext.Provider value={memoedConfig}>{childNode}</ConfigContext.Provider>;
|
||||
};
|
||||
|
||||
const ConfigProvider: React.FC<ConfigProviderProps> & {
|
||||
|
@ -47,6 +47,7 @@ export default () => (
|
||||
| form | 设置 Form 组件的通用属性 | { validateMessages?: [ValidateMessages](/components/form/#validateMessages), requiredMark?: boolean \| `optional` } | - | requiredMark: 4.8.0 |
|
||||
| getPopupContainer | 弹出框(Select, Tooltip, Menu 等等)渲染父节点,默认渲染到 body 上。 | function(triggerNode) | () => document.body | |
|
||||
| getTargetContainer | 配置 Affix、Anchor 滚动监听容器。 | () => HTMLElement | () => window | 4.2.0 |
|
||||
| iconPrefixCls | 设置图标统一样式前缀。注意:需要配合 `less` 变量 [@iconfont-css-prefix](https://github.com/ant-design/ant-design/blob/d943b85a523bdf181dabc12c928226f3b4b893de/components/style/themes/default.less#L106) 使用 | string | `anticon` | 4.11.0 |
|
||||
| input | 设置 Input 组件的通用属性 | { autoComplete?: string } | - | 4.2.0 |
|
||||
| locale | 语言包配置,语言包可到 [antd/lib/locale](http://unpkg.com/antd/lib/locale/) 目录下寻找 | object | - | |
|
||||
| pageHeader | 统一设置 PageHeader 的 ghost,参考 [PageHeader](/components/page-header) | { ghost: boolean } | true | |
|
||||
|
@ -47,8 +47,8 @@
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
> .anticon:first-child,
|
||||
> span > .anticon:first-child {
|
||||
> .@{iconfont-css-prefix}:first-child,
|
||||
> span > .@{iconfont-css-prefix}:first-child {
|
||||
.@{dropdown-prefix-cls}-rtl & {
|
||||
margin-right: 0;
|
||||
margin-left: 8px;
|
||||
|
@ -156,6 +156,55 @@ exports[`renders ./components/image/demo/placeholder.md correctly 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/image/demo/preview-mask.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-image"
|
||||
style="width:96px"
|
||||
>
|
||||
<img
|
||||
class="ant-image-img"
|
||||
src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png"
|
||||
/>
|
||||
<div
|
||||
class="ant-image-mask customize-mask"
|
||||
>
|
||||
<div
|
||||
class="ant-space ant-space-vertical ant-space-align-center"
|
||||
>
|
||||
<div
|
||||
class="ant-space-item"
|
||||
style="margin-bottom:8px"
|
||||
>
|
||||
<span
|
||||
aria-label="zoom-in"
|
||||
class="anticon anticon-zoom-in"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="zoom-in"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M637 443H519V309c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v134H325c-4.4 0-8 3.6-8 8v60c0 4.4 3.6 8 8 8h118v134c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V519h118c4.4 0 8-3.6 8-8v-60c0-4.4-3.6-8-8-8zm284 424L775 721c122.1-148.9 113.6-369.5-26-509-148-148.1-388.4-148.1-537 0-148.1 148.6-148.1 389 0 537 139.5 139.6 360.1 148.1 509 26l146 146c3.2 2.8 8.3 2.8 11 0l43-43c2.8-2.7 2.8-7.8 0-11zM696 696c-118.8 118.7-311.2 118.7-430 0-118.7-118.8-118.7-311.2 0-430 118.8-118.7 311.2-118.7 430 0 118.7 118.8 118.7 311.2 0 430z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-space-item"
|
||||
>
|
||||
示例
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/image/demo/previewGroup.md correctly 1`] = `
|
||||
Array [
|
||||
<div
|
||||
|
51
components/image/demo/preview-mask.md
Normal file
51
components/image/demo/preview-mask.md
Normal file
@ -0,0 +1,51 @@
|
||||
---
|
||||
order: 99
|
||||
title:
|
||||
zh-CN: 自定义预览文本
|
||||
en-US: Custom preview mask
|
||||
debug: true
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
自定义预览文本。
|
||||
|
||||
## en-US
|
||||
|
||||
Custom preview mask.
|
||||
|
||||
```tsx
|
||||
import React from 'react';
|
||||
import { Image, Space } from 'antd';
|
||||
import { ZoomInOutlined } from '@ant-design/icons';
|
||||
|
||||
function ImageDemo() {
|
||||
return (
|
||||
<Image
|
||||
width={96}
|
||||
src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png"
|
||||
preview={{
|
||||
maskClassName: 'customize-mask',
|
||||
mask: (
|
||||
<Space direction="vertical" align="center">
|
||||
<ZoomInOutlined />
|
||||
示例
|
||||
</Space>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
ReactDOM.render(<ImageDemo />, mountNode);
|
||||
```
|
||||
|
||||
```css
|
||||
.customize-mask {
|
||||
opacity: 1;
|
||||
font-size: 20px;
|
||||
}
|
||||
.customize-mask .anticon {
|
||||
font-size: 32px;
|
||||
}
|
||||
```
|
@ -33,6 +33,8 @@ Previewable image.
|
||||
onVisibleChange?: (visible, prevVisible) => void;
|
||||
getContainer?: string | HTMLElement | (() => HTMLElement); // V4.8.0
|
||||
src?: string; // V4.10.0
|
||||
mask?: ReactNode; // V4.9.0
|
||||
maskClassName?: string; // V4.11.0
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -34,6 +34,8 @@ cover: https://gw.alipayobjects.com/zos/antfincdn/D1dXz9PZqa/image.svg
|
||||
onVisibleChange?: (visible, prevVisible) => void;
|
||||
getContainer?: string | HTMLElement | (() => HTMLElement); // V4.8.0
|
||||
src?: string; // V4.10.0
|
||||
mask?: ReactNode; // V4.9.0
|
||||
maskClassName?: string; // V4.11.0
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -148,11 +148,11 @@
|
||||
&-disabled {
|
||||
color: @image-preview-operation-disabled-color;
|
||||
cursor: not-allowed;
|
||||
> .anticon {
|
||||
> .@{iconfont-css-prefix} {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
> .anticon {
|
||||
> .@{iconfont-css-prefix} {
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@
|
||||
}
|
||||
|
||||
&-dark &-inline&-sub {
|
||||
background: @menu-dark-submenu-bg;
|
||||
background: @menu-dark-inline-submenu-bg;
|
||||
}
|
||||
|
||||
&-dark&-horizontal {
|
||||
|
@ -542,6 +542,7 @@
|
||||
|
||||
&-sub&-inline {
|
||||
padding: 0;
|
||||
background: @menu-inline-submenu-bg;
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
box-shadow: none;
|
||||
|
@ -50,6 +50,14 @@ describe('PageHeader', () => {
|
||||
expect(wrapper.find('.ant-page-header-back')).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('pageHeader support breadcrumbRender', () => {
|
||||
const wrapper = mount(
|
||||
<PageHeader title="Page Title" breadcrumbRender={() => <div id="test">test</div>} />,
|
||||
);
|
||||
expect(wrapper.find('#test')).toHaveLength(1);
|
||||
expect(wrapper.find('.ant-page-header-back')).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('pageHeader do not has title', () => {
|
||||
const routes = [
|
||||
{
|
||||
|
@ -20,6 +20,7 @@ PageHeader can be used to highlight the page topic, display important informatio
|
||||
| avatar | Avatar next to the title bar | [AvatarProps](/components/avatar/) | - | |
|
||||
| backIcon | Custom back icon, if false the back icon will not be displayed | ReactNode \| boolean | <ArrowLeft /> | |
|
||||
| breadcrumb | Breadcrumb configuration | [Breadcrumb](/components/breadcrumb/) | - | |
|
||||
| breadcrumbRender | Customize the content of the breadcrumb area | `(props, originBreadcrumb)=> ReactNode` | - | 4.11.0 |
|
||||
| extra | Operating area, at the end of the line of the title line | ReactNode | - | |
|
||||
| footer | PageHeader's footer, generally used to render TabBar | ReactNode | - | |
|
||||
| ghost | PageHeader type, will change background color | boolean | true | |
|
||||
|
@ -17,6 +17,7 @@ export interface PageHeaderProps {
|
||||
subTitle?: React.ReactNode;
|
||||
style?: React.CSSProperties;
|
||||
breadcrumb?: BreadcrumbProps;
|
||||
breadcrumbRender?: (props: PageHeaderProps, defaultDom: React.ReactNode) => React.ReactNode;
|
||||
tags?: React.ReactElement<TagType> | React.ReactElement<TagType>[];
|
||||
footer?: React.ReactNode;
|
||||
extra?: React.ReactNode;
|
||||
@ -72,7 +73,7 @@ const renderTitle = (
|
||||
const { title, avatar, subTitle, tags, extra, onBack } = props;
|
||||
const headingPrefixCls = `${prefixCls}-heading`;
|
||||
const hasHeading = title || subTitle || tags || extra;
|
||||
// 如果 什么都没有,直接返回一个 null
|
||||
// If there is nothing, return a null
|
||||
if (!hasHeading) {
|
||||
return null;
|
||||
}
|
||||
@ -134,6 +135,7 @@ const PageHeader: React.FC<PageHeaderProps> = props => {
|
||||
footer,
|
||||
children,
|
||||
breadcrumb,
|
||||
breadcrumbRender,
|
||||
className: customizeClassName,
|
||||
} = props;
|
||||
let ghost: undefined | boolean = true;
|
||||
@ -146,7 +148,20 @@ const PageHeader: React.FC<PageHeaderProps> = props => {
|
||||
}
|
||||
|
||||
const prefixCls = getPrefixCls('page-header', customizePrefixCls);
|
||||
const breadcrumbDom = breadcrumb && breadcrumb.routes ? renderBreadcrumb(breadcrumb) : null;
|
||||
|
||||
const getDefaultBreadcrumbDom = () => {
|
||||
if ((breadcrumb as BreadcrumbProps)?.routes) {
|
||||
return renderBreadcrumb(breadcrumb as BreadcrumbProps);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const defaultBreadcrumbDom = getDefaultBreadcrumbDom();
|
||||
|
||||
// support breadcrumbRender function
|
||||
const breadcrumbDom =
|
||||
breadcrumbRender?.(props, defaultBreadcrumbDom) || defaultBreadcrumbDom;
|
||||
|
||||
const className = classNames(prefixCls, customizeClassName, {
|
||||
'has-breadcrumb': breadcrumbDom,
|
||||
'has-footer': footer,
|
||||
|
@ -20,6 +20,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/6bKE0Cq0R/PageHeader.svg
|
||||
| avatar | 标题栏旁的头像 | [AvatarProps](/components/avatar/) | - | |
|
||||
| backIcon | 自定义 back icon ,如果为 false 不渲染 back icon | ReactNode \| boolean | <ArrowLeft /> | |
|
||||
| breadcrumb | 面包屑的配置 | [Breadcrumb](/components/breadcrumb/) | - | |
|
||||
| breadcrumbRender | 自定义面包屑区域的内容 | `(props, originBreadcrumb) => ReactNode` | - | 4.11.0 |
|
||||
| extra | 操作区,位于 title 行的行尾 | ReactNode | - | |
|
||||
| footer | PageHeader 的页脚,一般用于渲染 TabBar | ReactNode | - | |
|
||||
| ghost | pageHeader 的类型,将会改变背景颜色 | boolean | true | |
|
||||
|
@ -6,19 +6,19 @@
|
||||
.@{result-prefix-cls} {
|
||||
padding: 48px 32px;
|
||||
// status color
|
||||
&-success &-icon > .anticon {
|
||||
&-success &-icon > .@{iconfont-css-prefix} {
|
||||
color: @success-color;
|
||||
}
|
||||
|
||||
&-error &-icon > .anticon {
|
||||
&-error &-icon > .@{iconfont-css-prefix} {
|
||||
color: @error-color;
|
||||
}
|
||||
|
||||
&-info &-icon > .anticon {
|
||||
&-info &-icon > .@{iconfont-css-prefix} {
|
||||
color: @info-color;
|
||||
}
|
||||
|
||||
&-warning &-icon > .anticon {
|
||||
&-warning &-icon > .@{iconfont-css-prefix} {
|
||||
color: @warning-color;
|
||||
}
|
||||
|
||||
@ -33,7 +33,7 @@
|
||||
margin-bottom: 24px;
|
||||
text-align: center;
|
||||
|
||||
> .anticon {
|
||||
> .@{iconfont-css-prefix} {
|
||||
font-size: @result-icon-font-size;
|
||||
}
|
||||
}
|
||||
|
@ -290,7 +290,7 @@
|
||||
// Menu
|
||||
// ---
|
||||
// dark theme
|
||||
@menu-dark-submenu-bg: @component-background;
|
||||
@menu-dark-inline-submenu-bg: @component-background;
|
||||
@menu-dark-bg: @popover-background;
|
||||
@menu-popup-bg: @popover-background;
|
||||
|
||||
|
@ -546,6 +546,7 @@
|
||||
@menu-bg: @component-background;
|
||||
@menu-popup-bg: @component-background;
|
||||
@menu-item-color: @text-color;
|
||||
@menu-inline-submenu-bg: @background-color-light;
|
||||
@menu-highlight-color: @primary-color;
|
||||
@menu-highlight-danger-color: @error-color;
|
||||
@menu-item-active-bg: @primary-1;
|
||||
@ -567,7 +568,7 @@
|
||||
@menu-dark-danger-color: @error-color;
|
||||
@menu-dark-bg: @layout-header-background;
|
||||
@menu-dark-arrow-color: #fff;
|
||||
@menu-dark-submenu-bg: #000c17;
|
||||
@menu-dark-inline-submenu-bg: #000c17;
|
||||
@menu-dark-highlight-color: #fff;
|
||||
@menu-dark-item-active-bg: @primary-color;
|
||||
@menu-dark-item-active-danger-bg: @error-color;
|
||||
|
@ -9,6 +9,8 @@ title:
|
||||
|
||||
通过 `filterDropdown` 自定义的列筛选功能,并实现一个搜索列的示例。
|
||||
|
||||
给函数 `confirm` 添加 `boolean` 类型参数 `closeDropdown`,是否关闭筛选菜单,默认为 `true`。
|
||||
|
||||
## en-US
|
||||
|
||||
Implement a customized column search example via `filterDropdown`.
|
||||
@ -77,6 +79,19 @@ class App extends React.Component {
|
||||
<Button onClick={() => this.handleReset(clearFilters)} size="small" style={{ width: 90 }}>
|
||||
Reset
|
||||
</Button>
|
||||
<Button
|
||||
type="link"
|
||||
size="small"
|
||||
onClick={() => {
|
||||
confirm({ closeDropdown: false });
|
||||
this.setState({
|
||||
searchText: selectedKeys[0],
|
||||
searchedColumn: dataIndex,
|
||||
});
|
||||
}}
|
||||
>
|
||||
Filter
|
||||
</Button>
|
||||
</Space>
|
||||
</div>
|
||||
),
|
||||
|
@ -8,7 +8,14 @@ import Checkbox from '../../../checkbox';
|
||||
import Radio from '../../../radio';
|
||||
import Dropdown from '../../../dropdown';
|
||||
import Empty from '../../../empty';
|
||||
import { ColumnType, ColumnFilterItem, Key, TableLocale, GetPopupContainer } from '../../interface';
|
||||
import {
|
||||
ColumnType,
|
||||
ColumnFilterItem,
|
||||
Key,
|
||||
TableLocale,
|
||||
GetPopupContainer,
|
||||
FilterConfirmProps,
|
||||
} from '../../interface';
|
||||
import FilterDropdownMenuWrapper from './FilterWrapper';
|
||||
import { FilterState } from '.';
|
||||
import useSyncState from '../../../_util/hooks/useSyncState';
|
||||
@ -160,8 +167,6 @@ function FilterDropdown<RecordType>(props: FilterDropdownProps<RecordType>) {
|
||||
|
||||
// ======================= Submit ========================
|
||||
const internalTriggerFilter = (keys: Key[] | undefined | null) => {
|
||||
triggerVisible(false);
|
||||
|
||||
const mergedKeys = keys && keys.length ? keys : null;
|
||||
if (mergedKeys === null && (!filterState || !filterState.filteredKeys)) {
|
||||
return null;
|
||||
@ -179,14 +184,21 @@ function FilterDropdown<RecordType>(props: FilterDropdownProps<RecordType>) {
|
||||
};
|
||||
|
||||
const onConfirm = () => {
|
||||
triggerVisible(false);
|
||||
internalTriggerFilter(getFilteredKeysSync());
|
||||
};
|
||||
|
||||
const onReset = () => {
|
||||
setFilteredKeysSync([]);
|
||||
triggerVisible(false);
|
||||
internalTriggerFilter([]);
|
||||
};
|
||||
|
||||
const doFilter = (param: FilterConfirmProps = { closeDropdown: true }) => {
|
||||
triggerVisible(!param.closeDropdown);
|
||||
internalTriggerFilter(getFilteredKeysSync());
|
||||
};
|
||||
|
||||
const onVisibleChange = (newVisible: boolean) => {
|
||||
if (newVisible && propFilteredKeys !== undefined) {
|
||||
// Sync filteredKeys on appear in controlled mode (propFilteredKeys !== undefiend)
|
||||
@ -213,7 +225,7 @@ function FilterDropdown<RecordType>(props: FilterDropdownProps<RecordType>) {
|
||||
prefixCls: `${dropdownPrefixCls}-custom`,
|
||||
setSelectedKeys: (selectedKeys: Key[]) => onSelectKeys({ selectedKeys }),
|
||||
selectedKeys: getFilteredKeysSync(),
|
||||
confirm: onConfirm,
|
||||
confirm: doFilter,
|
||||
clearFilters: onReset,
|
||||
filters: column.filters,
|
||||
visible: mergedVisible,
|
||||
|
@ -67,11 +67,15 @@ export type ColumnTitle<RecordType> =
|
||||
| React.ReactNode
|
||||
| ((props: ColumnTitleProps<RecordType>) => React.ReactNode);
|
||||
|
||||
export interface FilterConfirmProps {
|
||||
closeDropdown: boolean;
|
||||
}
|
||||
|
||||
export interface FilterDropdownProps {
|
||||
prefixCls: string;
|
||||
setSelectedKeys: (selectedKeys: React.Key[]) => void;
|
||||
selectedKeys: React.Key[];
|
||||
confirm: () => void;
|
||||
confirm: (param: FilterConfirmProps) => void;
|
||||
clearFilters?: () => void;
|
||||
filters?: ColumnFilterItem[];
|
||||
visible: boolean;
|
||||
|
@ -41,13 +41,14 @@ interface EditConfig {
|
||||
autoSize?: boolean | AutoSizeType;
|
||||
}
|
||||
|
||||
interface EllipsisConfig {
|
||||
export interface EllipsisConfig {
|
||||
rows?: number;
|
||||
expandable?: boolean;
|
||||
suffix?: string;
|
||||
symbol?: React.ReactNode;
|
||||
onExpand?: React.MouseEventHandler<HTMLElement>;
|
||||
onEllipsis?: (ellipsis: boolean) => void;
|
||||
tooltip?: React.ReactNode;
|
||||
}
|
||||
|
||||
export interface BlockProps extends TypographyProps {
|
||||
@ -287,9 +288,9 @@ class Base extends React.Component<InternalBlockProps, BaseState> {
|
||||
canUseCSSEllipsis(): boolean {
|
||||
const { clientRendered } = this.state;
|
||||
const { editable, copyable } = this.props;
|
||||
const { rows, expandable, suffix, onEllipsis } = this.getEllipsis();
|
||||
const { rows, expandable, suffix, onEllipsis, tooltip } = this.getEllipsis();
|
||||
|
||||
if (suffix) return false;
|
||||
if (suffix || tooltip) return false;
|
||||
// Can't use css ellipsis since we need to provide the place for button
|
||||
if (editable || copyable || expandable || !clientRendered || onEllipsis) {
|
||||
return false;
|
||||
@ -441,7 +442,7 @@ class Base extends React.Component<InternalBlockProps, BaseState> {
|
||||
const { ellipsisContent, isEllipsis, expanded } = this.state;
|
||||
const { component, children, className, type, disabled, style, ...restProps } = this.props;
|
||||
const { direction } = this.context;
|
||||
const { rows, suffix } = this.getEllipsis();
|
||||
const { rows, suffix, tooltip } = this.getEllipsis();
|
||||
|
||||
const prefixCls = this.getPrefixCls();
|
||||
|
||||
@ -486,6 +487,15 @@ class Base extends React.Component<InternalBlockProps, BaseState> {
|
||||
{suffix}
|
||||
</>
|
||||
);
|
||||
|
||||
// If provided tooltip, we need wrap with span to let Tooltip inject events
|
||||
if (tooltip) {
|
||||
textNode = (
|
||||
<Tooltip title={tooltip === true ? children : tooltip}>
|
||||
<span>{textNode}</span>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
} else {
|
||||
textNode = (
|
||||
<>
|
||||
|
@ -1,18 +1,30 @@
|
||||
import * as React from 'react';
|
||||
import omit from 'rc-util/lib/omit';
|
||||
import devWarning from '../_util/devWarning';
|
||||
import Base, { BlockProps } from './Base';
|
||||
import Base, { BlockProps, EllipsisConfig } from './Base';
|
||||
|
||||
export interface TextProps extends BlockProps {
|
||||
ellipsis?: boolean;
|
||||
ellipsis?: boolean | Omit<EllipsisConfig, 'expandable' | 'rows' | 'onExpand'>;
|
||||
}
|
||||
|
||||
const Text: React.FC<TextProps> = ({ ellipsis, ...restProps }) => {
|
||||
const mergedEllipsis = React.useMemo(() => {
|
||||
if (ellipsis && typeof ellipsis === 'object') {
|
||||
return omit(ellipsis as any, ['expandable', 'rows']);
|
||||
}
|
||||
|
||||
return ellipsis;
|
||||
}, [ellipsis]);
|
||||
|
||||
devWarning(
|
||||
typeof ellipsis !== 'object',
|
||||
typeof ellipsis !== 'object' ||
|
||||
!ellipsis ||
|
||||
(!('expandable' in ellipsis) && !('rows' in ellipsis)),
|
||||
'Typography.Text',
|
||||
'`ellipsis` only supports boolean value.',
|
||||
'`ellipsis` do not support `expandable` or `rows` props.',
|
||||
);
|
||||
return <Base {...restProps} ellipsis={!!ellipsis} component="span" />;
|
||||
|
||||
return <Base {...restProps} ellipsis={mergedEllipsis} component="span" />;
|
||||
};
|
||||
|
||||
export default Text;
|
||||
|
@ -217,6 +217,19 @@ exports[`renders ./components/typography/demo/basic.md correctly 1`] = `
|
||||
|
||||
exports[`renders ./components/typography/demo/ellipsis.md correctly 1`] = `
|
||||
Array [
|
||||
<button
|
||||
aria-checked="true"
|
||||
class="ant-switch ant-switch-checked"
|
||||
role="switch"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
class="ant-switch-handle"
|
||||
/>
|
||||
<span
|
||||
class="ant-switch-inner"
|
||||
/>
|
||||
</button>,
|
||||
<div
|
||||
class="ant-typography ant-typography-ellipsis"
|
||||
>
|
||||
@ -227,6 +240,12 @@ Array [
|
||||
>
|
||||
Ant Design, a design language for background applications, is refined by Ant UED Team. Ant Design, a design language for background applications, is refined by Ant UED Team. Ant Design, a design language for background applications, is refined by Ant UED Team. Ant Design, a design language for background applications, is refined by Ant UED Team. Ant Design, a design language for background applications, is refined by Ant UED Team. Ant Design, a design language for background applications, is refined by Ant UED Team.
|
||||
</div>,
|
||||
<span
|
||||
class="ant-typography ant-typography-ellipsis"
|
||||
style="width:100px"
|
||||
>
|
||||
Ant Design, a design language for background applications, is refined by Ant UED Team.
|
||||
</span>,
|
||||
]
|
||||
`;
|
||||
|
||||
|
@ -233,6 +233,32 @@ describe('Typography', () => {
|
||||
const wrapper = mount(<Base ellipsis component="p" />);
|
||||
expect(wrapper.find('.ant-typography-ellipsis-single-line').length).toBeTruthy();
|
||||
});
|
||||
|
||||
describe('should tooltip support', () => {
|
||||
function getWrapper(tooltip) {
|
||||
return mount(
|
||||
<Base ellipsis={{ tooltip }} component="p">
|
||||
{fullStr}
|
||||
</Base>,
|
||||
);
|
||||
}
|
||||
|
||||
it('boolean', async () => {
|
||||
const wrapper = getWrapper(true);
|
||||
await sleep(20);
|
||||
wrapper.update();
|
||||
|
||||
expect(wrapper.find('Tooltip').prop('title')).toEqual(fullStr);
|
||||
});
|
||||
|
||||
it('customize', async () => {
|
||||
const wrapper = getWrapper('Bamboo is Light');
|
||||
await sleep(20);
|
||||
wrapper.update();
|
||||
|
||||
expect(wrapper.find('Tooltip').prop('title')).toEqual('Bamboo is Light');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('copyable', () => {
|
||||
|
@ -7,37 +7,56 @@ title:
|
||||
|
||||
## zh-CN
|
||||
|
||||
多行文本省略。
|
||||
多行文本省略。你可以通过 `tooltip` 属性配置省略展示内容,大量文本时推荐优先使用 `expandable`。
|
||||
|
||||
## en-US
|
||||
|
||||
Multiple line ellipsis support.
|
||||
Multiple line ellipsis support. You can use `tooltip` to config ellipsis tooltip. Recommend `expandable` when have lots of content.
|
||||
|
||||
```jsx
|
||||
import { Typography } from 'antd';
|
||||
```tsx
|
||||
import { Typography, Switch } from 'antd';
|
||||
|
||||
const { Paragraph } = Typography;
|
||||
const { Paragraph, Text } = Typography;
|
||||
|
||||
ReactDOM.render(
|
||||
<>
|
||||
<Paragraph ellipsis>
|
||||
Ant Design, a design language for background applications, is refined by Ant UED Team. Ant
|
||||
Design, a design language for background applications, is refined by Ant UED Team. Ant Design,
|
||||
a design language for background applications, is refined by Ant UED Team. Ant Design, a
|
||||
design language for background applications, is refined by Ant UED Team. Ant Design, a design
|
||||
language for background applications, is refined by Ant UED Team. Ant Design, a design
|
||||
language for background applications, is refined by Ant UED Team.
|
||||
</Paragraph>
|
||||
const Demo = () => {
|
||||
const [ellipsis, setEllipsis] = React.useState(true);
|
||||
|
||||
<Paragraph ellipsis={{ rows: 2, expandable: true, symbol: 'more' }}>
|
||||
Ant Design, a design language for background applications, is refined by Ant UED Team. Ant
|
||||
Design, a design language for background applications, is refined by Ant UED Team. Ant Design,
|
||||
a design language for background applications, is refined by Ant UED Team. Ant Design, a
|
||||
design language for background applications, is refined by Ant UED Team. Ant Design, a design
|
||||
language for background applications, is refined by Ant UED Team. Ant Design, a design
|
||||
language for background applications, is refined by Ant UED Team.
|
||||
</Paragraph>
|
||||
</>,
|
||||
mountNode,
|
||||
);
|
||||
return (
|
||||
<>
|
||||
<Switch
|
||||
checked={ellipsis}
|
||||
onChange={() => {
|
||||
setEllipsis(!ellipsis);
|
||||
}}
|
||||
/>
|
||||
|
||||
<Paragraph ellipsis={ellipsis}>
|
||||
Ant Design, a design language for background applications, is refined by Ant UED Team. Ant
|
||||
Design, a design language for background applications, is refined by Ant UED Team. Ant
|
||||
Design, a design language for background applications, is refined by Ant UED Team. Ant
|
||||
Design, a design language for background applications, is refined by Ant UED Team. Ant
|
||||
Design, a design language for background applications, is refined by Ant UED Team. Ant
|
||||
Design, a design language for background applications, is refined by Ant UED Team.
|
||||
</Paragraph>
|
||||
|
||||
<Paragraph ellipsis={ellipsis ? { rows: 2, expandable: true, symbol: 'more' } : false}>
|
||||
Ant Design, a design language for background applications, is refined by Ant UED Team. Ant
|
||||
Design, a design language for background applications, is refined by Ant UED Team. Ant
|
||||
Design, a design language for background applications, is refined by Ant UED Team. Ant
|
||||
Design, a design language for background applications, is refined by Ant UED Team. Ant
|
||||
Design, a design language for background applications, is refined by Ant UED Team. Ant
|
||||
Design, a design language for background applications, is refined by Ant UED Team.
|
||||
</Paragraph>
|
||||
|
||||
<Text
|
||||
style={ellipsis ? { width: 100 } : undefined}
|
||||
ellipsis={ellipsis ? { tooltip: 'I am ellipsis now!' } : false}
|
||||
>
|
||||
Ant Design, a design language for background applications, is refined by Ant UED Team.
|
||||
</Text>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
ReactDOM.render(<Demo />, mountNode);
|
||||
```
|
||||
|
@ -113,14 +113,15 @@ Basic text writing, including headings, body text, lists, and more.
|
||||
onEllipsis: function(ellipsis),
|
||||
}
|
||||
|
||||
| Property | Description | Type | Default | Version |
|
||||
| ---------- | ----------------------------------------- | ------------------ | -------- | ------- |
|
||||
| expandable | Whether to be expandable | boolean | - | |
|
||||
| rows | Max rows of content | number | - | |
|
||||
| suffix | Suffix of ellipsis content | string | - | |
|
||||
| symbol | Custom symbol of ellipsis | ReactNode | `Expand` | |
|
||||
| onEllipsis | Called when enter or leave ellipsis state | function(ellipsis) | - | 4.2.0 |
|
||||
| onExpand | Called when expand content | function(event) | - | |
|
||||
| Property | Description | Type | Default | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| expandable | Whether to be expandable | boolean | - | |
|
||||
| rows | Max rows of content | number | - | |
|
||||
| suffix | Suffix of ellipsis content | ReactNode | - | |
|
||||
| symbol | Custom `...` symbol of ellipsis | ReactNode | `...` | |
|
||||
| tooltip | Show tooltip when ellipsis | boolean \| ReactNode | - | 4.11.0 |
|
||||
| onEllipsis | Called when enter or leave ellipsis state | function(ellipsis) | - | 4.2.0 |
|
||||
| onExpand | Called when expand content | function(event) | - | |
|
||||
|
||||
## FAQ
|
||||
|
||||
|
@ -113,14 +113,15 @@ cover: https://gw.alipayobjects.com/zos/alicdn/GOM1KQ24O/Typography.svg
|
||||
onEllipsis: function(ellipsis),
|
||||
}
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||
| ---------- | ------------------ | ------------------ | ------ | ----- |
|
||||
| expandable | 是否可展开 | boolean | - | |
|
||||
| rows | 最多显示的行数 | number | - | |
|
||||
| suffix | 自定义省略内容后缀 | string | - | |
|
||||
| symbol | 自定义展开符号 | ReactNode | `展开` | |
|
||||
| onEllipsis | 触发省略时的回调 | function(ellipsis) | - | 4.2.0 |
|
||||
| onExpand | 点击展开时的回调 | function(event) | - | |
|
||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||
| ---------- | -------------------- | -------------------- | ------ | ------ |
|
||||
| expandable | 是否可展开 | boolean | - | |
|
||||
| rows | 最多显示的行数 | number | - | |
|
||||
| suffix | 自定义省略内容后缀 | ReactNode | - | |
|
||||
| symbol | 自定义省略符号 | ReactNode | `...` | |
|
||||
| tooltip | 省略时,展示提示信息 | boolean \| ReactNode | - | 4.11.0 |
|
||||
| onEllipsis | 触发省略时的回调 | function(ellipsis) | - | 4.2.0 |
|
||||
| onExpand | 点击展开时的回调 | function(event) | - | |
|
||||
|
||||
## FAQ
|
||||
|
||||
|
@ -108,7 +108,7 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@ant-design/colors": "^5.0.0",
|
||||
"@ant-design/icons": "^4.3.0",
|
||||
"@ant-design/icons": "^4.4.0",
|
||||
"@ant-design/react-slick": "~0.28.1",
|
||||
"@babel/runtime": "^7.11.2",
|
||||
"array-tree-filter": "^2.1.0",
|
||||
@ -123,7 +123,7 @@
|
||||
"rc-drawer": "~4.2.0",
|
||||
"rc-dropdown": "~3.2.0",
|
||||
"rc-field-form": "~1.18.0",
|
||||
"rc-image": "~5.0.2",
|
||||
"rc-image": "~5.1.1",
|
||||
"rc-input-number": "~6.1.0",
|
||||
"rc-mentions": "~1.5.0",
|
||||
"rc-menu": "~8.10.0",
|
||||
|
Loading…
Reference in New Issue
Block a user