app.js

36.55 KB
15/12/2025 15:55
JS
app.js
// Tab functionality
const tabs = document.querySelectorAll('.tab');
const tabContents = document.querySelectorAll('.tab-content');

tabs.forEach(tab => {
  tab.addEventListener('click', () => {
    const tabId = tab.getAttribute('data-tab');

    tabs.forEach(t => t.classList.remove('active'));
    tabContents.forEach(tc => tc.classList.remove('active'));

    tab.classList.add('active');
    document.getElementById(tabId).classList.add('active');
  });
});

// Notification
function showNotification() {
  const notification = document.getElementById('notification');
  notification.classList.add('show');
  setTimeout(() => {
    notification.classList.remove('show');
  }, 2000);
}

// Copy functionality
document.querySelectorAll('.copy-btn').forEach(btn => {
  btn.addEventListener('click', () => {
    const targetId = btn.getAttribute('data-target');
    const codeElement = document.getElementById(targetId);
    const textToCopy = codeElement.textContent;

    navigator.clipboard.writeText(textToCopy).then(() => {
      btn.textContent = 'Copied!';
      btn.classList.add('copied');
      showNotification();

      setTimeout(() => {
        btn.textContent = 'Copy Code';
        btn.classList.remove('copied');
      }, 2000);
    });
  });
});

// Sync range and number inputs
function syncInputs(rangeId, numberId) {
  const range = document.getElementById(rangeId);
  const number = document.getElementById(numberId);

  range.addEventListener('input', () => {
    number.value = range.value;
  });

  number.addEventListener('input', () => {
    range.value = number.value;
  });
}

// SVG Generator
let currentShape = 'circle';

document.querySelectorAll('.shape-option').forEach(option => {
  option.addEventListener('click', () => {
    document.querySelectorAll('.shape-option').forEach(o => o.classList.remove('selected'));
    option.classList.add('selected');
    currentShape = option.getAttribute('data-shape');

    // Hide all control groups
    document.getElementById('circle-controls').style.display = 'none';
    document.getElementById('rect-controls').style.display = 'none';
    document.getElementById('polygon-controls').style.display = 'none';
    document.getElementById('star-controls').style.display = 'none';
    document.getElementById('ellipse-controls').style.display = 'none';

    // Show relevant control group
    document.getElementById(`${currentShape}-controls`).style.display = 'block';

    updateSVG();
  });
});

// Sync all SVG inputs
syncInputs('circle-radius', 'circle-radius-value');
syncInputs('rect-width', 'rect-width-value');
syncInputs('rect-height', 'rect-height-value');
syncInputs('rect-radius', 'rect-radius-value');
syncInputs('polygon-sides', 'polygon-sides-value');
syncInputs('polygon-size', 'polygon-size-value');
syncInputs('star-points', 'star-points-value');
syncInputs('star-outer', 'star-outer-value');
syncInputs('star-inner', 'star-inner-value');
syncInputs('ellipse-rx', 'ellipse-rx-value');
syncInputs('ellipse-ry', 'ellipse-ry-value');
syncInputs('stroke-width', 'stroke-width-value');
syncInputs('rotation', 'rotation-value');

// Color inputs sync
document.getElementById('fill-color').addEventListener('input', (e) => {
  document.getElementById('fill-color-text').value = e.target.value;
  updateSVG();
});

document.getElementById('fill-color-text').addEventListener('input', (e) => {
  document.getElementById('fill-color').value = e.target.value;
  updateSVG();
});

document.getElementById('stroke-color').addEventListener('input', (e) => {
  document.getElementById('stroke-color-text').value = e.target.value;
  updateSVG();
});

document.getElementById('stroke-color-text').addEventListener('input', (e) => {
  document.getElementById('stroke-color').value = e.target.value;
  updateSVG();
});

// Update SVG on any input change
document.querySelectorAll('#svg input[type="range"], #svg input[type="number"]').forEach(input => {
  input.addEventListener('input', updateSVG);
});

