UNPKG

@lincy/tnui-vue3-uniapp

Version:
173 lines (154 loc) 4.34 kB
import { computed, nextTick, ref, watch } from 'vue' import { trim } from '../../../../libs/lodash' import { CHANGE_EVENT, INPUT_EVENT, UPDATE_MODEL_EVENT, } from '../../../../constants' import { FormValidateIconsMap, debugWarn, isEmptyVariableInDefault, } from '../../../../utils' import { useToggle } from '../../../../hooks' import { useFormDisabled, useFormItem } from '../../../form' import type { SetupContext } from 'vue' import type { FormItemValidateStates } from '../../../form' import type { InputEmit, InputProps } from '../input' export const useInput = ( props: InputProps, emits: SetupContext<InputEmit>['emit'] ) => { const { form, formItem } = useFormItem() // 输入框内容 const inputText = ref<string>( String(isEmptyVariableInDefault(props.modelValue, '')) ) watch( () => props.modelValue, (val) => { inputText.value = String(isEmptyVariableInDefault(val, '')) if (props.validateEvent) { formItem?.validate?.('change').catch((err) => { debugWarn(err) }) } } ) // 显示/隐藏密码状态 const [passwordVisible, togglePasswordVisible] = useToggle(false) // 是否显示状态图标 const needStatusIcon = computed(() => isEmptyVariableInDefault(form?.statusIcon, false) ) // 校验状态 const validateState = computed(() => isEmptyVariableInDefault<FormItemValidateStates>( formItem?.validateState, '' ) ) // 校验状态图标 const validateIcon = computed( () => validateState.value && FormValidateIconsMap[validateState.value] ) // 密码显示密码图标 const passwordIcon = computed(() => passwordVisible.value ? 'eye-hide' : 'eye' ) // 是否显示图标 const showIcon = computed(() => { let status = false if (validateState.value && needStatusIcon.value && validateIcon.value) status = true if (props.showPassword) status = true if (props.rightIcon) status = true if (props.clearable) status = true return status }) // 输入框禁止事件 const disabled = useFormDisabled(props.disabled) // 是否显示字数统计 const showWordLimit = computed<boolean>( () => props.type === 'textarea' && !!props?.maxlength && !!props?.showWordLimit ) // 当前的字数 const currentWordCount = computed<number>(() => { if (props.showWordLimit && props.type === 'textarea') { return inputText.value?.length || 0 } return 0 }) // 内容输入触发事件 const inputInputEvent = (event: any) => { const { value } = event.detail _updateInputText(value) } // 输入框聚焦事件 const inputFocusEvent = (event: any) => { emits('focus', event) } // 输入框失去焦点事件 const inputBlurEvent = (event: any) => { emits('blur', event) if (props.validateEvent) { // eslint-disable-next-line @typescript-eslint/no-empty-function formItem?.validate?.('blur').catch((err) => { debugWarn(err) }) } } // 点击完成时触发事件 const confirmEvent = (event: any) => { const { value } = event.detail emits('confirm', _formatInputText(value)) } // 点击清除按钮 const clearClickEvent = () => { if (disabled.value) return _updateInputText('') emits('clear') } // 更新输入框内容 const _updateInputText = (value: string) => { value = props.trim ? trim(value) : value // inputText.value = value emits(UPDATE_MODEL_EVENT, _formatInputText(value)) nextTick(() => { emits(INPUT_EVENT, _formatInputText(value)) emits(CHANGE_EVENT, _formatInputText(value)) }) } // 输入框点击事件 const inputClickEvent = () => { if (props.type === 'select') { emits('click') } } const _formatInputText = (value: string) => { if (value === '') return '' if (props.type === 'number' || props.type === 'digit') return Number.parseFloat(value) return value } return { inputText, needStatusIcon, validateState, validateIcon, passwordVisible, passwordIcon, showIcon, disabled, showWordLimit, currentWordCount, togglePasswordVisible, inputInputEvent, inputFocusEvent, inputBlurEvent, clearClickEvent, confirmEvent, inputClickEvent, } }