# @mostajs/qrpanel — fiche LLM
> Panneau QR code : générateur serveur PNG/SVG à 12 thèmes (image-as-frame, ECC=H), piloté par config (.qrconfig.json), sans chromium, + composant React <QrPanel> avec copier/partager/mailto.

- Version: 0.5.0 · Licence: AGPL-3.0-or-later · Auteur: Dr Hamid MADANI <drmdh@msn.com>
- Chemin: mostajs/mosta-qrpanel · Statut audit: complet (dist/)

## RÔLE
Génère des QR codes pour apps Node/React. Trois briques complémentaires : (1) serveur —
PNG/SVG/DataURL thématiques rendus côté Node via @resvg/resvg-js (pas de chromium) ;
(2) client `<QrPanel>` — panneau d'invitation interactif (QR + lien + copier/partager) ;
(3) `<QrImage>` — génération locale navigateur, COEP-safe. Inclut un CLI `qrpanel`.

## INSTALLATION
npm i @mostajs/qrpanel
Dépendance directe : qrcode. Peers optionnelles : react (>=18 <20) pour ./client et
./qr-image ; @mostajs/auth + @resvg/resvg-js requis uniquement par ./server.

## EXPORTS
- ./server : generateQrPng, generateQrSvg, generateQrDataUrl, buildInviteUrls + (ré-export) themes & config
- ./client : QrPanel
- ./qr-image : QrImage (default), useQrDataUrl
- ./themes : THEMES, THEME_KEYS, listThemes, getTheme, pickRandomTheme, buildThemeFrameSvg
- ./config : DEFAULT_CONFIG, loadQrConfig, ensureQrConfig, clearConfigCache
- "." (barrel) : ré-exporte server + client + themes + config
- bin `qrpanel` → CLI

## EXPORTS PAR SOUS-CHEMIN
- "." → barrel complet (server + client + themes + config) — ⚠ tire le code natif serveur
- "./server" → generateQr*, buildInviteUrls, themes, config (Node uniquement)
- "./client" → QrPanel (React, qrSrc fourni par l'app)
- "./qr-image" → QrImage, useQrDataUrl (React, génération locale)
- "./themes" → registry des 12 thèmes natifs
- "./config" → chargement/écriture de .qrconfig.json

## API — SIGNATURES
- function generateQrPng(text: string, opts?: QrOptions): Promise<Buffer>
- function generateQrSvg(text: string, opts?: QrOptions): Promise<string>
- function generateQrDataUrl(text: string, opts?: QrOptions): Promise<string>   // data:image/png;base64
- function buildInviteUrls(opts: BuildInviteUrlsOptions): InviteUrls
- function QrPanel(props: QrPanelProps): JSX.Element | null
- function QrImage(props: QrImageProps): JSX.Element
- function useQrDataUrl(data: string, opts?: QrDataUrlOptions): { src: string; loading: boolean; error: string|null }
- function listThemes(): ThemeKey[]
- function getTheme(key: ThemeKey): ThemeAsset
- function pickRandomTheme(pool?: ThemeKey[]): ThemeKey
- function buildThemeFrameSvg(theme: ThemeAsset, opts: BuildFrameOpts): string
- function loadQrConfig(cwd?: string): QrConfig
- function ensureQrConfig(cwd?: string, overrides?: Partial<QrConfigDefaults>): string
- function clearConfigCache(): void

## TYPES CLÉS
- QrOptions { width?=600; margin?=2; errorCorrectionLevel?='L'|'M'|'Q'|'H'; darkColor?='#0f172a';
    lightColor?='#ffffff'; genimage?: boolean; theme?: ThemeKey|'random'|'none'|{ svg; label? };
    themePool?: ThemeKey[]; framePadding?=0.13; centerWhiteRatio?=0.62; themeOpacity?=1; themeColor?='#1e293b' }
- BuildInviteUrlsOptions { baseUrl: string; directPath: string; inviteSecret: string|Buffer;
    inviteId: string; ttlMs?; invitePath?='/invite'; inviteMeta? }
- InviteUrls { directUrl: string; inviteUrl: string; inviteToken: string }
- QrPanelMode { key; label; url; qrSrc: string; description? }
- QrPanelProps { modes: QrPanelMode[]; initialModeIndex?=0; title?; mailSubject?; mailBodyTemplate?;
    mailTo?: string[]|string; mailBcc?: string[]|string; qrSize?=260; className? }
- QrImageProps extends QrDataUrlOptions { data: string; alt?; style?; className? }
- QrDataUrlOptions { size?=200; margin?=2; errorCorrectionLevel?='M'; darkColor?='#0f172a'; lightColor?='#ffffff' }
- ThemeKey = 'baby'|'animals'|'science'|'physics'|'chemistry'|'math'|'nature'|'tech'|'space'|'music'|'book'|'health'
- ThemeAsset { key: ThemeKey; label: string; motif: string }
- QrConfig { default: QrConfigDefaults; customThemes?: Record<string,{svg;label?}> }
- QrFormat = 'svg'|'png'|'dataUrl' ; QrEcc = 'L'|'M'|'Q'|'H'

## PATTERN
```ts
// Serveur — QR thématique en route API (Node uniquement)
import { generateQrPng } from '@mostajs/qrpanel/server';
const png = await generateQrPng('https://app.example.com/x', { theme: 'tech', errorCorrectionLevel: 'H' });

// Client — panneau d'invitation
import { QrPanel } from '@mostajs/qrpanel/client';
<QrPanel modes={[{ key: 'direct', label: 'Lien', url, qrSrc: '/api/qr?u=' + url }]} />

// Génération locale navigateur (COEP-safe)
import QrImage from '@mostajs/qrpanel/qr-image';
<QrImage data="https://example.com" size={240} />
```

## DÉPEND DE
- @mostajs/auth (peer optionnel, >=3.2.0) — requis par buildInviteUrls (signature HMAC du token)
- @resvg/resvg-js (peer optionnel, >=2.6.2) — requis par generateQr* (rasterisation SVG → PNG)
- react (peer optionnel, >=18 <20) — pour ./client et ./qr-image

## PIÈGES
- Ne PAS importer le barrel "." ni "./server" dans un bundle navigateur : @resvg/resvg-js
  est un binaire natif Node. Côté client, utiliser exclusivement ./client ou ./qr-image.
- `<QrPanel>` NE génère PAS le QR : l'app fournit `qrSrc` (endpoint API ou data URL).
- `<QrPanel>` requiert Tailwind (style compilé par l'app) ; `<QrImage>` est style-neutre.
- `genimage: false` court-circuite tout le pipeline thématique (QR pur, comportement legacy).
- `theme: 'H'` (ECC=30%) recommandé pour les thèmes image-as-frame ; un ECC plus bas peut
  rendre le QR illisible avec un cadre.
- `loadQrConfig` peut auto-créer `.qrconfig.json` à `process.cwd()` ; désactiver via
  `QRPANEL_AUTO_ENSURE=false`. Échec d'écriture → fallback transparent sur DEFAULT_CONFIG.
- `mailBcc` recommandé pour les cohortes (les destinataires ne se voient pas) vs `mailTo`.

## RÉFÉRENCES
- README.md
- CHANGELOG.md
- src/, dist/cli.js (CLI `npx qrpanel`)
