Global Provider
Provider component for Chrome AI APIs (Summarizer, Writer, Rewriter, Language Detector, Proofreader).
Overview
The GencnUIProvider is a required context provider that enables Chrome AI APIs (Summarizer, Writer, Rewriter, Language Detector, and Proofreader) throughout your application. It manages the configuration and state for all GencnUI components and hooks.
You must wrap your application with GencnUIProvider before using any GencnUI components or hooks.
Installation
Setup Required: Make sure you have configured components.json first. See
the installation guide for setup instructions.
npx shadcn@latest add @gencn-ui/gencn-ui-provider"use client"; import { createContext, useState, useRef, useMemo, useCallback, type ReactNode, } from "react"; import { AvailabilityStatus, } from "@/registry/new-york/gencn-ui/items/shared/gencn-ui-types"; import { GencnUIDownloadWidget } from "@/registry/new-york/gencn-ui/items/shared/components/gencn-ui-download-widget"; export interface ServerModel { modelCode: string; modelLabel: string; } export interface ClientModel { modelCode: string; modelLabel: string; } export interface GencnUIContextValue { // Server LLM State enableServerLLM: boolean; setEnableServerLLM: (enabled: boolean) => void; dangerouslySetServerLLMKey: boolean; serverKey: string; serverModel: ServerModel | null; setServerModel: (model: ServerModel | null) => void; setServerKey: (key: string) => void; // Client Models clientModel: ClientModel | null; setClientModel: (model: ClientModel | null) => void; // Translation cache management (used by useTranslator hook) getTranslationCache: ( text: string, targetLanguage: string, sourceLanguage?: string ) => string | "L" | null; getTranslationCacheKey: ( text: string, targetLanguage: string, sourceLanguage?: string ) => string; updateTranslationCache: (key: string, value: string | "L") => void; deleteTranslationCache: (key: string) => void; } export const GencnUIContext = createContext<GencnUIContextValue | undefined>( undefined ); export interface GencnUIProviderProps { children: ReactNode; enableServerLLM?: boolean; dangerouslySetServerLLMKey?: boolean; serverModel?: ServerModel; clientModel?: ClientModel; } export function GencnUIProvider({ children, enableServerLLM = true, dangerouslySetServerLLMKey = false, serverModel, clientModel, }: GencnUIProviderProps) { // ============================================================================ // STATE DECLARATIONS // ============================================================================ // Server LLM State const [enableServerLLMState, setEnableServerLLMState] = useState<boolean>(enableServerLLM); const [serverModelState, setServerModelState] = useState<ServerModel | null>(serverModel || null); const [serverKey, setServerKey] = useState<string>(""); // Client Model State const [clientModelState, setClientModelState] = useState<ClientModel | null>(clientModel || null); // Translation cache: Map<key, value> where value is "L" for loading or the translated text // Use state to make it reactive so components can react to cache updates const [translationCache, setTranslationCache] = useState< Map<string, string | "L"> >(new Map()); // Generate cache key from text, sourceLanguage, and targetLanguage const getTranslationCacheKey = useCallback( (text: string, targetLanguage: string, sourceLanguage?: string): string => { // Simple hash function for cache key const keyString = `${text}|${sourceLanguage || "auto"}|${targetLanguage}`; // Use a simple hash (in production, you might want a more robust hash) let hash = 0; for (let i = 0; i < keyString.length; i++) { const char = keyString.charCodeAt(i); hash = (hash << 5) - hash + char; hash = hash & hash; // Convert to 32-bit integer } return `trans_${Math.abs(hash)}`; }, [] ); // Get translation from cache - returns current cache value for specific translation const getTranslationCache = useCallback( ( text: string, targetLanguage: string, sourceLanguage?: string ): string | "L" | null => { const key = getTranslationCacheKey(text, targetLanguage, sourceLanguage); return translationCache.get(key) || null; }, [getTranslationCacheKey, translationCache] ); // Update cache helper - updates state reactively const updateTranslationCache = useCallback( (key: string, value: string | "L") => { setTranslationCache((prev) => { // Only update if value actually changed to avoid unnecessary re-renders const currentValue = prev.get(key); if (currentValue === value) { return prev; // Return same reference if value unchanged } const newCache = new Map(prev); newCache.set(key, value); return newCache; }); }, [] ); // Delete from cache helper const deleteTranslationCache = useCallback((key: string) => { setTranslationCache((prev) => { if (!prev.has(key)) { return prev; // Return same reference if key doesn't exist } const newCache = new Map(prev); newCache.delete(key); return newCache; }); }, []); // Memoize context value to prevent unnecessary re-renders of consumers // Only recreate when actual values change, not on every render const value: GencnUIContextValue = useMemo( () => ({ // Server LLM enableServerLLM: enableServerLLMState, setEnableServerLLM: setEnableServerLLMState, dangerouslySetServerLLMKey, serverKey, serverModel: serverModelState, setServerModel: setServerModelState, setServerKey, clientModel: clientModelState, setClientModel: setClientModelState, // Translation cache getTranslationCache, getTranslationCacheKey, updateTranslationCache, deleteTranslationCache, }), [ // Only include values that actually change enableServerLLMState, serverKey, serverModelState, clientModelState, dangerouslySetServerLLMKey, getTranslationCache, // Changes when translationCache changes // Setters and stable callbacks are excluded - they never change // but included in object for API consistency ] ); return ( <GencnUIContext.Provider value={value}> {children} <GencnUIDownloadWidget /> </GencnUIContext.Provider> ); }
Usage
Wrap your application with GencnUIProvider at the root level of your app. Once wrapped, you can use GencnUI components and hooks throughout your application.
In Next.js, wrap your application in the root layout file:
import { GencnUIProvider } from "@/registry/new-york/gencn-ui/items/shared/provider/gencn-ui-provider";
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>
<GencnUIProvider>{children}</GencnUIProvider>
</body>
</html>
);
}If you're using the App Router, make sure to add 'use client' if the layout file needs to be a client component:
"use client";
import { GencnUIProvider } from "@/registry/new-york/gencn-ui/items/shared/provider/gencn-ui-provider";
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>
<GencnUIProvider>{children}</GencnUIProvider>
</body>
</html>
);
}In a standard React application, wrap your app component:
import { GencnUIProvider } from "@/registry/new-york/gencn-ui/items/shared/provider/gencn-ui-provider";
function App() {
return <GencnUIProvider>{/* Your app components */}</GencnUIProvider>;
}
export default App;Or in your main entry file:
import React from "react";
import ReactDOM from "react-dom/client";
import { GencnUIProvider } from "@/registry/new-york/gencn-ui/items/shared/provider/gencn-ui-provider";
import App from "./App";
ReactDOM.createRoot(document.getElementById("root")!).render(
<React.StrictMode>
<GencnUIProvider>
<App />
</GencnUIProvider>
</React.StrictMode>
);After wrapping your application with GencnUIProvider, you can start using GencnUI components (like GencnUIInput, GencnUITextarea) and hooks (like useGencnUIChat, useGencnUISummarizer) throughout your application.

