first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,106 @@
# `<MissingKeyOverlay>`
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
`<MissingKeyOverlay>` is a dev-mode visual diagnostic that surfaces every
`missingKey` event emitted by the active `I18nInstance` as a fixed-position
list anchored to the bottom-right corner of the viewport. The overlay
gives engineers a passive, always-on view of translation gaps as they
develop — no console-tab toggling, no debug flag, no polling. In
production builds the component renders `null` and registers no event
listener so it costs nothing once shipped.
## Features
- Subscribes to `missingKey` events on the Provider's instance bus
- Renders a fixed-position list with `aria-live="polite"` so screen
readers announce new entries without focus theft
- Caps retained entries at the most-recent `maxEntries` (default 50);
older entries silently drop off
- Returns `null` in production (`process.env.NODE_ENV === 'production'`)
- Returns `null` when no Provider is mounted yet (no listener leak)
- Ergonomic style defaults (monospace, dark background) plus per-entry
locale and namespace meta
## Usage: Basic Example
Mount the overlay once near the root of the application — it auto-tracks
every miss for the lifetime of the active Provider:
```tsx
import { TranslationProvider } from "@suaveplan/react-i18n";
import { MissingKeyOverlay } from "@suaveplan/react-i18n/components/missing-key-overlay";
<TranslationProvider config={i18nConfig}>
<App />
<MissingKeyOverlay />
</TranslationProvider>;
```
In dev, every `t('absent.key')` call appears in the overlay. In a
production bundle the component compiles to a no-op return.
## Usage: Advanced Example
A custom cap with explicit prod override and a portal mount so the
overlay sits in a dedicated DOM root:
```tsx
import { createPortal } from "react-dom";
import { MissingKeyOverlay } from "@suaveplan/react-i18n/components/missing-key-overlay";
function DiagnosticsPortal() {
const root = document.getElementById("diagnostics-root");
if (!root) return null;
return createPortal(
<MissingKeyOverlay
// Force the overlay on even in a prod build for QA staging
production={false}
maxEntries={200}
/>,
root
);
}
```
## API Reference
### `MissingKeyOverlay(props?: MissingKeyOverlayProps): ReactElement | null`
Props:
- `maxEntries?: number` — hard cap on retained entries. Default: `50`.
- `production?: boolean` — override for the runtime env-check. When
`true`, the component returns `null` and does not subscribe.
Returns: `null` in production, when no Provider ancestor is mounted, or
when no `missingKey` events have fired yet. Otherwise returns the
fixed-position overlay.
### `MissingKeyEntry`
- `id: number` — monotonically increasing counter (used as React key)
- `key: string` — the missing translation key
- `locale: string` — locale at the moment the event was observed
- `namespace: string` — namespace label (empty string when no namespace)
## Implementation Notes
- The component uses `useEffect` (not `useSyncExternalStore`) for the bus
subscription because the entry list is a piece of internal React state
driven by the bus rather than a snapshot of an external store. The two
patterns are interchangeable here, and `useEffect` is simpler to
reason about for a buffer with bounded capacity.
- The append-and-cap helper (`appendCapped`) does the slice work outside
the React update so the overlay never re-allocates the entire history
on every event — only the bounded tail.
- The fixed-position styles are applied inline so the overlay is
self-contained: no external CSS file, no Tailwind dependency, no risk
of the host app's stylesheet hiding it.
- The `production` prop exists to make the prod-path testable without
mutating `process.env.NODE_ENV`. The default reads `isProductionEnv()`
on every render so consumers do not need to thread the flag through
manually in their own builds.