custom
pixel-perfect/customFreeBlock
Layout-aware custom renderers from the `animate-text` catalog that cannot be
Install it
npx shadcn@latest add https://www.pixel-perfect.space/r/custom.jsonSource
1"use client";23/**4 * Layout-aware custom renderers from the `animate-text` catalog that cannot be5 * expressed as a plain generic stagger:6 *7 * - SharedSlideText → `shared-slide-opacity-stage` (short-slide-right)8 * - KineticCenterText → `kinetic-center-build`9 * - KineticStackText → `kinetic-top-build` (short-slide-down)10 *11 * Timings below are the website-scaled values (source × 0.72) taken from each12 * effect's `showcase.timing` block. Kinetic build x/y values are raw renderer13 * pixels and are intentionally NOT scaled by the vertical-travel multiplier.14 */1516import { useRef } from "react";17import gsap from "gsap";18import { useGSAP } from "@gsap/react";19import { toEase } from "./engine";2021type Anim = gsap.core.Tween | gsap.core.Timeline;2223const mix = (a: number, b: number, t: number) => a + (b - a) * t;2425type WordState = { x: number; y: number; scale: number; blur: number; opacity: number };2627function writeWord(el: HTMLElement, s: WordState) {28 el.style.transform = `translate(-50%, -50%) translate3d(${s.x}px, ${s.y}px, 0) scale(${s.scale})`;29 el.style.filter = `blur(${s.blur}px)`;30 el.style.opacity = String(s.opacity);31}3233function createAbsWord(word: string) {34 const el = document.createElement("span");35 el.textContent = word;36 el.style.position = "absolute";37 el.style.left = "50%";38 el.style.top = "50%";39 el.style.whiteSpace = "pre";40 el.style.opacity = "0";41 el.style.willChange = "transform, opacity, filter";42 el.style.transform = "translate(-50%, -50%)";43 el.style.backfaceVisibility = "hidden";44 return el;45}4647type KeyFrame = { offset: number } & WordState;4849const SLIDE_SAMPLES = ["Move with intent.", "Words glide across.", "Build the rhythm."];5051export function SharedSlideText({ className }: { className?: string }) {52 const containerRef = useRef<HTMLDivElement>(null);53 const titleRef = useRef<HTMLSpanElement>(null);5455 useGSAP(56 () => {57 const title = titleRef.current;58 if (!title) return;5960 let cancelled = false;61 const timers: number[] = [];62 const active: Anim[] = [];63 const enterEase = toEase("cubic-bezier(0.2, 0.8, 0.2, 1)");64 const exitEase = toEase("cubic-bezier(0.4, 0, 0.2, 1)");6566 const sleep = (ms: number) =>67 new Promise<void>((resolve) => {68 const t = window.setTimeout(resolve, ms);69 timers.push(t);70 });71 const tween = (target: gsap.TweenTarget, vars: gsap.TweenVars) =>72 new Promise<void>((resolve) => {73// … truncated
What it pulls in
npm packages
Files it writes
More from pixel-perfect
All 60 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| 3d-button3d-button | pixel-perfect | Blocks | Unverified | 2 deps | |
| abhinav-bento-buttonabhinav-bento-button | pixel-perfect | Blocks | Unverified | no deps | |
| accordion-carouselaccordion-carousel | pixel-perfect | Blocks | Free | 1 dep | |
| accordion-foldaccordion-fold | pixel-perfect | Blocks | Free | 1 dep | |
| activity-wheel-motionactivity-wheel-motion | pixel-perfect | Blocks | Free | 2 deps | |
| animated-textureanimated-texture | pixel-perfect | Blocks | Free | 1 dep | |
| aperture-mask-revealaperture-mask-reveal | pixel-perfect | Blocks | Free | 1 dep | |
| aurora-curtainaurora-curtain | pixel-perfect | Blocks | Free | no deps |
