local C=script.Parent.Parent.Parent local U=C.Parent local Z=require(C.Theme)local b=Z.WithTheme local p=C.Validators local w=require(p.StyleValidator)local m=require(U.Sift)local O=require(U.t)local M=require(U.Roact)local r=M.createElement local W=NumberSequence.new({NumberSequenceKeypoint.new(0,0);NumberSequenceKeypoint.new(.5,0);NumberSequenceKeypoint.new(.505,1),NumberSequenceKeypoint.new(1,1)})local V=M.PureComponent:extend(script.Name)V.defaultProps={StrokeColor="\099\111\108\111\114\115\047\085\078\075\078\079\087\078";Value=1,Size=UDim2.fromOffset(100,100),Thickness=30;Clockwise=true}V.validateProps=O.strictInterface({AnchorPoint=O.optional(O.Vector2),StrokeColor=O.optional(w),Clockwise=O.optional(O.boolean);Position=O.optional(O.UDim2);Size=O.optional(O.UDim2);Thickness=O.optional(O.number),Value=O.optional(O.numberConstrained(0,1)),Native=O.optional(O.table)})function V.init(C)C:setState({Size=UDim2.new()})end function V.render(C)local U=C.props local Z=C.state return b(function(b)local p=nil local w=U.Value local m=nil local O=nil if U.Clockwise then p=w<.5 and"\082\105\103\104\116"or w>=.5 and"\076\101\102\116"m=p=="\076\101\102\116"or w>=.5 or nil O=p=="\082\105\103\104\116"or w>=.5 or nil else w=.5-w p=w<.5 and"\076\101\102\116"or w>=.5 and"\082\105\103\104\116"m=p=="\076\101\102\116"or w>=.5 or true O=p=="\082\105\103\104\116"or w>=.5 or true end local V=p=="\076\101\102\116"and r("\085\073\071\114\097\100\105\101\110\116",{Transparency=W;Rotation=w*360})or nil local X=p=="\082\105\103\104\116"and r("\085\073\071\114\097\100\105\101\110\116",{Transparency=W,Rotation=w*360})or nil local i=b[U.StrokeColor]local l=-UDim2.fromOffset(U.Thickness*2,U.Thickness*2)local n=UDim2.new(U.Size.X.Scale/2,U.Size.X.Offset/2,U.Size.Y.Scale,U.Size.Y.Offset)local o=r("\070\114\097\109\101",{AnchorPoint=Vector2.new(.5,.5);Position=UDim2.fromScale(1,.5);BackgroundTransparency=1,Size=Z.Size+l},{Stroke=r("\085\073\083\116\114\111\107\101",{Thickness=U.Thickness;Color=i.Color;Transparency=i.Transparency},{Gradient=V});Corner=r("\085\073\067\111\114\110\101\114",{CornerRadius=UDim.new(1,0)})})local x=r("\070\114\097\109\101",{AnchorPoint=Vector2.new(.5,.5);Position=UDim2.fromScale(0,.5);BackgroundTransparency=1,Size=Z.Size+l},{Stroke=r("\085\073\083\116\114\111\107\101",{Thickness=U.Thickness;Color=i.Color;Transparency=i.Transparency},{Gradient=X}),Corner=r("\085\073\067\111\114\110\101\114",{CornerRadius=UDim.new(1,0)})})local G=m and r("\067\097\110\118\097\115\071\114\111\117\112",{BackgroundTransparency=1;AnchorPoint=Vector2.new(1,.5);Position=UDim2.fromScale(.5,.5);Size=n},{StrokeWrapper=o})local A=O and r("\067\097\110\118\097\115\071\114\111\117\112",{BackgroundTransparency=1;AnchorPoint=Vector2.new(0,.5);Position=UDim2.fromScale(.5,.5),Size=n},{StrokeWrapper=x})return r("\070\114\097\109\101",{Anchorpoint=U.AnchorPoint;BackgroundTransparency=1,Positon=U.Position;Size=U.Size,[M.Change.AbsoluteSize]=function(U)local Z=U.AbsoluteSize C:setState({Size=UDim2.fromOffset(Z.X,Z.Y)})end},{LeftSemiCircle=G;RightSemiCircle=A})end)end return V
-- RadialProgressBar: A circular progress bar
-- Adapted from https://gist.github.com/Reselim/6550108641a3f0f88d69033e7b6556dc

local Winro = script.Parent.Parent.Parent
local Packages = Winro.Parent

local Theme = require(Winro.Theme)
local WithTheme = Theme.WithTheme

local Validators = Winro.Validators
local StyleValidator = require(Validators.StyleValidator)

local Sift = require(Packages.Sift)
local t = require(Packages.t)
local Roact = require(Packages.Roact)
local new = Roact.createElement

local TRANSPARENCY_SEQUENCE = NumberSequence.new({
	NumberSequenceKeypoint.new(0, 0),
	NumberSequenceKeypoint.new(0.5, 0),
	NumberSequenceKeypoint.new(0.505, 1),
	NumberSequenceKeypoint.new(1, 1)
})

local RadialProgressBar = Roact.PureComponent:extend(script.Name)

RadialProgressBar.defaultProps = {
	StrokeColor = 'colors/UNKNOWN',
	Value = 1, --- @defaultProp
	Size = UDim2.fromOffset(100, 100), --- @defaultProp
	Thickness = 30, --- @defaultProp
	Clockwise = true, --- @defaultProp
}

