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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@profesornoobz1440x/otter

v1.0.3

Published

Declarative animation library for Roblox Lua built around (but not limited to) springs.

Readme

Otter

Installation

Filesystem

  • Add this repository as a Git submodule or copy it into your project
  • Use a plugin like Rojo to sync the lib folder into a place

Model File

  • Download the rbxmx model file attached to the latest release from the GitHub releases page
  • Insert the model into Studio into a place like ReplicatedStorage

Documentation

Documentation for Otter is available on the official documentation website.

Usage

For each value that needs to be animated, create a motor object and subscribe to it.

You can create a single motor to track a single value:

local object = Instance.new("Frame")
object.Size = UDim2.new(0, 50, 0, 50)

-- Our initial value is 0
local motor = Otter.createSingleMotor(0)

-- ...but we're moving to 50!
motor:setGoal(Otter.spring(50))

motor:onStep(function(value)
	object.Position = UDim2.new(0, value, 0, 0)
end)

-- Once started, our motor will run every frame until it reaches its goal.
motor:start()

Or you can create a group motor for transitioning multiple values:

local object = Instance.new("Frame")
object.Size = UDim2.new(0, 50, 0, 50)

-- Our initial value is { x = 0, y = 0 }.
local multimotor = Otter.createGroupMotor({
	x = 0,
	y = 0,
})

-- We're moving to { x = 50, y = 50 } with a spring on the X axis.
multimotor:setGoal({
	x = Otter.spring(50),
	y = Otter.instant(50),
})

multimotor:onStep(function(values)
	object.Position = UDim2.new(0, values.x, 0, values.y)
end)

-- Start your engine!
multimotor:start()

The motor object is in charge of tracking all of the values involved in an animation. Otter.spring and Otter.instant are called goal specifiers. They describe what value we're trying to animate to and how to get there.

We can update our goals whenever and Otter will continue our animation:

-- Immediately move the motor's value to 100
motor:setGoal(Otter.instant(100))

-- Spring on both axes to 300
multimotor:setGoal({
	x = Otter.spring(300),
	y = Otter.spring(300),
})

At any time, we can stop our motor, and even step it manually. This is useful for tests!

motor:stop()

motor:step(0.5)

motor:start()

When you're done, destructing a motor object will tear everything down and stop it:

motor:destroy()
multimotor:destroy()

Demo App

You can play with spring settings in a demo app on Roblox: https://www.roblox.com/games/4739513533
Try setting Damping Ratio to 0.1.

License

Licensed under MIT license (LICENSE or http://opensource.org/licenses/MIT)

Contribution

Take a look at the contributing guide for guidelines on how to contribute to Otter.