{"version":3,"file":"I18nProvider.cjs","names":[],"sources":["../../src/i18n/I18nProvider.tsx"],"sourcesContent":["import { createContext, useCallback, useContext, useEffect, useMemo, useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { createI18n, type Catalog, type I18n } from \"./create-i18n\";\n\nexport interface I18nContextValue extends I18n {\n    /** Switch the active locale. Persisted when `storageKey` is set. */\n    setLocale: (locale: string) => void;\n    /** Locales available in the catalog. */\n    availableLocales: string[];\n}\n\nconst I18nContext = createContext<I18nContextValue | null>(null);\n\nexport interface I18nProviderProps {\n    children: ReactNode;\n    /** Initial locale. */\n    locale: string;\n    /** Fallback locale used when a key is missing. */\n    fallbackLocale?: string;\n    /** Translation catalog. */\n    messages: Catalog;\n    /** localStorage key for persisting the user choice. Pass `null` to disable. Default: `\"tempest-locale\"`. */\n    storageKey?: string | null;\n}\n\nfunction readStored(storageKey: string | null, available: string[]): string | null {\n    if (!storageKey || typeof window === \"undefined\") return null;\n    try {\n        const value = window.localStorage.getItem(storageKey);\n        if (value && available.includes(value)) return value;\n        return null;\n    } catch {\n        return null;\n    }\n}\n\n/**\n * React provider for the SDK's lightweight i18n. Exposes the translation\n * helpers and a `setLocale` setter to children.\n *\n * @tempest-limits empty-catch — remembering the chosen locale is best-effort. The\n * switch itself is React state and already happened by the time the write runs, so\n * a storage failure costs the preference on the next load and nothing in this one.\n */\nexport function I18nProvider({\n    children,\n    locale: initialLocale,\n    fallbackLocale,\n    messages,\n    storageKey = \"tempest-locale\",\n}: I18nProviderProps) {\n    const availableLocales = useMemo(() => Object.keys(messages), [messages]);\n    const [locale, setLocaleState] = useState<string>(\n        () => readStored(storageKey, availableLocales) ?? initialLocale,\n    );\n\n    useEffect(() => {\n        if (typeof document !== \"undefined\") {\n            document.documentElement.setAttribute(\"lang\", locale);\n        }\n    }, [locale]);\n\n    const setLocale = useCallback(\n        (next: string) => {\n            setLocaleState(next);\n            if (storageKey && typeof window !== \"undefined\") {\n                try {\n                    window.localStorage.setItem(storageKey, next);\n                } catch {\n                    /* empty */\n                }\n            }\n        },\n        [storageKey],\n    );\n\n    const value = useMemo<I18nContextValue>(() => {\n        const i18n = createI18n({ locale, fallbackLocale, messages });\n        return { ...i18n, setLocale, availableLocales };\n    }, [locale, fallbackLocale, messages, setLocale, availableLocales]);\n\n    return <I18nContext.Provider value={value}>{children}</I18nContext.Provider>;\n}\n\n/**\n * Access translation helpers. Must be used inside an {@link I18nProvider}.\n */\nexport function useI18n(): I18nContextValue {\n    const ctx = useContext(I18nContext);\n    if (!ctx) throw new Error(\"useI18n must be used inside an <I18nProvider>\");\n    return ctx;\n}\n\n/**\n * Access translation helpers when there may be no {@link I18nProvider} above.\n *\n * Returns `null` instead of throwing, which is what a piece of the SDK needs\n * when it wants to be translated where a catalog exists and still work where one\n * does not — i18n is opt-in in this SDK, and a helper that demanded a provider\n * would turn \"you did not configure translations\" into a crash.\n *\n * @returns The context value, or `null` outside a provider.\n */\nexport function useOptionalI18n(): I18nContextValue | null {\n    return useContext(I18nContext);\n}\n\n/**\n * Shortcut for components that only need the `t` function — avoids destructuring.\n */\nexport function useTranslate(): I18nContextValue[\"t\"] {\n    return useI18n().t;\n}\n"],"mappings":"2FAWA,IAAM,GAAA,EAAc,EAAA,cAAA,CAAuC,IAAI,EAc/D,SAAS,EAAW,EAA2B,EAAoC,CAC/E,GAAI,CAAC,GAAc,OAAO,OAAW,IAAa,OAAO,KACzD,GAAI,CACA,IAAM,EAAQ,OAAO,aAAa,QAAQ,CAAU,EAEpD,OADI,GAAS,EAAU,SAAS,CAAK,EAAU,EACxC,IACX,MAAQ,CACJ,OAAO,IACX,CACJ,CAUA,SAAgB,EAAa,CACzB,WACA,OAAQ,EACR,iBACA,WACA,aAAa,kBACK,CAClB,IAAM,GAAA,EAAmB,EAAA,QAAA,KAAc,OAAO,KAAK,CAAQ,EAAG,CAAC,CAAQ,CAAC,EAClE,CAAC,EAAQ,IAAA,EAAkB,EAAA,SAAA,KACvB,EAAW,EAAY,CAAgB,GAAK,CACtD,GAEA,EAAA,EAAA,UAAA,KAAgB,CACR,OAAO,SAAa,KACpB,SAAS,gBAAgB,aAAa,OAAQ,CAAM,CAE5D,EAAG,CAAC,CAAM,CAAC,EAEX,IAAM,GAAA,EAAY,EAAA,YAAA,CACb,GAAiB,CAEd,GADA,EAAe,CAAI,EACf,GAAc,OAAO,OAAW,IAChC,GAAI,CACA,OAAO,aAAa,QAAQ,EAAY,CAAI,CAChD,MAAQ,CAER,CAER,EACA,CAAC,CAAU,CACf,EAEM,GAAA,EAAQ,EAAA,QAAA,MAEH,CAAE,GADI,EAAA,WAAW,CAAE,SAAQ,iBAAgB,UAAS,CAC/C,EAAM,YAAW,kBAAiB,GAC/C,CAAC,EAAQ,EAAgB,EAAU,EAAW,CAAgB,CAAC,EAElE,OAAO,EAAA,EAAA,IAAA,CAAC,EAAY,SAAb,CAA6B,QAAQ,UAA+B,CAAA,CAC/E,CAKA,SAAgB,GAA4B,CACxC,IAAM,GAAA,EAAM,EAAA,WAAA,CAAW,CAAW,EAClC,GAAI,CAAC,EAAK,MAAU,MAAM,+CAA+C,EACzE,OAAO,CACX,CAYA,SAAgB,GAA2C,CACvD,OAAA,EAAO,EAAA,WAAA,CAAW,CAAW,CACjC,CAKA,SAAgB,GAAsC,CAClD,OAAO,EAAQ,CAAC,CAAC,CACrB"}