Skip to content

Commit

Permalink
Merge pull request #19544 from ant-design/feature-merge-master
Browse files Browse the repository at this point in the history
chore: Feature merge master
  • Loading branch information
zombieJ committed Nov 4, 2019
2 parents 696f560 + 5bf96bb commit 15d8494
Show file tree
Hide file tree
Showing 78 changed files with 1,983 additions and 712 deletions.
23 changes: 23 additions & 0 deletions components/avatar/__tests__/__snapshots__/demo.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,29 @@ exports[`renders ./components/avatar/demo/toggle-debug.md correctly 1`] = `

exports[`renders ./components/avatar/demo/type.md correctly 1`] = `
<div>
<span
class="ant-avatar ant-avatar-circle ant-avatar-icon"
>
<i
aria-label="icon: user"
class="anticon anticon-user"
>
<svg
aria-hidden="true"
class=""
data-icon="user"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M858.5 763.6a374 374 0 0 0-80.6-119.5 375.63 375.63 0 0 0-119.5-80.6c-.4-.2-.8-.3-1.2-.5C719.5 518 760 444.7 760 362c0-137-111-248-248-248S264 225 264 362c0 82.7 40.5 156 102.8 201.1-.4.2-.8.3-1.2.5-44.8 18.9-85 46-119.5 80.6a375.63 375.63 0 0 0-80.6 119.5A371.7 371.7 0 0 0 136 901.8a8 8 0 0 0 8 8.2h60c4.4 0 7.9-3.5 8-7.8 2-77.2 33-149.5 87.8-204.3 56.7-56.7 132-87.9 212.2-87.9s155.5 31.2 212.2 87.9C779 752.7 810 825 812 902.2c.1 4.4 3.6 7.8 8 7.8h60a8 8 0 0 0 8-8.2c-1-47.8-10.9-94.3-29.5-138.2zM512 534c-45.9 0-89.1-17.9-121.6-50.4S340 407.9 340 362c0-45.9 17.9-89.1 50.4-121.6S466.1 190 512 190s89.1 17.9 121.6 50.4S684 316.1 684 362c0 45.9-17.9 89.1-50.4 121.6S557.9 534 512 534z"
/>
</svg>
</i>
</span>
<span
class="ant-avatar ant-avatar-circle ant-avatar-icon"
>
Expand Down
3 changes: 2 additions & 1 deletion components/avatar/demo/type.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ title:
Image, Icon and letter are supported, and the latter two kinds of avatar can have custom colors and background colors.

