@assistant-ui/react
Version:
Open-source TypeScript/React library for building production-grade AI chat experiences
96 lines (95 loc) • 2.54 kB
JavaScript
"use client";
import { AssistantFrameHost } from "@assistant-ui/core";
import { useEffect } from "@assistant-ui/tap/react-shim";
// src/model-context/frame/useAssistantFrameHost.ts
/**
* React hook that manages the lifecycle of an AssistantFrameHost and its binding to the current AssistantRuntime.
*
* Usage example:
* ```typescript
* function MyComponent() {
* const iframeRef = useRef<HTMLIFrameElement>(null);
*
* useAssistantFrameHost({
* iframeRef,
* targetOrigin: "https://trusted-domain.com",
* });
*
* return <iframe ref={iframeRef} src="..." />;
* }
* ```
*/
const useAssistantFrameHost = ({ iframeRef, targetOrigin, register }) => {
useEffect(() => {
let active;
const syncFrame = () => {
const iframe = iframeRef.current;
const iframeWindow = iframe?.isConnected === false ? null : iframe?.contentWindow;
if (active && active.iframe === iframe && active.window === iframeWindow) return;
const previous = active;
active = void 0;
let disposalFailed = false;
let disposalError;
try {
previous?.dispose();
} catch (error) {
disposalFailed = true;
disposalError = error;
}
if (iframe && iframeWindow) {
const frameHost = new AssistantFrameHost(iframeWindow, targetOrigin);
let unsubscribe;
try {
unsubscribe = register(frameHost);
} catch (error_0) {
frameHost.dispose();
throw error_0;
}
const onLoad = () => frameHost.frameLoaded();
iframe.addEventListener("load", onLoad);
active = {
iframe,
window: iframeWindow,
dispose: () => {
iframe.removeEventListener("load", onLoad);
let cleanupFailed = false;
let cleanupError;
try {
frameHost.dispose();
} catch (error_1) {
cleanupFailed = true;
cleanupError = error_1;
}
try {
unsubscribe();
} catch (error_2) {
if (cleanupFailed) console.error("[assistant-ui] AssistantFrameHost unregistration failed.", error_2);
else {
cleanupFailed = true;
cleanupError = error_2;
}
}
if (cleanupFailed) throw cleanupError;
}
};
}
if (disposalFailed) throw disposalError;
};
syncFrame();
const observer = new MutationObserver(syncFrame);
observer.observe(document, {
childList: true,
subtree: true
});
return () => {
observer.disconnect();
active?.dispose();
};
}, [
iframeRef,
targetOrigin,
register
]);
};
export { useAssistantFrameHost };
//# sourceMappingURL=useAssistantFrameHost.js.map