gsap-presets-kit
v0.3.1
Published
Un set pequeño, tipado y validado en runtime de helpers para GSAP: animateFrom, animateTo y animateFromTo, más presets de SplitText, Typewriter y Marquee, con soporte de ScrollTrigger y timelines.
Maintainers
Readme
gsap-presets-kit
Un set pequeño, tipado y validado en runtime de helpers para GSAP. Anima cualquier cosa
con tres funciones — animateFrom, animateTo, animateFromTo — que traen valores por
defecto sensatos (como opacity) que puedes reemplazar en cada llamada, más tres
presets listos para usar: SplitText, Typewriter y Marquee.
Las animaciones por scroll (ScrollTrigger) y las timelines están integradas. Cada opción se valida y normaliza en runtime con Zod, y los tipos de TypeScript se infieren de los mismos schemas.
Requiere GSAP 3.13+ (todos los plugins, incluidos SplitText y ScrollTrigger, son gratis desde la adquisición por parte de Webflow).
Instalación
pnpm add gsap-presets-kit gsap zod
# npm install gsap-presets-kit gsap zod
# bun add gsap-presets-kit gsap zodgsap y zod son peer dependencies — tu app es dueña de una única copia de cada uno.
Skill para agentes de IA
El paquete incluye una skill (SKILL.md) que enseña a herramientas como opencode,
Claude Code, etc. a usar la API correctamente. Tienes dos formas de instalarla:
Opción 1 — plugin de opencode (no escribe en tu repo). Añade a tu opencode.json:
{
"plugin": ["gsap-presets-kit/opencode-plugin"]
}El plugin registra skills.paths para que la skill se lea desde node_modules sin copiar
ningún archivo. Reinicia opencode tras cambiarlo.
Opción 2 — instalar la skill en tu proyecto. Copia la skill a .agents/skills/:
npx gsap-presets-kit initCon -y para no preguntar, -f para sobrescribir si ya existe y --dest <ruta> para
elegir destino. Opencode lee automáticamente .agents/skills/<name>/SKILL.md, así que
basta con reiniciar la herramienta.
Inicio rápido
import { animateFrom, animateTo, animateFromTo, splitTextReveal, typewriter, marquee, scrollTimeline } from "gsap-presets-kit";
// Fade en el momento en que el elemento entra al viewport
animateFrom("#hero");
// Reemplaza los defaults — entrada solo con escala (sin fade)
animateFrom(".card", { opacity: 1, scale: 0.6, ease: "back.out(1.7)" });
// Salida / movimiento
animateTo("#btn", { x: 200 });
// Control total entre dos estados
animateFromTo("#box", { scale: 0, rotation: -45 }, { scale: 1, rotation: 0 });
// Presets
splitTextReveal("#title", { type: "chars", stagger: 0.02 });
typewriter("#typed", { speed: 60, highlight: ["gsap"], loop: true });
marquee(".marquee-track", { speed: 50, direction: "left" });Las tres funciones core
Todo es una variación de los modos de tween de GSAP con defaults reemplazables:
| Función | Modo | Defaults |
| --- | --- | --- |
| animateTo(target, options?) | gsap.to | { opacity: 0, duration: 0.8, ease: "power2.out" } |
| animateFrom(target, options?) | gsap.from | { opacity: 0, duration: 0.8, ease: "power2.out" } |
| animateFromTo(target, fromVars?, toVars?, options?) | gsap.fromTo | from: { opacity: 0 } · to: { opacity: 1, duration: 0.8, ease: "power2.out" } |
Pasa cualquiera de esas claves (o cualquier otro tween var de GSAP) para reemplazar el default:
animateFrom("#el", { opacity: 1, x: -120 }); // solo desplazamiento, desde la izquierda
animateFrom("#el", { opacity: 1, scale: 0.8 }); // entrada solo con escala
animateTo("#el", { opacity: 0 }); // fade de salida
animateFromTo("#el", { rotationX: 90 }, { rotationX: 0, duration: 1 });Opciones (todos los helpers y presets)
options es un objeto PresetOptions: cualquier gsap.TweenVars más:
El tipo público
PresetOptionsextiende directamentegsap.TweenVars, así que tu editor autocompleta todas las propiedades de animación (scale,x,rotation,opacity,stagger, …) igual que lo hacegsap.to.
| Opción | Tipo | Default | Descripción |
| --- | --- | --- | --- |
| scroll | boolean \| ScrollTriggerOptions | true | true dispara al entrar al viewport (start: "top 85%", once: true). false reproduce de inmediato. Pasa un objeto para control total. Solo aplica a animaciones sueltas. |
| timeline | gsap.core.Timeline | — | Si se define, la animación se añade a esa timeline en lugar de reproducirse suelta. El scroll individual se ignora — el gatillo vive en la timeline. |
| position | gsap.Position | — | Posición dentro de la timeline (p. ej. "<", "-=0.2", 2). |
ScrollTriggerOptions = cualquier ScrollTrigger.Vars más un atajo once: boolean:
animateFrom(".item", {
stagger: 0.1,
scroll: { start: "top 80%", once: false }, // se repite al salir/entrar
});
const tl = gsap.timeline();
animateFrom(".a", { timeline: tl });
animateFrom(".b", { timeline: tl, position: "-=0.2" });Scroll + timeline: scrollTimeline(options?)
Para secuenciar varias piezas que se disparan juntas al entrar un elemento en el
viewport, crea la timeline con scrollTimeline. El ScrollTrigger se pone en la
propia timeline y los helpers hijos se añaden con timeline (los scroll individuales
se ignoran ahí):
import { scrollTimeline, typewriter, splitTextReveal, animateFrom } from "gsap-presets-kit";
const tl = scrollTimeline({ trigger: "#hero", start: "top 75%", once: true });
typewriter("#hero-title", { timeline: tl, highlight: ["Orlando"], highlightClass: "text-primary-500" });
splitTextReveal("#hero-subtitle", { timeline: tl, position: "-=0.2", type: "words", y: 30, yPercent: 0 });
animateFrom("#hero-description", { timeline: tl, position: "-=0.2", x: -30, y: 0 });Toda la secuencia (antes/durante/después, ordenada con position) se reproduce cuando
#hero entra en el viewport. scrollTimeline acepta cualquier ScrollTriggerOptions
(trigger, start, once, toggleActions, end, pin, scrub, …).
Movimiento reducido:
animateFrom/animateTo/animateFromTono hacen nada especial (GSAP es instantáneo por defecto) — el presetmarqueese omite a sí mismo cuando hayprefers-reduced-motion: reduce(configurable).
Presets especiales
splitTextReveal(target, options?)
Divide el texto en chars, words o lines y los anima hacia dentro.
Defaults: { type: "words", yPercent: 110, opacity: 0, duration: 0.7, ease: "power3.out", stagger: 0.04 }.
splitTextReveal("#title", { type: "chars", stagger: 0.02 });
splitTextReveal("#title", { type: "lines", highlight: ["GSAP"], highlightClass: "text-accent" });
splitTextReveal("#title", { revertOnComplete: true });Opciones propias de SplitText: type ("chars" | "words" | "lines"), highlight
(string/string[] — las piezas que coincidan reciben highlightClass), highlightClass
(default "is-highlighted"), revertOnComplete.
typewriter(target, options?)
Escribe el texto del target char por char o palabra por palabra.
typewriter("#typed", {
speed: 55, // ms por char (se ignora si defines `duration`)
duration: 3, // segundos totales — sobrescribe speed
delay: 0.2, // segundos antes de empezar
mode: "chars", // "chars" | "words"
cursor: true,
cursorChar: "|",
blinkSpeed: 500, // ms
highlight: ["gsap"], // el texto que coincida recibe highlightClass
highlightClass: "is-highlighted",
loop: false,
scroll: true,
onStart: () => console.log("inicio"),
onUpdate: (count, total) => console.log(count, total),
onComplete: () => console.log("fin"),
});marquee(target, options?)
Loop infinito y sin costuras. Pasa el track (un contenedor flex; el padre debe tener
overflow: hidden) o un array de items más un container:
marquee(".track"); // usa los hijos de .track
marquee(".track", { speed: 90, direction: "right" });
marquee(items, { container: trackEl, speed: 70 }); // items explícitosOpciones: speed (px/s, default 50), direction ("left" | "right"),
pauseOnHover (default true), responsive (recalcula al redimensionar),
reducedMotion (default true), container (para el modo items).
ScrollTrigger y plugins
Los plugins se registran automáticamente (una sola vez) la primera vez que se
necesitan — ScrollTrigger cuando usas scroll, SplitText cuando usas splitTextReveal.
Nunca tienes que llamar a gsap.registerPlugin tú mismo, salvo que también crees tweens
crudos con esos plugins.
TypeScript y Zod
Cada objeto de opciones se valida con Zod antes de usarse — una entrada inválida lanza un error claro y legible en lugar de producir bugs de animación silenciosos:
import { presetOptionsSchema } from "gsap-presets-kit";
presetOptionsSchema.parse({ duration: -1 });
// ZodError: Too small: expected number to be >0Schemas exportados: presetOptionsSchema, scrollTriggerOptionsSchema,
scrollModeSchema, splitTextOptionsSchema, typewriterOptionsSchema,
marqueeOptionsSchema, además de targetSchema, easeSchema, timelineSchema,
positionSchema. Los tipos públicos de las opciones se derivan de ellos, así que lo que
escribes es lo que se valida.
SSR / frameworks
El paquete es seguro de importar en entornos SSR (p. ej. Astro, Next) — los helpers
devuelven undefined cuando no hay document. Para animaciones por scroll en React,
combínalo con useGSAP() de @gsap/react y llama a ScrollTrigger.refresh() tras
cambios de layout asíncronos.
Playground
Una demo Vite vanilla que cubre todos los helpers y presets vive en playground/:
pnpm install
pnpm build # primero compila la librería (el playground consume dist/)
pnpm --filter playground devDocumentación
Scripts
pnpm build # ESM + CJS + tipos con tsup
pnpm typecheck # tsc --noEmit
pnpm dev # modo watch de la libreríaLicencia
MIT © Orlando Lopez