function updateSVG() {
  const preview = document.getElementById('svg-preview');
  const fillColor = document.getElementById('fill-color').value;
  const strokeColor = document.getElementById('stroke-color').value;
  const strokeWidth = document.getElementById('stroke-width').value;
  const rotation = document.getElementById('rotation').value;

  let svgElement = '';
  let code = '<span class="tag">&lt;svg</span> <span class="attr">width</span>=<span class="value">"300"</span> <span class="attr">height</span>=<span class="value">"300"</span> <span class="attr">viewBox</span>=<span class="value">"0 0 300 300"</span><span class="tag">&gt;</span>\n    ';

  switch (currentShape) {
    case 'circle':
      const radius = document.getElementById('circle-radius').value;
      svgElement = `<circle cx="150" cy="150" r="${radius}" fill="${fillColor}" stroke="${strokeColor}" stroke-width="${strokeWidth}"/>`;
      code += `<span class="tag">&lt;circle</span> <span class="attr">cx</span>=<span class="value">"150"</span> <span class="attr">cy</span>=<span class="value">"150"</span> <span class="attr">r</span>=<span class="value">"${radius}"</span> <span class="attr">fill</span>=<span class="value">"${fillColor}"</span> <span class="attr">stroke</span>=<span class="value">"${strokeColor}"</span> <span class="attr">stroke-width</span>=<span class="value">"${strokeWidth}"</span><span class="tag">/&gt;</span>`;
      break;

    case 'rect':
      const width = document.getElementById('rect-width').value;
      const height = document.getElementById('rect-height').value;
      const rectRadius = document.getElementById('rect-radius').value;
      svgElement = `<rect x="${150 - width / 2}" y="${150 - height / 2}" width="${width}" height="${height}" rx="${rectRadius}" fill="${fillColor}" stroke="${strokeColor}" stroke-width="${strokeWidth}"/>`;
      code += `<span class="tag">&lt;rect</span> <span class="attr">x</span>=<span class="value">"${150 - width / 2}"</span> <span class="attr">y</span>=<span class="value">"${150 - height / 2}"</span> <span class="attr">width</span>=<span class="value">"${width}"</span> <span class="attr">height</span>=<span class="value">"${height}"</span> <span class="attr">rx</span>=<span class="value">"${rectRadius}"</span> <span class="attr">fill</span>=<span class="value">"${fillColor}"</span> <span class="attr">stroke</span>=<span class="value">"${strokeColor}"</span> <span class="attr">stroke-width</span>=<span class="value">"${strokeWidth}"</span><span class="tag">/&gt;</span>`;
      break;

    case 'polygon':
      const sides = document.getElementById('polygon-sides').value;
      const size = document.getElementById('polygon-size').value;
      let points = [];
      for (let i = 0; i < sides; i++) {
        const angle = (i * 2 * Math.PI) / sides - Math.PI / 2;
        const x = 150 + size * Math.cos(angle);
        const y = 150 + size * Math.sin(angle);
        points.push(`${x},${y}`);
      }
      svgElement = `<polygon points="${points.join(' ')}" fill="${fillColor}" stroke="${strokeColor}" stroke-width="${strokeWidth}"/>`;
      code += `<span class="tag">&lt;polygon</span> <span class="attr">points</span>=<span class="value">"${points.join(' ')}"</span> <span class="attr">fill</span>=<span class="value">"${fillColor}"</span> <span class="attr">stroke</span>=<span class="value">"${strokeColor}"</span> <span class="attr">stroke-width</span>=<span class="value">"${strokeWidth}"</span><span class="tag">/&gt;</span>`;
      break;

    case 'star':
      const points2 = document.getElementById('star-points').value;
      const outerRadius = document.getElementById('star-outer').value;
      const innerRadius = document.getElementById('star-inner').value;
      let starPoints = [];
      for (let i = 0; i < points2 * 2; i++) {
        const angle = (i * Math.PI) / points2 - Math.PI / 2;
        const radius = i % 2 === 0 ? outerRadius : innerRadius;
        const x = 150 + radius * Math.cos(angle);
        const y = 150 + radius * Math.sin(angle);
        starPoints.push(`${x},${y}`);
      }
      svgElement = `<polygon points="${starPoints.join(' ')}" fill="${fillColor}" stroke="${strokeColor}" stroke-width="${strokeWidth}"/>`;
      code += `<span class="tag">&lt;polygon</span> <span class="attr">points</span>=<span class="value">"${starPoints.join(' ')}"</span> <span class="attr">fill</span>=<span class="value">"${fillColor}"</span> <span class="attr">stroke</span>=<span class="value">"${strokeColor}"</span> <span class="attr">stroke-width</span>=<span class="value">"${strokeWidth}"</span><span class="tag">/&gt;</span>`;
      break;

    case 'ellipse':
      const rx = document.getElementById('ellipse-rx').value;
      const ry = document.getElementById('ellipse-ry').value;
      svgElement = `<ellipse cx="150" cy="150" rx="${rx}" ry="${ry}" fill="${fillColor}" stroke="${strokeColor}" stroke-width="${strokeWidth}"/>`;
      code += `<span class="tag">&lt;ellipse</span> <span class="attr">cx</span>=<span class="value">"150"</span> <span class="attr">cy</span>=<span class="value">"150"</span> <span class="attr">rx</span>=<span class="value">"${rx}"</span> <span class="attr">ry</span>=<span class="value">"${ry}"</span> <span class="attr">fill</span>=<span class="value">"${fillColor}"</span> <span class="attr">stroke</span>=<span class="value">"${strokeColor}"</span> <span class="attr">stroke-width</span>=<span class="value">"${strokeWidth}"</span><span class="tag">/&gt;</span>`;
      break;

    case 'path':
      svgElement = `<path d="M150,50 Q250,150 150,250 Q50,150 150,50" fill="${fillColor}" stroke="${strokeColor}" stroke-width="${strokeWidth}"/>`;
      code += `<span class="tag">&lt;path</span> <span class="attr">d</span>=<span class="value">"M150,50 Q250,150 150,250 Q50,150 150,50"</span> <span class="attr">fill</span>=<span class="value">"${fillColor}"</span> <span class="attr">stroke</span>=<span class="value">"${strokeColor}"</span> <span class="attr">stroke-width</span>=<span class="value">"${strokeWidth}"</span><span class="tag">/&gt;</span>`;
      break;
  }

  if (rotation != 0) {
    svgElement = `<g transform="rotate(${rotation} 150 150)">${svgElement}</g>`;
    code = `<span class="tag">&lt;g</span> <span class="attr">transform</span>=<span class="value">"rotate(${rotation} 150 150)"</span><span class="tag">&gt;</span>\n        ${code.replace('    ', '        ')}\n    <span class="tag">&lt;/g&gt;</span>`;
  }

  code += '\n<span class="tag">&lt;/svg&gt;</span>';

  preview.innerHTML = `<svg width="300" height="300" viewBox="0 0 300 300">${svgElement}</svg>`;
  document.getElementById('svg-code').innerHTML = code;
}

