Auto-sync enabled

FlatlyPage

Version 1.0.0 • 54 files • 724.77 KB
admin/theme-edit/generator.php
<?php
require_once __DIR__ . '/../../config.php';
require_login();
session_start();
?>

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Theme Generator - FlatlyPage CMS</title>
  <link rel="preload" href="/assets/fonts/inter/inter.ttf" as="font" type="font/ttf" crossorigin>
  <style>

    :root {
      --bg: #0a0a0a;
      --bg-card: #161616;
      --bg-hover: #1c1c1c;
      --border: #262626;
      --border-focus: #404040;
      --text: #fafafa;
      --text-muted: #737373;
      --accent: #d5d9e0;
      --radius: 12px;
      --section-bg: #1e1e1e;
    }

    *,
    *::before,
    *::after {
      box-sizing: border-box;
      margin: 0;
      padding: 0;
    }

    body {
      font-family: 'Inter', sans-serif;
      background: var(--bg);
      color: var(--text);
      line-height: 1.5;
      min-height: 100vh;
      display: flex;
      justify-content: center;
      align-items: flex-start;
      padding: 40px 20px;
    }

    .container {
      width: 100%;
      max-width: 900px;
      background: var(--bg-card);
      padding: 32px;
      border-radius: var(--radius);
      box-shadow: 0 8px 24px rgba(0, 0, 0, 0.7);
      display: flex;
      flex-direction: column;
      gap: 24px;
    }

    h1 {
      font-size: 1.75rem;
      font-weight: 600;
      text-align: center;
      color: var(--accent);
      margin-bottom: 10px;
    }

    h3 {
      font-size: 0.95rem;
      text-transform: uppercase;
      letter-spacing: 0.05em;
      color: var(--text-muted);
      margin-bottom: 12px;
      border-bottom: 1px solid var(--border);
      padding-bottom: 8px;
    }

    label {
      display: block;
      font-size: 0.85rem;
      font-weight: 500;
      margin-bottom: 6px;
      color: var(--text);
    }

    .required::after {
      content: " *";
      color: #ff4d4d;
    }

    textarea,
    input {
      width: 100%;
      padding: 12px;
      border-radius: var(--radius);
      border: 1px solid var(--border);
      background: var(--bg);
      color: var(--text);
      font-family: monospace;
      font-size: 0.9rem;
      transition: border-color 0.2s;
    }

    textarea {
      resize: vertical;
      min-height: 150px;
    }

    textarea:focus,
    input:focus {
      outline: none;
      border-color: var(--accent);
    }

    .meta-inputs {
      display: flex;
      gap: 16px;
    }
    
    .meta-inputs > div {
      flex: 1;
    }

    .colors-wrapper {
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: 20px;
      background: var(--section-bg);
      padding: 20px;
      border-radius: var(--radius);
      border: 1px solid var(--border);
    }

    .color-column {
      display: flex;
      flex-direction: column;
      gap: 12px;
    }

    .color-input-group {
      display: flex;
      flex-direction: column;
    }

    .buttons {
      display: flex;
      gap: 10px;
      margin-top: 10px;
    }

    button {
      padding: 12px 24px;
      border: none;
      border-radius: var(--radius);
      cursor: pointer;
      background: var(--accent);
      color: var(--bg);
      font-weight: 600;
      transition: all 0.2s;
      font-size: 0.95rem;
    }

    button:hover {
      background: #ffffff;
    }

    button.secondary {
      background: var(--bg-hover);
      color: var(--text);
      border: 1px solid var(--border);
    }
    
    button.secondary:hover {
      border-color: var(--accent);
    }

    @media (max-width: 700px) {
      .colors-wrapper, .meta-inputs {
        grid-template-columns: 1fr;
        flex-direction: column;
      }
    }
  </style>
</head>

