"use client"; import { useLayoutEffect, useRef } from "react"; import { acquireBrowserSurface } from "./browserSurfaceStore"; export function BrowserSurfaceSlot(props: { readonly tabId: string; readonly visible: boolean; readonly cornerRadius?: number; readonly zIndex?: number; readonly layoutVersion?: string | number; readonly className?: string; readonly fitSourceContent?: boolean;}) { const { tabId, visible, cornerRadius = 0, zIndex = 30, layoutVersion, className, fitSourceContent = false, } = props; const elementRef = useRef<HTMLDivElement | null>(null); const presentationRef = useRef({ visible, cornerRadius, zIndex }); const updateRef = useRef<(() => void) | null>(null); useLayoutEffect(() => { const element = elementRef.current; if (!element) return; let lease = acquireBrowserSurface(tabId, fitSourceContent); const update = () => { const rect = element.getBoundingClientRect(); const presentation = presentationRef.current; const presented = lease.present( { x: Math.round(rect.x), y: Math.round(rect.y), width: Math.max(1, Math.round(rect.width)), height: Math.max(1, Math.round(rect.height)), }, presentation.visible && rect.width > 0 && rect.height > 0, presentation.cornerRadius, presentation.zIndex, ); if (presentation.visible && !presented) { lease.release(); lease = acquireBrowserSurface(tabId, fitSourceContent); lease.present( { x: Math.round(rect.x), y: Math.round(rect.y), width: Math.max(1, Math.round(rect.width)), height: Math.max(1, Math.round(rect.height)), }, rect.width > 0 && rect.height > 0, presentation.cornerRadius, presentation.zIndex, ); } }; updateRef.current = update; update(); const observer = new ResizeObserver(update); observer.observe(element); window.addEventListener("resize", update); window.addEventListener("scroll", update, true); return () => { observer.disconnect(); window.removeEventListener("resize", update); window.removeEventListener("scroll", update, true); if (updateRef.current === update) updateRef.current = null; lease.release(); }; }, [fitSourceContent, tabId]); useLayoutEffect(() => { presentationRef.current = { visible, cornerRadius, zIndex }; updateRef.current?.(); }, [cornerRadius, layoutVersion, visible, zIndex]); return <div ref={elementRef} className={className} data-browser-surface-slot={tabId} />;}
"use client";
import { useLayoutEffect, useRef } from "react";
import { acquireBrowserSurface } from "./browserSurfaceStore";
export function BrowserSurfaceSlot(props: {
readonly tabId: string;
readonly visible: boolean;
readonly cornerRadius?: number;
readonly zIndex?: number;
readonly layoutVersion?: string | number;
readonly className?: string;
readonly fitSourceContent?: boolean;
}) {
const {
tabId,
visible,
cornerRadius = 0,
zIndex = 30,
layoutVersion,
className,
fitSourceContent = false,
} = props;
const elementRef = useRef<HTMLDivElement | null>(null);
const presentationRef = useRef({ visible, cornerRadius, zIndex });
const updateRef = useRef<(() => void) | null>(null);
useLayoutEffect(() => {
const element = elementRef.current;
if (!element) return;
let lease = acquireBrowserSurface(tabId, fitSourceContent);
const update = () => {
const rect = element.getBoundingClientRect();
const presentation = presentationRef.current;
const presented = lease.present(
{
x: Math.round(rect.x),
y: Math.round(rect.y),
width: Math.max(1, Math.round(rect.width)),
height: Math.max(1, Math.round(rect.height)),
},
presentation.visible && rect.width > 0 && rect.height > 0,
presentation.cornerRadius,
presentation.zIndex,
);
if (presentation.visible && !presented) {
lease.release();
lease = acquireBrowserSurface(tabId, fitSourceContent);
lease.present(
{
x: Math.round(rect.x),
y: Math.round(rect.y),
width: Math.max(1, Math.round(rect.width)),
height: Math.max(1, Math.round(rect.height)),
},
rect.width > 0 && rect.height > 0,
presentation.cornerRadius,
presentation.zIndex,
);
}
};
updateRef.current = update;
update();
const observer = new ResizeObserver(update);
observer.observe(element);
window.addEventListener("resize", update);
window.addEventListener("scroll", update, true);
return () => {
observer.disconnect();
window.removeEventListener("resize", update);
window.removeEventListener("scroll", update, true);
if (updateRef.current === update) updateRef.current = null;
lease.release();
};
}, [fitSourceContent, tabId]);
useLayoutEffect(() => {
presentationRef.current = { visible, cornerRadius, zIndex };
updateRef.current?.();
}, [cornerRadius, layoutVersion, visible, zIndex]);
return <div ref={elementRef} className={className} data-browser-surface-slot={tabId} />;
}