// Box Shadow Generator
syncInputs('box-h-offset', 'box-h-offset-value');
syncInputs('box-v-offset', 'box-v-offset-value');
syncInputs('box-blur', 'box-blur-value');
syncInputs('box-spread', 'box-spread-value');
syncInputs('box-opacity', 'box-opacity-value');

document.getElementById('box-color').addEventListener('input', (e) => {
  document.getElementById('box-color-text').value = e.target.value;
  updateBoxShadow();
});

document.getElementById('box-color-text').addEventListener('input', (e) => {
  document.getElementById('box-color').value = e.target.value;
  updateBoxShadow();
});

document.getElementById('box-inset').addEventListener('change', updateBoxShadow);

document.querySelectorAll('#box-shadow input[type="range"], #box-shadow input[type="number"]').forEach(input => {
  input.addEventListener('input', updateBoxShadow);
});

function updateBoxShadow() {
  const hOffset = document.getElementById('box-h-offset').value;
  const vOffset = document.getElementById('box-v-offset').value;
  const blur = document.getElementById('box-blur').value;
  const spread = document.getElementById('box-spread').value;
  const color = document.getElementById('box-color').value;
  const opacity = document.getElementById('box-opacity').value / 100;
  const inset = document.getElementById('box-inset').checked ? 'inset ' : '';

  const shadow = `${inset}${hOffset}px ${vOffset}px ${blur}px ${spread}px ${hexToRgba(color, opacity)}`;

  const preview = document.getElementById('box-preview');
  preview.innerHTML = `<div style="width: 200px; height: 200px; background: white; border-radius: 8px; box-shadow: ${shadow};"></div>`;

  document.getElementById('box-code').innerHTML = `<span class="selector">.box-shadow</span> {\n    <span class="property">box-shadow</span>: <span class="value">${shadow}</span>;\n}`;
}

// Text Shadow Generator
syncInputs('text-size', 'text-size-value');
syncInputs('text-h-offset', 'text-h-offset-value');
syncInputs('text-v-offset', 'text-v-offset-value');
syncInputs('text-blur', 'text-blur-value');
syncInputs('text-opacity', 'text-opacity-value');

document.getElementById('text-color').addEventListener('input', (e) => {
  document.getElementById('text-color-text').value = e.target.value;
  updateTextShadow();
});

document.getElementById('text-color-text').addEventListener('input', (e) => {
  document.getElementById('text-color').value = e.target.value;
  updateTextShadow();
});

document.getElementById('text-shadow-color').addEventListener('input', (e) => {
  document.getElementById('text-shadow-color-text').value = e.target.value;
  updateTextShadow();
});

document.getElementById('text-shadow-color-text').addEventListener('input', (e) => {
  document.getElementById('text-shadow-color').value = e.target.value;
  updateTextShadow();
});

document.querySelectorAll('#text-shadow input[type="range"], #text-shadow input[type="number"], #text-shadow input[type="text"], #text-shadow select').forEach(input => {
  input.addEventListener('input', updateTextShadow);
});