<body>

  <div class="container">
    <h1>Theme Builder</h1>

    <div>
      <label for="cssInput" class="required">Input CSS (Paste here to auto-detect colors)</label>
      <textarea id="cssInput" placeholder="Paste your CSS here..."></textarea>
    </div>

    <div class="meta-inputs">
      <div>
        <label for="theme-name" class="required">Theme Name</label>
        <input type="text" id="theme-name" placeholder="My Awesome Theme">
      </div>
      <div>
        <label for="author" class="required">Author</label>
        <input type="text" id="author" placeholder="John Doe">
      </div>
    </div>

    <div class="colors-wrapper">
      <div class="color-column">
        <h3>Dark Mode</h3>
        <div class="color-input-group">
          <label for="dark_bg" class="required">Background</label>
          <input type="text" id="dark_bg" placeholder="#111111">
        </div>
        <div class="color-input-group">
          <label for="dark_fg" class="required">Foreground</label>
          <input type="text" id="dark_fg" placeholder="#fafafa">
        </div>
        <div class="color-input-group">
          <label for="dark_card" class="required">Card</label>
          <input type="text" id="dark_card" placeholder="#1a1a1a">
        </div>
      </div>

      <div class="color-column">
        <h3>Light Mode</h3>
        <div class="color-input-group">
          <label for="light_bg" class="required">Background</label>
          <input type="text" id="light_bg" placeholder="#ffffff">
        </div>
        <div class="color-input-group">
          <label for="light_fg" class="required">Foreground</label>
          <input type="text" id="light_fg" placeholder="#111111">
        </div>
        <div class="color-input-group">
          <label for="light_card" class="required">Card</label>
          <input type="text" id="light_card" placeholder="#f5f5f5">
        </div>
      </div>
    </div>

    <div class="buttons">
      <button onclick="processCSS()">Process & Generate</button>
      <button class="secondary" onclick="copyCSS()">Copy Result</button>
    </div>

    <div>
      <label for="cssOutput">Output CSS</label>
      <textarea id="cssOutput" placeholder="Generated CSS with header will appear here..." readonly></textarea>
    </div>
  </div>

  <script>
    document.getElementById('cssInput').addEventListener('input', function() {
      const css = this.value;
      
      function extractVar(block, varName) {
        const regex = new RegExp(`--${varName}:\\s*([^;]+)`);
        const match = block.match(regex);
        return match ? match[1].trim() : '';
      }

      const rootBlockMatch = css.match(/:root\s*(?!\[)\s*{([\s\S]*?)}/);
      if (rootBlockMatch) {
        const block = rootBlockMatch[1];
        const bg = extractVar(block, 'background');
        const fg = extractVar(block, 'foreground');
        const card = extractVar(block, 'card');

        if(bg) document.getElementById('dark_bg').value = bg;
        if(fg) document.getElementById('dark_fg').value = fg;
        if(card) document.getElementById('dark_card').value = card;
      }

      const lightBlockMatch = css.match(/:root\[data-theme="light"\]\s*{([\s\S]*?)}/);
      if (lightBlockMatch) {
        const block = lightBlockMatch[1];
        const bg = extractVar(block, 'background');
        const fg = extractVar(block, 'foreground');
        const card = extractVar(block, 'card');

        if(bg) document.getElementById('light_bg').value = bg;
        if(fg) document.getElementById('light_fg').value = fg;
        if(card) document.getElementById('light_card').value = card;
      }
    });

    function processCSS() {
      const cssInput = document.getElementById('cssInput').value.trim();
      const themeName = document.getElementById('theme-name').value.trim();
      const author = document.getElementById('author').value.trim();

      const colors = {
        dark: {
          bg: document.getElementById('dark_bg').value.trim(),
          fg: document.getElementById('dark_fg').value.trim(),
          card: document.getElementById('dark_card').value.trim()
        },
        light: {
          bg: document.getElementById('light_bg').value.trim(),
          fg: document.getElementById('light_fg').value.trim(),
          card: document.getElementById('light_card').value.trim()
        }
      };

      if (!cssInput || !themeName || !author || 
          !colors.dark.bg || !colors.dark.fg || !colors.dark.card ||
          !colors.light.bg || !colors.light.fg || !colors.light.card) {
        alert('Please fill in ALL required fields, including all 6 colors.');
        return;
      }

      const cleanedCSS = cssInput.replace(/\/\*[\s\S]*?\*\//g, '').trim();

      const colorString = `Dark[Bg:${colors.dark.bg}, Fg:${colors.dark.fg}, Card:${colors.dark.card}] | Light[Bg:${colors.light.bg}, Fg:${colors.light.fg}, Card:${colors.light.card}]`;

      const newComment = `/* ============================================================================\n` +
                         `   Theme: ${themeName}\n` +
                         `   Author: ${author}\n` +
                         `   Colors: ${colorString}\n` +
                         `   ============================================================================ */\n\n`;

      document.getElementById('cssOutput').value = newComment + cleanedCSS;
    }

    function copyCSS() {
      const output = document.getElementById('cssOutput');
      if(!output.value) return;
      
      output.select();
      output.setSelectionRange(0, 99999);
      navigator.clipboard.writeText(output.value).then(() => {
        const btn = document.querySelector('button.secondary');
        const originalText = btn.innerText;
        btn.innerText = 'Copied!';
        setTimeout(() => btn.innerText = originalText, 2000);
      });
    }
  </script>

</body>
</html>