"use client"; import { useEffect, useRef, useState, type CSSProperties } from "react"; import { motion, useReducedMotion } from "motion/react"; import { cn } from "@/lib/utils"; // public/kolay-tercih-mark.svg'nin inline, animasyonlu karşılığı (Motion). // İki varyant: // // - "rota" (varsayılan): her kare sıradakinin pozisyonuna süzülür (mavi → // şeftalinin yeri, şeftali → turuncunun, turuncu → mavinin), üç adımda // herkes başlangıç formuna döner. Uçuş sırasında kare hafifçe küçülüp // solar, varışta toparlanır. Site header'daki logo hover'da bunu oynatır. // - "nabiz": kareler yerlerinden ayrılmaz; 120° faz farkıyla dalga gibi // küçülüp büyür (danışman panel başlığının sakin, sürekli hâli). // // Not: motion.rect'te `x`/`y` transform değeridir (attribute değil) — kareler // attribute yerine translate ile konumlanır; scale, transform-box: fill-box // sayesinde karenin kendi merkezinden uygulanır. const POZISYONLAR = [ [27, 56], [91, 29], [91, 95], ] as const; const KARELER = [ { boyut: 57, renk: "#3b82f6", baslangic: 0 }, { boyut: 56, renk: "#fdc7a7", baslangic: 1 }, { boyut: 56, renk: "#ff5a00", baslangic: 2 }, ] as const; // Rota: tam tur 3.6s — 3 etap × (%25 yol = 0.9s + %8.3 varışta soluklanma). // 0.9s'lik yolculuk, nabız varyantının küçül-büyü temposuyla aynı hızda. const ROTA_SURE = 3.6; // Kalkışlar kademeli: kareler eş zamanlı değil, danışman başlığındaki gibi // sırayla (mavi → şeftali → turuncu) yola çıkıp küçülür. const ROTA_GECIKME_ADIMI = 0.2; const KONUM_ZAMANLARI = [0, 0.25, 1 / 3, 0.583, 2 / 3, 0.917, 1]; // Nabız (rota içi): her yolculuğun ortasında dibe vurur, varışta tam form. const ROTA_NABIZ_ZAMANLARI = [ 0, 0.125, 0.25, 1 / 3, 0.458, 0.583, 2 / 3, 0.792, 0.917, 1, ]; const ROTA_NABIZ_SCALE = [1, 0.84, 1, 1, 0.84, 1, 1, 0.84, 1, 1]; const ROTA_NABIZ_OPACITY = [1, 0.6, 1, 1, 0.6, 1, 1, 0.6, 1, 1]; // Yerinde nabız: kesintisiz tam-sinüs (dinlenme yok), delay'ler döngüyü üçe // böler — biri büyürken sıradaki küçülür, hiçbir kare beklemez. const NABIZ_SURE = 1.8; const NABIZ_GECIKMELER = [0, 0.6, 1.2] as const; const SINE = [0.37, 0, 0.63, 1] as const; /** Kare i için durak koordinatları: kendi yeri → sıradaki → ondan sonraki → * kendi yeri. Duraklarda bekleme için her hedef iki kez tekrarlanır * (KONUM_ZAMANLARI ile hizalı). */ function rota(baslangic: number, eksen: 0 | 1): number[] { const [p0, p1, p2] = [0, 1, 2].map( (adim) => POZISYONLAR[(baslangic + adim) % 3][eksen], ); return [p0, p1, p1, p2, p2, p0, p0]; } /** * Animasyonlu KolayTercih işareti. Varsayılanda koreografi sürekli döner; * `sadeceHover` ile yalnızca işaretin üzerine gelindiğinde oynar (ör. site * header'daki logo linki) ve hover bitince kareler yumuşakça yerine oturur. */ export function AnimasyonluMark({ className, sadeceHover = false, varyant = "rota", renk = "marka", }: { className?: string; sadeceHover?: boolean; varyant?: "rota" | "nabiz"; /** "marka": logodaki üç renk; "turuncu": tüm kareler sitenin CTA turuncusu * (orange-500) — ör. danışman panel başlığı. */ renk?: "marka" | "turuncu"; }) { const [hover, setHover] = useState(false); const svgRef = useRef(null); const azHareket = useReducedMotion(); const aktif = !azHareket && (!sadeceHover || hover); // Hover hedefi işaretin kendisi değil, en yakın `group` ebeveyni (site // header'da logo + "KolayTercih" yazısını saran Link): yazının üzerine // gelindiğinde de animasyon başlar. `group`'suz kullanımda svg'ye düşer. useEffect(() => { if (!sadeceHover) return; const hedef = svgRef.current?.closest(".group") ?? svgRef.current; if (!hedef) return; const ac = () => setHover(true); const kapat = () => setHover(false); hedef.addEventListener("mouseenter", ac); hedef.addEventListener("mouseleave", kapat); return () => { hedef.removeEventListener("mouseenter", ac); hedef.removeEventListener("mouseleave", kapat); }; }, [sadeceHover]); return ( ); }