Navigation Menu

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: ㊙️ Input passowrd custom icon #23792

Merged
merged 2 commits into from Apr 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 7 additions & 4 deletions components/input/Password.tsx
Expand Up @@ -11,6 +11,7 @@ export interface PasswordProps extends InputProps {
readonly inputPrefixCls?: string;
readonly action?: string;
visibilityToggle?: boolean;
iconRender?: (visible: boolean) => React.ReactNode;
}

export interface PasswordState {
Expand All @@ -28,6 +29,7 @@ export default class Password extends React.Component<PasswordProps, PasswordSta
static defaultProps = {
action: 'click',
visibilityToggle: true,
iconRender: (visible: boolean) => (visible ? <EyeOutlined /> : <EyeInvisibleOutlined />),
};

state: PasswordState = {
Expand All @@ -44,9 +46,10 @@ export default class Password extends React.Component<PasswordProps, PasswordSta
};

getIcon = (prefixCls: string) => {
const { action } = this.props;
const { action, iconRender = () => null } = this.props;
const { visible } = this.state;
const iconTrigger = ActionMap[action!] || '';
const icon = this.state.visible ? EyeOutlined : EyeInvisibleOutlined;
const icon = iconRender(visible);
const iconProps = {
[iconTrigger]: this.onVisibleChange,
className: `${prefixCls}-icon`,
Expand All @@ -62,7 +65,7 @@ export default class Password extends React.Component<PasswordProps, PasswordSta
e.preventDefault();
},
};
return React.createElement(icon as React.ComponentType, iconProps);
return React.cloneElement(React.isValidElement(icon) ? icon : <span>{icon}</span>, iconProps);
};

saveInput = (instance: Input) => {
Expand Down Expand Up @@ -102,7 +105,7 @@ export default class Password extends React.Component<PasswordProps, PasswordSta
});

