@passcore/vue

Vue

@passcore/vue ofrece un componente, <PasswordStrengthMeter>, y el composable usePasswordStrength(), para Vue 3.5 o posterior.

pnpm add @passcore/vue
Leer el README

Todos los indicadores de esta página hablan tu idioma. La zona de pruebas le da a cada uno los textos del idioma que elijas arriba y su nombre accesible. Para que los fragmentos de código sean breves, solo las demos de traducción muestran cómo se hace; el botón para mostrar y ocultar la contraseña es de la zona de pruebas, no del paquete.

Por defecto

El componente recibe la contraseña como prop, así que funciona con cualquier v-model. Siempre se ve; id lo asocia al campo.

Vue
<script setup>
import { ref } from 'vue'
import { PasswordStrengthMeter } from '@passcore/vue'
import '@passcore/vue/styles.css'

const password = ref('')
</script>

<template>
  <input id="password" v-model="password" type="password" aria-describedby="password-strength">
  <PasswordStrengthMeter id="password-strength" :password="password" />
</template>

Lista de requisitos

El clásico formulario de registro, con tu propio marcado: el composable usePasswordStrength() devuelve el resultado como ref, y result.rules enumera todas las reglas activas, por orden, con su id, passed y params. El componente dibuja la barra al lado. Cada elemento se queda en gris hasta que se escribe algo: una contraseña vacía tampoco es “común”, y mostrarlo en verde sería engañoso.

Vue
<script setup>
import { computed, ref } from 'vue'
import { PasswordStrengthMeter, usePasswordStrength } from '@passcore/vue'

const rules = { minLength: 8, lowercase: 1, uppercase: 1, numbers: 1, symbols: 1 }
const username = ref('')
const password = ref('')

const { result } = usePasswordStrength(password, () => ({ userInputs: [username.value], rules }))
const typed = computed(() => password.value !== '')
const met = computed(() => result.value.rules.filter((rule) => rule.passed).length)
</script>

<template>
  <PasswordStrengthMeter :password="password" :user-inputs="[username]" :rules="rules" />
  <ul>
    <li v-for="rule in result.rules" :key="rule.id" :data-state="!typed ? 'idle' : rule.passed ? 'met' : 'unmet'">
      {{ t(`requirements.rule.${rule.id}`, { count: rule.params.min }) }}
    </li>
  </ul>
  <p aria-live="polite">
    {{ typed ? `${met} of ${result.rules.length} requirements met` : `${result.rules.length} requirements to meet` }}
  </p>
</template>

Con el porcentaje

show-percent añade el número junto a la barra.

Vue
<PasswordStrengthMeter id="password-strength" :password="password" show-percent />

Vinculado a un nombre de usuario

Con user-inputs la contraseña no puede contener el nombre de usuario. Pásale los valores actuales, directamente desde tus refs.

Vue
<input v-model="username" type="text" autocomplete="username">
<PasswordStrengthMeter
  id="password-strength"
  :password="password"
  :user-inputs="[username]"
  show-percent
/>

Traducciones incluidas

Los archivos incluidos van en translations, locale elige las formas del plural y label da nombre al indicador para los lectores de pantalla. Cambia el idioma arriba: props nuevas, textos nuevos.

Vue
<script setup>
import en from '@passcore/vue/locales/en.json'
import es from '@passcore/vue/locales/es.json'
import ca from '@passcore/vue/locales/ca.json'

const locales = { en, es, ca }
</script>

<template>
  <PasswordStrengthMeter
    :password="password"
    :translations="locales[lang]"
    :locale="lang"
    :label="labels[lang]"
    show-percent
  />
</template>

Traducciones con i18next

translate recibe la función t de una instancia de i18next, aquí la de la propia zona de pruebas. La función no cambia nunca, así que locale le indica al componente cuándo debe volver a traducir.

Vue
<script setup>
import i18next from 'i18next'
import es from '@passcore/vue/locales/es.json'
import ca from '@passcore/vue/locales/ca.json'

i18next.addResourceBundle('es', 'passcore', es)
i18next.addResourceBundle('ca', 'passcore', ca)

const translate = (key, params) => i18next.t(key, { ns: 'passcore', ...params })
</script>

<template>
  <!-- locale tells the meter to translate again -->
  <PasswordStrengthMeter :password="password" :translate="translate" :locale="lang" :label="labels[lang]" show-percent />
</template>

Callbacks y eventos

El evento score trae el porcentaje cada vez que cambia el resultado (nunca al montarse). Aquí controla la puntuación y el botón Enviar.

Vue
<script setup>
const percent = ref(0)
</script>

<template>
  <PasswordStrengthMeter :password="password" @score="(value) => (percent = value)" />
  <output>{{ percent }}%</output>
  <button type="submit" :disabled="percent <= 75">Send</button>
</template>

Grupo de campos

El indicador es un elemento más: ponlo después del grupo de campos y ocupará todo el ancho del grupo.

Vue
<div class="form-group">
  <label for="password">Password</label>
  <div class="input-group">
    <span class="input-group__addon">…</span>
    <input id="password" v-model="password" type="password">
  </div>
  <PasswordStrengthMeter :password="password" />
</div>

Temas

Los colores, la pista y la altura son propiedades personalizadas de CSS: de --pass-color-very-weak a --pass-color-strong, --pass-track y --pass-height. Juega con ellas aquí: el CSS de abajo cambia a la vez.

  • Muy débil
  • Débil
  • Aceptable
  • Buena
  • Fuerte
Propiedades personalizadas
Combinaciones
CSS
.signup {
  --pass-height: 6px;
  --pass-track: #e4e2db;
  --pass-color-very-weak: #d92d20;
  --pass-color-weak: #e06a0f;
  --pass-color-fair: #c99400;
  --pass-color-good: #5e9e0f;
  --pass-color-strong: #16884a;
}

Los controles solo cambian esta vista previa, así que las demás demos conservan su aspecto. Define las propiedades en :root para aplicar el tema a todo un sitio.