From 8c976db165cea2896c86f2938ed95508c8d6af57 Mon Sep 17 00:00:00 2001 From: Sasial <44125644+sasial-dev@users.noreply.github.com> Date: Sat, 17 Aug 2024 17:55:36 +1000 Subject: [PATCH 1/3] feat: add `useSpring` hook --- src/index.ts | 1 + src/use-spring/README.md | 38 +++++++++++++++++++++++++++++++ src/use-spring/index.ts | 1 + src/use-spring/use-spring.spec.ts | 15 ++++++++++++ src/use-spring/use-spring.ts | 25 ++++++++++++++++++++ 5 files changed, 80 insertions(+) create mode 100644 src/use-spring/README.md create mode 100644 src/use-spring/index.ts create mode 100644 src/use-spring/use-spring.spec.ts create mode 100644 src/use-spring/use-spring.ts diff --git a/src/index.ts b/src/index.ts index 8e54fd7..e108294 100644 --- a/src/index.ts +++ b/src/index.ts @@ -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"; diff --git a/src/use-spring/README.md b/src/use-spring/README.md new file mode 100644 index 0000000..7cce5bd --- /dev/null +++ b/src/use-spring/README.md @@ -0,0 +1,38 @@ +## 🪝 `useSpring` + +```ts +function useSpring(goal: T | Binding, options?: SpringOptions): Binding +``` + +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 that fades in and out when hovered. + +```tsx +function Button() { + const [springValue, setSpringValue] = useBinding(0) + const hover = useSpring(springValue, config.spring.stiff); + + return ( + setSpringValue(1), + MouseLeave: () => setSpringValue(0), + }} + Size={new UDim2(0, 100, 0, 100)} + BackgroundTransparency={hover.map((t) => lerp(0.8, 0.5, t))} + /> + ); +} +``` diff --git a/src/use-spring/index.ts b/src/use-spring/index.ts new file mode 100644 index 0000000..a8cee41 --- /dev/null +++ b/src/use-spring/index.ts @@ -0,0 +1 @@ +export * from "./use-spring"; diff --git a/src/use-spring/use-spring.spec.ts b/src/use-spring/use-spring.spec.ts new file mode 100644 index 0000000..e907d96 --- /dev/null +++ b/src/use-spring/use-spring.spec.ts @@ -0,0 +1,15 @@ +/// + +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(); + }); +}; diff --git a/src/use-spring/use-spring.ts b/src/use-spring/use-spring.ts new file mode 100644 index 0000000..16a4a91 --- /dev/null +++ b/src/use-spring/use-spring.ts @@ -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, options?: SpringOptions): Binding; +export function useSpring(goal: T | Binding, options?: SpringOptions): Binding; +export function useSpring(goal: MotionGoal | Binding, 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; +} From a3b4e980a735a8ef207cc85e5698f891655e3798 Mon Sep 17 00:00:00 2001 From: Sasial <44125644+sasial-dev@users.noreply.github.com> Date: Sat, 17 Aug 2024 18:19:35 +1000 Subject: [PATCH 2/3] fix: apply review commments --- src/use-spring/README.md | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/src/use-spring/README.md b/src/use-spring/README.md index 7cce5bd..a33b01b 100644 --- a/src/use-spring/README.md +++ b/src/use-spring/README.md @@ -17,22 +17,14 @@ Applies spring animations to the given value, and updates the goal with the late ### 📘 Example -A button that fades in and out when hovered. +A button changes to the colour of its props. ```tsx function Button() { - const [springValue, setSpringValue] = useBinding(0) - const hover = useSpring(springValue, config.spring.stiff); + const color = useSpring(props.color, config.spring.stiff); return ( - setSpringValue(1), - MouseLeave: () => setSpringValue(0), - }} - Size={new UDim2(0, 100, 0, 100)} - BackgroundTransparency={hover.map((t) => lerp(0.8, 0.5, t))} - /> + ); } ``` From 4a9a0dc5c7860179567a2a15270a5f489cc804c4 Mon Sep 17 00:00:00 2001 From: richard <56808540+littensy@users.noreply.github.com> Date: Sat, 17 Aug 2024 01:24:19 -0700 Subject: [PATCH 3/3] refactor: use props param --- src/use-spring/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/use-spring/README.md b/src/use-spring/README.md index a33b01b..80fdf42 100644 --- a/src/use-spring/README.md +++ b/src/use-spring/README.md @@ -20,8 +20,8 @@ Applies spring animations to the given value, and updates the goal with the late A button changes to the colour of its props. ```tsx -function Button() { - const color = useSpring(props.color, config.spring.stiff); +function Button({ color }: Props) { + const color = useSpring(color, config.spring.stiff); return (