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,101 @@
# `provider-context.ts`
## Purpose
Defines the React context that carries the active `I18nInstance` from
`@suaveplan/i18n` to every descendant of `<TranslationProvider>`. The
context is the single coupling point between the Provider and every
hook in `@suaveplan/react-i18n` — hooks read the instance through this
context, which means they all see the same instance even when the
Provider is mounted under a portal, a nested tree, or a Storybook
decorator.
The default value is intentionally `null` so the consuming hooks (which
land in sub-wave 1c) can detect a missing Provider ancestor and route
to either the dev-mode loud-failure throw
(`ReactI18nError(REACT_I18N.NO_PROVIDER)`) or the production-mode
soft-fail identity translator. A `null` default — rather than a
factory-default no-op instance — keeps the failure path explicit and
prevents silent fall-through to identity behaviour in development.
## Features
- React-native `createContext` so descendants get the standard
context-update behaviour (re-render on value-reference change) for
free.
- `displayName` set so React DevTools shows
`SuaveplanTranslationContext` instead of the anonymous `Context.Provider`
default.
- Exports the context object (not a hook) so subpath consumers can
`useContext(TranslationContext)` directly when they need raw access
outside the canonical hook surface.
## Usage: Basic Example
```tsx
import { useContext } from "react";
import { TranslationContext } from "@suaveplan/react-i18n/provider";
export function PreviewBadge() {
const i18n = useContext(TranslationContext);
if (!i18n) return null;
return <span>{i18n.catalog.defaultLocale}</span>;
}
```
## Usage: Advanced Example
```tsx
import { useContext } from "react";
import { TranslationContext } from "@suaveplan/react-i18n/provider";
import {
REACT_I18N_CODES,
ReactI18nError,
} from "@suaveplan/react-i18n/errors";
import { isProductionEnv } from "@suaveplan/react-i18n";
export function useI18n() {
const i18n = useContext(TranslationContext);
if (i18n) return i18n;
if (isProductionEnv()) {
return null;
}
throw new ReactI18nError(
REACT_I18N_CODES.NO_PROVIDER,
"react-i18n.no_provider",
{ context: { hook: "useI18n" } }
);
}
```
## API Reference
### `TranslationContext: React.Context<I18nInstance | null>`
The context whose value is the active `I18nInstance` (when a
`<TranslationProvider>` is mounted) or `null` (when no Provider is
present).
- Default value: `null`.
- `displayName`: `"SuaveplanTranslationContext"`.
## Implementation Notes
- The default of `null` is deliberate. A "no-op identity instance"
default would silently pass renders through in development and mask
the missing-Provider misconfiguration the dev-mode loud-failure path
exists to surface.
- The context is exported (rather than wrapped behind a `useI18n()`
hook) because the hook lives in a separate sub-wave (1c) and
consumers in 1b — primarily test fixtures, Storybook decorators,
and the Provider itself — need raw access. Exporting both the
context AND the eventual hook is the long-standing React pattern
proven across `react-router`, `react-query`, and dozens of other
ecosystem libraries.
- The display name is stamped at module load. React DevTools picks it
up automatically; production bundlers strip the assignment under
the standard `production` mode flag set by Webpack/Vite.
- The context value type is `I18nInstance | null`. The `null` arm
forces every reader to handle the no-Provider case explicitly,
which catches misconfigurations at type-check time rather than at
runtime.