function updateTextShadow() {
  const content = document.getElementById('text-content').value;
  const size = document.getElementById('text-size').value;
  const weight = document.getElementById('text-weight').value;
  const color = document.getElementById('text-color').value;
  const hOffset = document.getElementById('text-h-offset').value;
  const vOffset = document.getElementById('text-v-offset').value;
  const blur = document.getElementById('text-blur').value;
  const shadowColor = document.getElementById('text-shadow-color').value;
  const opacity = document.getElementById('text-opacity').value / 100;

  const shadow = `${hOffset}px ${vOffset}px ${blur}px ${hexToRgba(shadowColor, opacity)}`;

  const preview = document.getElementById('text-preview');
  preview.innerHTML = `<div class="text-preview" style="color: ${color}; font-size: ${size}px; font-weight: ${weight}; text-shadow: ${shadow};">${content}</div>`;

  document.getElementById('text-code').innerHTML = `<span class="selector">.text-shadow</span> {\n    <span class="property">color</span>: <span class="value">${color}</span>;\n    <span class="property">font-size</span>: <span class="value">${size}px</span>;\n    <span class="property">font-weight</span>: <span class="value">${weight}</span>;\n    <span class="property">text-shadow</span>: <span class="value">${shadow}</span>;\n}`;
}

// Gradient Generator
syncInputs('gradient-angle', 'gradient-angle-value');

document.getElementById('gradient-type').addEventListener('change', updateGradient);
document.querySelectorAll('#gradient input[type="range"], #gradient input[type="number"]').forEach(input => {
  input.addEventListener('input', updateGradient);
});

document.getElementById('color-stops').addEventListener('input', updateGradient);
document.getElementById('color-stops').addEventListener('click', (e) => {
  if (e.target.classList.contains('remove-stop')) {
    e.target.parentElement.remove();
    updateGradient();
  }
});

document.querySelector('.add-stop').addEventListener('click', () => {
  const stopsContainer = document.getElementById('color-stops');
  const newStop = document.createElement('div');
  newStop.className = 'color-stop';
  newStop.innerHTML = `
        <input type="color" class="stop-color" value="#ff0000">
        <input type="number" class="stop-position" min="0" max="100" value="50" style="width: 80px;">
        <span>%</span>
        <button class="remove-stop">Remove</button>
    `;
  stopsContainer.appendChild(newStop);
  updateGradient();
});

function updateGradient() {
  const type = document.getElementById('gradient-type').value;
  const angle = document.getElementById('gradient-angle').value;

  const stops = Array.from(document.querySelectorAll('.color-stop')).map(stop => {
    const color = stop.querySelector('.stop-color').value;
    const position = stop.querySelector('.stop-position').value;
    return `${color} ${position}%`;
  });

  const gradient = type === 'linear'
    ? `linear-gradient(${angle}deg, ${stops.join(', ')})`
    : `radial-gradient(circle, ${stops.join(', ')})`;

  const preview = document.getElementById('gradient-preview');
  preview.innerHTML = `<div style="width: 100%; height: 100%; background: ${gradient};"></div>`;

  document.getElementById('gradient-code').innerHTML = `<span class="selector">.gradient</span> {\n    <span class="property">background</span>: <span class="value">${gradient}</span>;\n}`;

  // Show/hide angle control based on gradient type
  document.getElementById('gradient-angle-group').style.display = type === 'linear' ? 'block' : 'none';
}

// Helper function to convert hex to rgba
function hexToRgba(hex, opacity) {
  const r = parseInt(hex.slice(1, 3), 16);
  const g = parseInt(hex.slice(3, 5), 16);
  const b = parseInt(hex.slice(5, 7), 16);
  return `rgba(${r}, ${g}, ${b}, ${opacity})`;
}

// Initialize all generators
updateSVG();
updateBoxShadow();
updateTextShadow();
updateGradient();

// CSS Filter Generator
syncInputs('filter-blur', 'filter-blur-value');
syncInputs('filter-brightness', 'filter-brightness-value');
syncInputs('filter-contrast', 'filter-contrast-value');
syncInputs('filter-grayscale', 'filter-grayscale-value');
syncInputs('filter-hue', 'filter-hue-value');
syncInputs('filter-invert', 'filter-invert-value');
syncInputs('filter-opacity', 'filter-opacity-value');
syncInputs('filter-saturate', 'filter-saturate-value');
syncInputs('filter-sepia', 'filter-sepia-value');

document.querySelectorAll('#filter input[type="range"], #filter input[type="number"]').forEach(input => {
  input.addEventListener('input', updateFilter);
});

