<!--
  Forked from:
  https://quasar.dev/vue-components/input#Example--Design-Overview
-->
<div id="q-app">
  <q-card class="q-ma-sm bg-grey-10" style="max-width: 300px">
    <q-card-section>
      <div class="q-gutter-sm">
        <q-input v-model="landline" ref="landline" unmasked-value :mask="landlineMask" outlined dark label="Tel. Fixo"></q-input>
        <q-input v-model="cellphone" ref="cellphone" unmasked-value :mask="cellphoneMask" outlined dark label="Celular"></q-input>
      </div>
    </q-card-section>
  </q-card>
</div>
new Vue({
  el: '#q-app',
  data () {
    return {
      landline: '',
      cellphone: ''
    }
  },
  watch: {
    landlineMask () {
      let input = this.$refs.landline.$refs.input
      requestAnimationFrame(() => {
        input.selectionStart = input.value.length
      })
    },
    cellphoneMask () {
      let input = this.$refs.cellphone.$refs.input
      requestAnimationFrame(() => {
        input.selectionStart = input.value.length
      })
    }
  },
  computed: {
    landlineMask () {
      switch (true) {
        case this.landline.length <= 8: return '####-#####'
        case this.landline.length === 9: return '#####-#####'
        case this.landline.length === 10: return '(##) ####-#####'
        default: return '(##) #####-####'
      }
    },
    cellphoneMask () {
      switch (true) {
        case this.cellphone.length <= 8: return '####-#####'
        case this.cellphone.length === 9: return '#####-#####'
        case this.cellphone.length === 10: return '(##) ####-#####'
        default: return '(##) #####-####'
      }
    }
  }
})
View Compiled

External CSS

  1. https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons
  2. https://cdn.jsdelivr.net/npm/quasar@1.9.3/dist/quasar.min.css

External JavaScript

  1. https://cdn.jsdelivr.net/npm/vue/dist/vue.js
  2. https://cdn.jsdelivr.net/npm/quasar@1.9.3/dist/quasar.umd.min.js