import { useEffect, useMemo, useRef, useState } from 'react'; import useWindowSize, { useFetchAnyTruncatedContent } from './hooks'; import { nanoid } from 'nanoid'; import { useSelector } from 'react-redux'; import { host, actions } from '@curvenote/connect'; import type { MinifiedOutput } from '@curvenote/nbtx'; import { convertToIOutputs, fetchAndEncodeOutputImages } from '@curvenote/nbtx'; import { ChevronDoubleDownIcon } from '@heroicons/react/outline'; import type { State } from './selectors'; import { selectIFrameHeight, selectIFrameReady } from './selectors'; const PERCENT_OF_WINDOW = 0.9; export const NativeJupyterOutputs = ({ id, outputs, }: { id: string; outputs: MinifiedOutput[]; }) => { const windowSize = useWindowSize(); const { data, error } = useFetchAnyTruncatedContent(outputs); const [loading, setLoading] = useState(true); const [frameHeight, setFrameHeight] = useState(0); const [clamped, setClamped] = useState(false); const uid = useMemo(nanoid, []); const height = useSelector((state: State) => selectIFrameHeight(state, uid)); const rendererReady = useSelector((state: State) => selectIFrameReady(state, uid)); const iframeRef = useRef(null); useEffect(() => { if (iframeRef.current == null || !rendererReady || !data) return; fetchAndEncodeOutputImages(convertToIOutputs(data)).then((out) => { host.commsDispatch(iframeRef.current, actions.connectHostSendContent(uid, out)); }); }, [id, iframeRef.current, rendererReady]); useEffect(() => { if (height == null) return; if (height > PERCENT_OF_WINDOW * windowSize.height) { setFrameHeight(PERCENT_OF_WINDOW * windowSize.height); setClamped(true); } else { setFrameHeight(height + 25); setClamped(false); } setLoading(false); }, [height]); if (error) { return
Error rendering output: {error.message}
; } return (
{loading &&
Loading...
} {clamped && (
{ setFrameHeight(height ?? 0); setClamped(false); }} >
)}
); };