Files

126 lines
3.3 KiB
TypeScript
Raw Permalink Normal View History

feat: add comprehensive export functionality for palettes Implement full palette export system with multiple formats: **Export Utilities (lib/utils/export.ts):** - exportAsCSS() - CSS custom properties (:root variables) - exportAsSCSS() - SCSS variables ($color-name format) - exportAsTailwind() - Tailwind config module export - exportAsJSON() - Structured JSON with color objects - exportAsJavaScript() - JavaScript array of colors - downloadAsFile() - Browser download helper - ExportColor interface for typed exports **ExportMenu Component:** - Format selector dropdown (5 formats) - Live preview of export code - Syntax-highlighted code display - Copy to clipboard button - Download as file button - Success feedback (Check icon + toast) - Responsive layout - Conditional rendering (empty state) **Export Formats:** 1. CSS Variables: ```css :root { --color-1: #ff0099; --color-2: #0099ff; } ``` 2. SCSS Variables: ```scss $color-1: #ff0099; $color-2: #0099ff; ``` 3. Tailwind Config: ```js module.exports = { theme: { extend: { colors: { 'color-1': '#ff0099', }, }, }, }; ``` 4. JSON: ```json { "colors": [ { "name": "color-1", "hex": "#ff0099" } ] } ``` 5. JavaScript Array: ```js const colors = ['#ff0099', '#0099ff']; ``` **Integration:** - Added to Gradient Creator page - Added to Distinct Colors page - Conditional rendering (shows only when colors exist) - Proper spacing and layout **Features:** - Real-time preview of generated code - Copy with toast notification - Download with proper file extensions - Format-specific filenames - Clean, readable output - Proper indentation and formatting **User Experience:** - Select format from dropdown - See live preview immediately - One-click copy or download - Success feedback - Professional code formatting Build successful! Export functionality working on all palette pages. Next: Keyboard shortcuts and URL sharing. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-07 12:19:52 +01:00
'use client';
import { Button } from '@/components/ui/button';
import { Select } from '@/components/ui/select';
import { useState } from 'react';
import { Download, Copy, Check } from 'lucide-react';
import { toast } from 'sonner';
import {
exportAsCSS,
exportAsSCSS,
exportAsTailwind,
exportAsJSON,
exportAsJavaScript,
downloadAsFile,
type ExportColor,
} from '@/lib/utils/export';
interface ExportMenuProps {
colors: string[];
className?: string;
}
type ExportFormat = 'css' | 'scss' | 'tailwind' | 'json' | 'javascript';
export function ExportMenu({ colors, className }: ExportMenuProps) {
const [format, setFormat] = useState<ExportFormat>('css');
const [copied, setCopied] = useState(false);
const exportColors: ExportColor[] = colors.map((hex) => ({ hex }));
const getExportContent = (): string => {
switch (format) {
case 'css':
return exportAsCSS(exportColors);
case 'scss':
return exportAsSCSS(exportColors);
case 'tailwind':
return exportAsTailwind(exportColors);
case 'json':
return exportAsJSON(exportColors);
case 'javascript':
return exportAsJavaScript(exportColors);
}
};
const getFileExtension = (): string => {
switch (format) {
case 'css':
return 'css';
case 'scss':
return 'scss';
case 'tailwind':
return 'js';
case 'json':
return 'json';
case 'javascript':
return 'js';
}
};
const handleCopy = () => {
const content = getExportContent();
navigator.clipboard.writeText(content);
setCopied(true);
toast.success('Copied to clipboard!');
setTimeout(() => setCopied(false), 2000);
};
const handleDownload = () => {
const content = getExportContent();
const extension = getFileExtension();
downloadAsFile(content, `palette.${extension}`, 'text/plain');
toast.success('Downloaded!');
};
if (colors.length === 0) {
return null;
}
return (
<div className={className}>
<div className="space-y-4">
<div>
<h3 className="text-sm font-medium mb-2">Export Palette</h3>
<Select
value={format}
onChange={(e) => setFormat(e.target.value as ExportFormat)}
>
<option value="css">CSS Variables</option>
<option value="scss">SCSS Variables</option>
<option value="tailwind">Tailwind Config</option>
<option value="json">JSON</option>
<option value="javascript">JavaScript Array</option>
</Select>
</div>
<div className="p-4 bg-muted rounded-lg">
<pre className="text-xs overflow-x-auto">
<code>{getExportContent()}</code>
</pre>
</div>
<div className="flex gap-2">
<Button onClick={handleCopy} variant="outline" className="flex-1">
{copied ? (
<>
<Check className="h-4 w-4 mr-2" />
Copied!
</>
) : (
<>
<Copy className="h-4 w-4 mr-2" />
Copy
</>
)}
</Button>
<Button onClick={handleDownload} variant="default" className="flex-1">
<Download className="h-4 w-4 mr-2" />
Download
</Button>
</div>
</div>
</div>
);
}