import { useEffect, useState, useRef, useMemo } from "react"; import { useParams } from "react-router"; import { useWindowSize } from "@/app/utils"; import { IconButton } from "./button"; import { nanoid } from "nanoid"; import ExportIcon from "../icons/share.svg"; import CopyIcon from "../icons/copy.svg"; import DownloadIcon from "../icons/download.svg"; import GithubIcon from "../icons/github.svg"; import LoadingButtonIcon from "../icons/loading.svg"; import Locale from "../locales"; import { Modal, showToast } from "./ui-lib"; import { copyToClipboard, downloadAs } from "../utils"; import { Path, ApiPath, REPO_URL } from "@/app/constant"; import { Loading } from "./home"; import styles from "./artifacts.module.scss"; export function HTMLPreview(props: { code: string; autoHeight?: boolean; height?: number | string; onLoad?: (title?: string) => void; }) { const ref = useRef(null); const frameId = useRef(nanoid()); const [iframeHeight, setIframeHeight] = useState(600); const [title, setTitle] = useState(""); /* * https://stackoverflow.com/questions/19739001/what-is-the-difference-between-srcdoc-and-src-datatext-html-in-an * 1. using srcdoc * 2. using src with dataurl: * easy to share * length limit (Data URIs cannot be larger than 32,768 characters.) */ useEffect(() => { const handleMessage = (e: any) => { const { id, height, title } = e.data; setTitle(title); if (id == frameId.current) { setIframeHeight(height); } }; window.addEventListener("message", handleMessage); return () => { window.removeEventListener("message", handleMessage); }; }, []); const height = useMemo(() => { if (!props.autoHeight) return props.height || 600; if (typeof props.height === "string") { return props.height; } const parentHeight = props.height || 600; return iframeHeight + 40 > parentHeight ? parentHeight : iframeHeight + 40; }, [props.autoHeight, props.height, iframeHeight]); const srcDoc = useMemo(() => { const script = ``; if (props.code.includes("")) { props.code.replace("", "" + script); } return props.code + script; }, [props.code]); const handleOnLoad = () => { if (props?.onLoad) { props.onLoad(title); } }; return (