penframe
Version:
A lightweight DSL-based wireframe and UI structure visualization tool.
210 lines (189 loc) • 7 kB
HTML
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PenFrame Browser Demo</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
.container {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
margin-top: 20px;
}
.editor, .preview {
border: 1px solid #ccc;
border-radius: 4px;
}
.editor textarea {
width: 100%;
height: 300px;
border: none;
padding: 10px;
font-family: 'Courier New', monospace;
font-size: 14px;
resize: vertical;
}
.preview {
padding: 10px;
min-height: 300px;
background: #f9f9f9;
}
.controls {
margin: 10px 0;
}
button {
padding: 8px 16px;
margin: 0 5px;
border: none;
border-radius: 4px;
background: #007bff;
color: white;
cursor: pointer;
}
button:hover {
background: #0056b3;
}
button:disabled {
background: #6c757d;
cursor: not-allowed;
}
.error {
color: red;
padding: 10px;
background: #ffe6e6;
border-radius: 4px;
margin: 10px 0;
}
.success {
color: green;
padding: 10px;
background: #e6ffe6;
border-radius: 4px;
margin: 10px 0;
}
</style>
</head>
<body>
<h1>🎨 PenFrame Browser Demo</h1>
<p>Edit the PenFrame DSL on the left and see the live preview on the right!</p>
<div class="controls">
<button onclick="generateSVG()">Generate SVG</button>
<button onclick="generatePNG()">Generate PNG</button>
<button onclick="downloadSVG()">Download SVG</button>
<button onclick="downloadPNG()">Download PNG</button>
<button onclick="loadExample()">Load Example</button>
</div>
<div id="message"></div>
<div class="container">
<div class="editor">
<h3>PenFrame DSL Editor</h3>
<textarea id="dslInput" placeholder="Enter your PenFrame DSL here...">
@app { width: 800, height: 400, title: "Browser Demo" }
@headline "Welcome to PenFrame" { level: 1, color: "#2c3e50" }
@hr
@p "This is running in your browser!" { align: "center", color: "#7f8c8d" }
@tabs { items: ["Home", "Features", "About"], active: 0 }
@button "Click Me" { color: "#3498db", textColor: "#ffffff" }
@badge "Browser Ready!" { color: "#e74c3c", textColor: "#ffffff" }
</textarea>
</div>
<div class="preview">
<h3>Live Preview</h3>
<div id="svgPreview"></div>
</div>
</div>
<!-- Load PenFrame library -->
<script src="../dist/penframe.min.js"></script>
<script>
let currentSVG = '';
let currentPNG = '';
function showMessage(text, type = 'success') {
const messageDiv = document.getElementById('message');
messageDiv.innerHTML = `<div class="${type}">${text}</div>`;
setTimeout(() => {
messageDiv.innerHTML = '';
}, 3000);
}
function generateSVG() {
try {
const dslCode = document.getElementById('dslInput').value;
currentSVG = PenFrame.penframeToSvg(dslCode);
document.getElementById('svgPreview').innerHTML = currentSVG;
showMessage('SVG generated successfully!');
} catch (error) {
showMessage(`Error: ${error.message}`, 'error');
console.error('SVG generation error:', error);
}
}
async function generatePNG() {
try {
const dslCode = document.getElementById('dslInput').value;
currentPNG = await PenFrame.penframeToPngDataURL(dslCode, {
width: 800,
height: 600,
scale: 2,
background: 'white'
});
showMessage('PNG generated successfully!');
} catch (error) {
showMessage(`Error: ${error.message}`, 'error');
console.error('PNG generation error:', error);
}
}
function downloadSVG() {
if (!currentSVG) {
showMessage('Please generate SVG first!', 'error');
return;
}
const blob = new Blob([currentSVG], { type: 'image/svg+xml' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'penframe-output.svg';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
showMessage('SVG downloaded!');
}
function downloadPNG() {
if (!currentPNG) {
showMessage('Please generate PNG first!', 'error');
return;
}
const a = document.createElement('a');
a.href = currentPNG;
a.download = 'penframe-output.png';
document.body.appendChild(a);
showMessage('PNG downloaded!');
}
function loadExample() {
const exampleDSL = `@app { width: 600, height: 500, title: "Todo App Wireframe" }
@headline "My Todo App" { level: 1, color: "#333" }
@hr
@formcontrol "Add new task" { control: "textbox", placeholder: "Enter task..." }
@button "Add Task" { color: "#28a745", textColor: "#ffffff" }
@hr
@list { items: ["Design wireframe", "Implement features", "Test application"] }
@tabs { items: ["All", "Active", "Completed"], active: 0 }
@badge "3 tasks" { color: "#6c757d" }`;
document.getElementById('dslInput').value = exampleDSL;
generateSVG();
}
// Auto-generate on input change
document.getElementById('dslInput').addEventListener('input', function() {
clearTimeout(this.updateTimer);
this.updateTimer = setTimeout(generateSVG, 500);
});
// Generate initial preview
generateSVG();
</script>
</body>
</html>