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,87 @@
# `useValidationMessageBridge`
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
Centralised resolver factory turning a `SuaveplanError` (or any thrown value) into a locale-resolved user-facing message. Mirrors the resolution rules of `useErrorMessage` from `@suaveplan/react-i18n` but returns a function — so a single hook call gives you a resolver you can apply to many errors per render: a list of validation errors on a form, a batch of toasts, a fan-out of notifications, or a status panel summarising recent failures. Every UI surface in `react-ui` (Toast, Alert, Dialog, ConfirmDeleteDialog) that needs to render an error should resolve through this bridge so the catalog-lookup behaviour stays consistent across the chassis.
## Features
- One hook call yields a resolver suitable for many errors.
- Walks the `cause` chain to surface the deepest `SuaveplanError`.
- Catalog lookup (`errors:<code>`) on hit; falls back to `error.message` on miss.
- Coerces non-`Error` inputs (strings, undefined) without throwing.
- Stable function reference across renders (memoized by `useCallback`).
## Usage: Basic Example
```tsx
import { useValidationMessageBridge } from "@suaveplan/react-ui";
function FormErrors({ errors }: { errors: SuaveplanError[] }) {
const resolve = useValidationMessageBridge();
return (
<ul>
{errors.map((e, i) => <li key={i}>{resolve(e)}</li>)}
</ul>
);
}
```
## Usage: Advanced Example
Render a batch of validation errors inside an Alert with the bridge resolver:
```tsx
function ValidationSummary({ errors }: { errors: unknown[] }) {
const resolve = useValidationMessageBridge();
return (
<Alert variant="destructive">
<AlertTitle>Please fix the following</AlertTitle>
<AlertDescription>
<ul>
{errors.map((err, i) => (
<li key={i}>{resolve(err)}</li>
))}
</ul>
</AlertDescription>
</Alert>
);
}
```
A try/catch handler that surfaces a toast with the resolved message:
```tsx
function useSubmit() {
const resolve = useValidationMessageBridge();
const { toast } = useToast();
return useCallback(async (input: FormValues) => {
try {
await save(input);
} catch (err) {
toast({ variant: "destructive", description: resolve(err) });
}
}, [resolve, toast]);
}
```
## API Reference
### `useValidationMessageBridge(): ValidationMessageResolver`
Returns `(error: unknown) => string`. Resolution order:
1. `null` / `undefined` → `""`.
2. Walk cause chain → first `SuaveplanError` wins. Look up `errors:<code>`; on hit return the translation, on miss return the surfaced error's `.message`.
3. Plain `Error` → `error.message`.
4. `string` → itself.
5. Anything else → `""`.
## Implementation Notes
- The hook reads the i18n instance via `useI18n()` and memoizes the resolver with `useCallback([i18n])` so the function reference is stable as long as the i18n instance is. Languages-changed events bump i18n's snapshot counter; the bridge's resolver re-binds when that propagates so subsequent calls see the new locale's catalog.
- Cause-chain walking is bounded at depth 10 to prevent runaway loops on accidentally-cyclic error structures.
- The bridge does NOT perform any side effects (no logging, no telemetry). For metric emission on errors, wrap the call site or compose with `@suaveplan/logger`.