'use client'; import * as React from 'react'; import { toPng } from 'html-to-image'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Skeleton } from '@/components/ui/skeleton'; import { Badge } from '@/components/ui/badge'; import { ToggleGroup, ToggleGroupItem } from '@/components/ui/toggle-group'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/components/ui/select'; import { Tooltip, TooltipContent, TooltipTrigger, } from '@/components/ui/tooltip'; import { Empty, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle, } from "@/components/ui/empty" import { Copy, Download, Share2, Image as ImageIcon, AlignLeft, AlignCenter, AlignRight, Type, MessageSquareCode } from 'lucide-react'; import { cn } from '@/lib/utils/cn'; import { toast } from 'sonner'; export type CommentStyle = 'none' | '//' | '#' | '--' | ';' | '/* */' | '' | '"""'; const COMMENT_STYLES: { value: CommentStyle; label: string }[] = [ { value: 'none', label: 'None' }, { value: '//', label: '// C, JS, Go' }, { value: '#', label: '# Python, Shell' }, { value: '--', label: '-- SQL, Lua' }, { value: ';', label: '; Lisp, ASM' }, { value: '/* */', label: '/* */ Block' }, { value: '', label: ' HTML' }, { value: '"""', label: '""" Docstring' }, ]; function applyCommentStyle(text: string, style: CommentStyle): string { if (style === 'none' || !text) return text; const lines = text.split('\n'); switch (style) { case '//': case '#': case '--': case ';': return lines.map(line => `${style} ${line}`).join('\n'); case '/* */': return ['/*', ...lines.map(line => ` * ${line}`), ' */'].join('\n'); case '': return [''].join('\n'); case '"""': return ['"""', ...lines, '"""'].join('\n'); } } export interface FontPreviewProps { text: string; font?: string; isLoading?: boolean; onCopy?: () => void; onDownload?: () => void; onShare?: () => void; onCommentedTextChange?: (commentedText: string) => void; className?: string; } type TextAlign = 'left' | 'center' | 'right'; export function FontPreview({ text, font, isLoading, onCopy, onDownload, onShare, onCommentedTextChange, className }: FontPreviewProps) { const previewRef = React.useRef(null); const [textAlign, setTextAlign] = React.useState('left'); const [fontSize, setFontSize] = React.useState<'xs' | 'sm' | 'base'>('sm'); const [commentStyle, setCommentStyle] = React.useState('none'); const commentedText = React.useMemo(() => applyCommentStyle(text, commentStyle), [text, commentStyle]); const lineCount = commentedText ? commentedText.split('\n').length : 0; const charCount = commentedText ? commentedText.length : 0; React.useEffect(() => { onCommentedTextChange?.(commentedText); }, [commentedText, onCommentedTextChange]); const handleExportPNG = async () => { if (!previewRef.current || !text) return; try { const dataUrl = await toPng(previewRef.current, { backgroundColor: getComputedStyle(previewRef.current).backgroundColor, pixelRatio: 2, }); const link = document.createElement('a'); link.download = `ascii-${font || 'export'}-${Date.now()}.png`; link.href = dataUrl; link.click(); toast.success('Exported as PNG!'); } catch (error) { console.error('Failed to export PNG:', error); toast.error('Failed to export PNG'); } }; return (
Preview {font && ( {font} )}
{onCopy && ( Copy to clipboard )} {onShare && ( Copy shareable URL )} Export as PNG {onDownload && ( Download as text file )}
{/* Controls */}
v && setTextAlign(v as TextAlign)} variant="outline" size="sm" disabled={commentStyle !== 'none'} > v && setFontSize(v as 'xs' | 'sm' | 'base')} variant="outline" size="sm" > xs sm md {!isLoading && text && (
{lineCount} lines {charCount} chars
)}
{isLoading ? (
) : text ? (
              {commentedText}
            
) : ( Start typing to see your ASCII art Enter text in the input field above to generate ASCII art with the selected font )}
); }