diff --git a/components/FancyTextPreview.jsx b/components/FancyTextPreview.jsx
new file mode 100644
index 0000000..e2ab987
--- /dev/null
+++ b/components/FancyTextPreview.jsx
@@ -0,0 +1,64 @@
+import { useState } from "react";
+import { fontTransforms, transformText } from "@/components/fontTransforms";
+
+export default function FancyTextPreview() {
+ const [inputText, setInputText] = useState("Hello Instagram");
+ const [copiedIndex, setCopiedIndex] = useState(null);
+
+ const allFonts = Object.keys(fontTransforms);
+
+ const handleCopy = async (text, index) => {
+ try {
+ await navigator.clipboard.writeText(text);
+ setCopiedIndex(index);
+ setTimeout(() => setCopiedIndex(null), 1500);
+ } catch (err) {
+ console.error("Copy failed:", err);
+ }
+ };
+
+ return (
+
+
setInputText(e.target.value)}
+ placeholder="Type something..."
+ />
+
+
+ {allFonts.map((fontName, index) => {
+ const { transformed, fontClassName } = transformText(inputText, fontName);
+
+ return (
+
+
{fontName}
+
+ {/* ⬇️ Normale Textvorschau mit Webfont */}
+
+ {inputText || "Hello Instagram"}
+
+
+ {/* ⬇️ Fancy Unicode-Text */}
+
+ {transformed}
+
+
+
+
+
+ );
+ })}
+
+
+ );
+}
diff --git a/components/PerformanceOptimizedFontCard.jsx b/components/PerformanceOptimizedFontCard.jsx
index 5f28061..7f2cb58 100644
--- a/components/PerformanceOptimizedFontCard.jsx
+++ b/components/PerformanceOptimizedFontCard.jsx
@@ -39,7 +39,7 @@ const PerformanceOptimizedFontCard = forwardRef(({
});
const handleCopy = useCallback(async () => {
- const textToCopy = sStr(transformedText);
+ const textToCopy = sStr(transformedText?.transformed ?? transformedText);
try {
await navigator.clipboard.writeText(textToCopy);
setCopied(true);
@@ -76,7 +76,7 @@ const PerformanceOptimizedFontCard = forwardRef(({
}, [liked, fontName, onLike]);
const handleShare = useCallback(async () => {
- const shareText = `${sStr(transformedText)}\n\nErstellt mit FancyText: ${window.location.href}`;
+ const shareText = `${sStr(transformedText?.transformed ?? transformedText)}\n\nErstellt mit FancyText: ${window.location.href}`;
if (navigator.share) {
try {
await navigator.share({ title: "Schau dir diese coole Schriftart an! 🔥", text: shareText, url: window.location.href });
@@ -107,7 +107,8 @@ const PerformanceOptimizedFontCard = forwardRef(({
return style;
}, []);
- const previewText = sStr(transformedText) || "Hallo Instagram!";
+ const previewText = sStr(transformedText?.transformed ?? transformedText) || "Hallo Instagram!";
+ const fontClass = transformedText?.fontClassName ?? "";
return (
@@ -158,7 +159,7 @@ const PerformanceOptimizedFontCard = forwardRef(({
onKeyDown={(e) => (e.key === "Enter" || e.key === " ") && handleCopy()}
aria-label="Click to copy text"
style={{ ...getFontStyle(fontName), pointerEvents: "auto" }}
- className="text-xl sm-text-2xl md-text-3xl mb-4 p-3 sm:p-4 bg-gray-50 rounded-xl text-center select-all text-gray-800 min-h-[70px] sm:min-h-[80px] flex items-center justify-center cursor-pointer hover:bg-gray-100 transition-colors"
+ className={`text-xl sm-text-2xl md-text-3xl mb-4 p-3 sm:p-4 bg-gray-50 rounded-xl text-center select-all text-gray-800 min-h-[70px] sm:min-h-[80px] flex items-center justify-center cursor-pointer hover:bg-gray-100 transition-colors ${fontClass}`}
>
{previewText}
@@ -175,7 +176,7 @@ const PerformanceOptimizedFontCard = forwardRef(({
{copied ? (
<> Copy! ✨>
) : (
- <> Start Typing ✨ >
+ <> Copy! ✨>
)}
diff --git a/components/fontTransforms.jsx b/components/fontTransforms.jsx
index ea770a3..2fe528a 100644
--- a/components/fontTransforms.jsx
+++ b/components/fontTransforms.jsx
@@ -1,6 +1,6 @@
// components/fontTransforms.jsx
-// 1) Unicode-Blöcke (Startpunkte)
+// 1) Unicode-Blöcke
const unicodeBlocks = {
sansSerif: { upperStart: 0x1D5A0, lowerStart: 0x1D5BA },
sansSerifBold: { upperStart: 0x1D5D4, lowerStart: 0x1D5EE },
@@ -12,7 +12,7 @@ const unicodeBlocks = {
fullwidth: { upperStart: 0xFF21, lowerStart: 0xFF41 }
};
-// 2) Unicode-Mapping-Helfer
+// 2) Unicode-Mapping-Funktion
const mapUnicode = (char, block) => {
const code = char.charCodeAt(0);
if (code >= 65 && code <= 90) return String.fromCodePoint(block.upperStart + (code - 65));
@@ -23,102 +23,65 @@ const mapUnicode = (char, block) => {
const createTransform = (blockKey) => (text) =>
text.split('').map((c) => mapUnicode(c, unicodeBlocks[blockKey])).join('');
-// 3) Font-Transformationen
+// 3) Font-Definitionen
+const fontList = [
+ "abril-fatface", "alegreya", "alfa-slab-one", "almendra", "amatic-sc", "andika",
+ "architects-daughter", "audiowide", "averia-libre", "bebas-neue", "black-ops-one",
+ "caveat", "cinzel-decorative", "courgette", "dancing-script", "exo", "fjalla-one",
+ "germania-one", "glass-antiqua", "gloria-hallelujah", "great-vibes", "holtwood-one-sc",
+ "indie-flower", "italiana", "jost", "kaushan-script", "lato", "metal-mania", "montserrat",
+ "neucha", "noto-sans", "open-sans", "orbitron", "oswald", "pacifico", "permanent-marker",
+ "philosopher", "playfair-display", "poppins", "press-start-2p", "questrial", "quicksand",
+ "rajdhani", "raleway", "righteous", "roboto", "sacramento", "satisfy", "space-mono",
+ "spectral", "staatliches", "stint-ultra-condensed", "syncopate", "ultra", "unica-one",
+ "work-sans", "yellowtail"
+];
+
+// 4) Kategorie-Regeln (vereinfacht)
+const getCategory = (name) => {
+ if (["caveat", "dancing-script", "pacifico", "amatic-sc", "kaushan-script", "courgette", "great-vibes", "satisfy", "sacramento", "neucha", "gloria-hallelujah", "almendra", "indie-flower", "architects-daughter"].includes(name)) return "handwriting";
+ if (["bebas-neue", "black-ops-one", "holtwood-one-sc", "abril-fatface", "playfair-display", "permanent-marker", "alfa-slab-one", "germania-one", "oswald", "stint-ultra-condensed"].includes(name)) return "statement";
+ if (["exo", "orbitron", "audiowide", "rajdhani", "space-mono", "questrial", "syncopate", "unica-one", "italiana", "staatliches"].includes(name)) return "futuristic";
+ if (["press-start-2p", "righteous", "metal-mania", "alegreya", "spectral", "fjalla-one", "glass-antiqua", "cinzel-decorative", "andika"].includes(name)) return "aesthetic";
+ return "modern";
+};
+
+const blockForCategory = {
+ modern: "sansSerif",
+ handwriting: "scriptBold",
+ statement: "fullwidth",
+ futuristic: "monospace",
+ aesthetic: "frakturBold"
+};
+
export const fontTransforms = Object.fromEntries(
- Object.entries({
- // 🔤 Modern
- Montserrat: ['sansSerifBold', 'modern', 'Montserrat – Sans-Serif Bold Unicode'],
- Lato: ['sansSerif', 'modern', 'Lato – Humanistischer Sans-Serif Unicode'],
- Raleway: ['sansSerif', 'modern', 'Raleway – Elegant Display Unicode'],
- Poppins: ['sansSerif', 'modern', 'Poppins – Rund & freundlich Unicode'],
- 'Open Sans': ['sansSerif', 'modern', 'Open Sans – Vielseitig Unicode'],
- Roboto: ['sansSerif', 'modern', 'Roboto – Modernes Grotesk Unicode'],
- 'Work Sans': ['sansSerif', 'modern', 'Work Sans – Tech & Clean Unicode'],
- 'Noto Sans': ['sansSerif', 'modern', 'Noto Sans – International Unicode'],
- Jost: ['sansSerif', 'modern', 'Jost – Geometrisch modern Unicode'],
- Quicksand: ['sansSerif', 'modern', 'Quicksand – Soft Rounded Unicode'],
- 'Averia Libre': ['sansSerif', 'modern', 'Averia Libre – Experimentell Unicode'],
- 'Philosopher': ['sansSerif', 'modern', 'Philosopher – Elegant Unicode'],
-
- // ✍️ Handwriting
- Pacifico: ['scriptBold', 'handwriting', 'Pacifico – Lockerer Pinsel Bold Script Unicode'],
- Sacramento: ['scriptBold', 'handwriting', 'Sacramento – Retro-Handlettering Bold Script Unicode'],
- Caveat: ['scriptBold', 'handwriting', 'Caveat – Natural Handwriting Bold Script Unicode'],
- 'Dancing Script': ['scriptBold', 'handwriting', 'Dancing Script – Lebhafte Kursive Bold Script Unicode'],
- 'Indie Flower': ['scriptBold', 'handwriting', 'Indie Flower – Verspieltes Bold Script Unicode'],
- 'Amatic SC': ['scriptBold', 'handwriting', 'Amatic SC – Skizzenartiges Bold Script Unicode'],
- 'Kaushan Script': ['scriptBold', 'handwriting', 'Kaushan Script – Fettere Kursive Bold Script Unicode'],
- 'Architects Daughter': ['scriptBold','handwriting', 'Architects Daughter – Skizzenhafte Handschrift Unicode'],
- Neucha: ['scriptBold', 'handwriting', 'Neucha – Persönlich und kantig Unicode'],
- 'Great Vibes': ['scriptBold', 'handwriting', 'Great Vibes – Elegante Kalligraphie Unicode'],
- Satisfy: ['scriptBold', 'handwriting', 'Satisfy – Weiche Script Unicode'],
- Yellowtail: ['scriptBold', 'handwriting', 'Yellowtail – Vintage Script Unicode'],
- 'Gloria Hallelujah': ['scriptBold', 'handwriting', 'Gloria Hallelujah – Lebendige Handschrift Unicode'],
-
- // 🧑🎤 Statement
- Oswald: ['sansSerifBold', 'statement', 'Oswald – Bold Grotesk Unicode'],
- 'Bebas Neue': ['fullwidth', 'statement', 'Bebas Neue – Fullwidth Caps Unicode'],
- Ultra: ['sansSerifBold', 'statement', 'Ultra – Kompakte Bold Unicode'],
- 'Stint Ultra Condensed': ['sansSerifBold', 'statement', 'Stint Ultra Condensed – Kompakte Bold Unicode'],
- 'Playfair Display': ['scriptBold', 'statement', 'Playfair Display – Elegante Bold Script Unicode'],
- 'Abril Fatface': ['scriptBold', 'statement', 'Abril Fatface – Fettere Bold Script Unicode'],
- 'Permanent Marker': ['scriptBold', 'statement', 'Permanent Marker – Marker-Style Unicode'],
- 'Alfa Slab One': ['fullwidth', 'statement', 'Alfa Slab One – Slab Serif Heavy Unicode'],
- 'Black Ops One': ['fullwidth', 'statement', 'Black Ops One – Military Display Unicode'],
- 'Germania One': ['frakturBold', 'statement', 'Germania One – Oldstyle Fraktur Unicode'],
- 'Holtwood One SC': ['fullwidth', 'statement', 'Holtwood One SC – Klassisch Bold Small Caps Unicode'],
- Courgette: ['scriptBold', 'statement', 'Courgette – Verspieltes Script Unicode'],
-
- // 🚀 Futuristic
- Exo: ['sansSerif', 'futuristic', 'Exo – Tech Grotesk Unicode'],
- Orbitron: ['monospace', 'futuristic', 'Orbitron – Sci-Fi Monospace Unicode'],
- Audiowide: ['monospace', 'futuristic', 'Audiowide – Rundes Monospace Unicode'],
- Rajdhani: ['monospace', 'futuristic', 'Rajdhani – Digital Monospace Unicode'],
- 'Space Mono': ['monospace', 'futuristic', 'Space Mono – Tech Monospace Unicode'],
- Questrial: ['sansSerif', 'futuristic', 'Questrial – Clean Sans-Serif Unicode'],
- 'Syncopate': ['monospace', 'futuristic', 'Syncopate – Techno Unicode'],
- 'Unica One': ['monospace', 'futuristic', 'Unica One – Monospace Mix Unicode'],
- 'Italiana': ['sansSerif', 'futuristic', 'Italiana – Futuristisch Serif Unicode'],
- 'Staatliches': ['monospace', 'futuristic', 'Staatliches – Moderne Grotesk Unicode'],
-
- // 🧢 Aesthetic
- 'Press Start 2P': ['monospace', 'aesthetic', 'Press Start 2P – Pixel Monospace Unicode'],
- Righteous: ['frakturBold', 'aesthetic', 'Righteous – Stylische Bold Fraktur Unicode'],
- 'Metal Mania': ['scriptBold', 'aesthetic', 'Metal Mania – Fettere Script Unicode'],
- 'Alegreya': ['frakturBold', 'aesthetic', 'Alegreya – Literatur Serif Unicode'],
- 'Spectral': ['frakturBold', 'aesthetic', 'Spectral – Editorial Serif Unicode'],
- 'Fjalla One': ['sansSerifBold', 'aesthetic', 'Fjalla One – Headline Sans Unicode'],
- 'Glass Antiqua': ['scriptBold', 'aesthetic', 'Glass Antiqua – Zarte Antiqua Script Unicode'],
- 'Cinzel Decorative': ['scriptBold', 'aesthetic', 'Cinzel Decorative – Klassische Zier-Serif Unicode'],
- 'Andika': ['sansSerif', 'aesthetic', 'Andika – Leserlich Unicode'],
- 'Almendra': ['scriptBold', 'aesthetic', 'Almendra – Historische Handschrift Unicode'],
- }).map(([name, [block, category, description]]) => [
- name,
- {
+ fontList.map((font) => {
+ const name = font.replace(/-/g, " ").replace(/\b\w/g, (l) => l.toUpperCase());
+ const category = getCategory(font);
+ const block = blockForCategory[category];
+ return [name, {
transform: createTransform(block),
category,
- description,
- className: `font-${name.toLowerCase().replace(/\s+/g, '')}`,
- },
- ])
+ description: `${name} – Unicode-Stil automatisch zugewiesen` ,
+ className: `font-${font}`
+ }];
+ })
);
-// 🔝 Neue transformText-Funktion – gibt transformierten Text **und** Tailwind-Klasse zurück
export const transformText = (text, fontName) => {
const font = fontTransforms[fontName];
- if (!font || !text) return { transformed: text, fontClassName: '' };
+ if (!font || !text) return { transformed: text, fontClassName: "" };
return {
transformed: font.transform(text),
- fontClassName: font.className,
+ fontClassName: font.className
};
};
-// Weitere Helfer
export const getPopularFonts = () => Object.keys(fontTransforms).slice(0, 10);
export const getFontsByCategory = (category) =>
- category === 'all'
+ category === "all"
? Object.keys(fontTransforms)
: Object.keys(fontTransforms).filter(
(f) => fontTransforms[f].category === category
- );
+ );
\ No newline at end of file
diff --git a/components/ui/FontCard.jsx b/components/ui/FontCard.jsx
index 21cf50d..c3fbab0 100644
--- a/components/ui/FontCard.jsx
+++ b/components/ui/FontCard.jsx
@@ -5,8 +5,6 @@ import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Copy, Check, Heart, Share2, Info } from "lucide-react";
import { transformText, fontTransforms } from "../fontTransforms";
-import { getFontData } from "@/lib/fonts";
-import fontMap from "@/lib/tailwind-font-map";
export default function FontCard({
fontName,
@@ -19,71 +17,24 @@ export default function FontCard({
const [liked, setLiked] = useState(false);
const fontInfo = fontTransforms[fontName];
- const fontData = getFontData(fontName);
- const fontKey = fontName.toLowerCase().replace(/\s+/g, "");
- const fontVarName = fontMap[fontKey];
- const fontVar = fontVarName ? { fontFamily: `var(${fontVarName})` } : {};
- const fontClass = fontData?.className || "";
+ // Dynamisch Font-Klasse aus Fontnamen generieren (z. B. "Open Sans" → "font-open-sans")
+ const fontClass = `font-${fontName.toLowerCase().replace(/\s+/g, "-")}`;
+
+ // Fancy-Transformation
const rawText = "Hallo Instagram!";
- const transformed = transformText(rawText, fontName);
- const finalText = transformed?.transformed || rawText;
- const copyText = transformed?.transformed || rawText;
+ const { transformed } = transformText(rawText, fontName);
+ const finalText = transformed || rawText;
const handleCopy = () => {
- if (navigator.clipboard && window.isSecureContext) {
- navigator.clipboard
- .writeText(copyText)
- .then(() => flashCopied())
- .catch(() => fallbackCopy());
- } else {
- fallbackCopy();
- }
+ navigator.clipboard.writeText(finalText).then(() => {
+ setCopied(true);
+ setTimeout(() => setCopied(false), 1500);
+ });
};
- const flashCopied = () => {
- setCopied(true);
- setTimeout(() => setCopied(false), 2000);
- };
-
- const fallbackCopy = () => {
- const textarea = document.createElement("textarea");
- textarea.value = copyText;
- textarea.setAttribute("readonly", "");
- textarea.style.position = "fixed";
- textarea.style.top = "0";
- textarea.style.left = "0";
- textarea.style.width = "1px";
- textarea.style.height = "1px";
- textarea.style.padding = "0";
- textarea.style.border = "none";
- textarea.style.outline = "none";
- textarea.style.boxShadow = "none";
- textarea.style.background = "transparent";
-
- document.body.appendChild(textarea);
- textarea.focus();
- textarea.select();
- try {
- document.execCommand("copy");
- flashCopied();
- } catch (err) {
- console.error("Fallback Copy fehlgeschlagen:", err);
- }
- document.body.removeChild(textarea);
- };
-
- const handleShare = async () => {
- if (!navigator.share) return;
- try {
- await navigator.share({
- title: `FancyText – ${fontName}`,
- text: copyText,
- url: window.location.href,
- });
- } catch (err) {
- console.error("Share fehlgeschlagen:", err);
- }
+ const handleShare = () => {
+ alert(`Teilen von: ${fontName}`);
};
return (
@@ -117,7 +68,7 @@ export default function FontCard({
variant="ghost"
size="sm"
onClick={handleShare}
- className="text-gray-400 hover:text-blue-500"
+ className="text-gray-400 hover:text-blue-500 pointer-events-auto"
>
@@ -135,8 +86,8 @@ export default function FontCard({
type="text"
value={finalText}
readOnly
- className={`${fontClass} text-2xl md:text-3xl mb-6 p-4 bg-gray-50 rounded-xl text-center text-gray-800 min-h-[80px] w-full select-all border-0 focus:ring-0`}
- style={{ ...fontVar, lineHeight: "1.2" }}
+ className={`${fontClass} text-2xl md:text-3xl mb-6 p-4 bg-gray-50 rounded-xl text-center text-gray-800 min-h-[80px] w-full select-all border-0 focus:ring-0 pointer-events-auto`}
+ style={{ lineHeight: "1.2" }}
/>