remove special chars & .next ignore

This commit is contained in:
Andreas Knuth 2025-08-09 12:31:08 -05:00
parent 97057765b4
commit 878dbc63f7
2 changed files with 154 additions and 153 deletions

1
.gitignore vendored
View File

@ -1 +1,2 @@
node_modules node_modules
.next

View File

@ -9,169 +9,169 @@ import { fontTransforms } from "@/components/fontTransforms";
const sStr = (v) => (v ?? "").toString(); const sStr = (v) => (v ?? "").toString();
const updateFontHistory = (fontName) => { const updateFontHistory = (fontName) => {
  if (typeof window === "undefined") return; if (typeof window === "undefined") return;
  try { try {
    const key = "fancytext_recent_fonts"; const key = "fancytext_recent_fonts";
    const stored = JSON.parse(sessionStorage.getItem(key) || "[]"); const stored = JSON.parse(sessionStorage.getItem(key) || "[]");
    const updated = [fontName, ...stored.filter((f) => f !== fontName)].slice(0, 5); const updated = [fontName, ...stored.filter((f) => f !== fontName)].slice(0, 5);
    sessionStorage.setItem(key, JSON.stringify(updated)); sessionStorage.setItem(key, JSON.stringify(updated));
  } catch {} } catch {}
}; };
const PerformanceOptimizedFontCard = forwardRef(({ const PerformanceOptimizedFontCard = forwardRef(({
  fontName, fontName,
  transformedText, transformedText,
  category, category,
  isPopular, isPopular,
  animationsEnabled, animationsEnabled,
  index, index,
  onCopy, onCopy,
  onLike, onLike,
  onShare onShare
}, ref) => { }, ref) => {
  const [copied, setCopied] = useState(false); const [copied, setCopied] = useState(false);
  const [liked, setLiked] = useState(() => { const [liked, setLiked] = useState(() => {
    if (typeof window === "undefined") return false; if (typeof window === "undefined") return false;
    try { try {
      return localStorage.getItem(`liked_${fontName}`) === "true"; return localStorage.getItem(`liked_${fontName}`) === "true";
    } catch { } catch {
      return false; return false;
    } }
  }); });
  const handleCopy = useCallback(async () => { const handleCopy = useCallback(async () => {
    const textToCopy = sStr(transformedText?.transformed ?? transformedText); const textToCopy = sStr(transformedText?.transformed ?? transformedText);
    try { try {
      await navigator.clipboard.writeText(textToCopy); await navigator.clipboard.writeText(textToCopy);
      setCopied(true); setCopied(true);
      updateFontHistory(fontName); updateFontHistory(fontName);
      navigator.vibrate?.(50); navigator.vibrate?.(50);
      onCopy?.(fontName, textToCopy); onCopy?.(fontName, textToCopy);
      setTimeout(() => setCopied(false), 2000); setTimeout(() => setCopied(false), 2000);
    } catch { } catch {
      const textarea = document.createElement("textarea"); const textarea = document.createElement("textarea");
      textarea.value = textToCopy; textarea.value = textToCopy;
      textarea.setAttribute("readonly", ""); textarea.setAttribute("readonly", "");
      textarea.style.position = "fixed"; textarea.style.position = "fixed";
      textarea.style.opacity = "0"; textarea.style.opacity = "0";
      document.body.appendChild(textarea); document.body.appendChild(textarea);
      textarea.select(); textarea.select();
      try { try {
        document.execCommand("copy"); document.execCommand("copy");
        setCopied(true); setCopied(true);
        updateFontHistory(fontName); updateFontHistory(fontName);
        setTimeout(() => setCopied(false), 2000); setTimeout(() => setCopied(false), 2000);
      } catch (e) { } catch (e) {
        console.error("Fallback copy failed:", e); console.error("Fallback copy failed:", e);
      } }
      document.body.removeChild(textarea); document.body.removeChild(textarea);
    } }
  }, [transformedText, fontName, onCopy]); }, [transformedText, fontName, onCopy]);
  const handleLike = useCallback(() => { const handleLike = useCallback(() => {
    const newLiked = !liked; const newLiked = !liked;
    setLiked(newLiked); setLiked(newLiked);
    try { localStorage.setItem(`liked_${fontName}`, newLiked.toString()); } catch {} try { localStorage.setItem(`liked_${fontName}`, newLiked.toString()); } catch {}
    navigator.vibrate?.(newLiked ? 30 : 0); navigator.vibrate?.(newLiked ? 30 : 0);
    onLike?.(fontName, newLiked); onLike?.(fontName, newLiked);
  }, [liked, fontName, onLike]); }, [liked, fontName, onLike]);
  const handleShare = useCallback(async () => { const handleShare = useCallback(async () => {
    const shareText = `${sStr(transformedText?.transformed ?? transformedText)}\n\nErstellt mit FancyText: ${window.location.href}`; const shareText = `${sStr(transformedText?.transformed ?? transformedText)}\n\nErstellt mit FancyText: ${window.location.href}`;
    if (navigator.share) { if (navigator.share) {
      try { try {
        await navigator.share({ title: "Schau dir diese coole Schriftart an! 🔥", text: shareText, url: window.location.href }); await navigator.share({ title: "Schau dir diese coole Schriftart an! 🔥", text: shareText, url: window.location.href });
        onShare?.(fontName); onShare?.(fontName);
      } catch {} } catch {}
    } else { } else {
      try { try {
        await navigator.clipboard.writeText(shareText); await navigator.clipboard.writeText(shareText);
        setCopied(true); setCopied(true);
        setTimeout(() => setCopied(false), 2000); setTimeout(() => setCopied(false), 2000);
      } catch (e) { } catch (e) {
        console.error("Share fallback failed:", e); console.error("Share fallback failed:", e);
      } }
    } }
  }, [transformedText, fontName, onShare]); }, [transformedText, fontName, onShare]);
  const previewText = sStr(transformedText?.transformed ?? transformedText) || "Hallo Instagram!"; const previewText = sStr(transformedText?.transformed ?? transformedText) || "Hallo Instagram!";
  const fontClass = transformedText?.fontClassName ?? ""; const fontClass = transformedText?.fontClassName ?? "";
  const displayName = fontTransforms[fontName]?.description; const displayName = fontTransforms[fontName]?.description;
  return ( return (
    <div ref={ref} className="will-change-transform mb-6"> <div ref={ref} className="will-change-transform mb-6">
      <Card className="bg-white/95 backdrop-blur-sm border-0 shadow-xl hover:shadow-2xl transition-all duration-200 overflow-hidden touch-manipulation"> <Card className="bg-white/95 backdrop-blur-sm border-0 shadow-xl hover:shadow-2xl transition-all duration-200 overflow-hidden touch-manipulation">
        <div className="p-4 sm:p-6"> <div className="p-4 sm:p-6">
          <div className="flex items-center justify-between mb-3"> <div className="flex items-center justify-between mb-3">
            <div className="flex items-center gap-2 min-w-0 flex-1"> <div className="flex items-center gap-2 min-w-0 flex-1">
              <h3 className="font-semibold text-gray-800 truncate text-sm sm:text-base">{fontName}</h3> <h3 className="font-semibold text-gray-800 truncate text-sm sm:text-base">{fontName}</h3>
              {isPopular && ( {isPopular && (
                <Badge className="bg-gradient-to-r from-pink-500 to-purple-500 text-white text-xs shrink-0"> <Badge className="bg-gradient-to-r from-pink-500 to-purple-500 text-white text-xs shrink-0">
                  <Zap className="w-3 h-3 mr-1" /> Top <Zap className="w-3 h-3 mr-1" /> Top
                </Badge> </Badge>
              )} )}
            </div> </div>
            <div className="flex items-center gap-1 shrink-0"> <div className="flex items-center gap-1 shrink-0">
              <Button <Button
                variant="ghost" variant="ghost"
                size="sm" size="sm"
                onClick={handleLike} onClick={handleLike}
                style={{ pointerEvents: "auto" }} style={{ pointerEvents: "auto" }}
                className={`p-2 touch-manipulation ${liked ? "text-pink-500" : "text-gray-400"}`} className={`p-2 touch-manipulation ${liked ? "text-pink-500" : "text-gray-400"}`}
                aria-label={liked ? "Unlike font" : "Like font"} aria-label={liked ? "Unlike font" : "Like font"}
              > >
                <Heart className={`w-4 h-4 ${liked ? "fill-current" : ""}`} /> <Heart className={`w-4 h-4 ${liked ? "fill-current" : ""}`} />
              </Button> </Button>
              <Button <Button
                variant="ghost" variant="ghost"
                size="sm" size="sm"
                onClick={handleShare} onClick={handleShare}
                style={{ pointerEvents: "auto" }} style={{ pointerEvents: "auto" }}
                className="p-2 touch-manipulation text-gray-400 hover:text-blue-500" className="p-2 touch-manipulation text-gray-400 hover:text-blue-500"
                aria-label="Share font" aria-label="Share font"
              > >
                <Share2 className="w-4 h-4" /> <Share2 className="w-4 h-4" />
              </Button> </Button>
            </div> </div>
          </div> </div>
          {displayName && ( {displayName && (
            <p className="text-xs text-gray-500 mb-3 flex items-start gap-1 leading-tight"> <p className="text-xs text-gray-500 mb-3 flex items-start gap-1 leading-tight">
              <Info className="w-3 h-3 mt-0.5 shrink-0" /> <Info className="w-3 h-3 mt-0.5 shrink-0" />
              {displayName} {displayName}
            </p> </p>
          )} )}
          <div <div
            onClick={handleCopy} onClick={handleCopy}
            role="button" role="button"
            tabIndex={0} tabIndex={0}
            onKeyDown={(e) => (e.key === "Enter" || e.key === " ") && handleCopy()} onKeyDown={(e) => (e.key === "Enter" || e.key === " ") && handleCopy()}
            aria-label="Click to copy text" aria-label="Click to copy text"
            style={{ pointerEvents: "auto" }} style={{ 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 ${fontClass}`} 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} {previewText}
          </div> </div>
          <Button <Button
            onClick={handleCopy} onClick={handleCopy}
            disabled={copied} disabled={copied}
            style={{ pointerEvents: "auto" }} style={{ pointerEvents: "auto" }}
            className={`w-full transition-all duration-200 touch-manipulation text-white font-medium py-3 rounded-xl shadow-lg hover:shadow-xl active:scale-95 ${ className={`w-full transition-all duration-200 touch-manipulation text-white font-medium py-3 rounded-xl shadow-lg hover:shadow-xl active:scale-95 ${
              copied copied
                ? "bg-green-500 hover:bg-green-600 shadow-green-200" ? "bg-green-500 hover:bg-green-600 shadow-green-200"
                : "bg-gradient-to-r from-pink-500 to-purple-500 hover:from-pink-600 hover:to-purple-600 shadow-pink-200" : "bg-gradient-to-r from-pink-500 to-purple-500 hover:from-pink-600 hover:to-purple-600 shadow-pink-200"
            }`} }`}
          > >
            {copied ? ( {copied ? (
              <><Check className="w-4 h-4 mr-2" /> Copy! </> <><Check className="w-4 h-4 mr-2" /> Copy! </>
            ) : ( ) : (
              <><Copy className="w-4 h-4 mr-2" /> Copy! </> <><Copy className="w-4 h-4 mr-2" /> Copy! </>
            )} )}
          </Button> </Button>
        </div> </div>
      </Card> </Card>
    </div> </div>
  ); );
}); });
PerformanceOptimizedFontCard.displayName = "PerformanceOptimizedFontCard"; PerformanceOptimizedFontCard.displayName = "PerformanceOptimizedFontCard";