@passcore/vanilla

JavaScript puro

@passcore/vanilla no necesita ningún framework ni jQuery: llama a createPasswordMeter() sobre un campo, o escribe un elemento <passcore-meter> donde quieras el indicador.

pnpm add @passcore/vanilla
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

Con hideUntilFocus el indicador se mantiene oculto hasta que el campo recibe el foco, y vuelve a ocultarse al perderlo si el campo está vacío.

JavaScript
import { createPasswordMeter } from '@passcore/vanilla'
import '@passcore/vanilla/styles.css'

createPasswordMeter('#default-password', { hideUntilFocus: true })

Lista de requisitos

El clásico formulario de registro: todas las condiciones, en rojo o en verde mientras se escribe. El callback onScore (o el evento passcore:score, que se propaga) trae el resultado completo, y result.rules enumera todas las reglas activas, por orden, con su id, passed y params. Al escribir el nombre de usuario se llama a refresh(), para que la regla de los datos personales lo tenga en cuenta. 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.

Requisitos

  • Al menos 8 caracteres , cumplido , no cumplido
  • Que no sea una contraseña común , cumplido , no cumplido
  • Sin datos personales, como tu nombre de usuario , cumplido , no cumplido
  • Una letra minúscula , cumplido , no cumplido
  • Una letra mayúscula , cumplido , no cumplido
  • Un número , cumplido , no cumplido
  • Un símbolo , cumplido , no cumplido

7 requisitos por cumplir

JavaScript
// the list: <li data-rule="minLength" data-state="idle">At least 8 characters</li>, and so on
const input = document.querySelector('#signup-password')
const summary = document.querySelector('#checklist-summary')

function check(result) {
  const typed = input.value !== ''
  for (const rule of result.rules) {
    const item = document.querySelector(`#checklist [data-rule="${rule.id}"]`)
    item.dataset.state = !typed ? 'idle' : rule.passed ? 'met' : 'unmet'
  }
  // a live region: only touch it when the count changes
  const met = result.rules.filter((rule) => rule.passed).length
  const text = typed ? `${met} of ${result.rules.length} requirements met` : `${result.rules.length} requirements to meet`
  if (summary.textContent !== text) {
    summary.textContent = text
  }
}

const meter = createPasswordMeter(input, {
  userInputs: ['#signup-username'],
  rules: { minLength: 8, lowercase: 1, uppercase: 1, numbers: 1, symbols: 1 },
  onScore: (percent, result) => check(result),
})
// or: input.addEventListener('passcore:score', (event) => check(event.detail.result))

// the username is read on each update: refresh when it changes
document.querySelector('#signup-username').addEventListener('input', () => meter.refresh())

Siempre visible, con el porcentaje

Sin hideUntilFocus el indicador se ve desde el principio, y showPercent añade el número.

JavaScript
createPasswordMeter('#always-password', { showPercent: true })

Vinculado a un nombre de usuario

Con userInputs la contraseña no puede contener el nombre de usuario. Las cadenas son selectores y se leen con cada pulsación; también admite funciones.

JavaScript
createPasswordMeter('#linked-password', {
  userInputs: ['#username'],
  showPercent: true,
})

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. Las opciones se leen una sola vez, así que otro idioma significa otro indicador.

JavaScript
import en from '@passcore/vanilla/locales/en.json'
import es from '@passcore/vanilla/locales/es.json'
import ca from '@passcore/vanilla/locales/ca.json'

const locales = { en, es, ca }

// the options are read once: create the meter again for another language
meter?.destroy()
meter = createPasswordMeter('#translations-password', {
  translations: locales[lang],
  locale: lang,
  label: labels[lang],
  showPercent: true,
})

Traducciones con i18next

translate recibe la función t de una instancia de i18next, aquí la de la propia zona de pruebas. Los textos se traducen en cada actualización, así que para cambiar de idioma basta con refresh().

JavaScript
import i18next from 'i18next'
import es from '@passcore/vanilla/locales/es.json'
import ca from '@passcore/vanilla/locales/ca.json'

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

const meter = createPasswordMeter('#i18next-password', {
  translate: (key, params) => i18next.t(key, { ns: 'passcore', ...params }),
  showPercent: true,
})

// the texts are translated on every update: refresh them
i18next.on('languageChanged', () => meter.refresh())

Callbacks y eventos

El callback onScore y el evento passcore:score, que se propaga, reciben el porcentaje en cada actualización. Aquí controlan el botón Enviar y la puntuación.

Puntuación 0%

El botón se activa en cuanto la puntuación supera el 75 %.

JavaScript
const input = document.querySelector('#events-password')
const send = document.querySelector('#send')

createPasswordMeter(input, {
  onScore: (percent) => {
    send.disabled = percent <= 75
  },
})

input.addEventListener('passcore:score', (event) => {
  document.querySelector('#events-score').textContent = `${event.detail.percent}%`
})

Contenedor propio

Por defecto, el indicador va justo después del campo. container lo añade en otro sitio: aquí, debajo de todo el grupo de campos.

JavaScript
createPasswordMeter('#group-password', { container: '#group-field' })

El elemento <passcore-meter>

<passcore-meter> dibuja el indicador justo donde lo escribes. Los atributos cubren las opciones sencillas: min-length, show-percent, user-inputs, locale, label y alguna más.

HTML
<script type="module">
  import '@passcore/vanilla/element'
</script>

<input type="text" id="element-username">
<input type="password" id="element-password">
<passcore-meter
  for="element-password"
  min-length="10"
  show-percent
  user-inputs="#element-username"
></passcore-meter>

Opciones del elemento desde JavaScript

Lo que no cabe en un atributo (traducciones, reglas, callbacks) va en la propiedad options, que se combina con los atributos. Este, además, pide un número y un símbolo.

JavaScript
const element = document.querySelector('passcore-meter[for="options-password"]')

// merged over the attributes: show-percent still applies
element.options = {
  translations: locales[lang],
  locale: lang,
  rules: { numbers: 1, symbols: 1 },
}

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.