document.getElementById('filter-reset').addEventListener('click', () => {
  document.getElementById('filter-blur').value = 0;
  document.getElementById('filter-blur-value').value = 0;
  document.getElementById('filter-brightness').value = 100;
  document.getElementById('filter-brightness-value').value = 100;
  document.getElementById('filter-contrast').value = 100;
  document.getElementById('filter-contrast-value').value = 100;
  document.getElementById('filter-grayscale').value = 0;
  document.getElementById('filter-grayscale-value').value = 0;
  document.getElementById('filter-hue').value = 0;
  document.getElementById('filter-hue-value').value = 0;
  document.getElementById('filter-invert').value = 0;
  document.getElementById('filter-invert-value').value = 0;
  document.getElementById('filter-opacity').value = 100;
  document.getElementById('filter-opacity-value').value = 100;
  document.getElementById('filter-saturate').value = 100;
  document.getElementById('filter-saturate-value').value = 100;
  document.getElementById('filter-sepia').value = 0;
  document.getElementById('filter-sepia-value').value = 0;
  updateFilter();
});

function updateFilter() {
  const blur = document.getElementById('filter-blur').value;
  const brightness = document.getElementById('filter-brightness').value;
  const contrast = document.getElementById('filter-contrast').value;
  const grayscale = document.getElementById('filter-grayscale').value;
  const hue = document.getElementById('filter-hue').value;
  const invert = document.getElementById('filter-invert').value;
  const opacity = document.getElementById('filter-opacity').value;
  const saturate = document.getElementById('filter-saturate').value;
  const sepia = document.getElementById('filter-sepia').value;

  const filters = [];
  if (blur != 0) filters.push(`blur(${blur}px)`);
  if (brightness != 100) filters.push(`brightness(${brightness}%)`);
  if (contrast != 100) filters.push(`contrast(${contrast}%)`);
  if (grayscale != 0) filters.push(`grayscale(${grayscale}%)`);
  if (hue != 0) filters.push(`hue-rotate(${hue}deg)`);
  if (invert != 0) filters.push(`invert(${invert}%)`);
  if (opacity != 100) filters.push(`opacity(${opacity}%)`);
  if (saturate != 100) filters.push(`saturate(${saturate}%)`);
  if (sepia != 0) filters.push(`sepia(${sepia}%)`);

  const filterString = filters.length > 0 ? filters.join(' ') : 'none';

  const preview = document.getElementById('filter-preview');
  preview.innerHTML = `<div class="filter-demo-box" style="filter: ${filterString};">
    <div class="filter-demo-gradient"></div>
    <span>Filter Preview</span>
  </div>`;

  document.getElementById('filter-code').innerHTML = `<span class="selector">.filtered</span> {
    <span class="property">filter</span>: <span class="value">${filterString}</span>;
}`;
}

updateFilter();

// Animation Generator
let currentAnimation = 'fade';

const animationKeyframes = {
  fade: {
    keyframes: `@keyframes fade {
    from { opacity: 0; }
    to { opacity: 1; }
}`,
    displayKeyframes: `<span class="property">from</span> { <span class="value">opacity: 0;</span> }
    <span class="property">to</span> { <span class="value">opacity: 1;</span> }`
  },
  slideIn: {
    keyframes: `@keyframes slideIn {
    from { transform: translateX(-100px); opacity: 0; }
    to { transform: translateX(0); opacity: 1; }
}`,
    displayKeyframes: `<span class="property">from</span> { <span class="value">transform: translateX(-100px); opacity: 0;</span> }
    <span class="property">to</span> { <span class="value">transform: translateX(0); opacity: 1;</span> }`
  },
  bounce: {
    keyframes: `@keyframes bounce {
    0%, 20%, 50%, 80%, 100% { transform: translateY(0); }
    40% { transform: translateY(-30px); }
    60% { transform: translateY(-15px); }
}`,
    displayKeyframes: `<span class="property">0%, 20%, 50%, 80%, 100%</span> { <span class="value">transform: translateY(0);</span> }
    <span class="property">40%</span> { <span class="value">transform: translateY(-30px);</span> }
    <span class="property">60%</span> { <span class="value">transform: translateY(-15px);</span> }`
  },
  pulse: {
    keyframes: `@keyframes pulse {
    0% { transform: scale(1); }
    50% { transform: scale(1.1); }
    100% { transform: scale(1); }
}`,
    displayKeyframes: `<span class="property">0%</span> { <span class="value">transform: scale(1);</span> }
    <span class="property">50%</span> { <span class="value">transform: scale(1.1);</span> }
    <span class="property">100%</span> { <span class="value">transform: scale(1);</span> }`
  },
  shake: {
    keyframes: `@keyframes shake {
    0%, 100% { transform: translateX(0); }
    10%, 30%, 50%, 70%, 90% { transform: translateX(-10px); }
    20%, 40%, 60%, 80% { transform: translateX(10px); }
}`,
    displayKeyframes: `<span class="property">0%, 100%</span> { <span class="value">transform: translateX(0);</span> }
    <span class="property">10%, 30%, 50%, 70%, 90%</span> { <span class="value">transform: translateX(-10px);</span> }
    <span class="property">20%, 40%, 60%, 80%</span> { <span class="value">transform: translateX(10px);</span> }`
  },
  rotate: {
    keyframes: `@keyframes rotate {
    from { transform: rotate(0deg); }
    to { transform: rotate(360deg); }
}`,
    displayKeyframes: `<span class="property">from</span> { <span class="value">transform: rotate(0deg);</span> }
    <span class="property">to</span> { <span class="value">transform: rotate(360deg);</span> }`
  },
  scale: {
    keyframes: `@keyframes scale {
    0% { transform: scale(0); }
    100% { transform: scale(1); }
}`,
    displayKeyframes: `<span class="property">0%</span> { <span class="value">transform: scale(0);</span> }
    <span class="property">100%</span> { <span class="value">transform: scale(1);</span> }`
  },
  flip: {
    keyframes: `@keyframes flip {
    from { transform: perspective(400px) rotateY(0); }
    to { transform: perspective(400px) rotateY(360deg); }
}`,
    displayKeyframes: `<span class="property">from</span> { <span class="value">transform: perspective(400px) rotateY(0);</span> }
    <span class="property">to</span> { <span class="value">transform: perspective(400px) rotateY(360deg);</span> }`
  }
};