const props = {
...omit(restProps, ['suffix']),
...omit(restProps, ['suffix', 'iconRender']),
type: this.state.visible ? 'text' : 'password',
className: inputClassName,
prefixCls: inputPrefixCls,
Expand Down
118 changes: 85 additions & 33 deletions components/input/__tests__/__snapshots__/demo.test.js.snap
Expand Up @@ -1899,45 +1899,97 @@ exports[`renders ./components/input/demo/group.md correctly 1`] = `
`;

exports[`renders ./components/input/demo/password-input.md correctly 1`] = `
<span
class="ant-input-password ant-input-affix-wrapper"
<div
class="ant-space ant-space-vertical"
>
<input
action="click"
class="ant-input"
placeholder="input password"
type="password"
value=""
/>
<span
class="ant-input-suffix"
<div
class="ant-space-item"
style="margin-bottom:8px"
>
<span
aria-label="eye-invisible"
class="anticon anticon-eye-invisible ant-input-password-icon"
role="img"
tabindex="-1"
class="ant-input-password ant-input-affix-wrapper"
>
<svg
aria-hidden="true"
class=""
data-icon="eye-invisible"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
<input
action="click"
class="ant-input"
placeholder="input password"
type="password"
value=""
/>
<span
class="ant-input-suffix"
>
<path
d="M942.2 486.2Q889.47 375.11 816.7 305l-50.88 50.88C807.31 395.53 843.45 447.4 874.7 512 791.5 684.2 673.4 766 512 766q-72.67 0-133.87-22.38L323 798.75Q408 838 512 838q288.3 0 430.2-300.3a60.29 60.29 0 000-51.5zm-63.57-320.64L836 122.88a8 8 0 00-11.32 0L715.31 232.2Q624.86 186 512 186q-288.3 0-430.2 300.3a60.3 60.3 0 000 51.5q56.69 119.4 136.5 191.41L112.48 835a8 8 0 000 11.31L155.17 889a8 8 0 0011.31 0l712.15-712.12a8 8 0 000-11.32zM149.3 512C232.6 339.8 350.7 258 512 258c54.54 0 104.13 9.36 149.12 28.39l-70.3 70.3a176 176 0 00-238.13 238.13l-83.42 83.42C223.1 637.49 183.3 582.28 149.3 512zm246.7 0a112.11 112.11 0 01146.2-106.69L401.31 546.2A112 112 0 01396 512z"
/>
<path
d="M508 624c-3.46 0-6.87-.16-10.25-.47l-52.82 52.82a176.09 176.09 0 00227.42-227.42l-52.82 52.82c.31 3.38.47 6.79.47 10.25a111.94 111.94 0 01-112 112z"
/>
</svg>
<span
aria-label="eye-invisible"
class="anticon anticon-eye-invisible ant-input-password-icon"
role="img"
tabindex="-1"
>
<svg
aria-hidden="true"
class=""
data-icon="eye-invisible"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M942.2 486.2Q889.47 375.11 816.7 305l-50.88 50.88C807.31 395.53 843.45 447.4 874.7 512 791.5 684.2 673.4 766 512 766q-72.67 0-133.87-22.38L323 798.75Q408 838 512 838q288.3 0 430.2-300.3a60.29 60.29 0 000-51.5zm-63.57-320.64L836 122.88a8 8 0 00-11.32 0L715.31 232.2Q624.86 186 512 186q-288.3 0-430.2 300.3a60.3 60.3 0 000 51.5q56.69 119.4 136.5 191.41L112.48 835a8 8 0 000 11.31L155.17 889a8 8 0 0011.31 0l712.15-712.12a8 8 0 000-11.32zM149.3 512C232.6 339.8 350.7 258 512 258c54.54 0 104.13 9.36 149.12 28.39l-70.3 70.3a176 176 0 00-238.13 238.13l-83.42 83.42C223.1 637.49 183.3 582.28 149.3 512zm246.7 0a112.11 112.11 0 01146.2-106.69L401.31 546.2A112 112 0 01396 512z"
/>
<path
d="M508 624c-3.46 0-6.87-.16-10.25-.47l-52.82 52.82a176.09 176.09 0 00227.42-227.42l-52.82 52.82c.31 3.38.47 6.79.47 10.25a111.94 111.94 0 01-112 112z"
/>
</svg>
</span>
</span>
</span>
</span>
</span>
</div>
<div
class="ant-space-item"
>
<span
class="ant-input-password ant-input-affix-wrapper"
>
<input
action="click"
class="ant-input"
placeholder="input password"
type="password"
value=""
/>
<span
class="ant-input-suffix"
>
<span
aria-label="eye-invisible"
class="anticon anticon-eye-invisible ant-input-password-icon"
role="img"
tabindex="-1"
>
<svg
aria-hidden="true"
class=""
data-icon="eye-invisible"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M942.2 486.2Q889.47 375.11 816.7 305l-50.88 50.88C807.31 395.53 843.45 447.4 874.7 512 791.5 684.2 673.4 766 512 766q-72.67 0-133.87-22.38L323 798.75Q408 838 512 838q288.3 0 430.2-300.3a60.29 60.29 0 000-51.5zm-63.57-320.64L836 122.88a8 8 0 00-11.32 0L715.31 232.2Q624.86 186 512 186q-288.3 0-430.2 300.3a60.3 60.3 0 000 51.5q56.69 119.4 136.5 191.41L112.48 835a8 8 0 000 11.31L155.17 889a8 8 0 0011.31 0l712.15-712.12a8 8 0 000-11.32zM149.3 512C232.6 339.8 350.7 258 512 258c54.54 0 104.13 9.36 149.12 28.39l-70.3 70.3a176 176 0 00-238.13 238.13l-83.42 83.42C223.1 637.49 183.3 582.28 149.3 512zm246.7 0a112.11 112.11 0 01146.2-106.69L401.31 546.2A112 112 0 01396 512z"
/>
<path
d="M508 624c-3.46 0-6.87-.16-10.25-.47l-52.82 52.82a176.09 176.09 0 00227.42-227.42l-52.82 52.82c.31 3.38.47 6.79.47 10.25a111.94 111.94 0 01-112 112z"
/>
</svg>
</span>
</span>
</span>
</div>
</div>
`;

exports[`renders ./components/input/demo/presuffix.md correctly 1`] = `
Expand Down
14 changes: 12 additions & 2 deletions components/input/demo/password-input.md
Expand Up @@ -14,7 +14,17 @@ title:
Input type of password.

```jsx
import { Input } from 'antd';
import { Input, Space } from 'antd';
import { EyeInvisibleOutlined, EyeTwoTone } from '@ant-design/icons';

ReactDOM.render(<Input.Password placeholder="input password" />, mountNode);
ReactDOM.render(
<Space direction="vertical">
<Input.Password placeholder="input password" />
<Input.Password
placeholder="input password"
iconRender={visible => (visible ? <EyeTwoTone /> : <EyeInvisibleOutlined />)}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EyeTwoTone 自带颜色。

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😅 没注意这块

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IconRender does give an error saying its not a property for <Input.Password>
However the VisibilityToggle does work. Can someone please address this.

/>
</Space>,
mountNode,
);
```