packages/live-previews/pages/preview.tsx
import React from "react";
import type { NextPage } from "next";
import { LivePreview, LiveProvider } from "@aliemir/react-live";
import Error from "@/pages/_error";
import { Loading } from "@/src/components/loading";
import { LiveError } from "@/src/components/live-error";
import { RefineCommonScope } from "@/src/scope/common";
import { replaceImports } from "@/src/utils/replace-imports";
import { useCode } from "@/src/utils/use-code";
import { checkPackage } from "@/src/utils/check-package";
const Preview: NextPage = () => {
const [ready, setReady] = React.useState(false);
const { code, css, hasQuery, isReady, disableScroll, useTailwind } =
useCode();
const [scope, setScope] = React.useState({ ...RefineCommonScope });
const [scopeSettled, setScopeSettled] = React.useState(false);
const scopeResolver = React.useCallback(async () => {
if (code && hasQuery && isReady && !scopeSettled) {
const usedPackages = checkPackage(code);
const callbacks: (() => Promise<{}>)[] = Array.from(usedPackages).map(
(scope) => async () => (await import(`../src/scope/${scope}`)).default,
);
if (code.includes("React.createElement(GoogleButton,")) {
callbacks.push(
async () => (await import(`${"../src/scope/google"}`)).default,
);
}
let scopesToUse: Record<string, any> = {};
const resolvedScopes = await Promise.all(callbacks.map((cb) => cb()));
resolvedScopes.forEach((scope) => {
scopesToUse = {
...scopesToUse,
...scope,
};
});
setScope({
...RefineCommonScope,
...scopesToUse,
});
setScopeSettled(true);
}
}, [code, hasQuery, isReady, scopeSettled]);
React.useEffect(() => {
scopeResolver();
}, [scopeResolver]);
if (isReady && !hasQuery) {
return <Error statusCode={404} />;
}
if (isReady && hasQuery && !code) {
return <Error statusCode={400} />;
}
if (isReady && code && typeof window !== "undefined" && !ready) {
const pkgs = checkPackage(code);
const hasAntd = pkgs.has("antd") || pkgs.has("antd-inferencer");
if (hasAntd || useTailwind) {
if (hasAntd) {
const element = document.createElement("link");
element.setAttribute("rel", "stylesheet");
element.onload = () => {
setTimeout(() => {
setReady(true);
}, 300);
};
element.setAttribute(
"href",
"https://refine.ams3.cdn.digitaloceanspaces.com/antd%2Fdist%2Freset.css",
);
document.head.appendChild(element);
}
if (useTailwind) {
const element = document.createElement("script");
element.setAttribute("defer", "true");
element.onload = () => {
setTimeout(() => {
setReady(true);
}, 300);
};
element.setAttribute("src", "https://cdn.tailwindcss.com");
document.head.appendChild(element);
}
} else {
setReady(true);
}
}
return (
<>
<style jsx global>
{`
body {
overflow: ${
disableScroll ? "hidden !important" : "auto"
};
}
${css ?? ""}
`}
</style>
<Loading loading={!ready || !scopeSettled} />
{ready && scopeSettled && (
<LiveProvider scope={scope} noInline code={replaceImports(code ?? "")}>
<LiveError />
<LivePreview />
</LiveProvider>
)}
</>
);
};
export default Preview;