document.querySelectorAll('.animation-option').forEach(option => {
  option.addEventListener('click', () => {
    document.querySelectorAll('.animation-option').forEach(o => o.classList.remove('selected'));
    option.classList.add('selected');
    currentAnimation = option.getAttribute('data-animation');
    updateAnimation();
  });
});

syncInputs('anim-duration', 'anim-duration-value');
syncInputs('anim-delay', 'anim-delay-value');
syncInputs('anim-iteration', 'anim-iteration-value');

document.querySelectorAll('#animation input[type="range"], #animation input[type="number"], #animation select').forEach(input => {
  input.addEventListener('input', updateAnimation);
});

document.getElementById('anim-infinite').addEventListener('change', updateAnimation);

document.getElementById('anim-play').addEventListener('click', () => {
  const box = document.getElementById('animation-box');
  box.style.animation = 'none';
  box.offsetHeight; // Trigger reflow
  playAnimation();
});

function playAnimation() {
  const duration = document.getElementById('anim-duration').value;
  const timing = document.getElementById('anim-timing').value;
  const delay = document.getElementById('anim-delay').value;
  const iteration = document.getElementById('anim-infinite').checked ? 'infinite' : document.getElementById('anim-iteration').value;
  const direction = document.getElementById('anim-direction').value;
  const fill = document.getElementById('anim-fill').value;

  const box = document.getElementById('animation-box');
  box.style.animation = `${currentAnimation} ${duration}s ${timing} ${delay}s ${iteration} ${direction} ${fill}`;
}

function updateAnimation() {
  const duration = document.getElementById('anim-duration').value;
  const timing = document.getElementById('anim-timing').value;
  const delay = document.getElementById('anim-delay').value;
  const iteration = document.getElementById('anim-infinite').checked ? 'infinite' : document.getElementById('anim-iteration').value;
  const direction = document.getElementById('anim-direction').value;
  const fill = document.getElementById('anim-fill').value;

  const animData = animationKeyframes[currentAnimation];
  const animationValue = `${currentAnimation} ${duration}s ${timing} ${delay}s ${iteration} ${direction} ${fill}`;

  document.getElementById('animation-code').innerHTML = `<span class="comment">/* Keyframes */</span>
<span class="selector">@keyframes ${currentAnimation}</span> {
    ${animData.displayKeyframes}
}

<span class="comment">/* Animation */</span>
<span class="selector">.animated</span> {
    <span class="property">animation</span>: <span class="value">${animationValue}</span>;
}`;
}

updateAnimation();

// Border Radius Generator
syncInputs('radius-all', 'radius-all-value');
syncInputs('radius-tl', 'radius-tl-value');
syncInputs('radius-tr', 'radius-tr-value');
syncInputs('radius-br', 'radius-br-value');
syncInputs('radius-bl', 'radius-bl-value');
syncInputs('radius-size', 'radius-size-value');