RadialProgressBar.validateProps = t.strictInterface({

	--- @prop @optional AnchorPoint Vector2 Anchor point
	AnchorPoint = t.optional(t.Vector2),

	--- @prop @optional Color string|Table The stroke's color
	StrokeColor = t.optional(StyleValidator),

	--- @prop @optional Clockwise boolean Determines if the rotation is clockwise
	Clockwise = t.optional(t.boolean),

	--- @prop @optional Position UDim2 Position
	Position = t.optional(t.UDim2),

	--- @prop @optional Size UDim2 Size
	Size = t.optional(t.UDim2),

	--- @prop @optional Thickness number The stroke's thickness, in pixels
	Thickness = t.optional(t.number),

	--- @prop @optional Value number The value of the radial progress bar
	Value = t.optional(t.numberConstrained(0, 1)),

	--- @prop @optional Native table Native props
	Native = t.optional(t.table),
})

function RadialProgressBar:init()
	
	-- Initial state
	self:setState({
		Size = UDim2.new(),
	})
end

function RadialProgressBar:render()
	local props = self.props
	local state = self.state

	return WithTheme(function(Theme)

		-- ///////// Determine focus and progress

		local FocusedSide = nil
		local Progress = props.Value
		local IsLeftVisible = nil
		local IsRightVisible = nil

		if props.Clockwise then

			FocusedSide = Progress < 0.5 and 'Right'
			or Progress >= 0.5 and 'Left'

			IsLeftVisible = (FocusedSide == 'Left' or Progress >= 0.5) or nil
			IsRightVisible = (FocusedSide == 'Right' or Progress >= 0.5) or nil
		else
			Progress = 0.5 - Progress

			FocusedSide = Progress < 0.5 and 'Left'
			or Progress >= 0.5 and 'Right'

			IsLeftVisible = (FocusedSide == 'Left' or Progress >= 0.5) or true
			IsRightVisible = (FocusedSide == 'Right' or Progress >= 0.5) or true
		end

		-- ////////// Gradients

		local LeftGradient = FocusedSide == 'Left' and new('UIGradient', {
			Transparency = TRANSPARENCY_SEQUENCE,
			Rotation = Progress * 360,
		}) or nil

		local RightGradient = FocusedSide == 'Right' and new('UIGradient', {
			Transparency = TRANSPARENCY_SEQUENCE,
			Rotation = Progress * 360,
		}) or nil
		
		-- ////////// Stroke Wrappers
		
		local StrokeFill = Theme[props.StrokeColor]

		local StrokeSizeOffset = -UDim2.fromOffset(props.Thickness * 2, props.Thickness * 2)
		local SemiSize = UDim2.new(props.Size.X.Scale / 2, props.Size.X.Offset / 2, props.Size.Y.Scale, props.Size.Y.Offset)

		local LeftStrokeWrapper = new('Frame', {
			AnchorPoint = Vector2.new(0.5, 0.5),
			Position = UDim2.fromScale(1, 0.5),
			BackgroundTransparency = 1,
			Size = state.Size + StrokeSizeOffset,
		}, {

			Stroke = new('UIStroke', {
				Thickness = props.Thickness,
				Color = StrokeFill.Color,
				Transparency = StrokeFill.Transparency,
			}, {
				Gradient = LeftGradient,
			}),
			Corner = new('UICorner', {
				CornerRadius = UDim.new(1, 0),
			}),
		})

		local RightStrokeWrapper = new('Frame', {
			AnchorPoint = Vector2.new(0.5, 0.5),
			Position = UDim2.fromScale(0, 0.5),
			BackgroundTransparency = 1,
			Size = state.Size + StrokeSizeOffset,
		}, {

			Stroke = new('UIStroke', {
				Thickness = props.Thickness,
				Color = StrokeFill.Color,
				Transparency = StrokeFill.Transparency,
			}, {
				Gradient = RightGradient,
			}),
			Corner = new('UICorner', {
				CornerRadius = UDim.new(1, 0),
			}),
		})

		-- ////////// Semi Circles

		local LeftSemiCircle = IsLeftVisible and new('CanvasGroup', {
			BackgroundTransparency = 1,
			AnchorPoint = Vector2.new(1, 0.5),
			Position = UDim2.fromScale(0.5, 0.5),
			Size = SemiSize,
		}, {
			StrokeWrapper = LeftStrokeWrapper,
		})

		local RightSemiCircle = IsRightVisible and new('CanvasGroup', {
			BackgroundTransparency = 1,
			AnchorPoint = Vector2.new(0, 0.5),
			Position = UDim2.fromScale(0.5, 0.5),
			Size = SemiSize,
		}, {
			StrokeWrapper = RightStrokeWrapper,
		})

		-- ////////// Radial Progress Bar
		return new('Frame', {
			Anchorpoint = props.AnchorPoint,
			BackgroundTransparency = 1,
			Positon = props.Position,
			Size = props.Size,

			[Roact.Change.AbsoluteSize] = function (rbx)
				local AbsoluteSize = rbx.AbsoluteSize

				self:setState({
					Size = UDim2.fromOffset(AbsoluteSize.X, AbsoluteSize.Y),
				})
			end,
		}, {
			LeftSemiCircle = LeftSemiCircle,
			RightSemiCircle = RightSemiCircle,
		})
	end)
end

return RadialProgressBar
