diff --git a/components/input/Password.tsx b/components/input/Password.tsx index 0a62f90619..0d65270b42 100644 --- a/components/input/Password.tsx +++ b/components/input/Password.tsx @@ -6,7 +6,8 @@ import EyeOutlined from '@ant-design/icons-vue/EyeOutlined'; import EyeInvisibleOutlined from '@ant-design/icons-vue/EyeInvisibleOutlined'; import type { InputProps } from './inputProps'; import inputProps from './inputProps'; -import { computed, defineComponent, shallowRef } from 'vue'; +import type { PropType } from 'vue'; +import { computed, defineComponent, shallowRef, watchEffect } from 'vue'; import useConfigInject from '../config-provider/hooks/useConfigInject'; import omit from '../_util/omit'; @@ -26,9 +27,11 @@ export default defineComponent({ inputPrefixCls: String, action: { type: String, default: 'click' }, visibilityToggle: { type: Boolean, default: true }, + visible: { type: Boolean, default: undefined }, + 'onUpdate:visible': Function as PropType<(visible: boolean) => void>, iconRender: Function, }, - setup(props, { slots, attrs, expose }) { + setup(props, { slots, attrs, expose, emit }) { const visible = shallowRef(false); const onVisibleChange = () => { const { disabled } = props; @@ -36,7 +39,13 @@ export default defineComponent({ return; } visible.value = !visible.value; + emit('update:visible', visible.value); }; + watchEffect(() => { + if (props.visible !== undefined) { + visible.value = !!props.visible; + } + }); const inputRef = shallowRef(); const focus = () => { inputRef.value?.focus(); diff --git a/components/input/__tests__/__snapshots__/demo.test.js.snap b/components/input/__tests__/__snapshots__/demo.test.js.snap index ba0df76926..416dd244ca 100644 --- a/components/input/__tests__/__snapshots__/demo.test.js.snap +++ b/components/input/__tests__/__snapshots__/demo.test.js.snap @@ -33,8 +33,8 @@ exports[`renders ./components/input/demo/addon.vue correctly 1`] = ` `; exports[`renders ./components/input/demo/allow-clear.vue correctly 1`] = ` -
-

+
+

`; @@ -124,14 +124,37 @@ exports[`renders ./components/input/demo/group.vue correctly 1`] = ` `; exports[`renders ./components/input/demo/password-input.vue correctly 1`] = ` - - +
+
+ +
+ +
+ +
+ +
+ +
+
+
+ +
+ +
+ +
+
+ +
`; exports[`renders ./components/input/demo/presuffix.vue correctly 1`] = `
-

RMB +

RMB
`; diff --git a/components/input/__tests__/index.test.js b/components/input/__tests__/index.test.js index 6a15b2f4ff..5dad154468 100644 --- a/components/input/__tests__/index.test.js +++ b/components/input/__tests__/index.test.js @@ -163,4 +163,30 @@ describe('Input.Password', () => { expect(wrapper.findAll('.anticon-sync').length).toBe(1); }, 100); }); + + it('should support visibilityToggle(boolean)', async () => { + const wrapper = mount(Input.Password, { props: { visibilityToggle: false }, sync: false }); + await asyncExpect(() => { + expect(wrapper.findAll('.anticon-eye').length).toBe(0); + }, 100); + }); + + it('should support visible', async () => { + const cbMock = jest.fn(); + const wrapper = mount({ + render() { + return ; + }, + }); + + await asyncExpect(() => { + expect(wrapper.findAll('.anticon-eye').length).toBe(1); + }, 100); + + await asyncExpect(() => { + wrapper.find('.anticon-eye').trigger('click'); + }, 100); + + expect(cbMock).toHaveBeenCalledWith(false); + }); }); diff --git a/components/input/demo/password-input.vue b/components/input/demo/password-input.vue index ff05b81a51..c2c4ec6660 100644 --- a/components/input/demo/password-input.vue +++ b/components/input/demo/password-input.vue @@ -16,9 +16,36 @@ Input type of password. diff --git a/components/input/index.en-US.md b/components/input/index.en-US.md index 0a0cb4f2dd..a57cd983c2 100644 --- a/components/input/index.en-US.md +++ b/components/input/index.en-US.md @@ -94,6 +94,8 @@ Supports all props of `Input`. #### Input.Password (Added in 1.14.0) -| Property | Description | Type | Default | -| ---------------- | -------------------------- | ------- | ------- | -| visibilityToggle | Whether show toggle button | boolean | true | +| Property | Description | Type | Default | +| ---------------- | ------------------------------------------------------ | ------- | ------- | +| visible(v-model) | password visibility | boolean | false | +| iconRender | Custom toggle button | slot | - | +| visibilityToggle | Whether show toggle button or control password visible | boolean | true | diff --git a/components/input/index.zh-CN.md b/components/input/index.zh-CN.md index d6c3e01b2e..06489389d4 100644 --- a/components/input/index.zh-CN.md +++ b/components/input/index.zh-CN.md @@ -95,6 +95,8 @@ coverDark: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*sBqqTatJ-AkAAA #### Input.Password (1.14.0 中新增) -| 参数 | 说明 | 类型 | 默认值 | -| ---------------- | ---------------- | ------- | ------ | -| visibilityToggle | 是否显示切换按钮 | boolean | true | +| 参数 | 说明 | 类型 | 默认值 | +| ---------------- | -------------------------------- | ------- | ------ | +| visible(v-model) | 密码是否可见 | boolean | false | +| iconRender | 自定义切换按钮 | slot | - | +| visibilityToggle | 是否显示切换按钮或者控制密码显隐 | boolean | true |