import { Easing } from "remotion"; export const clamp01 = (t: number) => Math.max(0, Math.min(1, t)); export const lerp = (a: number, b: number, t: number) => a + (b - a) * t; /** Sitedeki pixel-decor.tsx ile aynı deterministik sözde-rastgele */ export const hash = (x: number, y: number, seed = 0) => { const n = Math.sin(x * 127.1 + y * 311.7 + seed * 74.7) * 43758.5453; return n - Math.floor(n); }; export const ease = { out: Easing.bezier(0.22, 1, 0.36, 1), inOut: Easing.bezier(0.65, 0, 0.35, 1), in: Easing.bezier(0.64, 0, 0.78, 0), // Sitenin yay hissi: bounce 0 (Apple damping 1) yay: Easing.bezier(0.2, 0.8, 0.2, 1), geriTep: Easing.bezier(0.34, 1.56, 0.64, 1), }; /** f, [a, b] aralığında 0→1 ilerleme (kırpılmış, isteğe bağlı eğri) */ export const aralik = ( f: number, a: number, b: number, egri: (t: number) => number = (t) => t, ) => egri(clamp01((f - a) / (b - a))); /** İki CSS rengi arasında oklab karışımı (oklch token'larla çalışır) */ export const karis = (a: string, b: string, t: number) => { const p = Math.round(clamp01(t) * 1000) / 10; if (p <= 0) return a; if (p >= 100) return b; return `color-mix(in oklab, ${b} ${p}%, ${a})`; }; /** Sayıyı Türkçe binlik ayraçla yazar: 45000 → "45.000" */ export const tr = (n: number) => Math.round(n).toLocaleString("tr-TR"); /** Metin ölçümü: kinetik yerleşimler için gerçek yazı tipiyle genişlik */ export const olc = ( metin: string, font: { family: string; size: number; weight?: number; italic?: boolean; tracking?: number }, ) => { if (typeof document === "undefined") return metin.length * font.size * 0.55; const ctx = document.createElement("canvas").getContext("2d"); if (!ctx) return metin.length * font.size * 0.55; ctx.font = `${font.italic ? "italic " : ""}${font.weight ?? 400} ${font.size}px "${font.family}"`; return ( ctx.measureText(metin).width + (font.tracking ?? 0) * font.size * Array.from(metin).length ); };