mirror of
https://github.com/ant-design/ant-design.git
synced 2025-01-19 06:43:16 +08:00
chore: merge feature into master
This commit is contained in:
commit
d35576d675
@ -479,6 +479,43 @@ Array [
|
|||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</div>,
|
</div>,
|
||||||
|
<div
|
||||||
|
class="ant-divider ant-divider-horizontal"
|
||||||
|
role="separator"
|
||||||
|
/>,
|
||||||
|
<div
|
||||||
|
class="ant-avatar-group"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-avatar ant-avatar-lg ant-avatar-circle ant-avatar-image"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="ant-avatar ant-avatar-lg ant-avatar-circle"
|
||||||
|
style="background-color:#f56a00"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-avatar-string"
|
||||||
|
style="opacity:0"
|
||||||
|
>
|
||||||
|
K
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="ant-avatar ant-avatar-lg ant-avatar-circle"
|
||||||
|
style="color:#f56a00;background-color:#fde3cf;cursor:pointer"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-avatar-string"
|
||||||
|
style="opacity:0"
|
||||||
|
>
|
||||||
|
+2
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</div>,
|
||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -49,6 +49,20 @@ const Demo = () => (
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Avatar style={{ backgroundColor: '#1890ff' }} icon={<AntDesignOutlined />} />
|
<Avatar style={{ backgroundColor: '#1890ff' }} icon={<AntDesignOutlined />} />
|
||||||
</Avatar.Group>
|
</Avatar.Group>
|
||||||
|
<Divider />
|
||||||
|
<Avatar.Group
|
||||||
|
maxCount={2}
|
||||||
|
maxPopoverTrigger="click"
|
||||||
|
size="large"
|
||||||
|
maxStyle={{ color: '#f56a00', backgroundColor: '#fde3cf', cursor: 'pointer' }}
|
||||||
|
>
|
||||||
|
<Avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />
|
||||||
|
<Avatar style={{ backgroundColor: '#f56a00' }}>K</Avatar>
|
||||||
|
<Tooltip title="Ant User" placement="top">
|
||||||
|
<Avatar style={{ backgroundColor: '#87d068' }} icon={<UserOutlined />} />
|
||||||
|
</Tooltip>
|
||||||
|
<Avatar style={{ backgroundColor: '#1890ff' }} icon={<AntDesignOutlined />} />
|
||||||
|
</Avatar.Group>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ export interface GroupProps {
|
|||||||
maxCount?: number;
|
maxCount?: number;
|
||||||
maxStyle?: React.CSSProperties;
|
maxStyle?: React.CSSProperties;
|
||||||
maxPopoverPlacement?: 'top' | 'bottom';
|
maxPopoverPlacement?: 'top' | 'bottom';
|
||||||
|
maxPopoverTrigger?: 'hover' | 'focus' | 'click';
|
||||||
/*
|
/*
|
||||||
* Size of avatar, options: `large`, `small`, `default`
|
* Size of avatar, options: `large`, `small`, `default`
|
||||||
* or a custom number size
|
* or a custom number size
|
||||||
@ -36,7 +37,7 @@ const Group: React.FC<GroupProps> = props => {
|
|||||||
className,
|
className,
|
||||||
);
|
);
|
||||||
|
|
||||||
const { children, maxPopoverPlacement = 'top' } = props;
|
const { children, maxPopoverPlacement = 'top', maxPopoverTrigger = 'hover' } = props;
|
||||||
const childrenWithProps = toArray(children).map((child, index) =>
|
const childrenWithProps = toArray(children).map((child, index) =>
|
||||||
cloneElement(child, {
|
cloneElement(child, {
|
||||||
key: `avatar-key-${index}`,
|
key: `avatar-key-${index}`,
|
||||||
@ -51,7 +52,7 @@ const Group: React.FC<GroupProps> = props => {
|
|||||||
<Popover
|
<Popover
|
||||||
key="avatar-popover-key"
|
key="avatar-popover-key"
|
||||||
content={childrenHidden}
|
content={childrenHidden}
|
||||||
trigger="hover"
|
trigger={maxPopoverTrigger}
|
||||||
placement={maxPopoverPlacement}
|
placement={maxPopoverPlacement}
|
||||||
overlayClassName={`${prefixCls}-popover`}
|
overlayClassName={`${prefixCls}-popover`}
|
||||||
>
|
>
|
||||||
|
@ -32,5 +32,6 @@ Avatars can be used to represent people or objects. It supports images, `Icon`s,
|
|||||||
| --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- |
|
||||||
| maxCount | Max avatars to show | number | - | |
|
| maxCount | Max avatars to show | number | - | |
|
||||||
| maxPopoverPlacement | The placement of excess avatar Popover | `top` \| `bottom` | `top` | |
|
| maxPopoverPlacement | The placement of excess avatar Popover | `top` \| `bottom` | `top` | |
|
||||||
|
| maxPopoverTrigger | Set the trigger of excess avatar Popover | `hover` \| `focus` \| `click` | `hover` | 4.17.0 |
|
||||||
| maxStyle | The style of excess avatar style | CSSProperties | - | |
|
| maxStyle | The style of excess avatar style | CSSProperties | - | |
|
||||||
| size | The size of the avatar | number \| `large` \| `small` \| `default` \| { xs: number, sm: number, ...} | `default` | 4.8.0 |
|
| size | The size of the avatar | number \| `large` \| `small` \| `default` \| { xs: number, sm: number, ...} | `default` | 4.8.0 |
|
||||||
|
@ -37,5 +37,6 @@ cover: https://gw.alipayobjects.com/zos/antfincdn/aBcnbw68hP/Avatar.svg
|
|||||||
| --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- |
|
||||||
| maxCount | 显示的最大头像个数 | number | - | |
|
| maxCount | 显示的最大头像个数 | number | - | |
|
||||||
| maxPopoverPlacement | 多余头像气泡弹出位置 | `top` \| `bottom` | `top` | |
|
| maxPopoverPlacement | 多余头像气泡弹出位置 | `top` \| `bottom` | `top` | |
|
||||||
|
| maxPopoverTrigger | 设置多余头像 Popover 的触发方式 | `hover` \| `focus` \| `click` | `hover` | 4.17.0 |
|
||||||
| maxStyle | 多余头像样式 | CSSProperties | - | |
|
| maxStyle | 多余头像样式 | CSSProperties | - | |
|
||||||
| size | 设置头像的大小 | number \| `large` \| `small` \| `default` \| { xs: number, sm: number, ...} | `default` | 4.8.0 |
|
| size | 设置头像的大小 | number \| `large` \| `small` \| `default` \| { xs: number, sm: number, ...} | `default` | 4.8.0 |
|
||||||
|
@ -173,5 +173,33 @@ Array [
|
|||||||
<p>
|
<p>
|
||||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||||
</p>,
|
</p>,
|
||||||
|
<div
|
||||||
|
class="ant-divider ant-divider-horizontal ant-divider-with-text ant-divider-with-text-left ant-divider-no-default-orientation-margin-left"
|
||||||
|
role="separator"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-divider-inner-text"
|
||||||
|
style="margin-left:0"
|
||||||
|
>
|
||||||
|
Left Text with 0 orientationMargin
|
||||||
|
</span>
|
||||||
|
</div>,
|
||||||
|
<p>
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||||
|
</p>,
|
||||||
|
<div
|
||||||
|
class="ant-divider ant-divider-horizontal ant-divider-with-text ant-divider-with-text-right ant-divider-no-default-orientation-margin-right"
|
||||||
|
role="separator"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-divider-inner-text"
|
||||||
|
style="margin-right:50px"
|
||||||
|
>
|
||||||
|
Right Text with 50px orientationMargin
|
||||||
|
</span>
|
||||||
|
</div>,
|
||||||
|
<p>
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||||
|
</p>,
|
||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
@ -37,6 +37,20 @@ ReactDOM.render(
|
|||||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista
|
||||||
probare, quae sunt a te dicta? Refert tamen, quo modo.
|
probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||||
</p>
|
</p>
|
||||||
|
<Divider orientation="left" orientationMargin="0">
|
||||||
|
Left Text with 0 orientationMargin
|
||||||
|
</Divider>
|
||||||
|
<p>
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista
|
||||||
|
probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||||
|
</p>
|
||||||
|
<Divider orientation="right" orientationMargin={50}>
|
||||||
|
Right Text with 50px orientationMargin
|
||||||
|
</Divider>
|
||||||
|
<p>
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista
|
||||||
|
probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||||
|
</p>
|
||||||
</>,
|
</>,
|
||||||
mountNode,
|
mountNode,
|
||||||
);
|
);
|
||||||
|
@ -16,9 +16,11 @@ A divider line separates different content.
|
|||||||
|
|
||||||
| Property | Description | Type | Default | Version |
|
| Property | Description | Type | Default | Version |
|
||||||
| --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- |
|
||||||
|
| children | The wrapped title | ReactNode | - | |
|
||||||
| className | The className of container | string | - | |
|
| className | The className of container | string | - | |
|
||||||
| dashed | Whether line is dashed | boolean | false | |
|
| dashed | Whether line is dashed | boolean | false | |
|
||||||
| orientation | The position of title inside divider | `left` \| `right` \| `center` | `center` | |
|
| orientation | The position of title inside divider | `left` \| `right` \| `center` | `center` | |
|
||||||
|
| orientationMargin | The margin-left/right between the title and its closest border, while the `orientation` must be `left` or `right` | string \| number | - | |
|
||||||
| plain | Divider text show as plain style | boolean | true | 4.2.0 |
|
| plain | Divider text show as plain style | boolean | true | 4.2.0 |
|
||||||
| style | The style object of container | CSSProperties | - | |
|
| style | The style object of container | CSSProperties | - | |
|
||||||
| type | The direction type of divider | `horizontal` \| `vertical` | `horizontal` | |
|
| type | The direction type of divider | `horizontal` \| `vertical` | `horizontal` | |
|
||||||
|
@ -6,6 +6,7 @@ export interface DividerProps {
|
|||||||
prefixCls?: string;
|
prefixCls?: string;
|
||||||
type?: 'horizontal' | 'vertical';
|
type?: 'horizontal' | 'vertical';
|
||||||
orientation?: 'left' | 'right' | 'center';
|
orientation?: 'left' | 'right' | 'center';
|
||||||
|
orientationMargin?: string | number;
|
||||||
className?: string;
|
className?: string;
|
||||||
children?: React.ReactNode;
|
children?: React.ReactNode;
|
||||||
dashed?: boolean;
|
dashed?: boolean;
|
||||||
@ -20,6 +21,7 @@ const Divider: React.FC<DividerProps> = props => (
|
|||||||
prefixCls: customizePrefixCls,
|
prefixCls: customizePrefixCls,
|
||||||
type = 'horizontal',
|
type = 'horizontal',
|
||||||
orientation = 'center',
|
orientation = 'center',
|
||||||
|
orientationMargin,
|
||||||
className,
|
className,
|
||||||
children,
|
children,
|
||||||
dashed,
|
dashed,
|
||||||
@ -29,6 +31,8 @@ const Divider: React.FC<DividerProps> = props => (
|
|||||||
const prefixCls = getPrefixCls('divider', customizePrefixCls);
|
const prefixCls = getPrefixCls('divider', customizePrefixCls);
|
||||||
const orientationPrefix = orientation.length > 0 ? `-${orientation}` : orientation;
|
const orientationPrefix = orientation.length > 0 ? `-${orientation}` : orientation;
|
||||||
const hasChildren = !!children;
|
const hasChildren = !!children;
|
||||||
|
const hasCustomMarginLeft = orientation === 'left' && orientationMargin != null;
|
||||||
|
const hasCustomMarginRight = orientation === 'right' && orientationMargin != null;
|
||||||
const classString = classNames(
|
const classString = classNames(
|
||||||
prefixCls,
|
prefixCls,
|
||||||
`${prefixCls}-${type}`,
|
`${prefixCls}-${type}`,
|
||||||
@ -38,12 +42,24 @@ const Divider: React.FC<DividerProps> = props => (
|
|||||||
[`${prefixCls}-dashed`]: !!dashed,
|
[`${prefixCls}-dashed`]: !!dashed,
|
||||||
[`${prefixCls}-plain`]: !!plain,
|
[`${prefixCls}-plain`]: !!plain,
|
||||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||||
|
[`${prefixCls}-no-default-orientation-margin-left`]: hasCustomMarginLeft,
|
||||||
|
[`${prefixCls}-no-default-orientation-margin-right`]: hasCustomMarginRight,
|
||||||
},
|
},
|
||||||
className,
|
className,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const innerStyle = {
|
||||||
|
...(hasCustomMarginLeft && { marginLeft: orientationMargin }),
|
||||||
|
...(hasCustomMarginRight && { marginRight: orientationMargin }),
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classString} {...restProps} role="separator">
|
<div className={classString} {...restProps} role="separator">
|
||||||
{children && <span className={`${prefixCls}-inner-text`}>{children}</span>}
|
{children && (
|
||||||
|
<span className={`${prefixCls}-inner-text`} style={innerStyle}>
|
||||||
|
{children}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
|
@ -17,9 +17,11 @@ cover: https://gw.alipayobjects.com/zos/alicdn/5swjECahe/Divider.svg
|
|||||||
|
|
||||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||||
| --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- |
|
||||||
|
| children | 嵌套的标题 | ReactNode | - | |
|
||||||
| className | 分割线样式类 | string | - | |
|
| className | 分割线样式类 | string | - | |
|
||||||
| dashed | 是否虚线 | boolean | false | |
|
| dashed | 是否虚线 | boolean | false | |
|
||||||
| orientation | 分割线标题的位置 | `left` \| `right` \| `center` | `center` | |
|
| orientation | 分割线标题的位置 | `left` \| `right` \| `center` | `center` | |
|
||||||
|
| orientationMargin | 标题和最近 left/right 边框之间的距离,去除了分割线,同时 `orientation` 必须为 `left` 或 `right` | string \| number | - | |
|
||||||
| plain | 文字是否显示为普通正文样式 | boolean | false | 4.2.0 |
|
| plain | 文字是否显示为普通正文样式 | boolean | false | 4.2.0 |
|
||||||
| style | 分割线样式对象 | CSSProperties | - | |
|
| style | 分割线样式对象 | CSSProperties | - | |
|
||||||
| type | 水平还是垂直类型 | `horizontal` \| `vertical` | `horizontal` | |
|
| type | 水平还是垂直类型 | `horizontal` \| `vertical` | `horizontal` | |
|
||||||
|
@ -103,6 +103,30 @@
|
|||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
font-size: @font-size-base;
|
font-size: @font-size-base;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&-horizontal&-with-text-left&-no-default-orientation-margin-left {
|
||||||
|
&::before {
|
||||||
|
width: 0;
|
||||||
|
}
|
||||||
|
&::after {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.ant-divider-inner-text {
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-horizontal&-with-text-right&-no-default-orientation-margin-right {
|
||||||
|
&::before {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
&::after {
|
||||||
|
width: 0;
|
||||||
|
}
|
||||||
|
.ant-divider-inner-text {
|
||||||
|
padding-right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@import './rtl';
|
@import './rtl';
|
||||||
|
@ -41,6 +41,8 @@ interface EditConfig {
|
|||||||
onEnd?: () => void;
|
onEnd?: () => void;
|
||||||
maxLength?: number;
|
maxLength?: number;
|
||||||
autoSize?: boolean | AutoSizeType;
|
autoSize?: boolean | AutoSizeType;
|
||||||
|
triggerType?: ('icon' | 'text')[];
|
||||||
|
enterIcon?: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface EllipsisConfig {
|
export interface EllipsisConfig {
|
||||||
@ -372,12 +374,12 @@ class Base extends React.Component<InternalBlockProps, BaseState> {
|
|||||||
const { editable } = this.props;
|
const { editable } = this.props;
|
||||||
if (!editable) return;
|
if (!editable) return;
|
||||||
|
|
||||||
const { icon, tooltip } = editable as EditConfig;
|
const { icon, tooltip, triggerType = ['icon'] } = editable as EditConfig;
|
||||||
|
|
||||||
const title = toArray(tooltip)[0] || this.editStr;
|
const title = toArray(tooltip)[0] || this.editStr;
|
||||||
const ariaLabel = typeof title === 'string' ? title : '';
|
const ariaLabel = typeof title === 'string' ? title : '';
|
||||||
|
|
||||||
return (
|
return triggerType.indexOf('icon') !== -1 ? (
|
||||||
<Tooltip key="edit" title={tooltip === false ? '' : title}>
|
<Tooltip key="edit" title={tooltip === false ? '' : title}>
|
||||||
<TransButton
|
<TransButton
|
||||||
ref={this.setEditRef}
|
ref={this.setEditRef}
|
||||||
@ -388,7 +390,7 @@ class Base extends React.Component<InternalBlockProps, BaseState> {
|
|||||||
{icon || <EditOutlined role="button" />}
|
{icon || <EditOutlined role="button" />}
|
||||||
</TransButton>
|
</TransButton>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
);
|
) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderCopy() {
|
renderCopy() {
|
||||||
@ -427,7 +429,7 @@ class Base extends React.Component<InternalBlockProps, BaseState> {
|
|||||||
renderEditInput() {
|
renderEditInput() {
|
||||||
const { children, className, style } = this.props;
|
const { children, className, style } = this.props;
|
||||||
const { direction } = this.context;
|
const { direction } = this.context;
|
||||||
const { maxLength, autoSize, onEnd } = this.getEditable();
|
const { maxLength, autoSize, onEnd, enterIcon } = this.getEditable();
|
||||||
return (
|
return (
|
||||||
<Editable
|
<Editable
|
||||||
value={typeof children === 'string' ? children : ''}
|
value={typeof children === 'string' ? children : ''}
|
||||||
@ -440,6 +442,7 @@ class Base extends React.Component<InternalBlockProps, BaseState> {
|
|||||||
direction={direction}
|
direction={direction}
|
||||||
maxLength={maxLength}
|
maxLength={maxLength}
|
||||||
autoSize={autoSize}
|
autoSize={autoSize}
|
||||||
|
enterIcon={enterIcon}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -455,6 +458,7 @@ class Base extends React.Component<InternalBlockProps, BaseState> {
|
|||||||
const { component, children, className, type, disabled, style, ...restProps } = this.props;
|
const { component, children, className, type, disabled, style, ...restProps } = this.props;
|
||||||
const { direction } = this.context;
|
const { direction } = this.context;
|
||||||
const { rows, suffix, tooltip } = this.getEllipsis();
|
const { rows, suffix, tooltip } = this.getEllipsis();
|
||||||
|
const { triggerType = ['icon'] } = this.getEditable() as EditConfig;
|
||||||
|
|
||||||
const prefixCls = this.getPrefixCls();
|
const prefixCls = this.getPrefixCls();
|
||||||
|
|
||||||
@ -549,6 +553,7 @@ class Base extends React.Component<InternalBlockProps, BaseState> {
|
|||||||
component={component}
|
component={component}
|
||||||
ref={this.contentRef}
|
ref={this.contentRef}
|
||||||
direction={direction}
|
direction={direction}
|
||||||
|
onClick={triggerType.indexOf('text') !== -1 ? this.onEditClick : () => {}}
|
||||||
{...textProps}
|
{...textProps}
|
||||||
>
|
>
|
||||||
{textNode}
|
{textNode}
|
||||||
|
@ -5,6 +5,7 @@ import EnterOutlined from '@ant-design/icons/EnterOutlined';
|
|||||||
import { AutoSizeType } from 'rc-textarea/lib/ResizableTextArea';
|
import { AutoSizeType } from 'rc-textarea/lib/ResizableTextArea';
|
||||||
import TextArea from '../input/TextArea';
|
import TextArea from '../input/TextArea';
|
||||||
import { DirectionType } from '../config-provider';
|
import { DirectionType } from '../config-provider';
|
||||||
|
import { cloneElement } from '../_util/reactNode';
|
||||||
|
|
||||||
interface EditableProps {
|
interface EditableProps {
|
||||||
prefixCls?: string;
|
prefixCls?: string;
|
||||||
@ -18,6 +19,7 @@ interface EditableProps {
|
|||||||
direction?: DirectionType;
|
direction?: DirectionType;
|
||||||
maxLength?: number;
|
maxLength?: number;
|
||||||
autoSize?: boolean | AutoSizeType;
|
autoSize?: boolean | AutoSizeType;
|
||||||
|
enterIcon?: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Editable: React.FC<EditableProps> = ({
|
const Editable: React.FC<EditableProps> = ({
|
||||||
@ -32,6 +34,7 @@ const Editable: React.FC<EditableProps> = ({
|
|||||||
onSave,
|
onSave,
|
||||||
onCancel,
|
onCancel,
|
||||||
onEnd,
|
onEnd,
|
||||||
|
enterIcon = <EnterOutlined />,
|
||||||
}) => {
|
}) => {
|
||||||
const ref = React.useRef<any>();
|
const ref = React.useRef<any>();
|
||||||
|
|
||||||
@ -129,7 +132,9 @@ const Editable: React.FC<EditableProps> = ({
|
|||||||
aria-label={ariaLabel}
|
aria-label={ariaLabel}
|
||||||
autoSize={autoSize}
|
autoSize={autoSize}
|
||||||
/>
|
/>
|
||||||
<EnterOutlined className={`${prefixCls}-edit-content-confirm`} />
|
{enterIcon !== null
|
||||||
|
? cloneElement(enterIcon, { className: `${prefixCls}-edit-content-confirm` })
|
||||||
|
: null}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -436,6 +436,165 @@ Array [
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>,
|
</div>,
|
||||||
|
"Trigger edit with: ",
|
||||||
|
<div
|
||||||
|
class="ant-radio-group ant-radio-group-outline"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
class="ant-radio-wrapper ant-radio-wrapper-checked"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-radio ant-radio-checked"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
checked=""
|
||||||
|
class="ant-radio-input"
|
||||||
|
type="radio"
|
||||||
|
value="icon"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="ant-radio-inner"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
icon
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<label
|
||||||
|
class="ant-radio-wrapper"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-radio"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
class="ant-radio-input"
|
||||||
|
type="radio"
|
||||||
|
value="text"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="ant-radio-inner"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
text
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<label
|
||||||
|
class="ant-radio-wrapper"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="ant-radio"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
class="ant-radio-input"
|
||||||
|
type="radio"
|
||||||
|
value="both"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="ant-radio-inner"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
both
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</div>,
|
||||||
|
<div
|
||||||
|
class="ant-typography"
|
||||||
|
>
|
||||||
|
Text or icon as trigger - click to start editing.
|
||||||
|
<div
|
||||||
|
aria-label="click to edit text"
|
||||||
|
class="ant-typography-edit"
|
||||||
|
role="button"
|
||||||
|
style="border:0;background:transparent;padding:0;line-height:inherit;display:inline-block"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
aria-label="edit"
|
||||||
|
class="anticon anticon-edit"
|
||||||
|
role="button"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
data-icon="edit"
|
||||||
|
fill="currentColor"
|
||||||
|
focusable="false"
|
||||||
|
height="1em"
|
||||||
|
viewBox="64 64 896 896"
|
||||||
|
width="1em"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M257.7 752c2 0 4-.2 6-.5L431.9 722c2-.4 3.9-1.3 5.3-2.8l423.9-423.9a9.96 9.96 0 000-14.1L694.9 114.9c-1.9-1.9-4.4-2.9-7.1-2.9s-5.2 1-7.1 2.9L256.8 538.8c-1.5 1.5-2.4 3.3-2.8 5.3l-29.5 168.2a33.5 33.5 0 009.4 29.8c6.6 6.4 14.9 9.9 23.8 9.9zm67.4-174.4L687.8 215l73.3 73.3-362.7 362.6-88.9 15.7 15.6-89zM880 836H144c-17.7 0-32 14.3-32 32v36c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-36c0-17.7-14.3-32-32-32z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>,
|
||||||
|
<div
|
||||||
|
class="ant-typography"
|
||||||
|
>
|
||||||
|
Editable text with a custom enter icon in edit field.
|
||||||
|
<div
|
||||||
|
aria-label="click to edit text"
|
||||||
|
class="ant-typography-edit"
|
||||||
|
role="button"
|
||||||
|
style="border:0;background:transparent;padding:0;line-height:inherit;display:inline-block"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
aria-label="highlight"
|
||||||
|
class="anticon anticon-highlight"
|
||||||
|
role="img"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
data-icon="highlight"
|
||||||
|
fill="currentColor"
|
||||||
|
focusable="false"
|
||||||
|
height="1em"
|
||||||
|
viewBox="64 64 896 896"
|
||||||
|
width="1em"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M957.6 507.4L603.2 158.2a7.9 7.9 0 00-11.2 0L353.3 393.4a8.03 8.03 0 00-.1 11.3l.1.1 40 39.4-117.2 115.3a8.03 8.03 0 00-.1 11.3l.1.1 39.5 38.9-189.1 187H72.1c-4.4 0-8.1 3.6-8.1 8V860c0 4.4 3.6 8 8 8h344.9c2.1 0 4.1-.8 5.6-2.3l76.1-75.6 40.4 39.8a7.9 7.9 0 0011.2 0l117.1-115.6 40.1 39.5a7.9 7.9 0 0011.2 0l238.7-235.2c3.4-3 3.4-8 .3-11.2zM389.8 796.2H229.6l134.4-133 80.1 78.9-54.3 54.1zm154.8-62.1L373.2 565.2l68.6-67.6 171.4 168.9-68.6 67.6zM713.1 658L450.3 399.1 597.6 254l262.8 259-147.3 145z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>,
|
||||||
|
<div
|
||||||
|
class="ant-typography"
|
||||||
|
>
|
||||||
|
Editable text with no enter icon in edit field.
|
||||||
|
<div
|
||||||
|
aria-label="click to edit text"
|
||||||
|
class="ant-typography-edit"
|
||||||
|
role="button"
|
||||||
|
style="border:0;background:transparent;padding:0;line-height:inherit;display:inline-block"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
aria-label="highlight"
|
||||||
|
class="anticon anticon-highlight"
|
||||||
|
role="img"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
data-icon="highlight"
|
||||||
|
fill="currentColor"
|
||||||
|
focusable="false"
|
||||||
|
height="1em"
|
||||||
|
viewBox="64 64 896 896"
|
||||||
|
width="1em"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M957.6 507.4L603.2 158.2a7.9 7.9 0 00-11.2 0L353.3 393.4a8.03 8.03 0 00-.1 11.3l.1.1 40 39.4-117.2 115.3a8.03 8.03 0 00-.1 11.3l.1.1 39.5 38.9-189.1 187H72.1c-4.4 0-8.1 3.6-8.1 8V860c0 4.4 3.6 8 8 8h344.9c2.1 0 4.1-.8 5.6-2.3l76.1-75.6 40.4 39.8a7.9 7.9 0 0011.2 0l117.1-115.6 40.1 39.5a7.9 7.9 0 0011.2 0l238.7-235.2c3.4-3 3.4-8 .3-11.2zM389.8 796.2H229.6l134.4-133 80.1 78.9-54.3 54.1zm154.8-62.1L373.2 565.2l68.6-67.6 171.4 168.9-68.6 67.6zM713.1 658L450.3 399.1 597.6 254l262.8 259-147.3 145z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>,
|
||||||
<div
|
<div
|
||||||
class="ant-typography"
|
class="ant-typography"
|
||||||
>
|
>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { mount } from 'enzyme';
|
import { mount } from 'enzyme';
|
||||||
import { SmileOutlined, LikeOutlined, HighlightOutlined } from '@ant-design/icons';
|
import { SmileOutlined, LikeOutlined, HighlightOutlined, CheckOutlined } from '@ant-design/icons';
|
||||||
import KeyCode from 'rc-util/lib/KeyCode';
|
import KeyCode from 'rc-util/lib/KeyCode';
|
||||||
import { resetWarned } from 'rc-util/lib/warning';
|
import { resetWarned } from 'rc-util/lib/warning';
|
||||||
import { spyElementPrototype } from 'rc-util/lib/test/domHook';
|
import { spyElementPrototype } from 'rc-util/lib/test/domHook';
|
||||||
@ -395,7 +395,11 @@ describe('Typography', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('editable', () => {
|
describe('editable', () => {
|
||||||
function testStep({ name = '', icon, tooltip } = {}, submitFunc, expectFunc) {
|
function testStep(
|
||||||
|
{ name = '', icon, tooltip, triggerType, enterIcon } = {},
|
||||||
|
submitFunc,
|
||||||
|
expectFunc,
|
||||||
|
) {
|
||||||
it(name, () => {
|
it(name, () => {
|
||||||
jest.useFakeTimers();
|
jest.useFakeTimers();
|
||||||
const onStart = jest.fn();
|
const onStart = jest.fn();
|
||||||
@ -406,7 +410,7 @@ describe('Typography', () => {
|
|||||||
|
|
||||||
const wrapper = mount(
|
const wrapper = mount(
|
||||||
<Paragraph
|
<Paragraph
|
||||||
editable={{ onChange, onStart, icon, tooltip }}
|
editable={{ onChange, onStart, icon, tooltip, triggerType, enterIcon }}
|
||||||
className={className}
|
className={className}
|
||||||
style={style}
|
style={style}
|
||||||
>
|
>
|
||||||
@ -414,12 +418,17 @@ describe('Typography', () => {
|
|||||||
</Paragraph>,
|
</Paragraph>,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (triggerType === undefined || triggerType.indexOf('icon') !== -1) {
|
||||||
if (icon) {
|
if (icon) {
|
||||||
expect(wrapper.find('.anticon-highlight').length).toBeTruthy();
|
expect(wrapper.find('.anticon-highlight').length).toBeTruthy();
|
||||||
} else {
|
} else {
|
||||||
expect(wrapper.find('.anticon-edit').length).toBeTruthy();
|
expect(wrapper.find('.anticon-edit').length).toBeTruthy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (triggerType === undefined || triggerType.indexOf('text') === -1) {
|
||||||
|
wrapper.simulate('click');
|
||||||
|
expect(onStart).not.toHaveBeenCalled();
|
||||||
|
}
|
||||||
wrapper.find('.ant-typography-edit').first().simulate('mouseenter');
|
wrapper.find('.ant-typography-edit').first().simulate('mouseenter');
|
||||||
jest.runAllTimers();
|
jest.runAllTimers();
|
||||||
wrapper.update();
|
wrapper.update();
|
||||||
@ -435,6 +444,21 @@ describe('Typography', () => {
|
|||||||
wrapper.find('.ant-typography-edit').first().simulate('click');
|
wrapper.find('.ant-typography-edit').first().simulate('click');
|
||||||
|
|
||||||
expect(onStart).toHaveBeenCalled();
|
expect(onStart).toHaveBeenCalled();
|
||||||
|
if (triggerType !== undefined && triggerType.indexOf('text') !== -1) {
|
||||||
|
wrapper.find('textarea').simulate('keyDown', { keyCode: KeyCode.ESC });
|
||||||
|
wrapper.find('textarea').simulate('keyUp', { keyCode: KeyCode.ESC });
|
||||||
|
expect(onChange).not.toHaveBeenCalled();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (triggerType !== undefined && triggerType.indexOf('text') !== -1) {
|
||||||
|
if (triggerType.indexOf('icon') === -1) {
|
||||||
|
expect(wrapper.find('.anticon-highlight').length).toBeFalsy();
|
||||||
|
expect(wrapper.find('.anticon-edit').length).toBeFalsy();
|
||||||
|
}
|
||||||
|
wrapper.simulate('click');
|
||||||
|
expect(onStart).toHaveBeenCalled();
|
||||||
|
}
|
||||||
|
|
||||||
// Should have className
|
// Should have className
|
||||||
const props = wrapper.find('div').first().props();
|
const props = wrapper.find('div').first().props();
|
||||||
@ -445,6 +469,18 @@ describe('Typography', () => {
|
|||||||
target: { value: 'Bamboo' },
|
target: { value: 'Bamboo' },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (enterIcon === undefined) {
|
||||||
|
expect(
|
||||||
|
wrapper.find('span.ant-typography-edit-content-confirm').first().props().className,
|
||||||
|
).toContain('anticon-enter');
|
||||||
|
} else if (enterIcon === null) {
|
||||||
|
expect(wrapper.find('span.ant-typography-edit-content-confirm').length).toBe(0);
|
||||||
|
} else {
|
||||||
|
expect(
|
||||||
|
wrapper.find('span.ant-typography-edit-content-confirm').first().props().className,
|
||||||
|
).not.toContain('anticon-enter');
|
||||||
|
}
|
||||||
|
|
||||||
if (submitFunc) {
|
if (submitFunc) {
|
||||||
submitFunc(wrapper);
|
submitFunc(wrapper);
|
||||||
} else {
|
} else {
|
||||||
@ -492,6 +528,13 @@ describe('Typography', () => {
|
|||||||
testStep({ name: 'customize edit show tooltip', tooltip: true });
|
testStep({ name: 'customize edit show tooltip', tooltip: true });
|
||||||
testStep({ name: 'customize edit hide tooltip', tooltip: false });
|
testStep({ name: 'customize edit hide tooltip', tooltip: false });
|
||||||
testStep({ name: 'customize edit tooltip text', tooltip: 'click to edit text' });
|
testStep({ name: 'customize edit tooltip text', tooltip: 'click to edit text' });
|
||||||
|
testStep({ name: 'enter icon - default', enterIcon: undefined });
|
||||||
|
testStep({ name: 'enter icon - null', enterIcon: null });
|
||||||
|
testStep({ name: 'enter icon - custom', enterIcon: <CheckOutlined /> });
|
||||||
|
|
||||||
|
testStep({ name: 'trigger by icon', triggerType: ['icon'] });
|
||||||
|
testStep({ name: 'trigger by text', triggerType: ['text'] });
|
||||||
|
testStep({ name: 'trigger by both icon and text', triggerType: ['icon', 'text'] });
|
||||||
|
|
||||||
it('should trigger onEnd when type Enter', () => {
|
it('should trigger onEnd when type Enter', () => {
|
||||||
const onEnd = jest.fn();
|
const onEnd = jest.fn();
|
||||||
|
@ -15,19 +15,48 @@ Provide additional interactive capacity of editable and copyable.
|
|||||||
|
|
||||||
```jsx
|
```jsx
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { Typography } from 'antd';
|
import { Checkbox, Radio, Typography } from 'antd';
|
||||||
import { HighlightOutlined, SmileOutlined, SmileFilled } from '@ant-design/icons';
|
import { CheckOutlined, HighlightOutlined, SmileOutlined, SmileFilled } from '@ant-design/icons';
|
||||||
|
|
||||||
const { Paragraph } = Typography;
|
const { Paragraph } = Typography;
|
||||||
|
|
||||||
const Demo = () => {
|
const Demo = () => {
|
||||||
const [editableStr, setEditableStr] = useState('This is an editable text.');
|
const [editableStr, setEditableStr] = useState('This is an editable text.');
|
||||||
const [customIconStr, setCustomIconStr] = useState('Custom Edit icon and replace tooltip text.');
|
const [customIconStr, setCustomIconStr] = useState('Custom Edit icon and replace tooltip text.');
|
||||||
|
const [clickTriggerStr, setClickTriggerStr] = useState(
|
||||||
|
'Text or icon as trigger - click to start editing.',
|
||||||
|
);
|
||||||
|
const [chooseTrigger, setChooseTrigger] = useState('icon');
|
||||||
|
const [customEnterIconStr, setCustomEnterIconStr] = useState(
|
||||||
|
'Editable text with a custom enter icon in edit field.',
|
||||||
|
);
|
||||||
|
const [noEnterIconStr, setNoEnterIconStr] = useState(
|
||||||
|
'Editable text with no enter icon in edit field.',
|
||||||
|
);
|
||||||
const [hideTooltipStr, setHideTooltipStr] = useState('Hide Edit tooltip.');
|
const [hideTooltipStr, setHideTooltipStr] = useState('Hide Edit tooltip.');
|
||||||
const [lengthLimitedStr, setLengthLimitedStr] = useState(
|
const [lengthLimitedStr, setLengthLimitedStr] = useState(
|
||||||
'This is an editable text with limited length.',
|
'This is an editable text with limited length.',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const radioToState = input => {
|
||||||
|
switch (input) {
|
||||||
|
case 'text':
|
||||||
|
return ['text'];
|
||||||
|
case 'both':
|
||||||
|
return ['icon', 'text'];
|
||||||
|
case 'icon':
|
||||||
|
default:
|
||||||
|
return ['icon'];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const stateToRadio = () => {
|
||||||
|
if (chooseTrigger.indexOf('text') !== -1) {
|
||||||
|
return chooseTrigger.indexOf('icon') !== -1 ? 'both' : 'text';
|
||||||
|
}
|
||||||
|
return 'icon';
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Paragraph editable={{ onChange: setEditableStr }}>{editableStr}</Paragraph>
|
<Paragraph editable={{ onChange: setEditableStr }}>{editableStr}</Paragraph>
|
||||||
@ -40,6 +69,44 @@ const Demo = () => {
|
|||||||
>
|
>
|
||||||
{customIconStr}
|
{customIconStr}
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
|
Trigger edit with:{' '}
|
||||||
|
<Radio.Group
|
||||||
|
onChange={e => setChooseTrigger(radioToState(e.target.value))}
|
||||||
|
value={stateToRadio()}
|
||||||
|
>
|
||||||
|
<Radio value="icon">icon</Radio>
|
||||||
|
<Radio value="text">text</Radio>
|
||||||
|
<Radio value="both">both</Radio>
|
||||||
|
</Radio.Group>
|
||||||
|
<Paragraph
|
||||||
|
editable={{
|
||||||
|
tooltip: 'click to edit text',
|
||||||
|
onChange: setClickTriggerStr,
|
||||||
|
triggerType: chooseTrigger,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{clickTriggerStr}
|
||||||
|
</Paragraph>
|
||||||
|
<Paragraph
|
||||||
|
editable={{
|
||||||
|
icon: <HighlightOutlined />,
|
||||||
|
tooltip: 'click to edit text',
|
||||||
|
onChange: setCustomEnterIconStr,
|
||||||
|
enterIcon: <CheckOutlined />,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{customEnterIconStr}
|
||||||
|
</Paragraph>
|
||||||
|
<Paragraph
|
||||||
|
editable={{
|
||||||
|
icon: <HighlightOutlined />,
|
||||||
|
tooltip: 'click to edit text',
|
||||||
|
onChange: setNoEnterIconStr,
|
||||||
|
enterIcon: null,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{noEnterIconStr}
|
||||||
|
</Paragraph>
|
||||||
<Paragraph editable={{ tooltip: false, onChange: setHideTooltipStr }}>
|
<Paragraph editable={{ tooltip: false, onChange: setHideTooltipStr }}>
|
||||||
{hideTooltipStr}
|
{hideTooltipStr}
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
|
@ -95,6 +95,8 @@ Basic text writing, including headings, body text, lists, and more.
|
|||||||
onChange: function(string),
|
onChange: function(string),
|
||||||
onCancel: function,
|
onCancel: function,
|
||||||
onEnd: function,
|
onEnd: function,
|
||||||
|
triggerType: ('icon' | 'text')[],
|
||||||
|
enterIcon: ReactNode,
|
||||||
}
|
}
|
||||||
|
|
||||||
| Property | Description | Type | Default | Version |
|
| Property | Description | Type | Default | Version |
|
||||||
@ -104,10 +106,12 @@ Basic text writing, including headings, body text, lists, and more.
|
|||||||
| icon | Custom editable icon | ReactNode | <EditOutlined /> | 4.6.0 |
|
| icon | Custom editable icon | ReactNode | <EditOutlined /> | 4.6.0 |
|
||||||
| maxLength | `maxLength` attribute of textarea | number | - | 4.4.0 |
|
| maxLength | `maxLength` attribute of textarea | number | - | 4.4.0 |
|
||||||
| tooltip | Custom tooltip text, hide when it is false | boolean \| ReactNode | `Edit` | 4.6.0 |
|
| tooltip | Custom tooltip text, hide when it is false | boolean \| ReactNode | `Edit` | 4.6.0 |
|
||||||
| onCancel | Called when type ESC to exit editable state | function | - | |
|
|
||||||
| onChange | Called when input at textarea | function(event) | - | |
|
|
||||||
| onEnd | Called when type ENTER to exit editable state | function | - | 4.14.0 |
|
|
||||||
| onStart | Called when enter editable state | function | - | |
|
| onStart | Called when enter editable state | function | - | |
|
||||||
|
| onChange | Called when input at textarea | function(event) | - | |
|
||||||
|
| onCancel | Called when type ESC to exit editable state | function | - | |
|
||||||
|
| onEnd | Called when type ENTER to exit editable state | function | - | 4.14.0 |
|
||||||
|
| triggerType | Edit mode trigger - icon, text or both (not specifying icon as trigger hides it) | Array<`icon`\|`text`> | \[`icon`] | |
|
||||||
|
| enterIcon | Custom "enter" icon in the edit field (passing `null` removes the icon) | ReactNode | `<EnterOutlined />` | 4.17.0 |
|
||||||
|
|
||||||
### ellipsis
|
### ellipsis
|
||||||
|
|
||||||
|
@ -96,6 +96,8 @@ cover: https://gw.alipayobjects.com/zos/alicdn/GOM1KQ24O/Typography.svg
|
|||||||
onChange: function(string),
|
onChange: function(string),
|
||||||
onCancel: function,
|
onCancel: function,
|
||||||
onEnd: function,
|
onEnd: function,
|
||||||
|
triggerType: ('icon' | 'text')[],
|
||||||
|
enterIcon: ReactNode,
|
||||||
}
|
}
|
||||||
|
|
||||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||||
@ -109,6 +111,8 @@ cover: https://gw.alipayobjects.com/zos/alicdn/GOM1KQ24O/Typography.svg
|
|||||||
| onChange | 文本域编辑时触发 | function(event) | - | |
|
| onChange | 文本域编辑时触发 | function(event) | - | |
|
||||||
| onEnd | 按 ENTER 结束编辑状态时触发 | function | - | 4.14.0 |
|
| onEnd | 按 ENTER 结束编辑状态时触发 | function | - | 4.14.0 |
|
||||||
| onStart | 进入编辑中状态时触发 | function | - | |
|
| onStart | 进入编辑中状态时触发 | function | - | |
|
||||||
|
| triggerType | Edit mode trigger - icon, text or both (not specifying icon as trigger hides it) | Array<`icon`\|`text`> | \[`icon`] | |
|
||||||
|
| enterIcon | 在编辑段中自定义“enter”图标(传递“null”将删除图标) | ReactNode | `<EnterOutlined />` | 4.17.0 |
|
||||||
|
|
||||||
### ellipsis
|
### ellipsis
|
||||||
|
|
||||||
|
@ -174,13 +174,13 @@ const InternalUpload: React.ForwardRefRenderFunction<unknown, UploadProps> = (pr
|
|||||||
let clone;
|
let clone;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
clone = (new File([originFileObj], originFileObj.name, {
|
clone = new File([originFileObj], originFileObj.name, {
|
||||||
type: originFileObj.type,
|
type: originFileObj.type,
|
||||||
}) as any) as UploadFile;
|
}) as any as UploadFile;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
clone = (new Blob([originFileObj], {
|
clone = new Blob([originFileObj], {
|
||||||
type: originFileObj.type,
|
type: originFileObj.type,
|
||||||
}) as any) as UploadFile;
|
}) as any as UploadFile;
|
||||||
clone.name = originFileObj.name;
|
clone.name = originFileObj.name;
|
||||||
clone.lastModifiedDate = new Date();
|
clone.lastModifiedDate = new Date();
|
||||||
clone.lastModified = new Date().getTime();
|
clone.lastModified = new Date().getTime();
|
||||||
@ -326,7 +326,14 @@ const InternalUpload: React.ForwardRefRenderFunction<unknown, UploadProps> = (pr
|
|||||||
showUploadList ? (
|
showUploadList ? (
|
||||||
<LocaleReceiver componentName="Upload" defaultLocale={defaultLocale.Upload}>
|
<LocaleReceiver componentName="Upload" defaultLocale={defaultLocale.Upload}>
|
||||||
{(locale: UploadLocale) => {
|
{(locale: UploadLocale) => {
|
||||||
const { showRemoveIcon, showPreviewIcon, showDownloadIcon, removeIcon, downloadIcon } =
|
const {
|
||||||
|
showRemoveIcon,
|
||||||
|
showPreviewIcon,
|
||||||
|
showDownloadIcon,
|
||||||
|
removeIcon,
|
||||||
|
previewIcon,
|
||||||
|
downloadIcon,
|
||||||
|
} =
|
||||||
typeof showUploadList === 'boolean' ? ({} as ShowUploadListInterface) : showUploadList;
|
typeof showUploadList === 'boolean' ? ({} as ShowUploadListInterface) : showUploadList;
|
||||||
return (
|
return (
|
||||||
<UploadList
|
<UploadList
|
||||||
@ -340,6 +347,7 @@ const InternalUpload: React.ForwardRefRenderFunction<unknown, UploadProps> = (pr
|
|||||||
showPreviewIcon={showPreviewIcon}
|
showPreviewIcon={showPreviewIcon}
|
||||||
showDownloadIcon={showDownloadIcon}
|
showDownloadIcon={showDownloadIcon}
|
||||||
removeIcon={removeIcon}
|
removeIcon={removeIcon}
|
||||||
|
previewIcon={previewIcon}
|
||||||
downloadIcon={downloadIcon}
|
downloadIcon={downloadIcon}
|
||||||
iconRender={iconRender}
|
iconRender={iconRender}
|
||||||
locale={{ ...locale, ...propLocale }}
|
locale={{ ...locale, ...propLocale }}
|
||||||
|
@ -30,6 +30,7 @@ export interface ListItemProps {
|
|||||||
showPreviewIcon?: boolean;
|
showPreviewIcon?: boolean;
|
||||||
removeIcon?: React.ReactNode | ((file: UploadFile) => React.ReactNode);
|
removeIcon?: React.ReactNode | ((file: UploadFile) => React.ReactNode);
|
||||||
downloadIcon?: React.ReactNode | ((file: UploadFile) => React.ReactNode);
|
downloadIcon?: React.ReactNode | ((file: UploadFile) => React.ReactNode);
|
||||||
|
previewIcon?: React.ReactNode | ((file: UploadFile) => React.ReactNode);
|
||||||
iconRender: (file: UploadFile) => React.ReactNode;
|
iconRender: (file: UploadFile) => React.ReactNode;
|
||||||
actionIconRender: (
|
actionIconRender: (
|
||||||
customIcon: React.ReactNode,
|
customIcon: React.ReactNode,
|
||||||
@ -62,6 +63,7 @@ const ListItem = React.forwardRef(
|
|||||||
showPreviewIcon,
|
showPreviewIcon,
|
||||||
showRemoveIcon,
|
showRemoveIcon,
|
||||||
showDownloadIcon,
|
showDownloadIcon,
|
||||||
|
previewIcon: customPreviewIcon,
|
||||||
removeIcon: customRemoveIcon,
|
removeIcon: customRemoveIcon,
|
||||||
downloadIcon: customDownloadIcon,
|
downloadIcon: customDownloadIcon,
|
||||||
onPreview,
|
onPreview,
|
||||||
@ -206,7 +208,9 @@ const ListItem = React.forwardRef(
|
|||||||
onClick={e => onPreview(file, e)}
|
onClick={e => onPreview(file, e)}
|
||||||
title={locale.previewFile}
|
title={locale.previewFile}
|
||||||
>
|
>
|
||||||
<EyeOutlined />
|
{typeof customPreviewIcon === 'function'
|
||||||
|
? customPreviewIcon(file)
|
||||||
|
: customPreviewIcon || <EyeOutlined />}
|
||||||
</a>
|
</a>
|
||||||
) : null;
|
) : null;
|
||||||
|
|
||||||
|
@ -38,6 +38,7 @@ const InternalUploadList: React.ForwardRefRenderFunction<unknown, UploadListProp
|
|||||||
showRemoveIcon,
|
showRemoveIcon,
|
||||||
showDownloadIcon,
|
showDownloadIcon,
|
||||||
removeIcon,
|
removeIcon,
|
||||||
|
previewIcon,
|
||||||
downloadIcon,
|
downloadIcon,
|
||||||
progress,
|
progress,
|
||||||
appendAction,
|
appendAction,
|
||||||
@ -210,6 +211,7 @@ const InternalUploadList: React.ForwardRefRenderFunction<unknown, UploadListProp
|
|||||||
showRemoveIcon={showRemoveIcon}
|
showRemoveIcon={showRemoveIcon}
|
||||||
showDownloadIcon={showDownloadIcon}
|
showDownloadIcon={showDownloadIcon}
|
||||||
removeIcon={removeIcon}
|
removeIcon={removeIcon}
|
||||||
|
previewIcon={previewIcon}
|
||||||
downloadIcon={downloadIcon}
|
downloadIcon={downloadIcon}
|
||||||
iconRender={internalIconRender}
|
iconRender={internalIconRender}
|
||||||
actionIconRender={actionIconRender}
|
actionIconRender={actionIconRender}
|
||||||
|
@ -40,7 +40,7 @@ Uploading is the process of publishing information (web pages, text, pictures, v
|
|||||||
| openFileDialogOnClick | Click open file dialog | boolean | true | |
|
| openFileDialogOnClick | Click open file dialog | boolean | true | |
|
||||||
| previewFile | Customize preview file logic | (file: File \| Blob) => Promise<dataURL: string> | - | |
|
| previewFile | Customize preview file logic | (file: File \| Blob) => Promise<dataURL: string> | - | |
|
||||||
| progress | Custom progress bar | [ProgressProps](/components/progress/#API) (support `type="line"` only) | { strokeWidth: 2, showInfo: false } | 4.3.0 |
|
| progress | Custom progress bar | [ProgressProps](/components/progress/#API) (support `type="line"` only) | { strokeWidth: 2, showInfo: false } | 4.3.0 |
|
||||||
| showUploadList | Whether to show default upload list, could be an object to specify `showPreviewIcon`, `showRemoveIcon`, `showDownloadIcon`, `removeIcon` and `downloadIcon` individually | boolean \| { showPreviewIcon?: boolean, showDownloadIcon?: boolean, showRemoveIcon?: boolean, removeIcon?: ReactNode \| (file: UploadFile) => ReactNode, downloadIcon?: ReactNode \| (file: UploadFile) => ReactNode } | true | function: 4.7.0 |
|
| showUploadList | Whether to show default upload list, could be an object to specify `showPreviewIcon`, `showRemoveIcon`, `showDownloadIcon`, `removeIcon` and `downloadIcon` individually | boolean \| { showPreviewIcon?: boolean, showDownloadIcon?: boolean, showRemoveIcon?: boolean, previewIcon?: ReactNode \| (file: UploadFile) => ReactNode, removeIcon?: ReactNode \| (file: UploadFile) => ReactNode, downloadIcon?: ReactNode \| (file: UploadFile) => ReactNode } | true | function: 4.7.0 |
|
||||||
| withCredentials | The ajax upload with cookie sent | boolean | false | |
|
| withCredentials | The ajax upload with cookie sent | boolean | false | |
|
||||||
| onChange | A callback function, can be executed when uploading state is changing, see [onChange](#onChange) | function | - | |
|
| onChange | A callback function, can be executed when uploading state is changing, see [onChange](#onChange) | function | - | |
|
||||||
| onDrop | A callback function executed when files are dragged and dropped into upload area | (event: React.DragEvent) => void | - | 4.16.0 |
|
| onDrop | A callback function executed when files are dragged and dropped into upload area | (event: React.DragEvent) => void | - | 4.16.0 |
|
||||||
|
@ -41,7 +41,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/QaeBt_ZMg/Upload.svg
|
|||||||
| openFileDialogOnClick | 点击打开文件对话框 | boolean | true | |
|
| openFileDialogOnClick | 点击打开文件对话框 | boolean | true | |
|
||||||
| previewFile | 自定义文件预览逻辑 | (file: File \| Blob) => Promise<dataURL: string> | - | |
|
| previewFile | 自定义文件预览逻辑 | (file: File \| Blob) => Promise<dataURL: string> | - | |
|
||||||
| progress | 自定义进度条样式 | [ProgressProps](/components/progress/#API)(仅支持 `type="line"`) | { strokeWidth: 2, showInfo: false } | 4.3.0 |
|
| progress | 自定义进度条样式 | [ProgressProps](/components/progress/#API)(仅支持 `type="line"`) | { strokeWidth: 2, showInfo: false } | 4.3.0 |
|
||||||
| showUploadList | 是否展示文件列表, 可设为一个对象,用于单独设定 `showPreviewIcon`, `showRemoveIcon`, `showDownloadIcon`, `removeIcon` 和 `downloadIcon` | boolean \| { showPreviewIcon?: boolean, showRemoveIcon?: boolean, showDownloadIcon?: boolean, removeIcon?: ReactNode \| (file: UploadFile) => ReactNode, downloadIcon?: ReactNode \| (file: UploadFile) => ReactNode } | true | function: 4.7.0 |
|
| showUploadList | 是否展示文件列表, 可设为一个对象,用于单独设定 `showPreviewIcon`, `showRemoveIcon`, `showDownloadIcon`, `removeIcon` 和 `downloadIcon` | boolean \| { showPreviewIcon?: boolean, showRemoveIcon?: boolean, showDownloadIcon?: boolean, previewIcon?: ReactNode \| (file: UploadFile) => ReactNode, removeIcon?: ReactNode \| (file: UploadFile) => ReactNode, downloadIcon?: ReactNode \| (file: UploadFile) => ReactNode } | true | function: 4.7.0 |
|
||||||
| withCredentials | 上传请求时是否携带 cookie | boolean | false | |
|
| withCredentials | 上传请求时是否携带 cookie | boolean | false | |
|
||||||
| onChange | 上传文件改变时的状态,详见 [onChange](#onChange) | function | - | |
|
| onChange | 上传文件改变时的状态,详见 [onChange](#onChange) | function | - | |
|
||||||
| onDrop | 当文件被拖入上传区域时执行的回调功能 | (event: React.DragEvent) => void | - | 4.16.0 |
|
| onDrop | 当文件被拖入上传区域时执行的回调功能 | (event: React.DragEvent) => void | - | 4.16.0 |
|
||||||
|
@ -52,6 +52,7 @@ export interface ShowUploadListInterface {
|
|||||||
showDownloadIcon?: boolean;
|
showDownloadIcon?: boolean;
|
||||||
removeIcon?: React.ReactNode | ((file: UploadFile) => React.ReactNode);
|
removeIcon?: React.ReactNode | ((file: UploadFile) => React.ReactNode);
|
||||||
downloadIcon?: React.ReactNode | ((file: UploadFile) => React.ReactNode);
|
downloadIcon?: React.ReactNode | ((file: UploadFile) => React.ReactNode);
|
||||||
|
previewIcon?: React.ReactNode | ((file: UploadFile) => React.ReactNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UploadLocale {
|
export interface UploadLocale {
|
||||||
@ -145,6 +146,7 @@ export interface UploadListProps<T = any> {
|
|||||||
showPreviewIcon?: boolean;
|
showPreviewIcon?: boolean;
|
||||||
removeIcon?: React.ReactNode | ((file: UploadFile) => React.ReactNode);
|
removeIcon?: React.ReactNode | ((file: UploadFile) => React.ReactNode);
|
||||||
downloadIcon?: React.ReactNode | ((file: UploadFile) => React.ReactNode);
|
downloadIcon?: React.ReactNode | ((file: UploadFile) => React.ReactNode);
|
||||||
|
previewIcon?: React.ReactNode | ((file: UploadFile) => React.ReactNode);
|
||||||
locale: UploadLocale;
|
locale: UploadLocale;
|
||||||
previewFile?: PreviewFileHandler;
|
previewFile?: PreviewFileHandler;
|
||||||
iconRender?: (file: UploadFile<T>, listType?: UploadListType) => React.ReactNode;
|
iconRender?: (file: UploadFile<T>, listType?: UploadListType) => React.ReactNode;
|
||||||
|
Loading…
Reference in New Issue
Block a user