Skip to content

Commit

Permalink
feat: add useSpring hook (#16)
Browse files Browse the repository at this point in the history
* feat: add `useSpring` hook

* fix: apply review commments

* refactor: use props param

---------

Co-authored-by: richard <56808540+littensy@users.noreply.github.com>
  • Loading branch information
sasial-dev and littensy committed Aug 17, 2024
1 parent 2f19297 commit 28c29a5
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export * from "./use-motion";
export * from "./use-mount-effect";
export * from "./use-mouse";
export * from "./use-previous";
export * from "./use-spring";
export * from "./use-tagged";
export * from "./use-throttle-callback";
export * from "./use-throttle-effect";
Expand Down
30 changes: 30 additions & 0 deletions src/use-spring/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
## 🪝 `useSpring`

```ts
function useSpring<T extends MotionGoal>(goal: T | Binding<T>, options?: SpringOptions): Binding<T>
```

Applies spring animations to the given value, and updates the goal with the latest value on every re-render. Returns a binding that updates with the Motion.

### 📕 Parameters

- `goal` - The goal of the motor.
- `options` - Options for the spring (or a spring config).

### 📗 Returns

- A binding of the motor's value.

### 📘 Example

A button changes to the colour of its props.

```tsx
function Button({ color }: Props) {
const color = useSpring(color, config.spring.stiff);
return (
<textbutton Size={new UDim2(0, 100, 0, 100)} BackgroundColor3={color} />
);
}
```
1 change: 1 addition & 0 deletions src/use-spring/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./use-spring";
15 changes: 15 additions & 0 deletions src/use-spring/use-spring.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/// <reference types="@rbxts/testez/globals" />

import { renderHook } from "../utils/testez";
import { useSpring } from "./use-spring";

export = () => {
it("should return a binding", () => {
const { result, unmount } = renderHook(() => useSpring(0));

expect(result.current.getValue()).to.be.a("number");
expect(result.current.getValue()).to.equal(0);

unmount();
});
};
25 changes: 25 additions & 0 deletions src/use-spring/use-spring.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import type { Binding } from "@rbxts/react";
import { useRef } from "@rbxts/react";
import type { MotionGoal, SpringOptions } from "@rbxts/ripple";
import { useMotion } from "../use-motion";
import { getBindingValue } from "../utils/binding";
import { useEventListener } from "../use-event-listener";
import { RunService } from "@rbxts/services";

export function useSpring(goal: number | Binding<number>, options?: SpringOptions): Binding<number>;
export function useSpring<T extends MotionGoal>(goal: T | Binding<T>, options?: SpringOptions): Binding<T>;
export function useSpring(goal: MotionGoal | Binding<MotionGoal>, options?: SpringOptions) {
const [binding, motion] = useMotion(getBindingValue(goal));
const previousValue = useRef(getBindingValue(goal));

useEventListener(RunService.Heartbeat, () => {
const currentValue = getBindingValue(goal);

if (currentValue !== previousValue.current) {
previousValue.current = currentValue;
motion.spring(currentValue, options);
}
});

return binding;
}

0 comments on commit 28c29a5

Please sign in to comment.