import { ref, watch, computed, Teleport, Transition } from 'vue'; import { createNamespace, stopPropagation } from '../utils'; import { useClickAway } from '@vant/use'; import Key from './Key'; const [createComponent, bem] = createNamespace('number-keyboard'); export default createComponent({ props: { show: Boolean, title: String, zIndex: [Number, String], teleport: [String, Object], randomKeyOrder: Boolean, closeButtonText: String, deleteButtonText: String, closeButtonLoading: Boolean, theme: { type: String, default: 'default', }, modelValue: { type: String, default: '', }, extraKey: { type: [String, Array], default: '', }, maxlength: { type: [Number, String], default: Number.MAX_VALUE, }, transition: { type: Boolean, default: true, }, showDeleteKey: { type: Boolean, default: true, }, hideOnClickOutside: { type: Boolean, default: true, }, safeAreaInsetBottom: { type: Boolean, default: true, }, }, emits: [ 'show', 'hide', 'blur', 'input', 'close', 'delete', 'update:modelValue', ], setup(props, { emit, slots }) { const root = ref(); const genBasicKeys = () => { const keys = []; for (let i = 1; i <= 9; i++) { keys.push({ text: i }); } if (props.randomKeyOrder) { keys.sort(() => (Math.random() > 0.5 ? 1 : -1)); } return keys; }; const genDefaultKeys = () => [ ...genBasicKeys(), { text: props.extraKey, type: 'extra' }, { text: 0 }, { text: props.showDeleteKey ? props.deleteButtonText : '', type: props.showDeleteKey ? 'delete' : '', }, ]; const genCustomKeys = () => { const keys = genBasicKeys(); const { extraKey } = props; const extraKeys = Array.isArray(extraKey) ? extraKey : [extraKey]; if (extraKeys.length === 1) { keys.push( { text: 0, wider: true }, { text: extraKeys[0], type: 'extra' } ); } else if (extraKeys.length === 2) { keys.push( { text: extraKeys[0], type: 'extra' }, { text: 0 }, { text: extraKeys[1], type: 'extra' } ); } return keys; }; const keys = computed(() => props.theme === 'custom' ? genCustomKeys() : genDefaultKeys() ); const onBlur = () => { if (props.show) { emit('blur'); } }; const onClose = () => { emit('close'); onBlur(); }; const onAnimationEnd = () => { emit(props.show ? 'show' : 'hide'); }; const onPress = (text, type) => { if (text === '') { if (type === 'extra') { onBlur(); } return; } const value = props.modelValue; if (type === 'delete') { emit('delete'); emit('update:modelValue', value.slice(0, value.length - 1)); } else if (type === 'close') { onClose(); } else if (value.length < props.maxlength) { emit('input', text); emit('update:modelValue', value + text); } }; const renderTitle = () => { const { title, theme, closeButtonText } = props; const leftSlot = slots['title-left']; const showClose = closeButtonText && theme === 'default'; const showTitle = title || showClose || leftSlot; if (!showTitle) { return; } return (
{leftSlot && {leftSlot()}} {title &&

{title}

} {showClose && ( )}
); }; const renderKeys = () => { return keys.value.map((key) => { const slots = {}; if (key.type === 'delete') { slots.default = slots.delete; } if (key.type === 'extra') { slots.default = slots['extra-key']; } return ( ); }); }; const renderSidebar = () => { if (props.theme === 'custom') { return (
{props.showDeleteKey && ( )}
); } }; watch( () => props.show, (value) => { if (!props.transition) { emit(value ? 'show' : 'hide'); } } ); if (props.hideOnClickOutside) { useClickAway(root, onClose, { eventName: 'touchstart' }); } return () => { const Title = renderTitle(); const Content = (
{Title}
{renderKeys()}
{renderSidebar()}
); if (props.teleport) { return {Content}; } return Content; }; }, });