319 lines
65beb53 samthecodingguy Jan 29, 2026
'use client';
import React, { useState } from 'react';
import { Palette, Sparkles, RotateCcw } from 'lucide-react';
import { HexColorPicker } from 'react-colorful';
import { useEditorStore } from '@/lib/store/editor-store';
import type { GradientConfig } from '@/types';
// Mesh gradient presets - beautiful gradient combinations
const meshGradientPresets = [
  {
    id: 'sunset',
    name: 'Sunset',
    colors: ['#FF6B6B', '#FFA07A', '#FFD700', '#FF8C00'],
    css: 'radial-gradient(at 40% 20%, #FF6B6B 0px, transparent 50%), radial-gradient(at 80% 0%, #FFA07A 0px, transparent 50%), radial-gradient(at 0% 50%, #FFD700 0px, transparent 50%), radial-gradient(at 80% 50%, #FF8C00 0px, transparent 50%), radial-gradient(at 0% 100%, #FF6B6B 0px, transparent 50%), radial-gradient(at 80% 100%, #FFA07A 0px, transparent 50%)',
    bgColor: '#FF8C00',
  },
  {
    id: 'ocean',
    name: 'Ocean',
    colors: ['#0077B6', '#00B4D8', '#90E0EF', '#CAF0F8'],
    css: 'radial-gradient(at 0% 0%, #0077B6 0px, transparent 50%), radial-gradient(at 100% 0%, #00B4D8 0px, transparent 50%), radial-gradient(at 100% 100%, #90E0EF 0px, transparent 50%), radial-gradient(at 0% 100%, #CAF0F8 0px, transparent 50%)',
    bgColor: '#023E8A',
  },
  {
    id: 'aurora',
    name: 'Aurora',
    colors: ['#9B5DE5', '#00F5D4', '#00BBF9', '#F15BB5'],
    css: 'radial-gradient(at 20% 20%, #9B5DE5 0px, transparent 50%), radial-gradient(at 80% 20%, #00F5D4 0px, transparent 50%), radial-gradient(at 20% 80%, #00BBF9 0px, transparent 50%), radial-gradient(at 80% 80%, #F15BB5 0px, transparent 50%)',
    bgColor: '#1A1A2E',
  },
  {
    id: 'midnight',
    name: 'Midnight',
    colors: ['#1A1A2E', '#16213E', '#0F3460', '#533483'],
    css: 'radial-gradient(at 30% 30%, #533483 0px, transparent 50%), radial-gradient(at 70% 20%, #0F3460 0px, transparent 50%), radial-gradient(at 20% 80%, #16213E 0px, transparent 50%), radial-gradient(at 90% 70%, #1A1A2E 0px, transparent 50%)',
    bgColor: '#0D0D1A',
  },
  {
    id: 'candy',
    name: 'Candy',
    colors: ['#FF69B4', '#FFB6C1', '#DDA0DD', '#E6E6FA'],
    css: 'radial-gradient(at 10% 10%, #FF69B4 0px, transparent 50%), radial-gradient(at 90% 10%, #FFB6C1 0px, transparent 50%), radial-gradient(at 50% 50%, #DDA0DD 0px, transparent 50%), radial-gradient(at 10% 90%, #E6E6FA 0px, transparent 50%), radial-gradient(at 90% 90%, #FF69B4 0px, transparent 50%)',
    bgColor: '#FFB6C1',
  },
  {
    id: 'forest',
    name: 'Forest',
    colors: ['#2D5016', '#4A7023', '#6B8E23', '#8FBC8F'],
    css: 'radial-gradient(at 0% 0%, #2D5016 0px, transparent 50%), radial-gradient(at 100% 0%, #4A7023 0px, transparent 50%), radial-gradient(at 50% 50%, #6B8E23 0px, transparent 50%), radial-gradient(at 0% 100%, #8FBC8F 0px, transparent 50%)',
    bgColor: '#1A3009',
  },
  {
    id: 'cosmic',
    name: 'Cosmic',
    colors: ['#2E1065', '#4C1D95', '#7C3AED', '#A78BFA'],
    css: 'radial-gradient(at 25% 25%, #7C3AED 0px, transparent 50%), radial-gradient(at 75% 25%, #A78BFA 0px, transparent 50%), radial-gradient(at 25% 75%, #4C1D95 0px, transparent 50%), radial-gradient(at 75% 75%, #2E1065 0px, transparent 50%)',
    bgColor: '#1E1033',
  },
  {
    id: 'fire',
    name: 'Fire',
    colors: ['#DC2626', '#EA580C', '#F59E0B', '#FBBF24'],
    css: 'radial-gradient(at 30% 20%, #DC2626 0px, transparent 50%), radial-gradient(at 70% 30%, #EA580C 0px, transparent 50%), radial-gradient(at 40% 70%, #F59E0B 0px, transparent 50%), radial-gradient(at 80% 80%, #FBBF24 0px, transparent 50%)',
    bgColor: '#7C2D12',
  },
  {
    id: 'mint',
    name: 'Mint',
    colors: ['#10B981', '#34D399', '#6EE7B7', '#A7F3D0'],
    css: 'radial-gradient(at 20% 20%, #10B981 0px, transparent 50%), radial-gradient(at 80% 30%, #34D399 0px, transparent 50%), radial-gradient(at 30% 80%, #6EE7B7 0px, transparent 50%), radial-gradient(at 70% 70%, #A7F3D0 0px, transparent 50%)',
    bgColor: '#064E3B',
  },
  {
    id: 'noir',
    name: 'Noir',
    colors: ['#18181B', '#27272A', '#3F3F46', '#52525B'],
    css: 'radial-gradient(at 0% 0%, #52525B 0px, transparent 50%), radial-gradient(at 100% 0%, #3F3F46 0px, transparent 50%), radial-gradient(at 50% 50%, #27272A 0px, transparent 50%), radial-gradient(at 100% 100%, #18181B 0px, transparent 50%)',
    bgColor: '#09090B',
  },
];
// Linear gradient presets
const linearGradientPresets = [
  {
    id: 'blue-purple',
    name: 'Blue Purple',
    gradient: { type: 'linear' as const, angle: 135, stops: [{ offset: 0, color: '#667eea' }, { offset: 1, color: '#764ba2' }] },
  },
  {
    id: 'sunset-linear',
    name: 'Sunset',
    gradient: { type: 'linear' as const, angle: 90, stops: [{ offset: 0, color: '#f093fb' }, { offset: 1, color: '#f5576c' }] },
  },
  {
    id: 'ocean-linear',
    name: 'Ocean',
    gradient: { type: 'linear' as const, angle: 135, stops: [{ offset: 0, color: '#4facfe' }, { offset: 1, color: '#00f2fe' }] },
  },
  {
    id: 'forest-linear',
    name: 'Forest',
    gradient: { type: 'linear' as const, angle: 135, stops: [{ offset: 0, color: '#11998e' }, { offset: 1, color: '#38ef7d' }] },
  },
  {
    id: 'warm',
    name: 'Warm',
    gradient: { type: 'linear' as const, angle: 135, stops: [{ offset: 0, color: '#f5af19' }, { offset: 1, color: '#f12711' }] },
  },
  {
    id: 'cool',
    name: 'Cool',
    gradient: { type: 'linear' as const, angle: 135, stops: [{ offset: 0, color: '#2193b0' }, { offset: 1, color: '#6dd5ed' }] },
  },
];
export function GradientPanel() {
  const { canvas, setBackgroundColor } = useEditorStore();
  const [activeTab, setActiveTab] = useState<'mesh' | 'linear' | 'solid'>('mesh');
  const [showColorPicker, setShowColorPicker] = useState(false);
  const [solidColor, setSolidColor] = useState('#1a1a2e');
  const handleMeshGradientSelect = (preset: typeof meshGradientPresets[0]) => {
    // For mesh gradients, we store them as a special gradient config
    // The canvas renderer will need to handle this specially
    setBackgroundColor({
      type: 'radial',
      stops: preset.colors.map((color, i) => ({
        offset: i / (preset.colors.length - 1),
        color,
      })),
    } as GradientConfig);
  };
  const handleLinearGradientSelect = (preset: typeof linearGradientPresets[0]) => {
    setBackgroundColor(preset.gradient);
  };
  const handleSolidColorSelect = (color: string) => {
    setSolidColor(color);
    setBackgroundColor(color);
  };
  return (
    <div className="p-4">
      <h2 className="text-lg font-semibold text-white mb-4">Background</h2>
      {/* Tab selector */}
      <div className="flex gap-1 mb-4 p-1 bg-neutral-800 rounded-lg">
        {[
          { id: 'mesh', label: 'Mesh', icon: Sparkles },
          { id: 'linear', label: 'Linear', icon: Palette },
          { id: 'solid', label: 'Solid', icon: null },
        ].map(({ id, label, icon: Icon }) => (
          <button
            key={id}
            onClick={() => setActiveTab(id as typeof activeTab)}
            className={`
              flex-1 py-2 px-3 rounded-md text-sm font-medium transition-colors
              flex items-center justify-center gap-1.5
              ${activeTab === id
                ? 'bg-neutral-700 text-white'
                : 'text-neutral-400 hover:text-white'
              }
            `}
          >
            {Icon && <Icon className="w-3.5 h-3.5" />}
            {label}
          </button>
        ))}
      </div>
      {/* Mesh gradients */}
      {activeTab === 'mesh' && (
        <div className="space-y-3">
          <p className="text-xs text-neutral-500">
            Beautiful multi-color mesh gradients for striking backgrounds
          </p>
          <div className="grid grid-cols-2 gap-2">
            {meshGradientPresets.map((preset) => (
              <button
                key={preset.id}
                onClick={() => handleMeshGradientSelect(preset)}
                className="
                  aspect-[4/3] rounded-lg overflow-hidden
                  border-2 border-transparent hover:border-indigo-500
                  transition-colors relative group
                "
              >
                <div
                  className="absolute inset-0"
                  style={{
                    background: preset.bgColor,
                  }}
                />
                <div
                  className="absolute inset-0"
                  style={{
                    backgroundImage: preset.css,
                  }}
                />
                <div className="absolute inset-x-0 bottom-0 p-2 bg-gradient-to-t from-black/60 to-transparent">
                  <span className="text-xs text-white font-medium">{preset.name}</span>
                </div>
              </button>
            ))}
          </div>
        </div>
      )}
      {/* Linear gradients */}
      {activeTab === 'linear' && (
        <div className="space-y-3">
          <p className="text-xs text-neutral-500">
            Classic linear gradients with smooth color transitions
          </p>
          <div className="grid grid-cols-2 gap-2">
            {linearGradientPresets.map((preset) => (
              <button
                key={preset.id}
                onClick={() => handleLinearGradientSelect(preset)}
                className="
                  aspect-[4/3] rounded-lg overflow-hidden
                  border-2 border-transparent hover:border-indigo-500
                  transition-colors relative group
                "
                style={{
                  background: `linear-gradient(${preset.gradient.angle}deg, ${preset.gradient.stops.map(s => s.color).join(', ')})`,
                }}
              >
                <div className="absolute inset-x-0 bottom-0 p-2 bg-gradient-to-t from-black/60 to-transparent">
                  <span className="text-xs text-white font-medium">{preset.name}</span>
                </div>
              </button>
            ))}
          </div>
        </div>
      )}
      {/* Solid colors */}
      {activeTab === 'solid' && (
        <div className="space-y-4">
          <p className="text-xs text-neutral-500">
            Pick a solid background color
          </p>
          {/* Quick colors */}
          <div className="flex flex-wrap gap-2">
            {[
              '#000000', '#1a1a2e', '#16213e', '#0f3460',
              '#ffffff', '#f8f9fa', '#e9ecef', '#dee2e6',
              '#6366f1', '#8b5cf6', '#ec4899', '#f43f5e',
              '#10b981', '#14b8a6', '#06b6d4', '#3b82f6',
            ].map((color) => (
              <button
                key={color}
                onClick={() => handleSolidColorSelect(color)}
                className="
                  w-8 h-8 rounded-lg border-2 transition-all
                  hover:scale-110
                "
                style={{
                  backgroundColor: color,
                  borderColor: solidColor === color ? '#6366f1' : 'rgba(255,255,255,0.1)',
                }}
              />
            ))}
          </div>
          {/* Color picker */}
          <div>
            <button
              onClick={() => setShowColorPicker(!showColorPicker)}
              className="
                w-full px-3 py-2 rounded-lg
                bg-neutral-800 border border-neutral-700
                flex items-center gap-3 hover:border-neutral-600 transition-colors
              "
            >
              <div
                className="w-6 h-6 rounded border border-neutral-600"
                style={{ backgroundColor: solidColor }}
              />
              <span className="text-white font-mono text-sm">{solidColor.toUpperCase()}</span>
            </button>
            {showColorPicker && (
              <div className="mt-2 p-3 bg-neutral-800 rounded-lg border border-neutral-700">
                <HexColorPicker color={solidColor} onChange={handleSolidColorSelect} />
                <input
                  type="text"
                  value={solidColor}
                  onChange={(e) => handleSolidColorSelect(e.target.value)}
                  className="
                    w-full mt-3 px-3 py-2 rounded
                    bg-neutral-900 border border-neutral-700
                    text-white text-sm font-mono
                    focus:outline-none focus:border-indigo-500
                  "
                />
              </div>
            )}
          </div>
        </div>
      )}
      {/* Current background info */}
      <div className="mt-6 p-3 rounded-lg bg-neutral-800/50 border border-neutral-700/50">
        <h3 className="text-sm font-medium text-white mb-2">Tips</h3>
        <ul className="text-xs text-neutral-400 space-y-1">
          <li>• Mesh gradients create depth and visual interest</li>
          <li>• Use dark backgrounds for app screenshots</li>
          <li>• Match gradients to your brand colors</li>
        </ul>
      </div>
    </div>
  );
}