import type { BuilderNode, BuilderStatePayload, FlexSettings, GridSettings, LayoutMode, } from "./types"; import { defaultFlexSettings, defaultGridSettings } from "./types"; function migrateNodeGrid(n: any): any { const g = n?.grid; if (!g || typeof g !== "object") return migrateNodeChildren(n); const hasOldContainerKeys = "columns" in g || "rows" in g || "gap" in g; const migrated = hasOldContainerKeys ? (() => { const { grid, ...rest } = n; return rest; })() : n; return migrateNodeChildren(migrated); } function migrateNodeChildren(n: any): any { if (!Array.isArray(n?.children) || n.children.length === 0) return n; return { ...n, children: n.children.map(migrateNodeGrid) }; } export type ParsedBuilderState = { layoutMode: LayoutMode; freeformNodes: BuilderNode[]; orderedNodes: BuilderNode[]; nodes?: BuilderNode[]; showGrid: boolean; gridSize: number; flexSettings: FlexSettings; gridSettings: GridSettings; canvasBackground: string; // ← NEW visibleLayoutModes?: Record; visibleCodeTabs?: Record<"html" | "css" | "combined", boolean>; showComponentSettingsInStudent?: boolean; showSidebarInStudent?: boolean; allowDeleteInStudent?: boolean; showToolbarInStudent?: boolean; showAddButton?: boolean; showLayoutDropdown?: boolean; }; export function serializeBuilderState(args: { layoutMode: LayoutMode; freeformNodes: BuilderNode[]; orderedNodes: BuilderNode[]; showGrid: boolean; gridSize: number; flexSettings: FlexSettings; gridSettings: GridSettings; canvasBackground: string; // ← NEW visibleLayoutModes: Record; visibleCodeTabs: Record<"html" | "css" | "combined", boolean>; showComponentSettingsInStudent: boolean; showSidebarInStudent: boolean; allowDeleteInStudent: boolean; showToolbarInStudent: boolean; showAddButton: boolean; showLayoutDropdown: boolean; }): string { const payload: any = { layoutMode: args.layoutMode, freeformNodes: args.freeformNodes, orderedNodes: args.orderedNodes, showGrid: args.showGrid, gridSize: args.gridSize, flexSettings: args.flexSettings, gridSettings: args.gridSettings, canvasBackground: args.canvasBackground, // ← NEW visibleLayoutModes: args.visibleLayoutModes, visibleCodeTabs: args.visibleCodeTabs, showComponentSettingsInStudent: args.showComponentSettingsInStudent, showSidebarInStudent: args.showSidebarInStudent, allowDeleteInStudent: args.allowDeleteInStudent, showToolbarInStudent: args.showToolbarInStudent, showAddButton: args.showAddButton, showLayoutDropdown: args.showLayoutDropdown, }; return JSON.stringify(payload); } export function parseBuilderState( serialized: string, ): ParsedBuilderState | null { if (!serialized) return null; try { const parsed = JSON.parse(serialized); const layoutMode = (parsed.layoutMode as LayoutMode | undefined) ?? "freeform"; const freeformNodesRaw = Array.isArray(parsed.freeformNodes) ? (parsed.freeformNodes as BuilderNode[]) : []; const orderedNodesRaw = Array.isArray(parsed.orderedNodes) ? (parsed.orderedNodes as BuilderNode[]) : Array.isArray(parsed.nodes) ? (parsed.nodes as BuilderNode[]) : []; const freeformNodes = freeformNodesRaw.map(migrateNodeGrid); const orderedNodes = orderedNodesRaw.map(migrateNodeGrid); const flexBase = defaultFlexSettings(); const gridBase = defaultGridSettings(); const flexSettings = parsed.flexSettings && typeof parsed.flexSettings === "object" ? { ...flexBase, ...parsed.flexSettings } : flexBase; const gridSettings = parsed.gridSettings && typeof parsed.gridSettings === "object" ? { ...gridBase, ...parsed.gridSettings } : gridBase; // ── canvasBackground ──────────────────────────────────────────────────── const canvasBackground = typeof parsed.canvasBackground === "string" && parsed.canvasBackground ? parsed.canvasBackground : "#ffffff"; const visibleLayoutModes = parsed.visibleLayoutModes && typeof parsed.visibleLayoutModes === "object" ? (parsed.visibleLayoutModes as Record) : undefined; const visibleCodeTabs = parsed.visibleCodeTabs && typeof parsed.visibleCodeTabs === "object" ? (parsed.visibleCodeTabs as Record< "html" | "css" | "combined", boolean >) : undefined; const showComponentSettingsInStudent = parsed.showComponentSettingsInStudent == null ? undefined : Boolean(parsed.showComponentSettingsInStudent); const showSidebarInStudent = parsed.showSidebarInStudent == null ? undefined : Boolean(parsed.showSidebarInStudent); const allowDeleteInStudent = parsed.allowDeleteInStudent == null ? undefined : Boolean(parsed.allowDeleteInStudent); const showToolbarInStudent = parsed.showToolbarInStudent == null ? undefined : Boolean(parsed.showToolbarInStudent); const showAddButton = parsed.showAddButton == null ? undefined : Boolean(parsed.showAddButton); const showLayoutDropdown = parsed.showLayoutDropdown == null ? undefined : Boolean(parsed.showLayoutDropdown); return { layoutMode, freeformNodes, orderedNodes, nodes: Array.isArray(parsed.nodes) ? (parsed.nodes as BuilderNode[]) : undefined, showGrid: Boolean(parsed.showGrid), gridSize: Number(parsed.gridSize ?? 20), flexSettings, gridSettings, canvasBackground, // ← NEW visibleLayoutModes, visibleCodeTabs, showComponentSettingsInStudent, showSidebarInStudent, allowDeleteInStudent, showAddButton, showLayoutDropdown, showToolbarInStudent, }; } catch { return null; } }