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,98 @@
# `<ReactUiProvider>` — opinionated chassis composition
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
The opinionated 95%-case wrapper for the chassis. Composes the three
primitive providers in the canonical order `<TranslationProvider>` →
`<ThemeProvider>` → `<PackRegistryProvider>` and adds an effect-driven
loader that auto-registers the chassis bundled translations into the
active i18n catalog (with optional consumer overrides applied on top).
Emits the `react_ui.provider.mount` OTel span on every mount.
## Features
- 15-line provider composition in the right order
- Auto-registration of the bundled chassis locale on mount
- Consumer overrides via `reactUiOverrides` win over the default
bundle keys
- Re-loads the bundle on `languageChanged` so a runtime locale switch
picks up the matching translations automatically
- Records `react_ui.locale.bundle.load_total{locale, outcome}` and
`react_ui.locale.bundle.load_duration_ms{locale}` per load
- Records the `react_ui.provider.mount` span carrying `theme`,
`pack.count`, and `locale` attributes
- Defers to `<TranslationProvider>` for the i18n instance (the
Provider is mode `caller-managed` because we always pass `i18n`)
## Usage: Basic example
```tsx
import { ReactUiProvider } from "@suaveplan/react-ui/provider";
import { lightTheme } from "@suaveplan/react-ui/theme";
import { createI18n } from "@suaveplan/i18n/plugin";
const i18n = createI18n({ defaultLocale: "en-GB" });
<ReactUiProvider i18n={i18n} themes={[lightTheme]} defaultTheme="light">
<App />
</ReactUiProvider>;
```
## Usage: Advanced example
```tsx
import { ReactUiProvider } from "@suaveplan/react-ui/provider";
import {
darkTheme,
highContrastTheme,
lightTheme,
} from "@suaveplan/react-ui/theme";
import { authPack } from "@suaveplan/react-ui-pack-auth";
<ReactUiProvider
i18n={i18n}
themes={[lightTheme, darkTheme, highContrastTheme]}
defaultTheme="light"
packs={[authPack]}
components={{ auth: { LoginForm: AcmeLoginForm } }}
reactUiOverrides={{
"en-GB": {
"react-ui.themeToggle.label": "Appearance",
},
}}
scriptNonce={cspNonce}
>
<App />
</ReactUiProvider>;
```
## API Reference
- `<ReactUiProvider>` — props per `ReactUiProviderProps`:
- `i18n: I18nInstance` — required
- `themes: ReadonlyArray<ThemePlugin>` — required
- `defaultTheme: string` — required
- `packs?: ReadonlyArray<ComponentPack>`
- `components?: RuntimeComponentOverride`
- `reactUiOverrides?: ReactUiLocaleOverrides`
- `logger?: PackLoggerLike`
- `scriptNonce?: string`
- `storageKey?: string`
- `attribute?: string`
- `children: ReactNode`
- `type ReactUiLocaleOverrides = Partial<Record<SupportedLocale, Partial<Record<TranslationKey, string>>>>`
## Implementation notes
The bundle loader runs inside a `useEffect` and tracks an aborted-flag
ref so a fast unmount does not leak a stale registration into the
catalog. The `languageChanged` listener is registered on the i18n
event bus rather than on the React reactive state because the i18n
instance owns the locale truth — re-deriving from React state would
introduce a one-render lag on every locale switch. The `span.end()`
fires synchronously (before the lazy bundle resolves) so the trace
boundary matches the React commit boundary; the bundle-load duration
is captured separately via the histogram.