import { LIVE_CONTROLS_SCRIPT, resolvePreviewRequest } from "@decocms/blocks-admin"; import { getPreviewWrapper, getRenderShellConfig } from "@decocms/blocks-admin/admin/setup"; import { headers } from "next/headers"; import { cloneElement, createElement, type ReactElement, type ReactNode } from "react"; import { SectionRenderer } from "./SectionRenderer"; export interface CreateDecoPreviewPageOptions { setup?: () => Promise; } export interface DecoPreviewPageProps { params: Promise<{ path?: string[] }>; searchParams: Promise>; } function appendSearchParams( target: URLSearchParams, source: Record, ) { for (const [key, value] of Object.entries(source)) { if (Array.isArray(value)) { for (const item of value) target.append(key, item); } else if (value !== undefined) { target.set(key, value); } } } async function buildPreviewRequest(props: DecoPreviewPageProps): Promise { const [params, searchParams, requestHeaders] = await Promise.all([ props.params, props.searchParams, headers(), ]); const host = requestHeaders.get("x-forwarded-host") ?? requestHeaders.get("host") ?? "localhost"; const protocol = requestHeaders.get("x-forwarded-proto") ?? "http"; const encodedPath = (params.path ?? []).map(encodeURIComponent).join("/"); const url = new URL(`/live/previews/${encodedPath}`, `${protocol}://${host}`); appendSearchParams(url.searchParams, searchParams); return new Request(url, { headers: new Headers(requestHeaders) }); } function PreviewResources() { const { cssHref, fontHrefs } = getRenderShellConfig(); return ( <> {fontHrefs.map((href) => ( ))} {cssHref ? : null} ); } function PreviewFrame({ children }: { children: ReactNode }) { const { themeName, bodyClass } = getRenderShellConfig(); const Wrapper = getPreviewWrapper(); const content = Wrapper ? createElement(Wrapper, null, children) : children; return ( <>
{content}