"use client"; import { A2UIProvider, useA2UIActions } from "./react-renderer/core/A2UIProvider.mjs"; import A2UIRenderer from "./react-renderer/core/A2UIRenderer.mjs"; import { initializeDefaultCatalog } from "./react-renderer/registry/defaultCatalog.mjs"; import { injectStyles } from "./react-renderer/styles/index.mjs"; import { theme } from "./theme/viewer-theme.mjs"; import React, { useEffect, useId, useMemo, useRef } from "react"; import { jsx } from "react/jsx-runtime"; //#region src/A2UIViewer.tsx let initialized = false; function ensureInitialized() { if (!initialized) { initializeDefaultCatalog(); injectStyles(); initialized = true; } } /** * A2UIViewer renders an A2UI component tree from a JSON definition and data. * It re-renders cleanly when props change, discarding previous state. */ function A2UIViewer({ root, components, data, onAction, styles, className }) { ensureInitialized(); const baseId = useId(); const surfaceId = useMemo(() => { const definitionKey = `${root}-${JSON.stringify(components)}`; let hash = 0; for (let i = 0; i < definitionKey.length; i++) { const char = definitionKey.charCodeAt(i); hash = (hash << 5) - hash + char; hash = hash & hash; } return `surface${baseId.replace(/:/g, "-")}${hash}`; }, [ baseId, root, components ]); const handleAction = useMemo(() => { if (!onAction) return void 0; return (message) => { const userAction = message.userAction; if (userAction) onAction({ actionName: userAction.name, sourceComponentId: userAction.sourceComponentId, timestamp: userAction.timestamp, context: userAction.context ?? {} }); }; }, [onAction]); if (!components || components.length === 0) return /* @__PURE__ */ jsx("div", { className, style: { padding: 16, color: "#666", fontFamily: "system-ui" }, children: "No content to display" }); return /* @__PURE__ */ jsx(A2UIProvider, { onAction: handleAction, theme, children: /* @__PURE__ */ jsx(A2UIViewerInner, { surfaceId, root, components, data: data ?? {}, styles, className }) }); } /** * Inner component that processes messages within the provider context. */ function A2UIViewerInner({ surfaceId, root, components, data, styles, className }) { const { processMessages } = useA2UIActions(); const lastProcessedRef = useRef(""); useEffect(() => { const key = `${surfaceId}-${JSON.stringify(components)}-${JSON.stringify(data)}`; if (key === lastProcessedRef.current) return; lastProcessedRef.current = key; const messages = [{ beginRendering: { surfaceId, root, styles: styles ?? {} } }, { surfaceUpdate: { surfaceId, components } }]; if (data && Object.keys(data).length > 0) { const contents = objectToValueMaps(data); if (contents.length > 0) messages.push({ dataModelUpdate: { surfaceId, path: "/", contents } }); } processMessages(messages); }, [ processMessages, surfaceId, root, components, data, styles ]); return /* @__PURE__ */ jsx("div", { className, children: /* @__PURE__ */ jsx(A2UIRenderer, { surfaceId }) }); } /** * Converts a nested JavaScript object to the ValueMap[] format * expected by A2UI's dataModelUpdate message. */ function objectToValueMaps(obj) { return Object.entries(obj).map(([key, value]) => valueToValueMap(key, value)); } /** * Converts a single key-value pair to a ValueMap. */ function valueToValueMap(key, value) { if (typeof value === "string") return { key, valueString: value }; if (typeof value === "number") return { key, valueNumber: value }; if (typeof value === "boolean") return { key, valueBoolean: value }; if (value === null || value === void 0) return { key }; if (Array.isArray(value)) return { key, valueMap: value.map((item, index) => valueToValueMap(String(index), item)) }; if (typeof value === "object") return { key, valueMap: objectToValueMaps(value) }; return { key }; } //#endregion export { A2UIViewer }; //# sourceMappingURL=A2UIViewer.mjs.map