From f333c7332aa4b5dcba54bf8c75e824d5a06f75dc Mon Sep 17 00:00:00 2001
From: Jack Fox <0xdeadbeef1@gmail.com>
Date: Wed, 12 Mar 2025 09:58:39 -0700
Subject: [PATCH 1/3] Add textSize tween animation to TestAnimation function

---
 test/Test.lua | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/test/Test.lua b/test/Test.lua
index 5604d65..7791381 100644
--- a/test/Test.lua
+++ b/test/Test.lua
@@ -60,6 +60,10 @@ end
 local function TestAnimation()
 	local sequence, play, stop = useGroupAnimation({
 		moveRight = useAnimation({
+			textSize = Tween({
+				info = TweenInfo.new(1, Enum.EasingStyle.Back),
+				target = 25,
+			}),
 			position = Spring({
 				target = UDim2.fromScale(0.8, 0),
 				speed = 5,
@@ -73,8 +77,13 @@ local function TestAnimation()
 				speed = 5,
 				damper = 0.7,
 			}),
+			textSize = Tween({
+				info = TweenInfo.new(1, Enum.EasingStyle.Back),
+				target = 10,
+			}),
 		}),
 	}, {
+		textSize = 10,
 		size = UDim2.fromOffset(200, 200),
 		position = UDim2.fromScale(0.5, 0),
 	})
@@ -101,6 +110,7 @@ local function TestAnimation()
 		Name = "Animation Group",
 		Position = sequence.position,
 		Size = sequence.size,
+		TextSize = sequence.textSize,
 		ParentSize = UDim2.fromScale(1, 0.25),
 	})
 end

From a935960cb715de31402463dd945092e1b908e477 Mon Sep 17 00:00:00 2001
From: Jack Fox <0xdeadbeef1@gmail.com>
Date: Wed, 12 Mar 2025 09:58:43 -0700
Subject: [PATCH 2/3] Add immediate playback option to animation functions

---
 src/Animations/Types/Spring.lua    |  4 +++-
 src/Animations/Types/Tween.lua     | 11 ++++++++++-
 src/Hooks/useAnimation.lua         |  4 ++--
 src/Hooks/useGroupAnimation.lua    | 11 +++++------
 src/Hooks/useSequenceAnimation.lua |  6 +++---
 src/Hooks/useSpring.lua            |  4 +++-
 src/Hooks/useTween.lua             |  6 +++---
 src/Utility/SpringValue.lua        | 15 +++++++++++++++
 8 files changed, 44 insertions(+), 17 deletions(-)

diff --git a/src/Animations/Types/Spring.lua b/src/Animations/Types/Spring.lua
index 3b850f2..f213ffd 100644
--- a/src/Animations/Types/Spring.lua
+++ b/src/Animations/Types/Spring.lua
@@ -12,6 +12,7 @@ export type SpringProperties = {
 	speed: number?,
 	start: any,
 	target: any,
+	force: any?,
 }
 
 function Spring.definition(props: SpringProperties)
@@ -30,7 +31,7 @@ function Spring.new(props: SpringProperties)
 	return self
 end
 
-function Spring:Play(from: any?)
+function Spring:Play(from: any?, immediate: boolean?)
 	if self.playing then
 		self:Stop()
 	end
@@ -47,6 +48,7 @@ function Spring:Play(from: any?)
 	end
 
 	local newSpring = SpringValue.new(baseFromValue, self.props.speed, self.props.damper)
+	newSpring:SetImmediate(immediate)
 	newSpring:SetGoal(baseToValue)
 
 	local oldVelocity = self._oldSpring and self._oldSpring:GetVelocity()
diff --git a/src/Animations/Types/Tween.lua b/src/Animations/Types/Tween.lua
index e14caad..1954142 100644
--- a/src/Animations/Types/Tween.lua
+++ b/src/Animations/Types/Tween.lua
@@ -146,7 +146,7 @@ function Tween.new<T>(props: TweenProperties<T>)
 	return self
 end
 
-function Tween:Play(from: any?)
+function Tween:Play(from: any?, immediate: boolean?)
 	if self.playing then
 		self:Stop()
 	end