// Linked mode toggle
document.getElementById('radius-linked').addEventListener('change', (e) => {
  const isLinked = e.target.checked;
  document.getElementById('radius-all-group').parentElement.style.display = isLinked ? 'block' : 'none';
  document.getElementById('radius-individual').style.display = isLinked ? 'none' : 'block';

  if (isLinked) {
    // Sync all corners to the "all" value
    const allValue = document.getElementById('radius-all').value;
    ['tl', 'tr', 'br', 'bl'].forEach(corner => {
      document.getElementById(`radius-${corner}`).value = allValue;
      document.getElementById(`radius-${corner}-value`).value = allValue;
    });
  }
  updateBorderRadius();
});

// Update individual corners when "all" changes
document.getElementById('radius-all').addEventListener('input', () => {
  const value = document.getElementById('radius-all').value;
  ['tl', 'tr', 'br', 'bl'].forEach(corner => {
    document.getElementById(`radius-${corner}`).value = value;
    document.getElementById(`radius-${corner}-value`).value = value;
  });
  updateBorderRadius();
});

document.getElementById('radius-all-value').addEventListener('input', () => {
  const value = document.getElementById('radius-all-value').value;
  document.getElementById('radius-all').value = value;
  ['tl', 'tr', 'br', 'bl'].forEach(corner => {
    document.getElementById(`radius-${corner}`).value = value;
    document.getElementById(`radius-${corner}-value`).value = value;
  });
  updateBorderRadius();
});

// Individual corner listeners
['tl', 'tr', 'br', 'bl'].forEach(corner => {
  document.getElementById(`radius-${corner}`).addEventListener('input', updateBorderRadius);
  document.getElementById(`radius-${corner}-value`).addEventListener('input', updateBorderRadius);
});

// Size and color listeners
document.getElementById('radius-size').addEventListener('input', updateBorderRadius);
document.getElementById('radius-size-value').addEventListener('input', updateBorderRadius);

document.getElementById('radius-bg-color').addEventListener('input', (e) => {
  document.getElementById('radius-bg-color-text').value = e.target.value;
  updateBorderRadius();
});

document.getElementById('radius-bg-color-text').addEventListener('input', (e) => {
  document.getElementById('radius-bg-color').value = e.target.value;
  updateBorderRadius();
});

// Presets
const radiusPresets = {
  none: {tl: 0, tr: 0, br: 0, bl: 0},
  rounded: {tl: 20, tr: 20, br: 20, bl: 20},
  pill: {tl: 100, tr: 100, br: 100, bl: 100},
  circle: {tl: 150, tr: 150, br: 150, bl: 150},
  blob: {tl: 60, tr: 30, br: 70, bl: 40},
  leaf: {tl: 100, tr: 0, br: 100, bl: 0}
};

document.querySelectorAll('.preset-btn').forEach(btn => {
  btn.addEventListener('click', () => {
    document.querySelectorAll('.preset-btn').forEach(b => b.classList.remove('active'));
    btn.classList.add('active');

    const preset = btn.getAttribute('data-preset');
    const values = radiusPresets[preset];

    // Unlink corners for custom presets
    if (preset === 'blob' || preset === 'leaf') {
      document.getElementById('radius-linked').checked = false;
      document.getElementById('radius-all-group').parentElement.style.display = 'none';
      document.getElementById('radius-individual').style.display = 'block';
    } else {
      document.getElementById('radius-linked').checked = true;
      document.getElementById('radius-all-group').parentElement.style.display = 'block';
      document.getElementById('radius-individual').style.display = 'none';
      document.getElementById('radius-all').value = values.tl;
      document.getElementById('radius-all-value').value = values.tl;
    }

    ['tl', 'tr', 'br', 'bl'].forEach(corner => {
      document.getElementById(`radius-${corner}`).value = values[corner];
      document.getElementById(`radius-${corner}-value`).value = values[corner];
    });

    updateBorderRadius();
  });
});

function updateBorderRadius() {
  const tl = document.getElementById('radius-tl').value;
  const tr = document.getElementById('radius-tr').value;
  const br = document.getElementById('radius-br').value;
  const bl = document.getElementById('radius-bl').value;
  const size = document.getElementById('radius-size').value;
  const bgColor = document.getElementById('radius-bg-color').value;

  const isLinked = document.getElementById('radius-linked').checked;
  let borderRadius, borderRadiusCode;

  if (isLinked || (tl === tr && tr === br && br === bl)) {
    borderRadius = `${tl}px`;
    borderRadiusCode = `${tl}px`;
  } else {
    borderRadius = `${tl}px ${tr}px ${br}px ${bl}px`;
    borderRadiusCode = `${tl}px ${tr}px ${br}px ${bl}px`;
  }

  const box = document.getElementById('radius-box');
  box.style.borderRadius = borderRadius;
  box.style.width = `${size}px`;
  box.style.height = `${size}px`;
  box.style.background = bgColor;

  document.getElementById('radius-code').innerHTML = `<span class="selector">.rounded-box</span> {
    <span class="property">border-radius</span>: <span class="value">${borderRadiusCode}</span>;
}`;
}

