You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte-kit-vice/src/uix/soma/components/password-field/README.md

86 lines
7.2 KiB

fix(uix audit): apply Kim audit remediations across morfo/soma/eidos/recipe layers Resolves 34 of 40 failures from src/uix/audit-uix-kimi-1.md. The remaining 6 are all Words component (excluded per project owner — actively developed on a separate track) or unrelated infra (cookie-adapter-client jsdom timeout). Key changes: - soma/provider/context.ts: swallow Svelte's `lifecycle_outside_component` in `context.set()` so unit tests can instantiate providers without a component tree (unblocked 18 picker tests in one line). - soma/textarea: route inline style writes through `dom.apply({attrs})` instead of direct `el.style.X = Y` (contract regex compliance). - soma/picker-shell: add minimal Provider component + morfo so the shared handle utility passes the morfo/component contract. - eidos/_layout: lift `shared.ts` to `eidos/lib/layout-helpers.ts` (the `_layout` directory wasn't a real component) and update 8 layout primitive imports. - eidos/command: replace `onMount` with `$effect` (visual layer can't use Svelte 4 lifecycle hooks per component-api contract); restructure `Item.Icon`/`Item.Shortcut` namespace so contract regex matches. - eidos/color-picker: extract hue spectrum hsl literals to sidecar `color-picker-spectrum.css`; keep main recipe color-literal-free. - eidos/lib/recipes/base.ts: declare 196 layout-primitive + chrome CSS vars (box, flex, grid, float, group, banner, container, section, separator, toggle-group, pin-input, scroll-area, splitter, navigation-menu, dropdown-menu, context-menu, date-range-field, time-range-field, plus per-component additions to date-field, color-picker, button, select). 197 missing → 0 non-Words. - morfo: add `data-dir` to carousel, `data-kind` to date-picker, add StrengthMeterLabel sub-part to password-field, register picker-shell. - 5 pickers (date/color/date-range/time/time-range): add `internals.ts` indirection so `exports.ts` doesn't re-export `*provider.svelte.ts` directly (contract D); rewrite virtual root types to plain object literals (no `WithChild`/`PrimitiveDivAttributes`). - 4 new READMEs (button, textarea, password-field, picker-shell) following the search-field canonical template. Test result: 2391/2397 passing (99.75%). Remaining 6 failures are all Words-scope or jsdom infra timeout — explicitly out of scope. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
# PasswordField
Single-line password input with masked value, visibility toggle, Caps Lock detection, and an optional strength meter. Composes inside `Field.Provider` (OR-merges `disabled` / `readonly` / `required` / `invalid`).
## Anatomy
```svelte
<PasswordField.Provider bind:value bind:visible purpose="new">
<PasswordField.Input placeholder="At least 8 characters" />
<PasswordField.VisibilityTrigger />
<PasswordField.CapsLockIndicator />
<PasswordField.StrengthMeter />
</PasswordField.Provider>
```
## Parts
| Part | Element | Description |
| --------------------- | ---------- | ------------------------------------------------------------------------------------------ |
| `Provider` | `<div>` | Root context. Holds value, visibility, autocomplete purpose, OR-merged Field state. |
| `Input` | `<input>` | The real input. `type` flips between `password` and `text` from `visible`. |
| `VisibilityTrigger` | `<button>` | Toggles `visible`. Renders Eye / EyeOff icons in the eidos wrapper. |
| `CapsLockIndicator` | `<span>` | Live region announcing Caps Lock state; visible only when the input is focused + caps on. |
| `StrengthMeter` | `<div>` | Visual 0–4 meter. Reads `calculateStrength(value)` by default; override via `strength`. |
## Props
### `Provider`
| Prop | Type | Default | Description |
| ------------------- | ------------------------------------------------- | ---------------------- | ---------------------------------------------------------------------- |
| `value` | `string` | `''` | Controlled value. `bind:value` supported. |
| `onValueChange` | `(value: string) => void` | — | Per-keystroke change. |
| `onSubmit` | `(value: string) => void` | — | Fires on `Enter` in the Input. |
| `visible` | `boolean` | `false` | Plaintext mode. `bind:visible` supported. |
| `onVisibilityChange`| `(visible: boolean) => void` | — | Fires when the trigger flips visibility. |
| `purpose` | `'current' \| 'new'` | `'current'` | Drives `autocomplete` (`current-password` / `new-password`). |
| `minLength` | `number` | — | Forwarded to the input. |
| `maxLength` | `number` | — | Forwarded to the input. |
| `disabled` | `boolean` | `false` | OR-merged with `Field.disabled`. |
| `readonly` | `boolean` | `false` | OR-merged with `Field.readonly`. |
| `required` | `boolean` | `false` | OR-merged with `Field.required`. |
| `invalid` | `boolean` | `false` | OR-merged with `Field.invalid`. |
| `calculateStrength` | `(pw: string) => number \| PasswordStrengthResult`| `passwordStrength` | Strength algorithm. Default is `passwordStrength` from `$libs/secs`. |
| `aria-label` | `string` | translated `Password` | Accessible name when no `Field.Label` is present. |
### `StrengthMeter`
| Prop | Type | Default | Description |
| ---------- | ----------------------------------------------------- | ---------------- | --------------------------------------------------------------------- |
| `strength` | `number` | provider-derived | Override the auto-computed score. Clamped to 0–4. |
| `labels` | `readonly [string, string, string, string, string]` | translated set | Bucket labels. Defaults to `Very weak / Weak / Acceptable / Strong / Very strong`. |
## ARIA
| Part | Attribute | Value |
| ------------------- | --------------------- | -------------------------------------------------------------------- |
| Input | `aria-invalid` | When `invalid` is true |
| Input | `aria-required` | When `required` is true |
| Input | `aria-labelledby` | From `Field.Label` when composed inside Field |
| Input | `autocomplete` | `current-password` / `new-password` from `purpose` |
| VisibilityTrigger | `aria-pressed` | Reflects `visible` |
| VisibilityTrigger | `aria-label` | `Show password` / `Hide password` (translated, flips with state) |
| VisibilityTrigger | `tabindex` | `-1` — not in the tab order (toggle via the icon, not Tab) |
| CapsLockIndicator | `aria-live` | `polite` |
| StrengthMeter | `role` | `meter` |
| StrengthMeter | `aria-valuemin` | `0` |
| StrengthMeter | `aria-valuemax` | `4` |
| StrengthMeter | `aria-valuenow` | Current 0–4 score |
## Keyboard
| Key | Action |
| ------- | ----------------------------------------------- |
| `Enter` | In the Input → fires `onSubmit(value)`. |
## Strength algorithm
The default `calculateStrength` is `passwordStrength` from `$libs/secs`. It returns a rich `PasswordStrengthResult` (`score`, `label`, `warnings[]`, `strength`, `isSecure`). The `warnings` are LangRef strings the consumer can translate via `langs.ts(...)`. Override per `<PasswordField>` to plug in zxcvbn, OWASP NIST 800-63B, server-side scoring, etc.
## See also
- Eidos visual: `src/uix/eidos/components/password-field/README.md`
- Strength canon: `src/libs/secs/README.md`
- Field composition: `src/uix/soma/components/field/README.md`

Powered by TurnKey Linux.