# `useValidationMessageBridge` _(no submodules)_ ## 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:`) 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 ( ); } ``` ## 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 ( Please fix the following
    {errors.map((err, i) => (
  • {resolve(err)}
  • ))}
); } ``` 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:`; 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`.