{"version":3,"file":"A2UIProvider.mjs","names":[],"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,qBAAqB,cAAkC,KAAK;;;;AAKlE,MAAM,mBAAmB,cAGf,KAAK;;;;;;;AAsBf,SAAgB,aAAa,EAC3B,UACA,OACA,SACA,YACoB;CAEpB,MAAM,cAAc,OAAgC,YAAY,KAAK;AACrE,aAAY,UAAU,YAAY;CAGlC,MAAM,eAAe,OAAqC,KAAK;AAC/D,KAAI,CAAC,aAAa,QAChB,cAAa,UAAU,IAAI,iBACzB,CAAC,WAAW,aAAa,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,cAAc,SAAS,EAAE;CAGzC,MAAM,CAAC,OAAO,YAAY,SAAwB,KAAK;CAGvD,MAAM,aAAa,OAA2B,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,aAAa,eAAe;EAAE;EAAS;EAAO,GAAG,CAAC,SAAS,MAAM,CAAC;AAExE,QACE,oBAAC,mBAAmB;EAAS,OAAO;YAClC,oBAAC,iBAAiB;GAAS,OAAO;aAChC,oBAAC;IAAqB;IAAQ;KAAyB;IAC7B;GACA;;;;;AAOlC,SAAgB,iBAA8B;CAC5C,MAAM,UAAU,WAAW,mBAAmB;AAC9C,KAAI,CAAC,QACH,OAAM,IAAI,MAAM,qDAAqD;AAEvE,QAAO;;;;;AAMT,SAAgB,eAAoC;CAClD,MAAM,QAAQ,WAAW,iBAAiB;AAC1C,KAAI,CAAC,MACH,OAAM,IAAI,MAAM,mDAAmD;AAErE,QAAO;;;;;AAMT,SAAgB,iBAAmC;CACjD,MAAM,UAAU,gBAAgB;CAChC,MAAM,QAAQ,cAAc;AAE5B,QAAO,eACE;EACL,GAAG;EACH,SAAS,MAAM;EACf,UAAU;EACX,GACD,CAAC,SAAS,MAAM,QAAQ,CACzB;;;AAIH,MAAa,eAAe;;;;AAK5B,SAAgB,eAA8B;AAE5C,QADc,WAAW,iBAAiB,EAC5B,SAAS;;;AAIzB,SAAgB,qBACd,UACG;AAEH,QAAO,SADS,gBAAgB,CACR"}