import React, { useState, useEffect } from 'react';
// Fire/Frost/Arcane CSS definitions (injected into preview)
const FIRE_FROST_CSS = `
:root {
/* Fire Colors (Meg/The Emissary) */
--fire-primary: #FF6B35;
--fire-secondary: #F7931E;
--fire-accent: #FFA500;
/* Frost Colors (Michael/The Wizard) */
--frost-primary: #4ECDC4;
--frost-secondary: #45B7D1;
--frost-accent: #00CED1;
/* Arcane Colors (Holly/The Catalyst) */
--arcane-primary: #A855F7;
--arcane-secondary: #9D4EDD;
--arcane-accent: #C77DFF;
--arcane-dark: #7F00FF;
/* Neutral Colors */
--neutral-dark: #1a1a1a;
--neutral-gray: #6b7280;
--neutral-light: #f3f4f6;
}
/* Fire/Frost/Arcane Gradient Utilities */
.fire-frost-gradient {
background: linear-gradient(135deg, #FF6B35 0%, #4ECDC4 100%);
}
.fire-gradient {
background: linear-gradient(135deg, #FF6B35 0%, #FFA500 100%);
}
.frost-gradient {
background: linear-gradient(135deg, #4ECDC4 0%, #00CED1 100%);
}
.arcane-gradient {
background: linear-gradient(135deg, #A855F7 0%, #C77DFF 100%);
}
.trinity-gradient {
background: linear-gradient(135deg, #FF6B35 0%, #A855F7 50%, #4ECDC4 100%);
}
.arcane-storm-gradient {
background: linear-gradient(135deg, #7F00FF 0%, #A855F7 50%, #C77DFF 100%);
}
/* Typography Colors */
.fire-text {
color: var(--fire-primary);
}
.frost-text {
color: var(--frost-primary);
}
.arcane-text {
color: var(--arcane-primary);
}
/* Border Utilities */
.fire-border {
border-color: var(--fire-primary);
}
.frost-border {
border-color: var(--frost-primary);
}
.arcane-border {
border-color: var(--arcane-primary);
}
/* Common Ghost page styles */
.gh-content {
max-width: 1200px;
margin: 0 auto;
padding: 40px 20px;
}
.gh-content h1 {
font-size: 3rem;
font-weight: 700;
margin-bottom: 1.5rem;
line-height: 1.2;
}
.gh-content h2 {
font-size: 2rem;
font-weight: 600;
margin: 2rem 0 1rem;
line-height: 1.3;
}
.gh-content p {
font-size: 1.125rem;
line-height: 1.75;
margin-bottom: 1.5rem;
}
.gh-content a {
color: var(--fire-primary);
text-decoration: underline;
}
.gh-content a:hover {
color: var(--frost-primary);
}
`;
// Sample templates with Ghost wrapper classes
const SAMPLE_TEMPLATES = {
blank: {
name: 'Blank Page',
html: '
Page Title
\nStart writing your content here...
'
},
simple: {
name: 'Simple Page',
html: `Welcome to Firefrost Gaming
This is a simple page template with basic structure.
Section Heading
Add your content here. This template includes proper Ghost content classes for consistent styling.
You can add more paragraphs, headings, and content as needed.
`
},
twoColumn: {
name: 'Trinity Layout (3 Columns)',
html: `The Trinity
๐ฅ Fire Path
GingerFury - The Emissary
Community-focused content goes here. Passionate, warm, welcoming.
- Community events
- Player stories
- Social activities
โก Arcane Path
unicorn20089 - The Catalyst
Creative, building-focused content. Innovation, transformation, foundation.
- Build showcases
- Creative projects
- World design
โ๏ธ Frost Path
Frostystyle - The Wizard
Technical, precise content goes here. Cool, calculated, systematic.
- Server specifications
- Technical guides
- Performance metrics
`
},
cardGrid: {
name: 'Trinity Card Grid',
html: `The Trinity - Fire + Arcane + Frost
Showcase the three elemental forces.
๐ฅ Fire - The Emissary
Passion, community, warmth. GingerFury brings the heart and the people.
โก Arcane - The Catalyst
Creative transformation, building, innovation. unicorn20089 brings the foundation.
โ๏ธ Frost - The Wizard
Precision, technical excellence, strategy. Frostystyle brings the architecture.
`
}
};
// Helper function to generate preview HTML for iframe srcdoc
const generatePreviewHtml = (htmlContent) => {
return `
Ghost Preview
${htmlContent}
`;
};
export default function GhostPageBuilder() {
// Two-state pattern: instant input + debounced preview
const [htmlInput, setHtmlInput] = useState('');
const [debouncedHtml, setDebouncedHtml] = useState('');
const [viewport, setViewport] = useState('desktop');
const [copied, setCopied] = useState(false);
// Load saved draft from localStorage on mount
useEffect(() => {
const saved = localStorage.getItem('firefrost_ghost_draft');
if (saved) {
setHtmlInput(saved);
setDebouncedHtml(saved);
} else {
// Start with simple template if no saved draft
setHtmlInput(SAMPLE_TEMPLATES.simple.html);
setDebouncedHtml(SAMPLE_TEMPLATES.simple.html);
}
}, []);
// Debounce preview updates and auto-save to localStorage
useEffect(() => {
const timer = setTimeout(() => {
setDebouncedHtml(htmlInput);
localStorage.setItem('firefrost_ghost_draft', htmlInput);
}, 500);
return () => clearTimeout(timer);
}, [htmlInput]);
// Tab key handler for textarea
const handleKeyDown = (e) => {
if (e.key === 'Tab') {
e.preventDefault();
const start = e.target.selectionStart;
const end = e.target.selectionEnd;
// Insert two spaces at cursor position
const newValue = htmlInput.substring(0, start) + " " + htmlInput.substring(end);
setHtmlInput(newValue);
// Move cursor after inserted spaces (wait for React state update)
setTimeout(() => {
e.target.selectionStart = e.target.selectionEnd = start + 2;
}, 0);
}
};
// Copy HTML to clipboard
const handleCopy = async () => {
try {
await navigator.clipboard.writeText(htmlInput);
setCopied(true);
setTimeout(() => setCopied(false), 2000);
} catch (err) {
console.error('Failed to copy:', err);
}
};
// Load sample template
const loadTemplate = (templateKey) => {
setHtmlInput(SAMPLE_TEMPLATES[templateKey].html);
};
// Clear editor
const handleReset = () => {
if (confirm('Clear the editor? Your current work will be lost.')) {
setHtmlInput('');
localStorage.removeItem('firefrost_ghost_draft');
}
};
// Viewport dimensions
const viewportWidths = {
desktop: '100%',
tablet: '768px',
mobile: '375px'
};
return (
{/* Header */}
๐ฅโกโ๏ธ Ghost Page Builder
Live preview with Fire + Arcane + Frost CSS
{/* Toolbar */}
{/* Sample Templates Dropdown */}
{/* Viewport Toggle */}
{/* Spacer */}
{/* Action Buttons */}
{/* Main Content: Split Pane */}
{/* Left: Editor */}
{/* Right: Preview */}
Live Preview
{viewport === 'desktop' ? 'Full Width' : viewportWidths[viewport]}
{/* Footer with Color Reference */}
Trinity Colors:
Fire #FF6B35
Arcane #A855F7
Frost #4ECDC4
Trinity Gradient
);
}