@passcore/svelte
Svelte
@passcore/svelte ofrece un componente, <PasswordStrengthMeter>, y passwordStrength(), una función auxiliar basada en runas, para Svelte 5.
pnpm add @passcore/svelte
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 basta con un bind:value en tu campo. Siempre se ve; id lo asocia al campo.
<script>
import { PasswordStrengthMeter } from '@passcore/svelte'
import '@passcore/svelte/styles.css'
let password = $state('')
</script>
<input id="password" type="password" bind:value={password} aria-describedby="password-strength" />
<PasswordStrengthMeter id="password-strength" {password} />
Lista de requisitos
El clásico formulario de registro, con tu propio marcado: passwordStrength() devuelve el resultado como getter, 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.
<script>
import { PasswordStrengthMeter, passwordStrength } from '@passcore/svelte'
const rules = { minLength: 8, lowercase: 1, uppercase: 1, numbers: 1, symbols: 1 }
let username = $state('')
let password = $state('')
const strength = passwordStrength(() => password, () => ({ userInputs: [username], rules }))
const typed = $derived(password !== '')
const met = $derived(strength.result.rules.filter((rule) => rule.passed).length)
</script>
<PasswordStrengthMeter {password} userInputs={[username]} {rules} />
<ul>
{#each strength.result.rules as rule (rule.id)}
<li data-state={!typed ? 'idle' : rule.passed ? 'met' : 'unmet'}>
{t(`requirements.rule.${rule.id}`, { count: rule.params.min })}
</li>
{/each}
</ul>
<p aria-live="polite">
{typed ? `${met} of ${strength.result.rules.length} requirements met` : `${strength.result.rules.length} requirements to meet`}
</p>
Con el porcentaje
showPercent añade el número junto a la barra.
<PasswordStrengthMeter id="password-strength" {password} showPercent />
Vinculado a un nombre de usuario
Con userInputs la contraseña no puede contener el nombre de usuario. Pásale los valores actuales, directamente desde tu estado.
<script>
let username = $state('')
</script>
<input type="text" autocomplete="username" bind:value={username} />
<PasswordStrengthMeter id="password-strength" {password} userInputs={[username]} showPercent />
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.
<script>
import en from '@passcore/svelte/locales/en.json'
import es from '@passcore/svelte/locales/es.json'
import ca from '@passcore/svelte/locales/ca.json'
const locales = { en, es, ca }
</script>
<PasswordStrengthMeter
{password}
translations={locales[lang]}
locale={lang}
label={labels[lang]}
showPercent
/>
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.
<script>
import i18next from 'i18next'
import es from '@passcore/svelte/locales/es.json'
import ca from '@passcore/svelte/locales/ca.json'
i18next.addResourceBundle('es', 'passcore', es)
i18next.addResourceBundle('ca', 'passcore', ca)
const translate = (key, params) => i18next.t(key, { ns: 'passcore', ...params })
</script>
<!-- locale tells the meter to translate again -->
<PasswordStrengthMeter {password} {translate} locale={lang} label={labels[lang]} showPercent />
Callbacks y eventos
onscore recibe el porcentaje cada vez que cambia el resultado (nunca al montarse). Aquí controla la puntuación y el botón Enviar.
<script>
let percent = $state(0)
</script>
<PasswordStrengthMeter {password} onscore={(value) => (percent = value)} />
<output>{percent}%</output>
<button type="submit" disabled={percent <= 75}>Send</button>
Grupo de campos
El indicador es un elemento más: ponlo después del grupo de campos y ocupará todo el ancho del grupo.
<div class="form-group">
<label for="password">Password</label>
<div class="input-group">
<span class="input-group__addon">…</span>
<input id="password" type="password" bind:value={password} />
</div>
<PasswordStrengthMeter {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
.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.