```jsx
import { Avatar } from 'antd';
import { Avatar, Icon } from 'antd';

ReactDOM.render(
<div>
<Avatar icon="user" />
<Avatar icon={<Icon type="user" />} />
<Avatar>U</Avatar>
<Avatar>USER</Avatar>
<Avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />
Expand Down
2 changes: 1 addition & 1 deletion components/avatar/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Avatars can be used to represent people or objects. It supports images, `Icon`s,

| Property | Description | Type | Default | Version |
| --- | --- | --- | --- | --- |
| icon | the `Icon` type for an icon avatar, see `Icon` Component | string | - | |
| icon | the `Icon` type for an icon avatar, see `Icon` Component or use ReactNode | string \| ReactNode | - | |
| shape | the shape of avatar | `circle` \| `square` | `circle` | |
| size | the size of the avatar | number \| string: `large` `small` `default` | `default` | |
| src | the address of the image for an image avatar | string | - | |
Expand Down
8 changes: 6 additions & 2 deletions components/avatar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export interface AvatarProps {
/** Srcset of image avatar */
srcSet?: string;
/** Type of the Icon to be used in avatar */
icon?: string;
icon?: string | React.ReactNode;
style?: React.CSSProperties;
prefixCls?: string;
className?: string;
Expand Down Expand Up @@ -137,7 +137,11 @@ export default class Avatar extends React.Component<AvatarProps, AvatarState> {
if (src && isImgExist) {
children = <img src={src} srcSet={srcSet} onError={this.handleImgLoadError} alt={alt} />;
} else if (icon) {
children = <Icon type={icon} />;
if (typeof icon === 'string') {
children = <Icon type={icon} />;
} else {
children = icon;
}
} else {
const childrenNode = this.avatarChildren;
if (childrenNode || scale !== 1) {
Expand Down
2 changes: 1 addition & 1 deletion components/avatar/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ title: Avatar

| 参数 | 说明 | 类型 | 默认值 | 版本 |
| --- | --- | --- | --- | --- |
| icon | 设置头像的图标类型,参考 `Icon` 组件 | string | - | |
| icon | 设置头像的图标类型,可设为 Icon`type` 或 ReactNode | string \| ReactNode | - | |
| shape | 指定头像的形状 | Enum{ 'circle', 'square' } | `circle` | |
| size | 设置头像的大小 | number \| Enum{ 'large', 'small', 'default' } | `default` | |
| src | 图片类头像的资源地址 | string | - | |
Expand Down
181 changes: 181 additions & 0 deletions components/input/ClearableLabeledInput.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
import * as React from 'react';
import { polyfill } from 'react-lifecycles-compat';
import classNames from 'classnames';
import Icon from '../icon';
import { tuple } from '../_util/type';
import { InputProps, InputSizes, getInputClassName } from './Input';

const ClearableInputType = tuple('text', 'input');

export function hasPrefixSuffix(props: InputProps | ClearableInputProps) {
return !!(props.prefix || props.suffix || props.allowClear);
}

/**
* This basic props required for input and textarea.
*/
interface BasicProps {
prefixCls: string;
inputType: (typeof ClearableInputType)[number];
value?: any;
defaultValue?: any;
allowClear?: boolean;
element: React.ReactElement<any>;
handleReset: (event: React.MouseEvent<HTMLElement, MouseEvent>) => void;
className?: string;
style?: object;
disabled?: boolean;
}

/**
* This props only for input.
*/
interface ClearableInputProps extends BasicProps {
size?: (typeof InputSizes)[number];
suffix?: React.ReactNode;
prefix?: React.ReactNode;
addonBefore?: React.ReactNode;
addonAfter?: React.ReactNode;
}

class ClearableLabeledInput extends React.Component<ClearableInputProps> {
renderClearIcon(prefixCls: string) {
const { allowClear, value, disabled, inputType, handleReset } = this.props;
if (!allowClear || disabled || value === undefined || value === null || value === '') {
return null;
}
const className =
inputType === ClearableInputType[0]
? `${prefixCls}-textarea-clear-icon`
: `${prefixCls}-clear-icon`;
return (
<Icon
type="close-circle"
theme="filled"
onClick={handleReset}
className={className}
role="button"
/>
);
}

renderSuffix(prefixCls: string) {
const { suffix, allowClear } = this.props;
if (suffix || allowClear) {
return (
<span className={`${prefixCls}-suffix`}>
{this.renderClearIcon(prefixCls)}
{suffix}
</span>
);
}
return null;
}

renderLabeledIcon(prefixCls: string, element: React.ReactElement<any>) {
const props = this.props;
const suffix = this.renderSuffix(prefixCls);
if (!hasPrefixSuffix(props)) {
return React.cloneElement(element, {
value: props.value,
});
}

const prefix = props.prefix ? (
<span className={`${prefixCls}-prefix`}>{props.prefix}</span>
) : null;

const affixWrapperCls = classNames(props.className, `${prefixCls}-affix-wrapper`, {
[`${prefixCls}-affix-wrapper-sm`]: props.size === 'small',
[`${prefixCls}-affix-wrapper-lg`]: props.size === 'large',
[`${prefixCls}-affix-wrapper-input-with-clear-btn`]:
props.suffix && props.allowClear && this.props.value,
});
return (
<span className={affixWrapperCls} style={props.style}>
{prefix}
{React.cloneElement(element, {
style: null,
value: props.value,
className: getInputClassName(prefixCls, props.size, props.disabled),
})}
{suffix}
</span>
);
}

renderInputWithLabel(prefixCls: string, labeledElement: React.ReactElement<any>) {
const { addonBefore, addonAfter, style, size, className } = this.props;
// Not wrap when there is not addons
if (!addonBefore && !addonAfter) {
return labeledElement;
}

const wrapperClassName = `${prefixCls}-group`;
const addonClassName = `${wrapperClassName}-addon`;
const addonBeforeNode = addonBefore ? (
<span className={addonClassName}>{addonBefore}</span>
) : null;
const addonAfterNode = addonAfter ? <span className={addonClassName}>{addonAfter}</span> : null;

const mergedWrapperClassName = classNames(`${prefixCls}-wrapper`, {
[wrapperClassName]: addonBefore || addonAfter,
});

const mergedGroupClassName = classNames(className, `${prefixCls}-group-wrapper`, {
[`${prefixCls}-group-wrapper-sm`]: size === 'small',
[`${prefixCls}-group-wrapper-lg`]: size === 'large',
});

// Need another wrapper for changing display:table to display:inline-block
// and put style prop in wrapper
return (
<span className={mergedGroupClassName} style={style}>
<span className={mergedWrapperClassName}>
{addonBeforeNode}
{React.cloneElement(labeledElement, { style: null })}
{addonAfterNode}
</span>
</span>
);
}

renderTextAreaWithClearIcon(prefixCls: string, element: React.ReactElement<any>) {
const { value, allowClear, className, style } = this.props;
if (!allowClear) {
return React.cloneElement(element, {
value,
});
}
const affixWrapperCls = classNames(
className,
`${prefixCls}-affix-wrapper`,
`${prefixCls}-affix-wrapper-textarea-with-clear-btn`,
);
return (
<span className={affixWrapperCls} style={style}>
{React.cloneElement(element, {
style: null,
value,
})}
{this.renderClearIcon(prefixCls)}
</span>
);
}

renderClearableLabeledInput() {
const { prefixCls, inputType, element } = this.props;
if (inputType === ClearableInputType[0]) {
return this.renderTextAreaWithClearIcon(prefixCls, element);
}
return this.renderInputWithLabel(prefixCls, this.renderLabeledIcon(prefixCls, element));
}

render() {
return this.renderClearableLabeledInput();
}
}

polyfill(ClearableLabeledInput);

export default ClearableLabeledInput;

0 comments on commit 15d8494

Please sign in to comment.