UNPKG

@coreui/vue-pro

Version:

UI Components Library for Vue.js

215 lines (186 loc) 5.33 kB
// CPasswordInput.ts import { defineComponent, h, ref, toRefs, watch, computed } from 'vue' import { CFormControlWrapper } from '../form/CFormControlWrapper' export const CPasswordInput = defineComponent({ name: 'CPasswordInput', inheritAttrs: false, props: { /** * Accessible label for the toggle visibility button. */ ariaLabelToggler: { type: String, default: 'Toggle password visibility', }, /** * Delay emitting `change` and `update:modelValue` events. * `true` = 500ms delay, or specify custom delay in ms. */ delay: { type: [Boolean, Number], default: false, }, /** * Disables the password input field. When `true`, the user cannot interact with the field. */ disabled: Boolean, /** * General feedback text shown below the input. */ feedback: String, /** * Feedback text shown when input is invalid. */ feedbackInvalid: String, /** * Feedback text shown when input is valid. */ feedbackValid: String, /** * Class for the floating label wrapper. */ floatingClassName: String, /** * Floating label text. */ floatingLabel: String, /** * ID of the input element. */ id: String, /** * Marks the input as invalid. */ invalid: Boolean, /** * Main label for the input. */ label: String, /** * The current value of the password input, used with v-model. */ modelValue: String, /** * Makes the input read-only, allowing text selection only. */ readOnly: Boolean, /** * Controls the initial visibility of the password. */ showPassword: Boolean, /** * Sets the visual size of the input. Accepts `'sm'`, `'lg'`, or undefined. */ size: { type: String as () => 'sm' | 'lg' | undefined, default: undefined, }, /** * Helper or hint text displayed below the input. */ text: String, /** * Enables tooltip-style validation feedback messages. */ tooltipFeedback: Boolean, /** * Marks the input as valid. */ valid: Boolean, /** * Alternative to `modelValue`, mostly for manual `:value` binding. */ value: String, }, emits: ['update:modelValue', 'change'], setup(props, { emit, attrs }) { const { delay, showPassword, size, invalid, valid } = toRefs(props) const localValue = ref(props.modelValue ?? props.value ?? '') const visible = ref(showPassword.value ?? false) const inputType = computed(() => (visible.value ? 'text' : 'password')) watch( () => props.modelValue ?? props.value, (val) => { if (val !== localValue.value) { localValue.value = val as string } } ) let timeout: ReturnType<typeof setTimeout> watch(localValue, (val) => { if (delay.value) { clearTimeout(timeout) timeout = setTimeout( () => { emit('update:modelValue', val) emit('change', val) }, typeof delay.value === 'number' ? delay.value : 500 ) } else { emit('update:modelValue', val) emit('change', val) } }) const togglePassword = () => { visible.value = !visible.value } return () => h( CFormControlWrapper, { describedby: attrs['aria-describedby'] as string, feedback: props.feedback, feedbackInvalid: props.feedbackInvalid, feedbackValid: props.feedbackValid, floatingClassName: props.floatingLabel ? ['form-password', props.floatingClassName].join(' ') : props.floatingClassName, floatingLabel: props.floatingLabel, id: props.id, invalid: props.invalid, label: props.label, text: props.text, tooltipFeedback: props.tooltipFeedback, valid: props.valid, }, { default: () => { const inputEl = h('input', { ...attrs, id: props.id, type: inputType.value, class: [ 'form-control', { [`form-control-${size.value}`]: size.value, 'is-invalid': invalid.value, 'is-valid': valid.value, }, attrs.class, ], value: localValue.value, onInput: (e: Event) => { localValue.value = (e.target as HTMLInputElement).value }, disabled: props.disabled, readOnly: props.readOnly, }) const buttonEl = h( 'button', { type: 'button', class: 'form-password-action', 'data-coreui-toggle': 'password', 'aria-label': props.ariaLabelToggler, onClick: togglePassword, }, [h('span', { class: 'form-password-action-icon' })] ) const content = [inputEl, buttonEl] return props.floatingLabel ? content : h('div', { class: 'form-password' }, content) }, } ) }, })