# password-portraits

> AI-powered visual password strength analyzer. Generates unique warrior portraits driven by entropy. **Zero-knowledge — the password never leaves the browser.**

[![npm](https://img.shields.io/npm/v/password-portraits)](https://www.npmjs.com/package/password-portraits)
[![license](https://img.shields.io/npm/l/password-portraits)](./LICENSE)
[![CDN](https://img.shields.io/badge/CDN-jsDelivr-orange)](https://cdn.jsdelivr.net/npm/password-portraits/)

---

## Install

```bash
npm install password-portraits
# peer deps (required in your project)
npm install react react-dom
# optional — only if you use 3D portrait components
npm install three
```

---

## CDN (no build tool needed)

```html
<!-- UMD bundle -->
<script src="https://cdn.jsdelivr.net/npm/password-portraits/dist/lib/index.umd.js"></script>
<!-- Styles -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/password-portraits/dist/lib/style.css">

<!-- unpkg alternative -->
<script src="https://unpkg.com/password-portraits/dist/lib/index.umd.js"></script>
```

---

## Quick Start — React (ESM)

```tsx
import { PasswordField, SecurityDashboard, ThreatSimulator, Portrait } from 'password-portraits';
import 'password-portraits/style.css';

export default function SignupPage() {
  return (
    <div>
      <PasswordField />
      <SecurityDashboard />
      <ThreatSimulator buttonLabel="Test your password" />
    </div>
  );
}
```

---

## 🚀 Production-Ready Setup

To get the premium "Password Portraits" look and ensure everything works smoothly, follow these 3 steps:

### 1. Import Google Fonts
Our UI uses specific premium fonts. Add this to your `index.html` `<head>` or your main CSS file:
```html
<link href="https://fonts.googleapis.com/css2?family=Syne:wght@700,800&family=DM+Sans:wght@400;500;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
```

### 2. Import Global Styles
Import our compiled stylesheet in your app's entry point (e.g., `App.tsx` or `main.tsx`):
```tsx
import 'password-portraits/style.css';
```
> [!NOTE]
> Our components are designed for a **Dark Theme**. We recommend setting your app background to `#020617`.

### 3. Run the Analysis Engine
For the widgets (Score, XP, Checklist) to update in real-time as you type, you **must** run the `usePasswordAnalysis` hook in your component:

```tsx
import { 
  PasswordField, 
  StrengthBadges, 
  usePasswordAnalysis 
} from 'password-portraits';

export default function MyForm() {
  // This hook runs the AI analysis in the background
  usePasswordAnalysis();

  return (
    <div className="p-8 bg-[#020617] min-h-screen text-white">
      <PasswordField />
      <StrengthBadges />
    </div>
  );
}
```

---

## Quick Start — Login / Signup Page

You can add password-portraits to any **signup or login form**:

```tsx
import {
  UsernameField,
  PasswordField,
  SubmitButton,
  SecurityDashboard,
  PasswordChecklist,
  StrengthBadges,
} from 'password-portraits';
import 'password-portraits/style.css';

export default function SignupPage() {
  return (
    <form>
      <h1>Create Account</h1>

      {/* Drop-in username + password fields with built-in state */}
      <UsernameField />
      <PasswordField />

      {/* Real-time visual strength feedback */}
      <StrengthBadges />
      <PasswordChecklist minLength={12} />
      <SecurityDashboard />

      {/* Submit button — disabled until password meets minScore */}
      <SubmitButton successLabel="Create Account" minScore={45} />
    </form>
  );
}
```

---

## Quick Start — CDN (Vanilla HTML)

```html
<!DOCTYPE html>
<html>
<head>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/password-portraits/dist/lib/style.css">
</head>
<body>
  <!-- Required React + ReactDOM first -->
  <script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
  <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>

  <!-- Then password-portraits UMD -->
  <script src="https://cdn.jsdelivr.net/npm/password-portraits/dist/lib/index.umd.js"></script>

  <div id="pp-root"></div>
  <script>
    const { PasswordField, SecurityDashboard } = PasswordPortraits;
    const { createElement } = React;
    const root = ReactDOM.createRoot(document.getElementById('pp-root'));
    root.render(
      createElement('div', null,
        createElement(PasswordField),
        createElement(SecurityDashboard)
      )
    );
  </script>
</body>
</html>
```

---

## Engine API (framework-agnostic)

```ts
import {
  extractFeatures,
  calculateEntropy,
  calculateScore,
  generateArtData,
  simulateAttacks,
} from 'password-portraits';

const pw = 'MyStr0ng!Pass#99';
const features  = extractFeatures(pw);
const entropy   = calculateEntropy(pw, features.hasLower, features.hasUpper, features.hasDigits, features.hasSymbols);
const score     = calculateScore(features.length, features.charTypeCount, entropy.bits, 0, false, 0);
const art       = generateArtData({ password: pw, score: score.score, grade: score.grade, ...features });
const attacks   = simulateAttacks(score.score, features, [], false, false);

console.log(`Grade: ${score.grade} | Score: ${score.score}/100`);
console.log(`Crack time: ${entropy.crackLabel}`);
```

---

## Component Reference

| Component | Description | Key Props |
|-----------|-------------|-----------|
| `<PasswordField />` | Password input with show/hide toggle | `len`, `placeholder`, `onPasswordChange` |
| `<UsernameField />` | Username input (used for name-in-password detection) | `placeholder`, `onUsernameChange` |
| `<SecurityDashboard />` | Full HUD: score gauge, crack risk, entropy, crack time | — |
| `<StrengthBadges />` | XP bar + badge chips (Symbol Master, Cosmic Guard…) | `analysis`, `className` |
| `<PasswordChecklist />` | ✓/✗ requirement rows | `minLength`, `analysis` |
| `<ThreatSimulator />` | 9-attack-vector modal | `buttonLabel`, `buttonClassName` |
| `<Portrait />` | SVG generative art portrait | `artData`, `size`, `animate` |
| `<ThreeJsPortrait />` | 3D plant/warrior animation | `grade`, `score`, `size`, `animate` |
| `<GradeDisplay />` | Grade badge + crack time label | `grade`, `score`, `crackLabel` |
| `<SubmitButton />` | Enforces minimum score before allowing submit | `minScore`, `successLabel`, `onClick` |
| `<PasswordGenerator />` | Suggest & apply a strong random password | `onApply` |
| `<SecurityBadge />` | Compact or premium grade badge | `variant` (`compact` \| `premium`) |

---

## State Store (Zustand)

All components share a built-in Zustand store. Access it anywhere:

```ts
import { useAppStore } from 'password-portraits';

function MyComponent() {
  const { analysis, password, setPassword } = useAppStore();
  return <div>Score: {analysis?.score.score ?? 0}</div>;
}
```

---

## Security Principles

- ✅ **Zero-knowledge** — password never sent to any server
- ✅ **Bloom filter** — 500 most-breached passwords checked locally
- ✅ **Breach API** — SHA-1 k-anonymity (only 5 chars of hash sent to HIBP)
- ✅ **Name detection** — cross-references username locally to catch personal-info passwords
- ✅ **9 AI attack vectors** — brute force, dictionary, passgan, shoulder surfing, and more

---

## License

MIT © Password Portraits Team
