diff --git a/components/converter/FontPreview.tsx b/components/converter/FontPreview.tsx index b8724da..dee80bf 100644 --- a/components/converter/FontPreview.tsx +++ b/components/converter/FontPreview.tsx @@ -1,10 +1,12 @@ 'use client'; import * as React from 'react'; +import { toPng } from 'html-to-image'; import { Card } from '@/components/ui/Card'; import { Button } from '@/components/ui/Button'; -import { Copy, Download, Share2 } from 'lucide-react'; +import { Copy, Download, Share2, Image as ImageIcon, AlignLeft, AlignCenter, AlignRight } from 'lucide-react'; import { cn } from '@/lib/utils/cn'; +import { useToast } from '@/components/ui/Toast'; export interface FontPreviewProps { text: string; @@ -16,40 +18,139 @@ export interface FontPreviewProps { className?: string; } +type TextAlign = 'left' | 'center' | 'right'; + export function FontPreview({ text, font, isLoading, onCopy, onDownload, onShare, className }: FontPreviewProps) { const lineCount = text ? text.split('\n').length : 0; const charCount = text ? text.length : 0; + const previewRef = React.useRef(null); + const [textAlign, setTextAlign] = React.useState('left'); + const [fontSize, setFontSize] = React.useState<'xs' | 'sm' | 'base'>('sm'); + const { addToast } = useToast(); + + 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 = `figlet-${font || 'export'}-${Date.now()}.png`; + link.href = dataUrl; + link.click(); + + addToast('Exported as PNG!', 'success'); + } catch (error) { + console.error('Failed to export PNG:', error); + addToast('Failed to export PNG', 'error'); + } + }; return (
-
-
-

Preview

- {font && ( - - {font} - - )} +
+
+
+

Preview

+ {font && ( + + {font} + + )} +
+
+ {onCopy && ( + + )} + {onShare && ( + + )} + + {onDownload && ( + + )} +
-
- {onCopy && ( - - )} - {onShare && ( - - )} - {onDownload && ( - - )} + + {/* Controls */} +
+
+ + + +
+ +
+ + + +
@@ -61,13 +162,25 @@ export function FontPreview({ text, font, isLoading, onCopy, onDownload, onShare
)} -
+
{isLoading ? (
Generating...
) : text ? ( -
+            
               {text}
             
) : ( diff --git a/components/ui/KeyboardShortcutsHelp.tsx b/components/ui/KeyboardShortcutsHelp.tsx index 9a7e40d..ed724df 100644 --- a/components/ui/KeyboardShortcutsHelp.tsx +++ b/components/ui/KeyboardShortcutsHelp.tsx @@ -13,10 +13,10 @@ export interface Shortcut { } const shortcuts: Shortcut[] = [ - { key: '/', description: 'Focus search' }, + { key: '/', description: 'Focus font search' }, { key: 'Esc', description: 'Clear search / Close dialog' }, - { key: 'D', description: 'Toggle dark mode', modifier: 'ctrl' }, - { key: '?', description: 'Show keyboard shortcuts', modifier: 'shift' }, + { key: 'D', description: 'Toggle dark/light mode', modifier: 'ctrl' }, + { key: '?', description: 'Show this help dialog', modifier: 'shift' }, ]; export function KeyboardShortcutsHelp() { @@ -65,22 +65,35 @@ export function KeyboardShortcutsHelp() {
-
- {shortcuts.map((shortcut, i) => ( -
- {shortcut.description} -
- {shortcut.modifier && ( +
+
+

Navigation

+ {shortcuts.map((shortcut, i) => ( +
+ {shortcut.description} +
+ {shortcut.modifier && ( + + {shortcut.modifier === 'ctrl' ? '⌘/Ctrl' : 'Shift'} + + )} - {shortcut.modifier === 'ctrl' ? '⌘/Ctrl' : 'Shift'} + {shortcut.key} - )} - - {shortcut.key} - +
-
- ))} + ))} +
+ +
+

Tips

+
    +
  • • Click the Shuffle button for random fonts
  • +
  • • Use the heart icon to favorite fonts
  • +
  • • Filter by All, Favorites, or Recent
  • +
  • • Text alignment and size controls in Preview
  • +
+
diff --git a/package.json b/package.json index 87ecf76..291f9bd 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "clsx": "^2.1.1", "figlet": "^1.8.0", "fuse.js": "^7.1.0", + "html-to-image": "^1.11.13", "lucide-react": "^0.553.0", "next": "^16.0.0", "react": "^19.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a2ace12..44de8ce 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -17,6 +17,9 @@ importers: fuse.js: specifier: ^7.1.0 version: 7.1.0 + html-to-image: + specifier: ^1.11.13 + version: 1.11.13 lucide-react: specifier: ^0.553.0 version: 0.553.0(react@19.2.0) @@ -1226,6 +1229,9 @@ packages: hermes-parser@0.25.1: resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==} + html-to-image@1.11.13: + resolution: {integrity: sha512-cuOPoI7WApyhBElTTb9oqsawRvZ0rHhaHwghRLlTuffoD1B2aDemlCruLeZrUIIdvG7gs9xeELEPm6PhuASqrg==} + ignore@5.3.2: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} @@ -3255,6 +3261,8 @@ snapshots: dependencies: hermes-estree: 0.25.1 + html-to-image@1.11.13: {} + ignore@5.3.2: {} ignore@7.0.5: {}