@@ -182,6 +182,15 @@ function Tween:Play(from: any?)
 	local fromValue = LinearValue.fromValue(baseFromValue)
 	local toValue = LinearValue.fromValue(baseToValue)
 
+	if immediate then
+		self.listener(baseToValue)
+
+		self.playing = false
+		self.player = nil
+
+		return Promise.resolve()
+	end
+
 	local animation = Promise.new(function(resolve, _, onCancel)
 		local play, cancel = playTween2(tweenInfo, function(value)
 			local newValue = fromValue:Lerp(toValue, value):ToValue()
diff --git a/src/Hooks/useAnimation.lua b/src/Hooks/useAnimation.lua
index e41baeb..67f6d08 100644
--- a/src/Hooks/useAnimation.lua
+++ b/src/Hooks/useAnimation.lua
@@ -38,7 +38,7 @@ function Animation:SetListener(listener: (string, any) -> ())
 	self.listener = listener
 end
 
-function Animation:Play(fromProps: AnimationProps)
+function Animation:Play(fromProps: AnimationProps, immediate: boolean?)
 	if self.playing then
 		self:Stop()
 	end
@@ -47,7 +47,7 @@ function Animation:Play(fromProps: AnimationProps)
 		local promises = {}
 
 		for name, animatable in self.animation do
-			local animationPromise = animatable:Play(fromProps[name])
+			local animationPromise = animatable:Play(fromProps[name], immediate)
 			table.insert(promises, animationPromise)
 		end
 
diff --git a/src/Hooks/useGroupAnimation.lua b/src/Hooks/useGroupAnimation.lua
index 4eb9dd5..f70a040 100644
--- a/src/Hooks/useGroupAnimation.lua
+++ b/src/Hooks/useGroupAnimation.lua
@@ -10,7 +10,7 @@ type StateSetters = {
 }
 
 export type Animation = {
-	Play: (DefaultProperties) -> Animation,
+	Play: (DefaultProperties, boolean?) -> Animation,
 	Stop: () -> nil,
 }
 
@@ -45,7 +45,7 @@ function GroupAnimationController.new(props: GroupAnimation, default: DefaultPro
 	return self
 end
 
-function GroupAnimationController:Play(newState: string)
+function GroupAnimationController:Play(newState: string, immediate: boolean?)
 	local animation = self.animations[newState]
 	assert(animation, `No animation found for state {newState}`)
 
@@ -56,7 +56,7 @@ function GroupAnimationController:Play(newState: string)
 	end
 
 	self.currentAnimation = animation
-	animation:Play(self.state)
+	animation:Play(self.state, immediate)
 end
 
 function GroupAnimationController:Stop()
@@ -98,10 +98,9 @@ local function useGroupAnimation(props: GroupAnimation, default: DefaultProperti
 				newController:UpdateSetters(newSetters)
 			end,
 
-			play = function(newState: string)
+			play = function(newState: string, immediate: boolean?)
 				assert(typeof(newState) == "string", "useGroupAnimation expects a string 'state'")
-
-				newController:Play(newState)
+				newController:Play(newState, immediate)
 			end,
 
 			stop = function()
diff --git a/src/Hooks/useSequenceAnimation.lua b/src/Hooks/useSequenceAnimation.lua
index 459d11c..21e6bcd 100644
--- a/src/Hooks/useSequenceAnimation.lua
+++ b/src/Hooks/useSequenceAnimation.lua
@@ -65,7 +65,7 @@ function Sequence:SetListener(listener: (string, any) -> ())
 	self.listener = listener
 end
 
-function Sequence:Play(fromProps: SequenceProps)
+function Sequence:Play(fromProps: SequenceProps, immediate: boolean?)
 	if self.playing then
 		self:Stop()
 	end
@@ -75,7 +75,7 @@ function Sequence:Play(fromProps: SequenceProps)
 		local playing = {}
 
 		for _, sequenced in self.animation do
-			local animationPromise = Promise.delay(sequenced.timestamp):andThen(function()
+			local animationPromise = Promise.delay(if immediate then 0 else sequenced.timestamp):andThen(function()
 				local allAnimatables = {}
 
 				for name, animatable in sequenced do
@@ -87,7 +87,7 @@ function Sequence:Play(fromProps: SequenceProps)
 						playing[name]:cancel()
 					end
 
-					local promise = animatable:Play(fromProps[name])
+					local promise = animatable:Play(fromProps[name], immediate)
 					playing[name] = promise
 
 					table.insert(allAnimatables, promise)
diff --git a/src/Hooks/useSpring.lua b/src/Hooks/useSpring.lua
index b33202c..b55f81f 100644
--- a/src/Hooks/useSpring.lua
+++ b/src/Hooks/useSpring.lua
@@ -14,9 +14,11 @@ local function useSpring(props: Spring.SpringProperties)
 		return {
 			spring = spring,
 
-			start = function(subProps: Spring.SpringProperties)
+			start = function(subProps: Spring.SpringProperties, immediate: boolean?)
 				assert(typeof(subProps) == "table", "useSpring expects a table of properties")
 
+				spring:SetImmediate(immediate)
+
 				if subProps.target then
 					spring:SetGoal(subProps.target)
 				end
diff --git a/src/Hooks/useTween.lua b/src/Hooks/useTween.lua
index a53eb06..7a05d42 100644
--- a/src/Hooks/useTween.lua
+++ b/src/Hooks/useTween.lua
@@ -14,15 +14,15 @@ local function useTween<T>(props: Tween.TweenProperties<T>)
 		return {
 			tween = tween,
 
-			start = function(subProps: Tween.TweenProperties<T>)
+			start = function(subProps: Tween.TweenProperties<T>, immediate: boolean?)
 				assert(typeof(subProps) == "table", "useTween expects a table of properties")
 
 				tween.props.info = subProps.info or tween.props.info
 				tween.props.start = subProps.start or binding:getValue()
 				tween.props.target = subProps.target or tween.props.target
-				tween.props.immediate = subProps.immediate or tween.props.immediate
+				tween.props.startImmediate = subProps.startImmediate or tween.props.startImmediate
 				tween.props.delay = subProps.delay or tween.props.delay
-				tween:Play(subProps.start or binding:getValue())
+				tween:Play(subProps.start or binding:getValue(), immediate)
 			end,
 
 			stop = function()
diff --git a/src/Utility/SpringValue.lua b/src/Utility/SpringValue.lua
index 98060ee..56964f0 100644
--- a/src/Utility/SpringValue.lua
+++ b/src/Utility/SpringValue.lua
@@ -23,6 +23,7 @@ function SpringValue.new(initial: LinearValue.LinearValueType, speed: number?, d
 		_velocities = velocity,
 		_speed = speed or 1,
 		_damper = damper or 1,
+		_immediate = false,
 		_updater = nil,
 	}, SpringValue)
 end
@@ -55,6 +56,10 @@ function SpringValue:SetDamper(damper: number)
 	self._damper = damper
 end
 
+function SpringValue:SetImmediate(immediate: boolean)
+	self._immediate = immediate
+end
+
 function SpringValue:SetUpdater(updater: (any) -> ())
 	self._updater = updater
 
@@ -118,6 +123,16 @@ function SpringValue:Run(update: () -> ()?)
 		self._updater = update
 	end
 
+	if self._immediate then
+		self._current = self._goal
+
+		if self._updater then
+			self._updater(self:GetValue())
+		end
+
+		return Promise.resolve()
+	end
+
 	return Promise.new(function(resolve, _, onCancel)
 		onCancel(function()
 			self:Stop()

From ed55027a8c0011ea4a1aec80c84c9fe370e4d2de Mon Sep 17 00:00:00 2001
From: Jack Fox <0xdeadbeef1@gmail.com>
Date: Wed, 12 Mar 2025 10:00:15 -0700
Subject: [PATCH 3/3] Bump version to 0.1.4 in wally.toml

---
 wally.toml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/wally.toml b/wally.toml
index d52cc05..3ba06eb 100644
--- a/wally.toml
+++ b/wally.toml
@@ -1,7 +1,7 @@
 [package]
 name = "outofbears/react-flow"
 description = "React Animation Library for Roblox"
-version = "0.1.3"
+version = "0.1.4"
 authors = ["Jack Fox <jack@infernal.io>"]
 homepage = "https://github.com/outofbears/react-flow"
 registry = "https://github.com/UpliftGames/wally-index"
