Skip to content

Commit

Permalink
feat:n-input Support hidden password
Browse files Browse the repository at this point in the history
  • Loading branch information
doom-9 committed Jun 17, 2021
1 parent 5b1e14b commit ea64917
Show file tree
Hide file tree
Showing 10 changed files with 185 additions and 4 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## 2.12.0 (2020-06-16)

### Feats

- `n-input` 的 password 属性支持查看隐藏特性

### Breaking Changes

- 移除了 `n-a``to` 属性。现在如果你需要把 `n-a` 用作 router-link,你可以参考文档网站。
Expand Down
1 change: 1 addition & 0 deletions src/_internal/eye/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './src/Eye'
70 changes: 70 additions & 0 deletions src/_internal/eye/src/Eye.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { h, defineComponent, PropType, toRef, ref } from 'vue'
import { useStyle, useConfig } from '../../../_mixins'
import { EyeIcon, EyeInvisibleIcon } from '../../icons'
import NBaseIcon from '../../icon'
import NIconSwitchTransition from '../../icon-switch-transition'
import style from './styles/index.cssr'

export default defineComponent({
name: 'BaseClear',
props: {
clsPrefix: {
type: String,
required: true
},
onClick: {
type: Function as PropType<() => void>,
required: true
}
},
setup (props) {
useStyle('BaseClear', style, toRef(props, 'clsPrefix'))
const { NConfigProvider } = useConfig()
const showPassWord = ref(false)
return {
NConfigProvider,
handleMouseDown (e: MouseEvent) {
e.preventDefault()
},
showPassWord,
handleShowPassWord () {
showPassWord.value = !showPassWord.value
}
}
},
render () {
const { clsPrefix, showPassWord, handleShowPassWord, onClick } = this
return (
<div class={`${clsPrefix}-base-clear`} data-clear>
<NIconSwitchTransition>
{{
default: () => {
return (
<NBaseIcon
clsPrefix={clsPrefix}
key="dismiss"
class={`${clsPrefix}-base-clear__clear`}
onClick={() => {
handleShowPassWord()
onClick()
}}
onMousedown={this.handleMouseDown}
>
{{
default: () => {
if (showPassWord) {
return <EyeIcon />
} else {
return <EyeInvisibleIcon />
}
}
}}
</NBaseIcon>
)
}
}}
</NIconSwitchTransition>
</div>
)
}
})
58 changes: 58 additions & 0 deletions src/_internal/eye/src/styles/index.cssr.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { cB, c, cE } from '../../../../_utils/cssr'
import createIconSwitchTransition from '../../../../_styles/transitions/icon-switch.cssr'

// vars:
// --bezier
// --clear-color
// --clear-size
// --clear-color-hover
// --clear-color-pressed
export default cB(
'base-clear',
{
flexShrink: 0,
height: '1em',
width: '1em',
position: 'relative'
},
[
c('>', [
cE(
'clear',
{
fontSize: 'var(--size)',
cursor: 'pointer',
color: 'var(--clear-color)',
transition: 'color .3s var(--bezier)'
},
[
c('&:hover', {
color: 'var(--clear-color-hover)!important'
}),
c('&:active', {
color: 'var(--clear-color-pressed)!important'
})
]
),
cE('placeholder', {
display: 'flex'
}),
cE(
'clear, placeholder',
{
position: 'absolute',
left: '50%',
top: '50%',
transform: 'translateX(-50%) translateY(-50%)'
},
[
createIconSwitchTransition({
originalTransform: 'translateX(-50%) translateY(-50%)',
left: '50%',
top: '50%'
})
]
)
])
]
)
12 changes: 12 additions & 0 deletions src/_internal/icons/Eye.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { h } from 'vue'
import { replaceable } from './replaceable'

export default replaceable(
'eye',
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
<path
d="M942.2 486.2C847.4 286.5 704.1 186 512 186c-192.2 0-335.4 100.5-430.2 300.3a60.3 60.3 0 0 0 0 51.5C176.6 737.5 319.9 838 512 838c192.2 0 335.4-100.5 430.2-300.3c7.7-16.2 7.7-35 0-51.5zM512 766c-161.3 0-279.4-81.8-362.7-254C232.6 339.8 350.7 258 512 258c161.3 0 279.4 81.8 362.7 254C791.5 684.2 673.4 766 512 766zm-4-430c-97.2 0-176 78.8-176 176s78.8 176 176 176s176-78.8 176-176s-78.8-176-176-176zm0 288c-61.9 0-112-50.1-112-112s50.1-112 112-112s112 50.1 112 112s-50.1 112-112 112z"
fill="currentColor"
></path>
</svg>
)
16 changes: 16 additions & 0 deletions src/_internal/icons/EyeInvisible.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { h } from 'vue'
import { replaceable } from './replaceable'

