"use client"; import { useCallback, useEffect, useMemo, useRef, useState, type MouseEvent, } from "react"; import { JsonEditor, type JsonValue } from "@visual-json/react"; import type { NextAppSpec } from "@json-render/next"; import { NextAppProvider, PageRenderer } from "@json-render/next"; import { ResizablePanelGroup, ResizablePanel, ResizableHandle, } from "@/components/ui/resizable"; import { AddressBar } from "@/components/route-tabs"; import { registry } from "@/lib/registry"; export function Editor() { const [spec, setSpec] = useState(null); const [activeRoute, setActiveRoute] = useState("/"); const [sidebarOpen, setSidebarOpen] = useState(true); const debounceRef = useRef | null>(null); useEffect(() => { fetch("/api/spec") .then((r) => r.json()) .then((data: NextAppSpec) => setSpec(data)); }, []); const handleChange = useCallback((value: JsonValue) => { const updated = value as unknown as NextAppSpec; setSpec(updated); if (debounceRef.current) clearTimeout(debounceRef.current); debounceRef.current = setTimeout(() => { fetch("/api/spec", { method: "PUT", headers: { "Content-Type": "application/json" }, body: JSON.stringify(updated), }); }, 500); }, []); const handlePreviewClick = useCallback((e: MouseEvent) => { const anchor = (e.target as HTMLElement).closest("a"); if (!anchor) return; const href = anchor.getAttribute("href"); if (!href || href.startsWith("http") || href.startsWith("mailto:")) return; e.preventDefault(); setActiveRoute(href); }, []); const currentRoute = useMemo(() => { if (!spec) return null; return spec.routes[activeRoute] ?? null; }, [spec, activeRoute]); const layoutSpec = useMemo(() => { if (!spec || !currentRoute?.layout || !spec.layouts) return null; return spec.layouts[currentRoute.layout] ?? null; }, [spec, currentRoute]); const initialState = useMemo(() => { if (!spec || !currentRoute) return undefined; const merged: Record = {}; if (spec.state) Object.assign(merged, spec.state); if (currentRoute.page.state) Object.assign(merged, currentRoute.page.state); return Object.keys(merged).length > 0 ? merged : undefined; }, [spec, currentRoute]); if (!spec) { return (
Loading...
); } return (
Next Website Builder View Website
spec.json
{currentRoute ? ( ) : (
Route not found
)}
); }