Skip to content

Commit

Permalink
fix(@uform/antd): support password add size props and use Input.Passw…
Browse files Browse the repository at this point in the history
…ord in antd(#192)
  • Loading branch information
atzcl authored and janryWang committed Jul 27, 2019
1 parent d5610db commit 633dd30
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 157 deletions.
22 changes: 19 additions & 3 deletions docs/Examples/antd/Validation.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,10 +138,20 @@ import {
FormLayout,
createFormActions
} from '@uform/antd'
import { Button } from 'antd'
import { Button, Icon } from 'antd'
import Printer from '@uform/printer'
import 'antd/dist/antd.css'

const PasswordPrefixIcon = (
<Icon
type="lock"
style={{
color: 'rgba(0, 0, 0, 0.25)',
fontSize: 14
}}
/>
)

const App = () => (
<Printer>
<SchemaForm
Expand Down Expand Up @@ -175,7 +185,10 @@ const App = () => (
type="password"
name="password"
title="密码"
x-props={{ checkStrength: true }}
x-props={{
checkStrength: true,
prefix: PasswordPrefixIcon,
}}
description={
<ul>
<li>1. 长度不小于8</li>
Expand All @@ -188,7 +201,10 @@ const App = () => (
type="password"
name="confirm"
title="确认密码"
x-props={{ checkStrength: true }}
x-props={{
checkStrength: true,
prefix: PasswordPrefixIcon,
}}
required
/>
<FormButtonGroup offset={6}>
Expand Down
216 changes: 62 additions & 154 deletions packages/antd/src/fields/password.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import React from 'react'
import React, { useState } from 'react'
import styled from 'styled-components'
import { Input } from 'antd'
import { InputProps } from 'antd/es/input'
import { connect, registerFormField } from '@uform/react'
import { mapStyledProps } from '../utils'

var isNum = function(c) {
return c >= 48 && c <= 57
Expand Down Expand Up @@ -150,162 +152,30 @@ const getStrength = val => {
}
}

export interface IPasswordProps {
value: any
defaultValue: any
className: string
// TODO 不知道下面三个是什么东西
checkStrength: any
htmlType: any
innerAfter: any
onChange: (value: any) => void
}

export interface IPasswordState {
value: any
interface IStrengthProps {
strength: number
eye: boolean
className?: string
}

const Password = styled(
class Password extends React.Component<IPasswordProps, IPasswordState> {
public state = {
value: this.props.value || this.props.defaultValue,
strength: 0,
eye: false
}

public componentDidUpdate(prevProps) {
if (
prevProps.value !== this.props.value &&
this.props.value !== this.state.value
) {
this.setState({
value: this.props.value,
strength: getStrength(this.props.value)
})
}
}

public onChangeHandler = e => {
const value = e.target.value
this.setState(
{
value,
strength: getStrength(value)
},
() => {
if (this.props.onChange) {
this.props.onChange(value)
}
}
)
}

public renderStrength() {
const { strength } = this.state
return (
<div className={'password-strength-wrapper'}>
<div className={'div-1 div'} />
<div className={'div-2 div'} />
<div className={'div-3 div'} />
<div className={'div-4 div'} />
<div
className={'password-strength-bar'}
style={{
clipPath: `polygon(0 0,${strength}% 0,${strength}% 100%,0 100%)`
}}
/>
</div>
)
}

public switchEye() {
return () => {
this.setState({
eye: !this.state.eye
})
}
}

public renderEye() {
if (!this.state.eye) {
return (
<img
className={'eye'}
onClick={this.switchEye()}
src={'//img.alicdn.com/tfs/TB1wyXlsVzqK1RjSZFvXXcB7VXa-200-200.svg'}
/>
)
} else {
return (
<img
className={'eye'}
onClick={this.switchEye()}
src={'//img.alicdn.com/tfs/TB1xiXlsVzqK1RjSZFvXXcB7VXa-200-200.svg'}
/>
)
}
}

public render() {
const {
className,
checkStrength,
value,
onChange,
htmlType,
innerAfter,
...others
} = this.props

return (
<div className={className}>
<Input
type={this.state.eye ? 'text' : 'password'}
className={`input-${this.state.eye ? 'text' : 'password'}`}
value={this.state.value}
onChange={this.onChangeHandler}
suffix={this.renderEye()}
{...others}
/>
{checkStrength && this.renderStrength()}
</div>
)
}
}
// 校验强度 UI
const StrengthFC = styled(
({ strength, className }: IStrengthProps) => (
<div {...{ className }}>
<div className={'password-strength-wrapper'}>
<div className={'div-1 div'} />
<div className={'div-2 div'} />
<div className={'div-3 div'} />
<div className={'div-4 div'} />
<div
className={'password-strength-bar'}
style={{
clipPath: `polygon(0 0,${strength}% 0,${strength}% 100%,0 100%)`
}}
/>
</div>
</div>
)
)`
.ant-input-prefix,
.ant-input-suffix {
z-index: 10;
right: 20px !important;
.eye {
position: absolute;
max-width: initial;
width: 20px;
height: 20px;
top: 50%;
left: -5px;
transform: translate(0, -50%);
opacity: 0.3;
cursor: pointer;
transition: all 0.15s ease-in-out;
&:hover {
opacity: 0.6;
}
}
}
.ant-input {
width: 100%;
position: relative;
&.input-password input {
font-size: 16px;
letter-spacing: 2px;
}
input {
padding-right: 25px;
}
}
.password-strength-wrapper {
background: #e0e0e0;
margin-bottom: 3px;
Expand Down Expand Up @@ -342,4 +212,42 @@ const Password = styled(
}
`

registerFormField('password', connect()(Password))
export interface IPasswordProps extends Omit<InputProps, 'onChange'> {
checkStrength: boolean // 是否启用密码强度校验
onChange: (value: InputProps['value']) => void
}

const PasswordFC = (props: Partial<IPasswordProps>) => {
const [strength, setStrength] = useState(0)

const { checkStrength, ...others } = props

const onChangeHandler = (e: React.ChangeEvent<HTMLInputElement>) => {
const value = e.target.value

// 开启才计算
checkStrength && setStrength(getStrength(value))

// 回调
props.onChange && props.onChange(value)
}

return (
<React.Fragment>
<Input.Password
{...others}
value={props.value || props.defaultValue}
onChange={onChangeHandler}
/>

{checkStrength && <StrengthFC {...{ strength }} />}
</React.Fragment>
)
}

registerFormField(
'password',
connect({
getProps: mapStyledProps,
})(PasswordFC)
)

0 comments on commit 633dd30

Please sign in to comment.