export default replaceable(
'eyeinvisible',
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
<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 512C791.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 0 0 0-51.5zm-63.57-320.64L836 122.88a8 8 0 0 0-11.32 0L715.31 232.2Q624.86 186 512 186q-288.3 0-430.2 300.3a60.3 60.3 0 0 0 0 51.5q56.69 119.4 136.5 191.41L112.48 835a8 8 0 0 0 0 11.31L155.17 889a8 8 0 0 0 11.31 0l712.15-712.12a8 8 0 0 0 0-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 0 0-238.13 238.13l-83.42 83.42C223.1 637.49 183.3 582.28 149.3 512zm246.7 0a112.11 112.11 0 0 1 146.2-106.69L401.31 546.2A112 112 0 0 1 396 512z"
fill="currentColor"
></path>
<path
d="M508 624c-3.46 0-6.87-.16-10.25-.47l-52.82 52.82a176.09 176.09 0 0 0 227.42-227.42l-52.82 52.82c.31 3.38.47 6.79.47 10.25a111.94 111.94 0 0 1-112 112z"
fill="currentColor"
></path>
</svg>
)
2 changes: 2 additions & 0 deletions src/_internal/icons/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ export { default as TrashIcon } from './Trash'
export { default as DownloadIcon } from './Download'
export { default as EmptyIcon } from './Empty'
export { default as ErrorIcon } from './Error'
export { default as EyeIcon } from './Eye'
export { default as EyeInvisibleIcon } from './EyeInvisible'
export { default as FastBackwardIcon } from './FastBackward'
export { default as FastForwardIcon } from './FastForward'
export { default as FilterIcon } from './Filter'
Expand Down
1 change: 1 addition & 0 deletions src/_internal/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ export { default as NInternalSelection } from './selection'
export type { InternalSelectionInst } from './selection'
export { default as NBaseSlotMachine } from './slot-machine'
export { default as NBaseClear } from './clear'
export { default as NBaseEye } from './eye'
2 changes: 2 additions & 0 deletions src/config-provider/src/internal-interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,8 @@ export interface GlobalIconConfig {
date?: () => VNodeChild
download?: () => VNodeChild
error?: () => VNodeChild
eye?: () => VNodeChild
eyeinvisible?: () => VNodeChild
info?: () => VNodeChild
retry?: () => VNodeChild
success?: () => VNodeChild
Expand Down
23 changes: 19 additions & 4 deletions src/input/src/Input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
import { useMergedState } from 'vooks'
import { toRgbString, getAlphaString, getPadding } from 'seemly'
import { VResizeObserver } from 'vueuc'
import { NBaseClear } from '../../_internal'
import { NBaseClear, NBaseEye } from '../../_internal'
import { useTheme, useLocale, useFormItem, useConfig } from '../../_mixins'
import type { ThemeProps } from '../../_mixins'
import { call, createKey, ExtractPublicPropTypes } from '../../_utils'
Expand Down Expand Up @@ -160,6 +160,7 @@ export default defineComponent({
const hoverRef = ref(false)
const isComposingRef = ref(false)
const activatedRef = ref(false)
const isShowPwd = ref(false)
let syncSource: string | null = null
// placeholder
const mergedPlaceholderRef = computed<[string, string] | [string]>(() => {
Expand Down Expand Up @@ -582,6 +583,9 @@ export default defineComponent({
function handleTextAreaMirrorResize (): void {
updateTextAreaStyle()
}
function handleShowPwd (): void {
isShowPwd.value = !isShowPwd.value
}

let stopWatchMergedValue: WatchStopHandle | null = null
watchEffect(() => {
Expand Down Expand Up @@ -641,6 +645,7 @@ export default defineComponent({
textDecorationStyle: textDecorationStyleRef,
mergedClsPrefix: mergedClsPrefixRef,
mergedBordered: mergedBorderedRef,
isShowPwd,
// methods
handleCompositionStart,
handleCompositionEnd,
Expand All @@ -657,6 +662,7 @@ export default defineComponent({
handleClear,
handleWrapperKeyDown,
handleTextAreaMirrorResize,
handleShowPwd,
mergedTheme: themeRef,
cssVars: computed(() => {
const { value: size } = mergedSizeRef
Expand Down Expand Up @@ -759,7 +765,7 @@ export default defineComponent({
}
},
render () {
const { mergedClsPrefix } = this
const { mergedClsPrefix, isShowPwd } = this
return (
<div
ref="wrapperElRef"
Expand Down Expand Up @@ -852,7 +858,7 @@ export default defineComponent({
<div class={`${mergedClsPrefix}-input__input`}>
<input
ref="inputElRef"
type={this.type}
type={isShowPwd ? 'input' : this.type}
class={`${mergedClsPrefix}-input__input-el`}
tabindex={
this.passivelyActivated && !this.activated ? -1 : undefined
Expand Down Expand Up @@ -892,7 +898,10 @@ export default defineComponent({
</div>
)}
{!this.pair &&
(this.$slots.suffix || this.clearable || this.showCount) ? (
(this.$slots.suffix ||
this.clearable ||
this.showCount ||
this.type === 'password') ? (
<div class={`${mergedClsPrefix}-input__suffix`}>
{[
renderSlot(this.$slots, 'suffix'),
Expand All @@ -907,6 +916,12 @@ export default defineComponent({
) : null,
this.showCount && this.type !== 'textarea' ? (
<WordCount />
) : null,
this.type === 'password' ? (
<NBaseEye
clsPrefix={mergedClsPrefix}
onClick={this.handleShowPwd}
/>
) : null
]}
</div>
Expand Down

0 comments on commit ea64917

Please sign in to comment.