Add createSpring primitive.
Summary
- This PR adds the
createSpringprimitive. Inspired and Forked from https://svelte.dev/docs/svelte-motion#spring - The API works exactly like createSignal, just that the setter will actually interpolate the value.
- It also has familiar opts as the one with svelte-motion/spring.
- I come from using Svelte and it's one of the most essential primitives I use for animation. I've been using Solid more and more and have come to love it. I think this primitive is one of the few missing for me here. I think Solid would greatly benefit from a primitive like this since we already have a
tweenprimitive.
Example Usage:
export default function SpringyPage() {
const [progress, setProgress] = createSpring(0);
const [radialProgress, setRadialProgress] = createSpring(0, {
stiffness: 0.05,
});
const [xy, setXY] = createSpring(
{ x: 50, y: 50 },
{ stiffness: 0.08, damping: 0.2, precision: 0.01 }
);
function toggleProgress() {
if (progress() === 0) setProgress(1);
else setProgress(0);
}
// ...
Witness, the springiness:
https://github.com/solidjs-community/solid-primitives/assets/38070918/7c4fa01f-7959-4a67-9588-e28448f7f20d
https://github.com/solidjs-community/solid-primitives/assets/38070918/4dcf9e6f-7a2e-44f8-b15a-d29d6551f561
Todos:
- [x] Tests
- [x] README.md
- [x] package.json
⚠️ No Changeset found
Latest commit: 0222ae166850e189ea2e8b7b354f19e6152bc66c
Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.
This PR includes no changesets
When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types
Click here to learn what changesets are, and how to add one.
Click here if you're a maintainer who wants to add a changeset to this PR
Update: I also figure of adding createDerivedSpring by the way, so that there's a similar API that works like the current createTween's API which doesn't return a setter, but takes in an Signal accessor.
const springValue = createDerivedSpring(signal, opts)
Will add this tonight.
Hi @thetarnav just pushed the latest changes based on your review. Thanks so much for the very thorough comments on it.
I haven't done the tests related to timeouts yet because as you said, timeouts are kind of my nightmare too lol. I'll take a gander at it again soon (maybe tomorrow or in a few hours).
If you want to try playing around with it (with the same example video above). Try running this: https://github.com/blankeos/spring-solid-test (currently I just copy paste the index.ts I didn't do pnpm link or anything lol)
I don't necessarly like that createSpring by default tries to handle various types of data recursively.
The core idea of a spring is just a simple math equation for tweening numbers, but the source code reads like something much more complex.
I wonder if it would be smart to separate it into more functions rather than one-does-all primitive. Maybe a separate primitive for numbers and objects?
It would be nice to have a vanilla-js spring(from, to, time, options) function as well.
Also maybe the primitive could be added to the tween package? The use and concepts are similar. Separate package for each tweening strategy would probably be a lot.
I still need to think about that.
I tried to inline the tasks thing from svelte to the primitive. The tests pass and it works as it should in my eyes, but could you double check @Blankeos? Probably will merge after that.
Awesome work guys! Couldn't really check the past week, it's been a very busy month for me.
Thanks for adding in your insights @thetarnav @rcoopr! 🦾🥳