npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

kinety

v0.1.1

Published

Lightweight animation primitives for Remotion — FadeIn, Spin, Pop, and more.

Readme

Kinety

Lightweight animation primitives for Remotion — declarative, keyframe-based motion for videos and motion graphics.

import { FadeIn, Spin, Pop } from "kinety"

export const MyVideo = () => (
  <>
    <FadeIn from={0} duration={30}>
      <h1>Welcome</h1>
    </FadeIn>

    <Spin from={30} duration={60} loop>
      <Logo />
    </Spin>
  </>
)

Why Kinety

Remotion gives you interpolate and spring, but wiring up multi-property, multi-stage animations (fade in, overshoot, settle) by hand means a lot of repeated boilerplate. Kinety wraps that pattern into:

  • Keyframe objects instead of manual interpolate calls per property
  • Ready-made components (<FadeIn>, <Spin>, <Pop>, ...) for common motion patterns
  • A <Motion> escape hatch for fully custom keyframes without writing a new component
  • Zero dependencies beyond react and remotion (both peer deps — nothing is bundled)

Install

npm install kinety remotion react

remotion and react are peer dependencies — Kinety uses whatever versions are already in your project.

Quick start

Every component wraps its children in a <div> and animates opacity, scale, rotate, translateX, and translateY via CSS transform, driven by the current Remotion frame.

import { FadeIn } from "kinety"

<FadeIn from={10} duration={20}>
  <p>Fades in starting at frame 10, over 20 frames.</p>
</FadeIn>

| Prop | Type | Default | Description | |-------------|------------|---------|-------------------------------------------------------------------------------| | from | number | 0 | Frame the animation starts on | | duration | number | 30 | Number of frames the animation runs over | | loop | boolean | false | Repeats the animation every duration frames after from | | keyframes | Keyframes| preset | Overrides the component's built-in keyframes entirely | | style | CSSProperties | — | Extra styles merged onto the wrapper <div>, applied before the animation |

Built-in components

| Component | Effect | |------------------|------------------------------------------------------| | <FadeIn> | Opacity 0 → 1 | | <FadeOut> | Opacity 1 → 0 | | <Spin> | Rotate 0 → 360deg (pair with loop for continuous spin) | | <ScaleIn> | Scale 0 → 1 with fade | | <Pop> | Scale 0 → 1.15 → 1 — overshoot pop-in with fade | | <SlideInLeft> | Translate in from the left with fade | | <SlideInRight> | Translate in from the right with fade | | <SlideInUp> | Translate in from below with fade | | <SlideInDown> | Translate in from above with fade | | <Bounce> | Vertical bounce, settles at rest | | <Pulse> | Scale breathing effect (1 → 1.08 → 1), good with loop | | <Motion> | No default keyframes — pass your own via keyframes |

Examples

Looping spinner:

<Spin from={0} duration={60} loop>
  <Icon name="loader" />
</Spin>

One-shot pop-in badge:

<Pop from={20} duration={20}>
  <Badge>New</Badge>
</Pop>

Custom keyframes with <Motion>:

<Motion
  from={0}
  duration={40}
  keyframes={{
    0:   { translateX: -200, rotate: -20, opacity: 0 },
    100: { translateX: 0, rotate: 0, opacity: 1 },
  }}
>
  <Card />
</Motion>

Overriding a preset's keyframes on a named component:

<FadeIn
  from={0}
  duration={30}
  keyframes={{ 0: { opacity: 0, scale: 0.8 }, 100: { opacity: 1, scale: 1 } }}
>
  <Title />
</FadeIn>

Writing custom keyframes

Keyframes are keyed by percentage of progress through the animation (0100), not raw frame numbers — Kinety maps from/duration onto that range internally. Any subset of properties can be set per keyframe; properties don't need to appear at every step.

const keyframes = {
  0:   { scale: 0, opacity: 0.2 },
  50:  { scale: 1.5 },
  100: { scale: 1, opacity: 1 },
}

Here, opacity only has two defined points (0 and 100) and interpolates directly between them, ignoring the scale-only keyframe at 50.

Animatable properties:

type AnimationProperties = {
  opacity: number
  rotate: number      // degrees
  scale: number
  translateX: number  // px
  translateY: number  // px
}

The useAnimation hook

For custom components that need animated styles without the <div> wrapper, use the hook directly:

import { useAnimation } from "kinety"

function MyComponent() {
  const style = useAnimation(
    { 0: { opacity: 0 }, 100: { opacity: 1 } },
    { from: 0, duration: 30 }
  )

  return <img src="logo.png" style={style} />
}

useAnimation(keyframes, options) returns { transform: string; opacity: number }, ready to spread onto any element's style.

The Animation class (core engine)

For advanced use — e.g. driving non-React consumers, or computing values outside a render — use Animation directly:

import { Animation } from "kinety"

const fadeIn = new Animation({
  0: { scale: 0, opacity: 0.2 },
  50: { scale: 1.5 },
  100: { scale: 1, opacity: 1 },
})

const { transform, opacity } = fadeIn.animate({ frame, from: 90, duration: 85 })

animate clamps frame to the [from, from + duration] window, so calling it with a frame outside that range holds the first or last defined state instead of throwing.

Loop behavior

loop: true repeats the animation on a duration-frame cycle, starting at from. This is intended for components like <Spin> or <Pulse> that are meant to repeat continuously — one-shot effects like <FadeIn> or <SlideInUp> typically shouldn't set loop, since they're designed to settle and hold their final state.

<Pulse from={0} duration={40} loop>
  <Dot />
</Pulse>

TypeScript

Kinety is written in TypeScript and ships its own .d.ts files — no @types package needed.

Contributing

Issues and PRs are welcome. If you're adding a new preset, add it to src/presets.ts and export a matching component from src/components.tsx following the existing createAnimatedComponent(name, keyframes) pattern.

License

MIT