V-mask plugin playground

by Dmitriy Belyaev

HTML

<script src="https://unpkg.com/vue"></script>
<script src="https://cdn.jsdelivr.net/npm/v-mask/dist/v-mask.min.js"></script>
<div id="app">
  <label>
    {{label}}:
    <input :type="type" :value="value" @input="onInput">
  </label>
</div>

JavaScript

// jsfiddle fix
if(!String.prototype.contains) {
	String.prototype.contains = {
  	contains(str) {
    	return this.indexOf(str) !== -1;
    }
  }.contains;
}

const DEFAULT_LABEL = 'Phone or e-mail';
const DEFAULT_TYPE = 'text';
new Vue({
  el: '#app',
  data: () => ({
  	label: DEFAULT_LABEL,
  	type: DEFAULT_TYPE,
    value: ''
  }),
  methods: {
  	onInput(e) {
      setTimeout(() => {
      	console.log(e.target.value = this.value);
      }, 100);
    	const {value} = e.target;
      const normalizedValue = value.trim().toLowerCase();
      if(normalizedValue === '') {	
        return this.reset();
      }
      const firstChar = normalizedValue.charAt(0);
      const firstCharCode = normalizedValue.charCodeAt(0);
      if(firstChar === '+' || isNumberChar(firstCharCode)) {
      	return this.checkPhone(normalizedValue);
      }
      if(isLetterChar(firstCharCode)) {
      	return this.checkEmail(normalizedValue);
      }
      this.reset();
    },
    reset() {
    	this.value = '';
  		this.type = DEFAULT_TYPE;
  		this.label = DEFAULT_LABEL;
    },
    checkPhone(value, target) {
    	this.type = 'phone';
      this.label = 'Phone';
      this.value = formatPhone(value);
    },
    checkEmail(value) {
    	this.type = 'email';
      this.label = 'Email';
      this.value = formatEmail(value);
    }
  }
});

function formatPhone(value) {
  // тут только для России, другие форматы доделывайте сами
  const validChars = [...value.slice(value.startsWith('+7')
  	? 2
    : ('+78'.contains(value[0])
    	? 1
      : 0
    )
  )].filter(char => isNumberChar(char.charCodeAt(0))).slice(0, 10).join('');
  return '+7' + (len => {
  	switch(true) {
    case len < 3:
    	return '(' + validChars;
    case len < 6:
    	return `(${validChars.slice(0, 3)}) ${validChars.slice(3)}`;
    case len < 8:
    	return `(${validChars.slice(0, 3)}) ${validChars.slice(3, 6)}-${validChars.slice(6)}`;
    default:
    	return `(${validChars.slice(0, 3)}) ${validChars.slice(3,...