UNPKG

@copilotkit/a2ui-renderer

Version:

A2UI Renderer for CopilotKit - render A2UI surfaces in React applications

1 lines 7.96 kB
{"version":3,"file":"A2UIProvider.cjs","names":["MessageProcessor","basicCatalog","ThemeProvider"],"sources":["../../../src/react-renderer/core/A2UIProvider.tsx"],"sourcesContent":["import {\n createContext,\n useContext,\n useRef,\n useState,\n useMemo,\n type ReactNode,\n} from \"react\";\nimport { MessageProcessor } from \"@a2ui/web_core/v0_9\";\nimport { basicCatalog } from \"../a2ui-react\";\nimport type { A2UIContextValue, A2UIActions } from \"./store\";\nimport { ThemeProvider } from \"../theme/ThemeContext\";\nimport type { OnActionCallback } from \"../types\";\nimport type { A2UIClientEventMessage, Theme } from \"../../a2ui-types\";\n\n/**\n * Context for stable actions (never changes reference, prevents re-renders).\n */\nconst A2UIActionsContext = createContext<A2UIActions | null>(null);\n\n/**\n * Context for reactive state (changes trigger re-renders).\n */\nconst A2UIStateContext = createContext<{\n version: number;\n error: string | null;\n} | null>(null);\n\n/**\n * Props for the A2UIProvider component.\n */\nexport interface A2UIProviderProps {\n /** Callback invoked when a user action is dispatched (button click, etc.) */\n onAction?: OnActionCallback;\n /** Theme configuration */\n theme?: Theme;\n /** Optional component catalog to use instead of the default basicCatalog */\n catalog?: any;\n /** Child components */\n children: ReactNode;\n}\n\n/**\n * Provider component that sets up the A2UI v0.9 context for descendant components.\n * Uses a two-context architecture for performance:\n * - A2UIActionsContext: Stable actions that never change (no re-renders)\n * - A2UIStateContext: Reactive state that triggers re-renders when needed\n */\nexport function A2UIProvider({\n onAction,\n theme,\n catalog,\n children,\n}: A2UIProviderProps) {\n // Store onAction in a ref so callbacks always have the latest value\n const onActionRef = useRef<OnActionCallback | null>(onAction ?? null);\n onActionRef.current = onAction ?? null;\n\n // Create v0.9 MessageProcessor only once using ref\n const processorRef = useRef<MessageProcessor<any> | null>(null);\n if (!processorRef.current) {\n processorRef.current = new MessageProcessor(\n [catalog ?? basicCatalog],\n // Action handler: convert v0.9 Action to A2UIClientEventMessage format\n (action: any) => {\n if (onActionRef.current) {\n const message: A2UIClientEventMessage = {\n userAction: {\n name: action?.name ?? \"unknown\",\n surfaceId: action?.surfaceId ?? \"default\",\n sourceComponentId: action?.sourceComponentId,\n context: action?.context,\n timestamp: action?.timestamp ?? new Date().toISOString(),\n },\n };\n onActionRef.current(message);\n }\n },\n );\n }\n const processor = processorRef.current;\n\n // Version counter for triggering re-renders\n const [version, setVersion] = useState(0);\n\n // Error state for graceful error handling\n const [error, setError] = useState<string | null>(null);\n\n // Create stable actions object once - stored in ref, never changes\n const actionsRef = useRef<A2UIActions | null>(null);\n if (!actionsRef.current) {\n actionsRef.current = {\n processMessages: (messages: Array<Record<string, unknown>>) => {\n try {\n processor.processMessages(messages as any[]);\n } catch (err) {\n console.warn(\"[A2UI] processMessages error:\", err);\n setError(err instanceof Error ? err.message : String(err));\n return;\n }\n setError(null);\n setVersion((v) => v + 1);\n },\n\n dispatch: (message: any) => {\n if (onActionRef.current) {\n onActionRef.current(message);\n }\n },\n\n getSurface: (surfaceId: string) => {\n return processor.model.getSurface(surfaceId);\n },\n\n clearSurfaces: () => {\n // Process a deleteSurface for all known surfaces\n const surfaces = processor.model.surfacesMap;\n for (const [id] of surfaces) {\n processor.processMessages([\n { version: \"v0.9\", deleteSurface: { surfaceId: id } } as any,\n ]);\n }\n setVersion((v) => v + 1);\n },\n };\n }\n const actions = actionsRef.current;\n\n // State context value - changes when version or error changes\n const stateValue = useMemo(() => ({ version, error }), [version, error]);\n\n return (\n <A2UIActionsContext.Provider value={actions}>\n <A2UIStateContext.Provider value={stateValue}>\n <ThemeProvider theme={theme}>{children}</ThemeProvider>\n </A2UIStateContext.Provider>\n </A2UIActionsContext.Provider>\n );\n}\n\n/**\n * Hook to access stable A2UI actions (won't cause re-renders).\n */\nexport function useA2UIActions(): A2UIActions {\n const actions = useContext(A2UIActionsContext);\n if (!actions) {\n throw new Error(\"useA2UIActions must be used within an A2UIProvider\");\n }\n return actions;\n}\n\n/**\n * Hook to subscribe to A2UI state changes.\n */\nexport function useA2UIState(): { version: number } {\n const state = useContext(A2UIStateContext);\n if (!state) {\n throw new Error(\"useA2UIState must be used within an A2UIProvider\");\n }\n return state;\n}\n\n/**\n * Hook to access the full A2UI context (actions + state).\n */\nexport function useA2UIContext(): A2UIContextValue {\n const actions = useA2UIActions();\n const state = useA2UIState();\n\n return useMemo(\n () => ({\n ...actions,\n version: state.version,\n onAction: null,\n }),\n [actions, state.version],\n );\n}\n\n/** @deprecated Use useA2UIContext instead. */\nexport const useA2UIStore = useA2UIContext;\n\n/**\n * Hook to access the current A2UI error state.\n */\nexport function useA2UIError(): string | null {\n const state = useContext(A2UIStateContext);\n return state?.error ?? null;\n}\n\n/** @deprecated Use useA2UIContext() or useA2UI() directly instead. */\nexport function useA2UIStoreSelector<T>(\n selector: (state: A2UIContextValue) => T,\n): T {\n const context = useA2UIContext();\n return selector(context);\n}\n"],"mappings":";;;;;;;;;;;;AAkBA,MAAM,8CAAuD,KAAK;;;;AAKlE,MAAM,4CAGI,KAAK;;;;;;;AAsBf,SAAgB,aAAa,EAC3B,UACA,OACA,SACA,YACoB;CAEpB,MAAM,gCAA8C,YAAY,KAAK;AACrE,aAAY,UAAU,YAAY;CAGlC,MAAM,iCAAoD,KAAK;AAC/D,KAAI,CAAC,aAAa,QAChB,cAAa,UAAU,IAAIA,qCACzB,CAAC,WAAWC,2BAAa,GAExB,WAAgB;AACf,MAAI,YAAY,SAAS;GACvB,MAAM,UAAkC,EACtC,YAAY;IACV,MAAM,QAAQ,QAAQ;IACtB,WAAW,QAAQ,aAAa;IAChC,mBAAmB,QAAQ;IAC3B,SAAS,QAAQ;IACjB,WAAW,QAAQ,8BAAa,IAAI,MAAM,EAAC,aAAa;IACzD,EACF;AACD,eAAY,QAAQ,QAAQ;;GAGjC;CAEH,MAAM,YAAY,aAAa;CAG/B,MAAM,CAAC,SAAS,kCAAuB,EAAE;CAGzC,MAAM,CAAC,OAAO,gCAAoC,KAAK;CAGvD,MAAM,+BAAwC,KAAK;AACnD,KAAI,CAAC,WAAW,QACd,YAAW,UAAU;EACnB,kBAAkB,aAA6C;AAC7D,OAAI;AACF,cAAU,gBAAgB,SAAkB;YACrC,KAAK;AACZ,YAAQ,KAAK,iCAAiC,IAAI;AAClD,aAAS,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CAAC;AAC1D;;AAEF,YAAS,KAAK;AACd,eAAY,MAAM,IAAI,EAAE;;EAG1B,WAAW,YAAiB;AAC1B,OAAI,YAAY,QACd,aAAY,QAAQ,QAAQ;;EAIhC,aAAa,cAAsB;AACjC,UAAO,UAAU,MAAM,WAAW,UAAU;;EAG9C,qBAAqB;GAEnB,MAAM,WAAW,UAAU,MAAM;AACjC,QAAK,MAAM,CAAC,OAAO,SACjB,WAAU,gBAAgB,CACxB;IAAE,SAAS;IAAQ,eAAe,EAAE,WAAW,IAAI;IAAE,CACtD,CAAC;AAEJ,eAAY,MAAM,IAAI,EAAE;;EAE3B;CAEH,MAAM,UAAU,WAAW;CAG3B,MAAM,uCAA4B;EAAE;EAAS;EAAO,GAAG,CAAC,SAAS,MAAM,CAAC;AAExE,QACE,2CAAC,mBAAmB;EAAS,OAAO;YAClC,2CAAC,iBAAiB;GAAS,OAAO;aAChC,2CAACC;IAAqB;IAAQ;KAAyB;IAC7B;GACA;;;;;AAOlC,SAAgB,iBAA8B;CAC5C,MAAM,gCAAqB,mBAAmB;AAC9C,KAAI,CAAC,QACH,OAAM,IAAI,MAAM,qDAAqD;AAEvE,QAAO;;;;;AAMT,SAAgB,eAAoC;CAClD,MAAM,8BAAmB,iBAAiB;AAC1C,KAAI,CAAC,MACH,OAAM,IAAI,MAAM,mDAAmD;AAErE,QAAO;;;;;AAMT,SAAgB,iBAAmC;CACjD,MAAM,UAAU,gBAAgB;CAChC,MAAM,QAAQ,cAAc;AAE5B,kCACS;EACL,GAAG;EACH,SAAS,MAAM;EACf,UAAU;EACX,GACD,CAAC,SAAS,MAAM,QAAQ,CACzB;;;AAIH,MAAa,eAAe;;;;AAK5B,SAAgB,eAA8B;AAE5C,8BADyB,iBAAiB,EAC5B,SAAS;;;AAIzB,SAAgB,qBACd,UACG;AAEH,QAAO,SADS,gBAAgB,CACR"}