updateBorderRadius();

// Flexbox Generator
syncInputs('flex-gap', 'flex-gap-value');
syncInputs('flex-items', 'flex-items-value');

document.querySelectorAll('#flexbox select, #flexbox input[type="range"], #flexbox input[type="number"]').forEach(input => {
  input.addEventListener('input', updateFlexbox);
  input.addEventListener('change', updateFlexbox);
});

function updateFlexbox() {
  const direction = document.getElementById('flex-direction').value;
  const justify = document.getElementById('flex-justify').value;
  const align = document.getElementById('flex-align').value;
  const wrap = document.getElementById('flex-wrap').value;
  const gap = document.getElementById('flex-gap').value;
  const itemCount = document.getElementById('flex-items').value;

  const container = document.getElementById('flex-container');
  container.style.flexDirection = direction;
  container.style.justifyContent = justify;
  container.style.alignItems = align;
  container.style.flexWrap = wrap;
  container.style.gap = `${gap}px`;

  // Update number of items
  const currentItems = container.querySelectorAll('.flex-item').length;
  if (itemCount > currentItems) {
    for (let i = currentItems; i < itemCount; i++) {
      const item = document.createElement('div');
      item.className = 'flex-item';
      item.textContent = i + 1;
      container.appendChild(item);
    }
  } else if (itemCount < currentItems) {
    for (let i = currentItems; i > itemCount; i--) {
      container.removeChild(container.lastChild);
    }
  }

  document.getElementById('flexbox-code').innerHTML = `<span class="selector">.flex-container</span> {
    <span class="property">display</span>: <span class="value">flex</span>;
    <span class="property">flex-direction</span>: <span class="value">${direction}</span>;
    <span class="property">justify-content</span>: <span class="value">${justify}</span>;
    <span class="property">align-items</span>: <span class="value">${align}</span>;
    <span class="property">flex-wrap</span>: <span class="value">${wrap}</span>;
    <span class="property">gap</span>: <span class="value">${gap}px</span>;
}`;
}

updateFlexbox();

// CSS Grid Generator
syncInputs('grid-cols', 'grid-cols-value');
syncInputs('grid-rows', 'grid-rows-value');
syncInputs('grid-col-gap', 'grid-col-gap-value');
syncInputs('grid-row-gap', 'grid-row-gap-value');

document.querySelectorAll('#grid select, #grid input[type="range"], #grid input[type="number"]').forEach(input => {
  input.addEventListener('input', updateGrid);
  input.addEventListener('change', updateGrid);
});

function updateGrid() {
  const cols = document.getElementById('grid-cols').value;
  const rows = document.getElementById('grid-rows').value;
  const colGap = document.getElementById('grid-col-gap').value;
  const rowGap = document.getElementById('grid-row-gap').value;
  const justifyItems = document.getElementById('grid-justify-items').value;
  const alignItems = document.getElementById('grid-align-items').value;
  const colSize = document.getElementById('grid-col-size').value;

  const container = document.getElementById('grid-container');
  const colTemplate = `repeat(${cols}, ${colSize})`;
  const rowTemplate = `repeat(${rows}, 1fr)`;

  container.style.gridTemplateColumns = colTemplate;
  container.style.gridTemplateRows = rowTemplate;
  container.style.columnGap = `${colGap}px`;
  container.style.rowGap = `${rowGap}px`;
  container.style.justifyItems = justifyItems;
  container.style.alignItems = alignItems;

  // Update number of items to match cols * rows
  const totalItems = cols * rows;
  const currentItems = container.querySelectorAll('.grid-item').length;

  if (totalItems > currentItems) {
    for (let i = currentItems; i < totalItems; i++) {
      const item = document.createElement('div');
      item.className = 'grid-item';
      item.textContent = i + 1;
      container.appendChild(item);
    }
  } else if (totalItems < currentItems) {
    for (let i = currentItems; i > totalItems; i--) {
      container.removeChild(container.lastChild);
    }
  }

  document.getElementById('grid-code').innerHTML = `<span class="selector">.grid-container</span> {
    <span class="property">display</span>: <span class="value">grid</span>;
    <span class="property">grid-template-columns</span>: <span class="value">${colTemplate}</span>;
    <span class="property">grid-template-rows</span>: <span class="value">${rowTemplate}</span>;
    <span class="property">column-gap</span>: <span class="value">${colGap}px</span>;
    <span class="property">row-gap</span>: <span class="value">${rowGap}px</span>;
    <span class="property">justify-items</span>: <span class="value">${justifyItems}</span>;
    <span class="property">align-items</span>: <span class="value">${alignItems}</span>;
}`;
}

updateGrid();