OpenPanel/packages/live-previews/pages/preview.tsx
2024-02-05 10:23:04 +01:00

240 lines
8.9 KiB
TypeScript

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<{}>)[] = [
async () =>
usedPackages.has("antd")
? (await import("../src/scope/antd")).default
: {},
async () =>
usedPackages.has("mui")
? (await import("../src/scope/mui")).default
: {},
async () =>
usedPackages.has("mantine")
? (await import("../src/scope/mantine")).default
: {},
async () =>
usedPackages.has("chakra")
? (await import("../src/scope/chakra")).default
: {},
async () =>
usedPackages.has("antd-inferencer")
? (await import("../src/scope/antd-inferencer")).default
: {},
async () =>
usedPackages.has("mui-inferencer")
? (await import("../src/scope/mui-inferencer")).default
: {},
async () =>
usedPackages.has("mantine-inferencer")
? (await import("../src/scope/mantine-inferencer"))
.default
: {},
async () =>
usedPackages.has("chakra-inferencer")
? (await import("../src/scope/chakra-inferencer"))
.default
: {},
async () =>
usedPackages.has("headless-inferencer")
? (await import("../src/scope/headless-inferencer"))
.default
: {},
async () =>
usedPackages.has("react-dom")
? (await import("../src/scope/react-dom")).default
: {},
async () =>
usedPackages.has("web-vitals")
? (await import("../src/scope/web-vitals")).default
: {},
async () =>
usedPackages.has("i18n")
? (await import("../src/scope/i18n")).default
: {},
async () =>
usedPackages.has("tabler-icons")
? (await import("../src/scope/tabler-icons")).default
: {},
async () =>
usedPackages.has("kbar")
? (await import("../src/scope/kbar")).default
: {},
async () =>
usedPackages.has("airtable")
? (await import("../src/scope/airtable")).default
: {},
async () =>
usedPackages.has("appwrite")
? (await import("../src/scope/appwrite")).default
: {},
async () =>
usedPackages.has("hasura")
? (await import("../src/scope/hasura")).default
: {},
async () =>
usedPackages.has("nestjsx-crud")
? (await import("../src/scope/nestjsx")).default
: {},
async () =>
usedPackages.has("strapi-v4")
? (await import("../src/scope/strapi-v4")).default
: {},
async () =>
usedPackages.has("strapi-graphql")
? (await import("../src/scope/strapi-graphql")).default
: {},
async () =>
usedPackages.has("supabase")
? (await import("../src/scope/supabase")).default
: {},
async () =>
usedPackages.has("devtools")
? (await import("../src/scope/devtools")).default
: {},
async () =>
usedPackages.has("axios")
? (await import("../src/scope/axios")).default
: {},
async () =>
usedPackages.has("auth0")
? (await import("../src/scope/auth0")).default
: {},
async () =>
usedPackages.has("keycloak")
? (await import("../src/scope/keycloak")).default
: {},
async () =>
usedPackages.has("casbin")
? (await import("../src/scope/casbin")).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 (
<>
{/* eslint-disable-next-line react/no-unknown-property */}
<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;