未验证 提交 2bcf9dcd 编写于 作者: D Drjingfubo 提交者: GitHub

feat(shortpassword): 优化demo,增加单元测试,增加国际化 (#222)

上级 033d535d
import * as React from 'react'
import { fireEvent, render } from '@testing-library/react'
import '@testing-library/jest-dom'
import { ShortPassword } from '../shortpassword'
test('should render shortpassword when visible is true', async () => {
const { container } = render(<ShortPassword visible modelValue={123} />)
const input = container.querySelector('.nut-shortpassword__input-real')
expect(input).toBeTruthy()
const psdLength = container.querySelectorAll(
'.nut-shortpassword__input-fake__li'
)
expect(psdLength.length).toBe(6)
expect((input as HTMLInputElement).value).toBe('123')
})
test('should render buttonShortpassword and error msg when noButton is false ', () => {
let value = 0
let inputValue: number | string = ''
const onCancel = () => {
value = 1
}
const onOk = (value: number | string) => {
inputValue = value
}
const { container } = render(
<ShortPassword
visible
modelValue={123}
length={4}
noButton={false}
errorMsg="错误信息"
onCancel={onCancel}
onOk={onOk}
/>
)
const input = container.querySelector('.nut-shortpassword__input-real')
expect(input).toBeTruthy()
const psdLength = container.querySelectorAll(
'.nut-shortpassword__input-fake__li'
)
expect(psdLength.length).toBe(4)
const error = container.querySelector('.nut-shortpassword__message__error')
expect(error).toBeTruthy()
expect((error as HTMLElement).innerHTML).toBe('错误信息')
const cancle = container.querySelector('.nut-shortpassword__footer__cancel')
expect(cancle).toBeTruthy()
const sure = container.querySelector('.nut-shortpassword__footer__sure')
expect(sure).toBeTruthy()
fireEvent.click(cancle as HTMLElement)
expect(value).toBe(1)
fireEvent.click(sure as HTMLElement)
expect(inputValue).toBe(123)
})
test('should limit input value when input', async () => {
let value = 0
const onChange = (v: string | number) => {
value = Number(v)
}
const { container } = render(
<ShortPassword visible modelValue={123} length={4} onChange={onChange} />
)
container.querySelector('input')?.focus()
fireEvent.change(container.querySelector('input')!, {
target: { value: '111111' },
})
expect(value).toBe(1111)
})
......@@ -29,8 +29,11 @@ const ShortPasswordDemo = () => {
<ShortPassword
visible={visible1}
modelValue={value}
onClose={() => setVisible1(false)}
change={(value) => change(value)}
onClose={() => {
setVisible1(false)
setValue('')
}}
onChange={(value) => change(value)}
/>
<h2>显示按钮组</h2>
<Cell
......@@ -42,7 +45,11 @@ const ShortPasswordDemo = () => {
/>
<ShortPassword
visible={visible2}
onClose={() => setVisible2(false)}
modelValue={value}
onClose={() => {
setVisible2(false)
setValue('')
}}
noButton={false}
onOk={() => setVisible2(false)}
onCancel={() => setVisible2(false)}
......@@ -57,7 +64,11 @@ const ShortPasswordDemo = () => {
/>
<ShortPassword
visible={visible3}
onClose={() => setVisible3(false)}
modelValue={value}
onClose={() => {
setVisible3(false)
setValue('')
}}
length={4}
/>
<h2>忘记密码提示语事件回调</h2>
......@@ -70,7 +81,11 @@ const ShortPasswordDemo = () => {
/>
<ShortPassword
visible={visible4}
onClose={() => setVisible4(false)}
modelValue={value}
onClose={() => {
setVisible4(false)
setValue('')
}}
onTips={() => onTips()}
/>
</div>
......
# ShortPassword 短密码
# ShortPassword
### 介绍
### Intro
短密码输入框,可用于输入密码、短信验证码等
Short password input box, which can be used to enter passwords, SMS verification codes, etc.
### 安装
### Install
```js
import { ShortPassword } from '@nutui/nutui-react';
```
## 代码演示
## Demo
### 基础用法
### Basic Usage
:::demo
```tsx
import React, { useState } from "react";
......@@ -21,13 +21,14 @@ import { Cell,ShortPassword } from '@nutui/nutui-react';
const App = () => {
const [visible,setVisible] = useState(false)
const [value,setValue] = useState('')
const change = (value)=>{
setValue(value)
const close = ()=>{
setVisible(false)
setValue('')
}
return (
<>
<Cell
title="基础用法"
title="Basic Usage"
isLink
onClick={() => {
setVisible(true)
......@@ -36,8 +37,8 @@ const App = () => {
<ShortPassword
visible={visible}
modelValue={value}
onClose={() => setVisible(false)}
change={(value) => change(value)}
onClose={() => close()}
onChange={(value) => setValue(value)}
/>
</>
)
......@@ -45,8 +46,11 @@ const App = () => {
export default App;
```
:::
### 显示按钮组
### Show Button Group
:::demo
```tsx
import React, { useState } from "react";
import { Cell,ShortPassword } from '@nutui/nutui-react';
......@@ -56,11 +60,15 @@ const App = () => {
const [value,setValue] = useState('')
const change = (value)=>{
setValue(value)
}
const close = ()=>{
setVisible(false)
setValue('')
}
return (
<>
<Cell
title="显示按钮组"
title="Show Button Group"
isLink
onClick={() => {
setVisible(true)
......@@ -68,8 +76,10 @@ const App = () => {
/>
<ShortPassword
visible={visible}
onClose={() => setVisible(false)}
modelValue={value}
onClose={() => close()}
noButton={false}
onChange={(value) => setValue(value)}
onOk={() => setVisible(false)}
onCancel={() => setVisible(false)}
/>
......@@ -79,8 +89,11 @@ const App = () => {
export default App;
```
:::
### 自定义密码长度4
### Custom Password Length
:::demo
```tsx
import React, { useState } from "react";
import { Cell,ShortPassword } from '@nutui/nutui-react';
......@@ -90,11 +103,15 @@ const App = () => {
const [value,setValue] = useState('')
const change = (value)=>{
setValue(value)
}
const close = ()=>{
setVisible(false)
setValue('')
}
return (
<>
<Cell
title="自定义密码长度4"
title="Custom Password Length"
isLink
onClick={() => {
setVisible(true)
......@@ -102,7 +119,9 @@ const App = () => {
/>
<ShortPassword
visible={visible}
onClose={() => setVisible(false)}
modelValue={value}
onChange={(value) => setValue(value)}
onClose={() => close()}
length={4}
/>
</>
......@@ -111,7 +130,10 @@ const App = () => {
export default App;
```
### 忘记密码提示语事件回调
:::
### Forget password callback
:::demo
```tsx
import React, { useState } from "react";
import { Cell,ShortPassword,Toast } from '@nutui/nutui-react';
......@@ -119,24 +141,27 @@ import { Cell,ShortPassword,Toast } from '@nutui/nutui-react';
const App = () => {
const [visible,setVisible] = useState(false)
const [value,setValue] = useState('')
const change = (value)=>{
setValue(value)
}
const onTips = () => {
Toast.text('执行忘记密码提示语')
Toast.text('Execute forgotten password logic')
}
const close = ()=>{
setVisible(false)
setValue('')
}
return (
<>
<Cell
title="忘记密码提示语事件回调"
title="Forget password"
isLink
onClick={() => {
setVisible(true)
}}
/>
<ShortPassword
<ShortPassword
visible={visible}
onClose={() => setVisible(false)}
modelValue={value}
onChange={(value) => setValue(value)}
onClose={() => close()}
onTips={() => onTips()}
/>
</>
......@@ -145,6 +170,7 @@ const App = () => {
export default App;
```
:::
......@@ -152,25 +178,25 @@ export default App;
### Props
| 参数 | 说明 | 类型 | 默认值 |
| Attribute | Description | Type | Default |
|--------------|----------------------------------|--------|------------------|
| modelValue | 密码初始值 | String|Number | - |
| visible | 是否展示短密码框 | Boolean | false |
| title | 标题 | String | 请输入密码 |
| desc | 密码框描述 | String | 您使用了虚拟资产,请进行验证 |
| tips | 提示语 | String | 忘记密码 |
| closeOnClickOverlay | 是否点击遮罩关闭 | Boolean | true |
| noButton | 是否隐藏底部按钮 | Boolean | true |
| length | 密码长度,取值为4~6 | String|Number | 6 |
| errorMsg | 错误信息提示 | String | '' |
| modelValue | Current value | String|Number | - |
| visible | Whether to show shortpassword | Boolean | false |
| title | title | String | Please input a password |
| desc | desc | String | Verify |
| tips | tips | String | Forget password |
| closeOnClickOverlay | Click to close the mask | Boolean | true |
| noButton | whether to hide the bottom button | Boolean | true |
| length | ShortPassword lenght The value is 4~6 | String|Number | 6 |
| errorMsg | Error message | String | '' |
### Events
| 事件名 | 说明 | 回调参数 |
| Event | Description | Arguments |
|--------|----------------|--------------|
| change | 输入密码时触发事件 | 当前输入框值value |
| onOk | 点击确实时触发事件 | 当前输入框值value |
| onCancel | 点击取消时触发事件 | - |
| onClose | 点击关闭图标和遮罩时触发事件 | - |
| onTips | 点击忘记密码时触发事件 | - |
| complete | 输入完成的回调 | 当前输入框值value |
| onChange | Trigger event when password is entered | value |
| onOk | Trigger event when true is clicked | value |
| onCancel | Trigger an event when the popup layer is clicked or canceled | - |
| onClose | Trigger an event when the close icon is clicked | - |
| onTips | Trigger an event when the forget password is clicked | - |
| onComplete | Input complete callback | value |
......@@ -21,8 +21,9 @@ import { Cell,ShortPassword } from '@nutui/nutui-react';
const App = () => {
const [visible,setVisible] = useState(false)
const [value,setValue] = useState('')
const change = (value)=>{
setValue(value)
const close = ()=>{
setVisible(false)
setValue('')
}
return (
<>
......@@ -36,8 +37,8 @@ const App = () => {
<ShortPassword
visible={visible}
modelValue={value}
onClose={() => setVisible(false)}
change={(value) => change(value)}
onClose={() => close()}
onChange={(value) => setValue(value)}
/>
</>
)
......@@ -45,8 +46,11 @@ const App = () => {
export default App;
```
:::
### 显示按钮组
:::demo
```tsx
import React, { useState } from "react";
import { Cell,ShortPassword } from '@nutui/nutui-react';
......@@ -56,6 +60,10 @@ const App = () => {
const [value,setValue] = useState('')
const change = (value)=>{
setValue(value)
}
const close = ()=>{
setVisible(false)
setValue('')
}
return (
<>
......@@ -68,8 +76,10 @@ const App = () => {
/>
<ShortPassword
visible={visible}
onClose={() => setVisible(false)}
modelValue={value}
onClose={() => close()}
noButton={false}
onChange={(value) => setValue(value)}
onOk={() => setVisible(false)}
onCancel={() => setVisible(false)}
/>
......@@ -79,8 +89,10 @@ const App = () => {
export default App;
```
:::
### 自定义密码长度4
:::demo
```tsx
import React, { useState } from "react";
import { Cell,ShortPassword } from '@nutui/nutui-react';
......@@ -90,6 +102,10 @@ const App = () => {
const [value,setValue] = useState('')
const change = (value)=>{
setValue(value)
}
const close = ()=>{
setVisible(false)
setValue('')
}
return (
<>
......@@ -102,7 +118,9 @@ const App = () => {
/>
<ShortPassword
visible={visible}
onClose={() => setVisible(false)}
modelValue={value}
onChange={(value) => setValue(value)}
onClose={() => close()}
length={4}
/>
</>
......@@ -111,7 +129,9 @@ const App = () => {
export default App;
```
:::
### 忘记密码提示语事件回调
:::demo
```tsx
import React, { useState } from "react";
import { Cell,ShortPassword,Toast } from '@nutui/nutui-react';
......@@ -119,11 +139,12 @@ import { Cell,ShortPassword,Toast } from '@nutui/nutui-react';
const App = () => {
const [visible,setVisible] = useState(false)
const [value,setValue] = useState('')
const change = (value)=>{
setValue(value)
}
const onTips = () => {
Toast.text('执行忘记密码提示语')
}
const close = ()=>{
setVisible(false)
setValue('')
}
return (
<>
......@@ -136,7 +157,9 @@ const App = () => {
/>
<ShortPassword
visible={visible}
onClose={() => setVisible(false)}
modelValue={value}
onChange={(value) => setValue(value)}
onClose={() => close()}
onTips={() => onTips()}
/>
</>
......@@ -145,6 +168,7 @@ const App = () => {
export default App;
```
:::
......@@ -154,7 +178,7 @@ export default App;
| 参数 | 说明 | 类型 | 默认值 |
|--------------|----------------------------------|--------|------------------|
| modelValue | 密码初始值 | String|Number | - |
| modelValue | 内容 | String|Number | - |
| visible | 是否展示短密码框 | Boolean | false |
| title | 标题 | String | 请输入密码 |
| desc | 密码框描述 | String | 您使用了虚拟资产,请进行验证 |
......@@ -168,9 +192,9 @@ export default App;
| 事件名 | 说明 | 回调参数 |
|--------|----------------|--------------|
| change | 输入密码时触发事件 | 当前输入框值value |
| onOk | 点击确时触发事件 | 当前输入框值value |
| onChange | 输入密码时触发事件 | 当前输入框值value |
| onOk | 点击确时触发事件 | 当前输入框值value |
| onCancel | 点击取消时触发事件 | - |
| onClose | 点击关闭图标和遮罩时触发事件 | - |
| onTips | 点击忘记密码时触发事件 | - |
| complete | 输入完成的回调 | 当前输入框值value |
| onComplete | 输入完成的回调 | 当前输入框值value |
# ShortPassword 短密码
# ShortPassword
### 介
### 介
短密码输入框,可用于输入密码、短信验证码
短密碼輸入框,可用於輸入密碼、短信驗證碼
### 安
### 安
```js
import { ShortPassword } from '@nutui/nutui-react';
```
## 代演示
## 代演示
### 基用法
### 基用法
:::demo
```tsx
import React, { useState } from "react";
......@@ -21,13 +21,14 @@ import { Cell,ShortPassword } from '@nutui/nutui-react';
const App = () => {
const [visible,setVisible] = useState(false)
const [value,setValue] = useState('')
const change = (value)=>{
setValue(value)
const close = ()=>{
setVisible(false)
setValue('')
}
return (
<>
<Cell
title="基用法"
title="基用法"
isLink
onClick={() => {
setVisible(true)
......@@ -36,8 +37,8 @@ const App = () => {
<ShortPassword
visible={visible}
modelValue={value}
onClose={() => setVisible(false)}
change={(value) => change(value)}
onClose={() => close()}
onChange={(value) => setValue(value)}
/>
</>
)
......@@ -45,8 +46,11 @@ const App = () => {
export default App;
```
:::
### 显示按钮组
### 顯示按鈕組
:::demo
```tsx
import React, { useState } from "react";
import { Cell,ShortPassword } from '@nutui/nutui-react';
......@@ -56,11 +60,15 @@ const App = () => {
const [value,setValue] = useState('')
const change = (value)=>{
setValue(value)
}
const close = ()=>{
setVisible(false)
setValue('')
}
return (
<>
<Cell
title="显示按钮组"
title="顯示按鈕組"
isLink
onClick={() => {
setVisible(true)
......@@ -68,8 +76,10 @@ const App = () => {
/>
<ShortPassword
visible={visible}
onClose={() => setVisible(false)}
modelValue={value}
onClose={() => close()}
noButton={false}
onChange={(value) => setValue(value)}
onOk={() => setVisible(false)}
onCancel={() => setVisible(false)}
/>
......@@ -79,8 +89,10 @@ const App = () => {
export default App;
```
:::
### 自定义密码长度4
### 自定義密碼長度
:::demo
```tsx
import React, { useState } from "react";
import { Cell,ShortPassword } from '@nutui/nutui-react';
......@@ -90,11 +102,15 @@ const App = () => {
const [value,setValue] = useState('')
const change = (value)=>{
setValue(value)
}
const close = ()=>{
setVisible(false)
setValue('')
}
return (
<>
<Cell
title="自定义密码长度4"
title="自定義密碼長度"
isLink
onClick={() => {
setVisible(true)
......@@ -102,7 +118,9 @@ const App = () => {
/>
<ShortPassword
visible={visible}
onClose={() => setVisible(false)}
modelValue={value}
onChange={(value) => setValue(value)}
onClose={() => close()}
length={4}
/>
</>
......@@ -111,7 +129,9 @@ const App = () => {
export default App;
```
### 忘记密码提示语事件回调
:::
### 忘記密碼提示語事件回調
:::demo
```tsx
import React, { useState } from "react";
import { Cell,ShortPassword,Toast } from '@nutui/nutui-react';
......@@ -119,16 +139,17 @@ import { Cell,ShortPassword,Toast } from '@nutui/nutui-react';
const App = () => {
const [visible,setVisible] = useState(false)
const [value,setValue] = useState('')
const change = (value)=>{
setValue(value)
}
const onTips = () => {
Toast.text('执行忘记密码提示语')
Toast.text('執行忘記密碼提示語')
}
const close = ()=>{
setVisible(false)
setValue('')
}
return (
<>
<Cell
title="忘记密码提示语事件回调"
title="忘記密碼提示語事件回調"
isLink
onClick={() => {
setVisible(true)
......@@ -136,7 +157,9 @@ const App = () => {
/>
<ShortPassword
visible={visible}
onClose={() => setVisible(false)}
modelValue={value}
onChange={(value) => setValue(value)}
onClose={() => close()}
onTips={() => onTips()}
/>
</>
......@@ -145,6 +168,7 @@ const App = () => {
export default App;
```
:::
......@@ -152,25 +176,25 @@ export default App;
### Props
| 参数 | 说明 | 类型 | 默认值 |
| 參數 | 說明 | 類型 | 默認值 |
|--------------|----------------------------------|--------|------------------|
| modelValue | 密码初始值 | String|Number | - |
| visible | 是否展示短密框 | Boolean | false |
| title | 标题 | String | 请输入密码 |
| desc | 密码框描述 | String | 您使用了虚拟资产,请进行验证 |
| tips | 提示语 | String | 忘记密码 |
| closeOnClickOverlay | 是否点击遮罩关闭 | Boolean | true |
| noButton | 是否隐藏底部按钮 | Boolean | true |
| length | 密码长度,取值为4~6 | String|Number | 6 |
| errorMsg | 错误信息提示 | String | '' |
| modelValue | 內容 | String|Number | - |
| visible | 是否展示短密框 | Boolean | false |
| title | 標題 | String | 請輸入密碼 |
| desc | 密碼框描述 | String | 您使用了虛擬資產,請進行驗證|
| tips | 提示語 | String | 忘記密碼 |
| closeOnClickOverlay | 是否點擊遮罩關閉 | Boolean | true |
| noButton | 是否隱藏底部按鈕 | Boolean | true |
| length | 密碼長度,取值為4~6 | String|Number | 6 |
| errorMsg | 錯誤信息提示 | String | '' |
### Events
| 事件名 | 说明 | 回调参数 |
| 事件名 | 說明 | 回調參數 |
|--------|----------------|--------------|
| change | 输入密码时触发事件 | 当前输入框值value |
| onOk | 点击确实时触发事件 | 当前输入框值value |
| onCancel | 点击取消时触发事件 | - |
| onClose | 点击关闭图标和遮罩时触发事件 | - |
| onTips | 点击忘记密码时触发事件 | - |
| complete | 输入完成的回调 | 当前输入框值value |
| onChange | 輸入密碼時觸發事件 | value |
| onOk | 點擊確認時觸發事件 | value |
| onCancel | 點擊取消時觸發事件 | - |
| onClose | 點擊關閉圖標和遮罩時觸發事件 | - |
| onTips | 點擊忘記密碼時觸發事件 | - |
| onComplete | 輸入完成的回調 | value |
......@@ -22,17 +22,17 @@ export interface ShortPasswordProps {
length: string | number
className: string
style?: CSSProperties
change: (value: string | number) => void
onChange: (value: string | number) => void
onOk: (value: string | number) => void
onCancel: () => void
onClose: () => void
onTips: () => void
complete: (value: string | number) => void
onComplete: (value: string | number) => void
}
const defaultProps = {
title: '请输入密码',
desc: '您使用了虚拟资产,请进行验证',
tips: '忘记密码',
title: '',
desc: '',
tips: '',
visible: false,
modelValue: '',
errorMsg: '',
......@@ -40,15 +40,16 @@ const defaultProps = {
closeOnClickOverlay: true,
length: 6, // 1~6
className: '',
change: (value: number | string) => {},
onChange: (value: number | string) => {},
onOk: (value: number | string) => {},
onCancel: () => {},
onClose: () => {},
onTips: () => {},
complete: (value: number | string) => {},
onComplete: (value: number | string) => {},
} as ShortPasswordProps
export const ShortPassword: FunctionComponent<
Partial<ShortPasswordProps> & React.HTMLAttributes<HTMLDivElement>
Partial<ShortPasswordProps> &
Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'>
> = (props) => {
const { locale } = useConfig()
const {
......@@ -63,12 +64,12 @@ export const ShortPassword: FunctionComponent<
length,
style,
className,
change,
onChange,
onOk,
onTips,
onCancel,
onClose,
complete,
onComplete,
...reset
} = props
const b = bem('shortpassword')
......@@ -83,7 +84,7 @@ export const ShortPassword: FunctionComponent<
setInnerVisible(visible)
}, [visible])
useEffect(() => {
if (modelValue) {
if (typeof modelValue !== 'undefined') {
setInputValue(modelValue)
}
}, [modelValue])
......@@ -94,25 +95,28 @@ export const ShortPassword: FunctionComponent<
}
setInputValue(inputValue)
if (String(inputValue).length === comLen) {
complete && complete(inputValue)
onComplete && onComplete(inputValue)
}
change && change(inputValue)
onChange && onChange(inputValue)
}
const systemStyle = () => {
const u = navigator.userAgent
const isAndroid = u.indexOf('Android') > -1 || u.indexOf('Linux') > -1 // g
const isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/) // ios终端
let style = {}
console.log(isIOS, isAndroid)
if (isIOS) {
return {
style = {
paddingRight: '1200px',
}
}
if (isAndroid) {
return {
style = {
opacity: 0,
zIndex: 10,
}
}
return style
}
const focus = () => {
if (textInput.current) {
......@@ -139,10 +143,10 @@ export const ShortPassword: FunctionComponent<
>
<div className={`${b()} ${className}`} style={{ ...style }} {...reset}>
<div className={b('title')}>
{locale.shortpassword.title || title}
{title || locale.shortpassword.title}
</div>
<div className={b('subtitle')}>
{locale.shortpassword.desc || desc}
{desc || locale.shortpassword.desc}
</div>
<div className={b('input')}>
......@@ -170,10 +174,10 @@ export const ShortPassword: FunctionComponent<
</div>
<div className={b('message')}>
<div className={b('message__error')}>{errorMsg}</div>
{tips ? (
{tips || locale.shortpassword.tips ? (
<div className={b('message__forget')}>
<Icon className="icon" size="11px" name="tips" />
<div onClick={onTips}>{locale.shortpassword.tips || tips}</div>
<div onClick={onTips}>{tips || locale.shortpassword.tips}</div>
</div>
) : null}
</div>
......
......@@ -495,7 +495,6 @@ $divider-vertical-top: 2px !default;
$divider-vertical-border-left: rgba(0, 0, 0, 0.06) !default;
$divider-vertical-margin: 0 8px !default;
// swiper
$swiper-pagination-item-background-color: #ddd !default;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册