local types = require("@types")

return function(self, properties: types.PullDownButtonProperties): types.PullDownButton
	--// Imports
	local creator = require("@modules/creator")
	local binder = require("@modules/binder")
	local services = require("@modules/services")

	--// References
	local create = creator.Create

	local userInputService = services.UserInputService
	local tweenService = services.TweenService
	local workspace = services.Workspace
	local guiService = services.GuiService

	local camera = workspace.CurrentCamera

	--// Variables
	local parent = self.__container or self.__instance or self
	local theme = self.Theme.Controls.MenuButton
	local structures = {
		Options = {},
	}

	--// Constants
	local HORIZONTAL_OFFSET = -1
	local VERTICAL_PADDING = 6
	local EDGE_BUFFER = 6

	--// Functions
	local function anchor()
		local body = structures.Body
		local menu = structures.Menu

		if not menu or not body then
			return
		end

		local bodyPos = body.AbsolutePosition
		local bodySize = body.AbsoluteSize
		local menuSize = menu.AbsoluteSize
		local viewportSize = camera.ViewportSize

		local desiredX = bodyPos.X + HORIZONTAL_OFFSET
		local desiredY = bodyPos.Y + (bodySize.Y * 3) + (VERTICAL_PADDING * 3) -- position below

		local maxX = math.max(EDGE_BUFFER, viewportSize.X - EDGE_BUFFER - menuSize.X)
		local maxY = math.max(EDGE_BUFFER, viewportSize.Y - EDGE_BUFFER - menuSize.Y)

		desiredX = math.clamp(desiredX, EDGE_BUFFER, maxX)
		desiredY = math.clamp(desiredY, EDGE_BUFFER, maxY)

		menu.Position = UDim2.new(0, desiredX, 0, desiredY)
	end

	local function option(object, name, index)
		local option = nil
		option = create("TextButton")({
			Name = "Item",
			Size = UDim2.fromScale(1, 0),
			AutoButtonColor = false,
			AutomaticSize = Enum.AutomaticSize.XY,
			BorderColor3 = Color3.fromRGB(0, 0, 0),
			BorderSizePixel = 0,
			Selectable = false,
			Text = "",
			LayoutOrder = index,
			Parent = structures.Menu,

			__dynamicKeys = {
				BackgroundColor3 = self.Theme.Controls.SelectionFocused[1],
				BackgroundTransparency = self.Theme.Controls.SelectionFocused[2],
			},
			__contextKeys = {
				BackgroundTransparency = function()
					if not option then
						return
					end
					return option.GuiState == Enum.GuiState.Hover and self.Theme.Controls.SelectionFocused[2].Value or 1
				end,
			},

			create("UIPadding")({
				Name = "UIPadding",
				PaddingBottom = UDim.new(0, 3),
				PaddingLeft = UDim.new(0, 7),
				PaddingRight = UDim.new(0, 12),
				PaddingTop = UDim.new(0, 3),
			}),

			create("UIListLayout")({
				Name = "UIListLayout",
				FillDirection = Enum.FillDirection.Horizontal,
				Padding = UDim.new(0, 2),
				SortOrder = Enum.SortOrder.LayoutOrder,
				VerticalAlignment = Enum.VerticalAlignment.Center,
			}),

			create("TextLabel")({
				Name = "Label",
				AutomaticSize = Enum.AutomaticSize.XY,
				BackgroundColor3 = Color3.fromRGB(255, 255, 255),
				BackgroundTransparency = 1,
				BorderColor3 = Color3.fromRGB(0, 0, 0),
				BorderSizePixel = 0,
				FontFace = Font.new("rbxassetid://12187365364"),
				LayoutOrder = 1,
				RichText = true,
				Text = name,
				TextColor3 = Color3.fromRGB(0, 0, 0),
				TextSize = 15,
				TextTransparency = 0.15,
				TextTruncate = Enum.TextTruncate.AtEnd,

				__dynamicKeys = {
					TextColor3 = self.Theme.Text.Primary[1],
					TextTransparency = self.Theme.Text.Primary[2],
				},
			}),

			create("UICorner")({
				Name = "UICorner",
				CornerRadius = UDim.new(0, 5),
			}),
		}) :: TextButton
		local label = option:FindFirstChild("Label")

		structures.Options[index] = option.__instance

		option:GetPropertyChangedSignal("GuiState"):Connect(function()
			if not object.Expanded then
				return
			end

			if option.GuiState == Enum.GuiState.Hover then
				option.BackgroundTransparency = self.Theme.Controls.SelectionFocused[2].Value

				label.TextColor3 = self.Theme.Controls.SelectionFocusedAccent[1].Value
				label.TextTransparency = self.Theme.Controls.SelectionFocusedAccent[2].Value
			else
				option.BackgroundTransparency = 1

				label.TextColor3 = self.Theme.Text.Primary[1].Value
				label.TextTransparency = self.Theme.Text.Primary[2].Value
			end
		end)

		option.MouseButton1Click:Connect(function()
			if object then
				object.Expanded = false
				object.Value = index
			end
		end)
	end

	--// UI
	properties = properties or {}
	properties.Expanded = properties.Expanded or false

	structures.Body = binder.Apply(
		properties,
		create("TextButton")({
			Name = "PullDownButton",
			AutomaticSize = Enum.AutomaticSize.XY,
			BackgroundColor3 = Color3.fromRGB(255, 255, 255),
			BackgroundTransparency = 1,
			BorderColor3 = Color3.fromRGB(0, 0, 0),
			BorderSizePixel = 0,
			Selectable = false,
			Text = "",
			Parent = parent,

			create("UIPadding")({
				Name = "UIPadding",
				PaddingBottom = UDim.new(0, 3),
				PaddingLeft = UDim.new(0, 7),
				PaddingRight = UDim.new(0, 3),
				PaddingTop = UDim.new(0, 3),
			}),

			create("UIListLayout")({
				Name = "UIListLayout",
				FillDirection = Enum.FillDirection.Horizontal,
				Padding = UDim.new(0, 7),
				SortOrder = Enum.SortOrder.LayoutOrder,
				VerticalAlignment = Enum.VerticalAlignment.Center,
			}),

			create("Frame")({
				Name = "PullDownIndicator",
				BorderColor3 = Color3.fromRGB(0, 0, 0),
				BorderSizePixel = 0,
				LayoutOrder = 1,
				Selectable = true,
				Size = UDim2.fromOffset(16, 16),

				__dynamicKeys = {
					BackgroundColor3 = theme.IndicatorBackground[1],
					BackgroundTransparency = theme.IndicatorBackground[2],
				},

				create("UICorner")({
					Name = "UICorner",
					CornerRadius = UDim.new(0, 4),
				}),

				create("ImageLabel")({
					Name = "Indicators",
					BackgroundColor3 = Color3.fromRGB(255, 255, 255),
					BackgroundTransparency = 1,
					BorderColor3 = Color3.fromRGB(0, 0, 0),
					BorderSizePixel = 0,
					Image = "rbxassetid://86693411280110",
					Size = UDim2.fromScale(1, 1),

					__dynamicKeys = {
						ImageColor3 = self.Theme.Text.Primary[1],
						ImageTransparency = self.Theme.Text.Primary[2],
					},
				}),
			}),

			create("TextLabel")({
				Name = "Label",
				AutomaticSize = Enum.AutomaticSize.XY,
				BackgroundColor3 = Color3.fromRGB(255, 255, 255),
				BackgroundTransparency = 1,
				BorderColor3 = Color3.fromRGB(0, 0, 0),
				BorderSizePixel = 0,
				FontFace = Font.new("rbxassetid://12187365364"),
				RichText = true,
				TextSize = 15,
				TextTransparency = 0.15,
				TextTruncate = Enum.TextTruncate.AtEnd,
				Visible = false,

				__dynamicKeys = {
					TextColor3 = self.Theme.Text.Primary[1],
					TextTransparency = self.Theme.Text.Primary[2],
				},
			}),
		})
	) :: TextButton

	--// Initialize
	structures.PullDownIndicator = structures.Body:FindFirstChild("PullDownIndicator") :: Frame
	structures.CurrentTab = structures.Body:FindFirstChild("Label") :: TextLabel

	structures.MenuContainer = create("ScreenGui")({
		Name = "Container",
		IgnoreGuiInset = true,
		ScreenInsets = Enum.ScreenInsets.None,
		ZIndexBehavior = Enum.ZIndexBehavior.Sibling,
		DisplayOrder = 201,
		OnTopOfCoreBlur = true,

		create("CanvasGroup")({
			Name = "MenuBody",
			BorderColor3 = Color3.fromRGB(0, 0, 0),
			BorderSizePixel = 0,
			BackgroundTransparency = 1,
			Size = UDim2.fromScale(1, 1),

			create("ScrollingFrame")({
				Name = "PullDownMenu",
				AutomaticSize = Enum.AutomaticSize.XY,
				BorderColor3 = Color3.fromRGB(0, 0, 0),
				BorderSizePixel = 0,
				AutomaticCanvasSize = Enum.AutomaticSize.Y,
				CanvasSize = UDim2.new(),
				ScrollBarImageColor3 = Color3.fromRGB(0, 0, 0),
				ScrollBarImageTransparency = 0.5,
				ScrollBarThickness = 3,

				__dynamicKeys = {
					BackgroundColor3 = theme.MenuBackground[1],
					BackgroundTransparency = theme.MenuBackground[2],
				},

				create("UICorner")({
					Name = "UICorner",
					CornerRadius = UDim.new(0, 6),
				}),

				create("UIStroke")({
					Name = "UIStroke",
					ApplyStrokeMode = Enum.ApplyStrokeMode.Border,
					Transparency = 0.9,
				}),

				create("UIPadding")({
					Name = "UIPadding",
					PaddingBottom = UDim.new(0, 5),
					PaddingLeft = UDim.new(0, 5),
					PaddingRight = UDim.new(0, 5),
					PaddingTop = UDim.new(0, 5),
				}),

				create("UIListLayout")({
					Name = "UIListLayout",
					SortOrder = Enum.SortOrder.LayoutOrder,
					Padding = UDim.new(0, 1),
				}),
			}),
		}),
	}) :: ScreenGui

	structures.MenuBody = structures.MenuContainer:FindFirstChild("MenuBody") :: CanvasGroup
	structures.Menu = structures.MenuBody:FindFirstChild("PullDownMenu") :: ScrollingFrame

	local object
	local bindings = {
		Options = function(value: { [number]: string })
			for _, option in ipairs(structures.Options) do
				option:Destroy()
			end

			for index, _option in ipairs(value) do
				option(object, _option, index)
			end
		end,

		Expanded = function(value: boolean)
			local expand = value == true

			if expand then
				structures.MenuContainer.Parent = structures.Body.__instance
			end

			anchor()

			local goal = { GroupTransparency = expand and 0 or 1 }
			local tweenInfo = TweenInfo.new(expand and 0 or 0.4, Enum.EasingStyle.Exponential)
			local tween = tweenService:Create(structures.MenuBody, tweenInfo, goal)

			tween:Play()
			tween.Completed:Connect(function()
				if object.Expanded == false then
					structures.MenuContainer.Parent = nil
				end
			end)
		end,

		Label = function(value: string)
			if type(value) == "string" then
				structures.CurrentTab.Visible = true
				structures.CurrentTab.Text = value
			end
		end,

		Value = function(value: number)
			if properties.ValueChanged then
				properties.Value = value
				task.spawn(properties.ValueChanged, object, value)
			end
		end,
	}

	object = binder.Wrap(properties, bindings, structures.Body)

	object.Type = "PullDownButton"
	object.Theme = self.Theme
	object.Structures = structures
	object.Option = function(self, name: string?)
		local index = #structures.Options + 1

		option(object, name, index)

		table.insert(object.Options, name)

		return structures.Options[index]
	end
	object.Remove = function(self, index: number?)
		if index and structures.Options[index] then
			structures.Options[index]:Destroy()
			object.Options[index] = nil
		end
	end

	binder.Apply(properties, object)

	structures.Body:GetPropertyChangedSignal("AbsolutePosition"):Connect(anchor)
	structures.Body:GetPropertyChangedSignal("AbsoluteSize"):Connect(anchor)
	structures.Menu:GetPropertyChangedSignal("AbsoluteSize"):Connect(anchor)

	userInputService.InputBegan:Connect(function(input)
		if
			object.Expanded
			and (
				input.UserInputType == Enum.UserInputType.MouseButton1
				or input.UserInputType == Enum.UserInputType.Touch
			)
		then
			local mouse = userInputService:GetMouseLocation()
			local inset = guiService:GetGuiInset()
			local menuFrame = structures.Menu
			local pos = menuFrame.AbsolutePosition
			local size = menuFrame.AbsoluteSize

			local adjustedMouseY = mouse.Y - inset.Y

			if
				mouse.X < pos.X
				or mouse.X > pos.X + size.X
				or adjustedMouseY < pos.Y
				or adjustedMouseY > pos.Y + size.Y
			then
				object.Expanded = false
			end
		end
	end)

	structures.Body.MouseButton1Click:Connect(function()
		object.Expanded = not object.Expanded
	end)

	return object
end


local types = require("@types")

return function(self, properties: types.RadioButtonGroupProperties): types.RadioButtonGroup
	--// Imports
	local creator = require("@modules/creator")
	local binder = require("@modules/binder")

	--// References
	local create = creator.Create

	--// Variables
	local parent = self.__container or self.__instance or self
	local theme = self.Theme.Controls.RadioButtonGroup
	local structures = {
		RadioButtons = {},
	}

	--// Functions
	local function radioButton(object, name, index)
		structures.RadioButtons[index] = create("Frame")({
			Name = "RadioButton",
			AutomaticSize = Enum.AutomaticSize.XY,
			BackgroundColor3 = Color3.fromRGB(255, 255, 255),
			BackgroundTransparency = 1,
			BorderColor3 = Color3.fromRGB(0, 0, 0),
			BorderSizePixel = 0,
			LayoutOrder = index,
			Parent = structures.Body.__instance,

			create("UIListLayout")({
				Name = "UIListLayout",
				FillDirection = Enum.FillDirection.Horizontal,
				HorizontalAlignment = Enum.HorizontalAlignment.Right,
				Padding = UDim.new(0, 6),
				SortOrder = Enum.SortOrder.LayoutOrder,
				VerticalAlignment = Enum.VerticalAlignment.Center,
			}),

			create("ImageButton")({
				Name = "Button",
				BackgroundColor3 = Color3.fromRGB(255, 255, 255),
				BackgroundTransparency = 1,
				BorderColor3 = Color3.fromRGB(0, 0, 0),
				BorderSizePixel = 0,
				Image = "rbxassetid://118333468121914",
				Size = UDim2.fromOffset(14, 14),

				__dynamicKeys = {
					ImageColor3 = theme.Background[1],
					ImageTransparency = theme.Background[2],
				},

				__contextKeys = {
					ImageColor3 = function()
						return properties.Value == index and self.Theme.Controls.Selection[1].Value
							or theme.Background[1].Value
					end,
					ImageTransparency = function()
						return properties.Value == index and self.Theme.Controls.Selection[2].Value
							or theme.Background[2].Value
					end,
				},

				create("ImageLabel")({
					Name = "Overlay",
					BackgroundColor3 = Color3.fromRGB(255, 255, 255),
					BackgroundTransparency = 1,
					BorderColor3 = Color3.fromRGB(0, 0, 0),
					BorderSizePixel = 0,
					Image = "rbxassetid://118333468121914",
					Size = UDim2.fromOffset(14, 14),

					__dynamicKeys = {
						ImageColor3 = theme.Overlay[1],
						ImageTransparency = theme.Overlay[2],
					},

					create("UIGradient")({
						Name = "UIGradient",
						Rotation = 90,
						Transparency = NumberSequence.new({
							NumberSequenceKeypoint.new(0, 0),
							NumberSequenceKeypoint.new(1, 1),
						}),
					}),
				}),

				create("ImageLabel")({
					Name = "Dot",
					AnchorPoint = Vector2.new(0.5, 0.5),
					BackgroundColor3 = Color3.fromRGB(255, 255, 255),
					BackgroundTransparency = 1,
					BorderColor3 = Color3.fromRGB(0, 0, 0),
					BorderSizePixel = 0,
					Image = "rbxassetid://118333468121914",
					Position = UDim2.fromScale(0.5, 0.5),
					ScaleType = Enum.ScaleType.Fit,
					Size = UDim2.fromOffset(6, 6),
					SliceCenter = Rect.new(7, 7, 7, 7),

					__dynamicKeys = {
						ImageColor3 = theme.Dot[1],
						ImageTransparency = theme.Dot[2],
					},

					__contextKeys = {
						ImageTransparency = function()
							return properties.Value == index and theme.Dot[2].Value or 1
						end,
					},
				}),

				create("ImageLabel")({
					Name = "Stroke",
					AnchorPoint = Vector2.new(0.5, 0.5),
					BackgroundColor3 = Color3.fromRGB(255, 255, 255),
					BackgroundTransparency = 1,
					BorderColor3 = Color3.fromRGB(0, 0, 0),
					BorderSizePixel = 0,
					Image = "rbxassetid://132968326823931",
					Position = UDim2.fromScale(0.5, 0.5),
					Size = UDim2.fromScale(1, 1),

					__dynamicKeys = {
						ImageColor3 = theme.Stroke[1],
						ImageTransparency = theme.Stroke[2],
					},

					__contextKeys = {
						ImageTransparency = function()
							return properties.Value == index and 1 or theme.Stroke[2].Value
						end,
					},
				}),

				create("ImageLabel")({
					Name = "InnerShadow",
					AnchorPoint = Vector2.new(0.5, 0.5),
					BackgroundColor3 = Color3.fromRGB(255, 255, 255),
					BackgroundTransparency = 1,
					BorderColor3 = Color3.fromRGB(0, 0, 0),
					BorderSizePixel = 0,
					Image = "rbxassetid://95115717327743",
					Position = UDim2.fromScale(0.5, 0.5),
					Size = UDim2.fromScale(1, 1),

					__dynamicKeys = {
						ImageColor3 = theme.InnerShadow[1],
						ImageTransparency = theme.InnerShadow[2],
					},

					__contextKeys = {
						ImageTransparency = function()
							return properties.Value == index and 1 or theme.InnerShadow[2].Value
						end,
					},
				}),

				create("ImageLabel")({
					Name = "DropShadow",
					AnchorPoint = Vector2.new(0.5, 0.5),
					BackgroundColor3 = Color3.fromRGB(255, 255, 255),
					BackgroundTransparency = 1,
					BorderColor3 = Color3.fromRGB(0, 0, 0),
					BorderSizePixel = 0,
					Image = "rbxassetid://110994967430153",
					Position = UDim2.new(0.5, 0, 0.5, 1),
					ScaleType = Enum.ScaleType.Fit,
					Size = UDim2.fromOffset(20, 20),

					__dynamicKeys = {
						ImageColor3 = self.Theme.Controls.Selection[1],
						ImageTransparency = self.Theme.Controls.Selection[2],
					},

					__contextKeys = {
						ImageTransparency = function()
							return properties.Value == index and 0.76 or 1
						end,
					},
				}),
			}),

			create("TextLabel")({
				Name = "Label",
				AutomaticSize = Enum.AutomaticSize.XY,
				BackgroundColor3 = Color3.fromRGB(255, 255, 255),
				BackgroundTransparency = 1,
				BorderColor3 = Color3.fromRGB(0, 0, 0),
				BorderSizePixel = 0,
				FontFace = Font.new("rbxassetid://12187365364"),
				LayoutOrder = 1,
				RichText = true,
				Text = name,
				TextSize = 15,
				TextTruncate = Enum.TextTruncate.AtEnd,
				Visible = not not name,

				__dynamicKeys = {
					TextColor3 = self.Theme.Text.Primary[1],
					TextTransparency = self.Theme.Text.Primary[2],
				},
			}),
		}) :: Frame

		local button = structures.RadioButtons[index]:FindFirstChild("Button") :: ImageButton
		if button and button:IsA("ImageButton") then
			button.MouseButton1Click:Connect(function()
				if object then
					object.Value = index
				end
			end)
		end
	end

	--// UI
	properties = properties or {}
	properties.Options = properties.Options or {}

	structures.Body = binder.Apply(
		properties,
		create("Frame")({
			Name = "RadioButtons",
			AutomaticSize = Enum.AutomaticSize.XY,
			BackgroundColor3 = Color3.fromRGB(255, 255, 255),
			BackgroundTransparency = 1,
			BorderColor3 = Color3.fromRGB(0, 0, 0),
			BorderSizePixel = 0,
			Parent = parent,

			create("UIListLayout")({
				Name = "UIListLayout",
				FillDirection = Enum.FillDirection.Horizontal,
				HorizontalAlignment = Enum.HorizontalAlignment.Right,
				Padding = UDim.new(0, 16),
				SortOrder = Enum.SortOrder.LayoutOrder,
				VerticalAlignment = Enum.VerticalAlignment.Center,
				Wraps = true,
			}),
		})
	) :: Frame

	--// Initialize
	local object
	local bindings = {
		Options = function(value: { [number]: string })
			for index, option in ipairs(value) do
				if structures.RadioButtons[index] then
					structures.RadioButtons[index]:Destroy()
				end

				radioButton(object, option, index)
			end
		end,
		Value = function(value: number)
			for index, radioButton in ipairs(structures.RadioButtons) do
				local currentIndex = index == value

				if radioButton then
					local button = radioButton:FindFirstChild("Button")

					button.ImageColor3 = currentIndex and self.Theme.Controls.Selection[1].Value
						or theme.Background[1].Value
					button.ImageTransparency = currentIndex and self.Theme.Controls.Selection[2].Value
						or theme.Background[2].Value

					button:FindFirstChild("Dot").ImageTransparency = currentIndex and theme.Dot[2].Value or 1

					button:FindFirstChild("Stroke").ImageTransparency = currentIndex and 1 or theme.Stroke[2].Value
					button:FindFirstChild("InnerShadow").ImageTransparency = currentIndex and 1
						or theme.InnerShadow[2].Value
					button:FindFirstChild("DropShadow").ImageTransparency = currentIndex and 0.76 or 1
				end
			end

			if properties.ValueChanged then
				properties.Value = value
				task.spawn(properties.ValueChanged, object, value)
			end
		end,
	}

	object = binder.Wrap(properties, bindings, structures.Body)

	object.Type = "RadioButtonGroup"
	object.Theme = self.Theme
	object.Structures = structures
	object.Option = function(self, name: string?)
		local index = #structures.RadioButtons + 1

		radioButton(object, name, index)

		table.insert(properties.Options or {}, name)

		return structures.RadioButtons[index]
	end

	binder.Apply(properties, object)

	return object
end


local types = require("@types")

return function(self, properties: types.RowProperties): types.Row
	--// Imports
	local creator = require("@modules/creator")
	local binder = require("@modules/binder")

	--// References
	local create = creator.Create

	--// Variables
	local parent = self.__container or self.__instance or self
	local structures = {}

	--// UI
	properties = properties or {}

	structures.Body = binder.Apply(
		properties,
		create("Frame")({
			Name = "Row",
			AutomaticSize = Enum.AutomaticSize.Y,
			BackgroundColor3 = Color3.fromRGB(255, 255, 255),
			BackgroundTransparency = 1,
			BorderColor3 = Color3.fromRGB(0, 0, 0),
			BorderSizePixel = 0,
			Size = UDim2.fromScale(1, 0),
			Parent = parent,

			create("Frame")({
				Name = "LeftAccessory",
				AutomaticSize = Enum.AutomaticSize.Y,
				BackgroundColor3 = Color3.fromRGB(255, 255, 255),
				BackgroundTransparency = 1,
				BorderColor3 = Color3.fromRGB(0, 0, 0),
				BorderSizePixel = 0,
				Size = UDim2.fromScale(0, 1),

				create("UIListLayout")({
					Name = "UIListLayout",
					FillDirection = Enum.FillDirection.Horizontal,
					HorizontalAlignment = Enum.HorizontalAlignment.Left,
					Padding = UDim.new(0, 10),
					SortOrder = Enum.SortOrder.LayoutOrder,
					VerticalAlignment = Enum.VerticalAlignment.Center,
					Wraps = true,
				}),

				create("UIPadding")({
					Name = "UIPadding",
					PaddingBottom = UDim.new(0, 10),
					PaddingRight = UDim.new(0, 10),
					PaddingTop = UDim.new(0, 10),
				}),
			}),

			create("Frame")({
				Name = "RightAccessory",
				AnchorPoint = Vector2.new(1, 0),
				AutomaticSize = Enum.AutomaticSize.XY,
				BackgroundColor3 = Color3.fromRGB(255, 255, 255),
				BackgroundTransparency = 1,
				BorderColor3 = Color3.fromRGB(0, 0, 0),
				BorderSizePixel = 0,
				LayoutOrder = 1,
				Position = UDim2.fromScale(1, 0),
				Size = UDim2.fromScale(0, 1),

				create("UIListLayout")({
					Name = "UIListLayout",
					FillDirection = Enum.FillDirection.Horizontal,
					HorizontalAlignment = Enum.HorizontalAlignment.Right,
					Padding = UDim.new(0, 10),
					SortOrder = Enum.SortOrder.LayoutOrder,
					VerticalAlignment = Enum.VerticalAlignment.Center,
					Wraps = true,
				}),

				create("UIPadding")({
					Name = "UIPadding",
					PaddingBottom = UDim.new(0, 10),
					PaddingLeft = UDim.new(0, 11),
					PaddingTop = UDim.new(0, 10),
				}),
			}),

			create("Folder")({
				Name = "LayoutIgnore",

				create("Frame")({
					Name = "Divider",
					AnchorPoint = Vector2.new(0, 1),
					BorderColor3 = Color3.fromRGB(0, 0, 0),
					BorderSizePixel = 0,
					Position = UDim2.fromScale(0, 1),
					Size = UDim2.new(1, 0, 0, 1),
					Visible = false,

					__dynamicKeys = {
						BackgroundColor3 = self.Theme.Controls.ViewBorder[1],
						BackgroundTransparency = self.Theme.Controls.ViewBorder[2],
					},
				}),
			}),
		})
	) :: Frame

	--// Initialize
	structures.LeftAccessories = structures.Body:FindFirstChild("LeftAccessory") :: Frame
	structures.RightAccessories = structures.Body:FindFirstChild("RightAccessory") :: Frame

	local function updateAccessories()
		local parentWidth = structures.LeftAccessories.Parent.AbsoluteSize.X
		local rightWidth = structures.RightAccessories.AbsoluteSize.X

		local minLeftWidth = 75
		local calculatedLeftWidth = math.max(parentWidth - rightWidth, minLeftWidth)

		if parentWidth - rightWidth < minLeftWidth then
			structures.LeftAccessories.Size = UDim2.new(0, minLeftWidth, 1, 0)
		else
			structures.LeftAccessories.Size = UDim2.new(0, calculatedLeftWidth, 1, 0)
		end
	end

	updateAccessories()
	structures.RightAccessories:GetPropertyChangedSignal("AbsoluteSize"):Connect(updateAccessories)
	structures.LeftAccessories.Parent:GetPropertyChangedSignal("AbsoluteSize"):Connect(updateAccessories)

	local object = binder.Wrap(properties, {
		SearchIndex = function(value: string)
			structures.Body:SetAttribute("SearchIndex", value)
		end,
	}, structures.Body)

	object.Type = "Row"
	object.Theme = self.Theme
	object.Structures = structures
	object.Left = function()
		local newObject = table.clone(object)

		newObject.__container = structures.LeftAccessories

		return newObject
	end
	object.Right = function()
		local newObject = table.clone(object)

		newObject.__container = structures.RightAccessories

		return newObject
	end

	binder.Apply(properties, object)

	return object
end


local types = require("@types")

return function(self, properties: types.SectionProperties): types.Section
	--// Imports
	local creator = require("@modules/creator")
	local binder = require("@modules/binder")
	local services = require("@modules/services")

	--// References
	local create = creator.Create

	local tweenService = services.TweenService

	--// Variables
	local parent = self.Type == "Window" and self.Structures.SidebarList or self.__instance or self
	local structures = {}

	--// Functions
	local function watchAutosize(structure: Frame, connections: { RBXScriptConnection }, update: (...any) -> (), ...)
		local args = table.pack(...)

		for _, child in ipairs(structure:GetChildren()) do
			if child:IsA("GuiObject") then
				table.insert(
					connections,
					child:GetPropertyChangedSignal("AbsoluteSize"):Connect(function(...)
						update(table.unpack(args, 1, args.n))
					end)
				)
				table.insert(
					connections,
					child:GetPropertyChangedSignal("Visible"):Connect(function(...)
						update(table.unpack(args, 1, args.n))
					end)
				)
			end
		end

		table.insert(
			connections,
			structure.ChildAdded:Connect(function(child)
				if child:IsA("GuiObject") then
					table.insert(
						connections,
						child:GetPropertyChangedSignal("AbsoluteSize"):Connect(function(...)
							update(table.unpack(args, 1, args.n))
						end)
					)
					table.insert(
						connections,
						child:GetPropertyChangedSignal("Visible"):Connect(function(...)
							update(table.unpack(args, 1, args.n))
						end)
					)
					update(table.unpack(args, 1, args.n))
				end
			end)
		)

		table.insert(
			connections,
			structure.ChildRemoved:Connect(function(...)
				update(table.unpack(args, 1, args.n))
			end)
		)
	end

	--// UI
	properties = properties or {}

	properties.Title = properties.Title or "Section Title"
	properties.Disclosure = properties.Disclosure ~= false
	properties.Expanded = properties.Expanded ~= false

	structures.SidebarGroup = binder.Apply(
		properties,
		create("TextButton")({
			AutomaticSize = Enum.AutomaticSize.Y,
			BackgroundColor3 = Color3.fromRGB(255, 255, 255),
			BackgroundTransparency = 1,
			BorderColor3 = Color3.fromRGB(0, 0, 0),
			BorderSizePixel = 0,
			ClipsDescendants = true,
			Size = UDim2.new(1, 0, 0, 23),
			Text = "",
			AutoButtonColor = false,
			Parent = parent,

			create("UIListLayout")({
				SortOrder = Enum.SortOrder.LayoutOrder,
				HorizontalAlignment = Enum.HorizontalAlignment.Right,
			}),

			create("Frame")({
				Name = "SectionHeader",
				AutomaticSize = Enum.AutomaticSize.Y,
				BackgroundColor3 = Color3.fromRGB(255, 255, 255),
				BackgroundTransparency = 1,
				BorderColor3 = Color3.fromRGB(0, 0, 0),
				BorderSizePixel = 0,
				Size = UDim2.fromScale(1, 0),

				create("Frame")({
					Name = "Disclosure",
					BackgroundColor3 = Color3.fromRGB(255, 255, 255),
					BackgroundTransparency = 1,
					BorderColor3 = Color3.fromRGB(0, 0, 0),
					BorderSizePixel = 0,
					FontFace = Font.new("rbxasset://fonts/families/SourceSansPro.json"),
					LayoutOrder = 1,
					Size = UDim2.fromOffset(13, 14),
					TextColor3 = Color3.fromRGB(0, 0, 0),
					TextSize = 14,

					create("ImageLabel")({
						Name = "DisclosureImage",
						AnchorPoint = Vector2.new(0.5, 0.5),
						BackgroundColor3 = Color3.fromRGB(255, 255, 255),
						BackgroundTransparency = 1,
						BorderColor3 = Color3.fromRGB(0, 0, 0),
						BorderSizePixel = 0,
						Image = "rbxassetid://115960806571685",
						Position = UDim2.fromScale(0.5, 0.5),
						Size = UDim2.fromOffset(11, 7),
						__dynamicKeys = {
							ImageColor3 = self.Theme.Text.Tertiary[1],
							ImageTransparency = self.Theme.Text.Tertiary[2],
						},
					}),
				}),

				create("UIListLayout")({
					FillDirection = Enum.FillDirection.Horizontal,
					HorizontalFlex = Enum.UIFlexAlignment.SpaceBetween,
					Padding = UDim.new(0, 10),
					SortOrder = Enum.SortOrder.LayoutOrder,
				}),

				create("UIPadding")({
					PaddingBottom = UDim.new(0, 6),
					PaddingLeft = UDim.new(0, 8),
					PaddingRight = UDim.new(0, 12),
					PaddingTop = UDim.new(0, 3),
				}),

				create("TextLabel")({
					Name = "Title",
					AutomaticSize = Enum.AutomaticSize.X,
					BackgroundColor3 = Color3.fromRGB(255, 255, 255),
					BackgroundTransparency = 1,
					BorderColor3 = Color3.fromRGB(0, 0, 0),
					BorderSizePixel = 0,
					FontFace = Font.new("rbxassetid://12187365364", Enum.FontWeight.Bold, Enum.FontStyle.Normal),
					LineHeight = 0,
					RichText = true,
					Size = UDim2.fromOffset(0, 14),
					Text = "Section Title",
					TextSize = 12,
					TextTruncate = Enum.TextTruncate.AtEnd,
					TextXAlignment = Enum.TextXAlignment.Left,
					__dynamicKeys = {
						TextColor3 = self.Theme.Text.Tertiary[1],
						TextTransparency = self.Theme.Text.Tertiary[2],
					},
				}),
			}),
		})
	) :: Frame

	--// Initialize
	structures.Layout = structures.SidebarGroup:FindFirstChild("UIListLayout") :: UIListLayout
	structures.SectionHeader = structures.SidebarGroup:FindFirstChild("SectionHeader") :: Frame
	structures.Title = structures.SectionHeader:FindFirstChild("Title") :: TextLabel
	structures.Disclosure = structures.SectionHeader:FindFirstChild("Disclosure") :: TextButton
	structures.DisclosureImage = structures.Disclosure:FindFirstChild("DisclosureImage") :: ImageLabel

	local connections = {}
	local bindings = {
		Title = function(name: string)
			structures.Title.Text = name
		end,
		Disclosure = function(state: boolean)
			structures.Disclosure.Visible = state
			structures.SidebarGroup.Active = state
		end,
		Expanded = function(state: boolean, tween: boolean?)
			tween = (tween == nil and true) or false

			local sidebarGroup = structures.SidebarGroup.__instance
			local disclosureImage = structures.DisclosureImage

			sidebarGroup.AutomaticSize = Enum.AutomaticSize.None

			for index, connection: RBXScriptConnection in pairs(connections) do
				connection:Disconnect()
				table.remove(connections, index)
			end

			local updateSize = function(useTween: boolean)
				local targetHeight = state and structures.Layout.AbsoluteContentSize.Y or 23
				local tween = tweenService:Create(
					sidebarGroup,
					TweenInfo.new(useTween and 0.35 or 0, Enum.EasingStyle.Exponential, Enum.EasingDirection.Out),
					{
						Size = UDim2.new(1, 0, 0, targetHeight),
					}
				)
				tween:Play()
			end

			if state then
				watchAutosize(sidebarGroup, connections, updateSize, false)
			end

			updateSize(tween)
			tweenService
				:Create(
					disclosureImage,
					TweenInfo.new(tween and 0.35 or 0, Enum.EasingStyle.Exponential, Enum.EasingDirection.Out),
					{
						Rotation = state and 0 or -90,
					}
				)
				:Play()
		end,
	}
	local object = binder.Wrap(properties, bindings, structures.SidebarGroup)

	object.Type = "Section"
	object.Theme = self.Theme
	object.Structures = structures
	object.__window = self

	structures.SidebarGroup.MouseButton1Click:Connect(function()
		if not properties.Disclosure then
			return
		end

		object.Expanded = not object.Expanded
	end)

	binder.Apply(properties, object)

	return object
end


local types = require("@types")

return function(self, properties: types.StepperProperties): types.Stepper
	--// Imports
	local creator = require("@modules/creator")
	local binder = require("@modules/binder")

	local textField = require("@structures/TextField")

	--// References
	local create = creator.Create

	--// Variables
	local parent = self.__container or self.__instance or self
	local theme = self.Theme.Controls.Stepper
	local structures = {}

	local holding = false
	local stepConnections = {}
	local repeatDelay = 0.35
	local repeatInterval = 0.083

	--// Functions
	local function getPrecision(step)
		local stepStr = tostring(step)
		local dot = string.find(stepStr, "%.")
		local precision = 0

		if dot then
			precision = #stepStr - dot
		end

		return precision
	end

	local function stepFormat(value, step)
		local stepPrecision = getPrecision(step)
		local valuePrecision = getPrecision(value)

		local displayPrecision = math.max(stepPrecision, valuePrecision)

		local formatStr = "%." .. displayPrecision .. "f"
		return string.format(formatStr, value)
	end

	local function round(value, decimals)
		local mult = 10 ^ (decimals or 0)
		return math.floor(value * mult + 0.5) / mult
	end

	--// UI
	properties = properties or {}
	properties.Value = properties.Value or 0
	properties.Step = properties.Step or 0.1
	properties.Maximum = properties.Maximum or 1
	properties.Minimum = properties.Minimum or 0
	properties.Fielded = properties.Fielded or false

	structures.Body = binder.Apply(
		properties,
		create("ImageLabel")({
			Name = "Stepper",
			BackgroundColor3 = Color3.fromRGB(255, 255, 255),
			BackgroundTransparency = 1,
			BorderColor3 = Color3.fromRGB(0, 0, 0),
			BorderSizePixel = 0,
			Image = "rbxassetid://85888499115674",
			Size = UDim2.fromOffset(13, 20),
			Parent = parent,

			__dynamicKeys = {
				ImageColor3 = theme.Background[1],
				ImageTransparency = theme.Background[2],
			},

			create("ImageLabel")({
				Name = "Shadow",
				BackgroundTransparency = 1,
				AnchorPoint = Vector2.new(0.5, 0.5),
				BorderColor3 = Color3.fromRGB(0, 0, 0),
				BorderSizePixel = 0,
				Image = "rbxassetid://105571270097608",
				LayoutOrder = 1,
				Position = UDim2.fromScale(0.5, 0.5),
				Size = UDim2.fromOffset(19, 27),

				__dynamicKeys = {
					ImageColor3 = theme.Dropshadow[1],
					ImageTransparency = theme.Dropshadow[2],
				},
			}),

			create("ImageButton")({
				Name = "Up",
				AutoButtonColor = false,
				BackgroundColor3 = Color3.fromRGB(255, 255, 255),
				BackgroundTransparency = 1,
				BorderColor3 = Color3.fromRGB(0, 0, 0),
				BorderSizePixel = 0,
				Image = "rbxassetid://133515997946294",
				Size = UDim2.new(1, 0, 0, 9),
				Position = UDim2.fromOffset(0, 1),

				__dynamicKeys = {
					ImageColor3 = self.Theme.Text.Primary[1],
					ImageTransparency = self.Theme.Text.Primary[2],
				},

				__contextKeys = {
					ImageColor3 = function()
						if properties.Value >= properties.Maximum then
							return self.Theme.Text.Tertiary[1].Value
						else
							return self.Theme.Text.Primary[1].Value
						end
					end,
					ImageTransparency = function()
						if properties.Value >= properties.Maximum then
							return self.Theme.Text.Tertiary[2].Value
						else
							return self.Theme.Text.Primary[2].Value
						end
					end,
				},
			}),

			create("ImageButton")({
				Name = "Down",
				AnchorPoint = Vector2.new(0, 1),
				AutoButtonColor = false,
				BackgroundColor3 = Color3.fromRGB(255, 255, 255),
				BackgroundTransparency = 1,
				BorderColor3 = Color3.fromRGB(0, 0, 0),
				BorderSizePixel = 0,
				Image = "rbxassetid://83836660987173",
				Position = UDim2.fromScale(0, 1),
				Size = UDim2.new(1, 0, 0, 9),

				__dynamicKeys = {
					ImageColor3 = self.Theme.Text.Primary[1],
					ImageTransparency = self.Theme.Text.Primary[2],
				},

				__contextKeys = {
					ImageColor3 = function()
						if properties.Value <= properties.Minimum then
							return self.Theme.Text.Tertiary[1].Value
						else
							return self.Theme.Text.Primary[1].Value
						end
					end,
					ImageTransparency = function()
						if properties.Value <= properties.Minimum then
							return self.Theme.Text.Tertiary[2].Value
						else
							return self.Theme.Text.Primary[2].Value
						end
					end,
				},
			}),

			create("Frame")({
				Name = "Top",
				BackgroundColor3 = Color3.fromRGB(255, 255, 255),
				BorderColor3 = Color3.fromRGB(0, 0, 0),
				BorderSizePixel = 0,
				Position = UDim2.fromOffset(0, 6),
				Size = UDim2.new(1, 0, 0, 4),
				ZIndex = 0,

				create("UIGradient")({
					Name = "UIGradient",
					Rotation = 90,
					Transparency = NumberSequence.new({
						NumberSequenceKeypoint.new(0, 0.949),
						NumberSequenceKeypoint.new(1, 0.949),
					}),

					__dynamicKeys = {
						Color = theme.SegmentShadow,
					},
				}),
			}),

			create("Frame")({
				Name = "Separator",
				AnchorPoint = Vector2.new(0, 0.5),
				BorderColor3 = Color3.fromRGB(0, 0, 0),
				BorderSizePixel = 0,
				Position = UDim2.fromScale(0, 0.5),
				Size = UDim2.new(1, 0, 0, 1),
				ZIndex = 0,

				__dynamicKeys = {
					BackgroundColor3 = theme.Separator[1],
					BackgroundTransparency = theme.Separator[2],
				},
			}),

			create("Frame")({
				Name = "Bottom",
				BackgroundColor3 = Color3.fromRGB(255, 255, 255),
				BorderColor3 = Color3.fromRGB(0, 0, 0),
				BorderSizePixel = 0,
				Position = UDim2.fromOffset(0, 10),
				Size = UDim2.new(1, 0, 0, 4),
				ZIndex = 0,

				create("UIGradient")({
					Name = "UIGradient",
					Rotation = -90,
					Transparency = NumberSequence.new({
						NumberSequenceKeypoint.new(0, 0.949),
						NumberSequenceKeypoint.new(1, 0.949),
					}),

					__dynamicKeys = {
						Color = theme.SegmentShadow,
					},
				}),
			}),

			create("Frame")({
				Name = "Filler",
				AnchorPoint = Vector2.new(0, 0.5),
				BorderColor3 = Color3.fromRGB(0, 0, 0),
				BorderSizePixel = 0,
				Position = UDim2.fromScale(0, 0.5),
				Size = UDim2.new(1, 0, 0, 2),
				ZIndex = 0,

				__dynamicKeys = {
					BackgroundColor3 = theme.Filler[1],
					BackgroundTransparency = theme.Filler[2],
				},
			}),
		})
	) :: ImageLabel

	--// Initialize
	structures.IPlus = structures.Body:FindFirstChild("Up") :: ImageButton
	structures.IMinus = structures.Body:FindFirstChild("Down") :: ImageButton

	structures.Field = textField(self)
	structures.Field.Padding.PaddingBottom = UDim.new(0, 2)
	structures.Field.Padding.PaddingTop = UDim.new(0, 2)
	structures.Field.Padding.PaddingRight = UDim.new(0, 2)
	structures.Field.Body.Size = UDim2.fromOffset(0, 23)
	structures.Field.Field.Size = UDim2.fromOffset(0, 0)
	structures.Field.Corner.CornerRadius = UDim.new(0, 6)
	structures.Field.FieldPadding:Destroy()

	local object
	local bindings = {
		Fielded = function(value: boolean)
			if value then
				structures.Field.Body.Parent = parent
				structures.Body.Parent = structures.Field.Body.__instance
				structures.Body.LayoutOrder = 1
			else
				structures.Field.Body.Parent = nil
				structures.Body.Parent = parent
				structures.Body.LayoutOrder = 0
			end
		end,
		Value = function(value: number)
			if value <= properties.Minimum then
				structures.IMinus.ImageColor3 = self.Theme.Text.Tertiary[1].Value
				structures.IMinus.ImageTransparency = self.Theme.Text.Tertiary[2].Value
				structures.IMinus.Interactable = false
			else
				structures.IMinus.ImageColor3 = self.Theme.Text.Primary[1].Value
				structures.IMinus.ImageTransparency = self.Theme.Text.Primary[2].Value
				structures.IMinus.Interactable = true
			end

			if value >= properties.Maximum then
				structures.IPlus.ImageColor3 = self.Theme.Text.Tertiary[1].Value
				structures.IPlus.ImageTransparency = self.Theme.Text.Tertiary[2].Value
				structures.IPlus.Interactable = false
			else
				structures.IPlus.ImageColor3 = self.Theme.Text.Primary[1].Value
				structures.IPlus.ImageTransparency = self.Theme.Text.Primary[2].Value
				structures.IPlus.Interactable = true
			end

			if structures.Field then
				structures.Field.Field.Text = stepFormat(value, properties.Step)
			end

			if properties.ValueChanged then
				properties.Value = value
				task.spawn(properties.ValueChanged, object, value)
			end
		end,
	}

	object = binder.Wrap(properties, bindings, structures.Body)

	object.Type = "Stepper"
	object.Theme = self.Theme
	object.Structures = structures
	object.Increment = function()
		assert(properties.Minimum)
		assert(properties.Maximum)

		local precision = math.max(getPrecision(object.Value), getPrecision(properties.Step))
		local rawValue = object.Value + properties.Step
		local newValue = round(rawValue, precision)

		object.Value = math.clamp(newValue, properties.Minimum, properties.Maximum)
	end

	object.Decrement = function()
		assert(properties.Minimum)
		assert(properties.Maximum)

		local precision = math.max(getPrecision(object.Value), getPrecision(properties.Step))
		local rawValue = object.Value - properties.Step
		local newValue = round(rawValue, precision)

		object.Value = math.clamp(newValue, properties.Minimum, properties.Maximum)
	end

	local function stepStart(direction: string)
		holding = true

		local action = (direction == "Up") and object.Increment or object.Decrement

		stepConnections[direction] = task.spawn(function()
			if  holding then
				task.wait(repeatDelay)
			end

			if not  holding then return end

			action()

			while  holding do
				task.wait(repeatInterval)
				if  holding then
					action()
				end
			end
		end)
	end

	local function stepStop(direction: string)
		 holding = false
		if stepConnections[direction] then
			task.cancel(stepConnections[direction])
			stepConnections[direction] = nil
		end
	end

	structures.IPlus.MouseButton1Down:Connect(function()
		object.Increment()
		stepStart("Up")
	end)
	structures.IPlus.MouseButton1Up:Connect(function()
		stepStop("Up")
	end)
	structures.IPlus.MouseLeave:Connect(function()
		stepStop("Up")
	end)

	structures.IMinus.MouseButton1Down:Connect(function()
		object.Decrement()
		stepStart("Down")
	end)
	structures.IMinus.MouseButton1Up:Connect(function()
		stepStop("Down")
	end)
	structures.IMinus.MouseLeave:Connect(function()
		stepStop("Down")
	end)

	structures.Body.AncestryChanged:Connect(function(_, parent)
		if not parent then
			stepStop("Up")
			stepStop("Down")
			for _, conn in pairs(stepConnections) do
				if typeof(conn) == "RBXScriptConnection" then
					conn:Disconnect()
				end
			end
			stepConnections = {}
		end
	end)

	structures.Field.Field.FocusLost:Connect(function(fromEnter)
		if fromEnter then
			assert(properties.Minimum)
			assert(properties.Maximum)

			local text = structures.Field.Field.Text
			local number = tonumber(text)

			if number and properties.Fielded then
				properties.Value = math.clamp(number, properties.Minimum, properties.Maximum)

				if properties.Value then
					bindings.Value(properties.Value)
				end
			end
		else
			structures.Field.Field.Text = tostring(properties.Value)
		end
	end)

	binder.Apply(properties, object)

	return object
end


local types = require("@types")

return function(self, properties: types.SymbolProperties): types.Symbol
	--// Imports
	local creator = require("@modules/creator")
	local binder = require("@modules/binder")

	--// References
	local create = creator.Create

	--// Variables
	local parent = self.__container or self.__instance or self
	local structures = {}

	--// UI
	properties = properties or {}
	properties.Style = properties.Style or "Primary"
	properties.Size = properties.Size or UDim2.fromOffset(20, 20)

	structures.Body = create("ImageLabel")({
		Name = "Image",
		AutomaticSize = Enum.AutomaticSize.XY,
		BackgroundColor3 = Color3.fromRGB(255, 255, 255),
		BackgroundTransparency = 1,
		BorderColor3 = Color3.fromRGB(0, 0, 0),
		BorderSizePixel = 0,
		Parent = parent,

		__dynamicKeys = {
			ImageColor3 = self.Theme.Text.Primary[1],
			ImageTransparency = self.Theme.Text.Primary[2],
		},

		__contextKeys = {
			ImageColor3 = function()
				return properties.Style == "Primary" and self.Theme.Text.Primary[1].Value or self.Theme.Text.Secondary[1].Value
			end,
			ImageTransparency = function()
				return properties.Style == "Primary" and self.Theme.Text.Primary[2].Value or self.Theme.Text.Secondary[2].Value
			end,
		},
	}) :: ImageLabel

	--// Initialize
	local object = binder.Wrap(properties, {
		Style = function(value: "Primary" | "Secondary")
			if value == "Primary" then
				structures.Body.ImageColor3 = self.Theme.Text.Primary[1].Value.Value
				structures.Body.ImageTransparency = self.Theme.Text.Primary[2].Value
			else
				structures.Body.ImageColor3 = self.Theme.Text.Secondary[1].Value
				structures.Body.ImageTransparency = self.Theme.Text.Secondary[2].Value
			end
		end,
	}, structures.Body)

	object.Type = "Symbol"
	object.Theme = self.Theme
	object.Structures = structures

	binder.Apply(properties, object)

	return object
end


local types = require("@types")

return function(self, properties: types.TabProperties): types.Tab
	--// Imports
	local creator = require("@modules/creator")
	local binder = require("@modules/binder")
	local Page = require("@components/Page")

	--// References
	local create = creator.Create
	local window = self.Type == "Window" and self or self.__window

	--// Variables
	local parent = self.Type == "Window" and self.Structures.SidebarList
		or self.Type == "Tab" and self.__instance.Parent
		or self.__instance
		or self
	local structures = {}

	--// UI
	properties = properties or {}

	properties.Title = properties.Title or "Label"
	properties.Indentation = properties.Indentation or 0
	properties.Selected = properties.Selected == true

	structures.Body = binder.Apply(
		properties,
		create("TextButton")({
			Name = "SidebarItem",
			AutoButtonColor = false,
			BorderColor3 = Color3.fromRGB(0, 0, 0),
			BorderSizePixel = 0,
			FontFace = Font.new("rbxasset://fonts/families/SourceSansPro.json"),
			LayoutOrder = window.Tabs and #window.Tabs or 1,
			Size = UDim2.new(1, 0, 0, 28),
			Text = "",
			TextColor3 = Color3.fromRGB(0, 0, 0),
			TextSize = 14,
			Parent = parent,

			__dynamicKeys = {
				BackgroundColor3 = self.Theme.Controls.SelectionFocused[1],
				BackgroundTransparency = self.Theme.Controls.SelectionFocused[2],
			},
			__contextKeys = {
				BackgroundTransparency = function()
					return properties.Selected and self.Theme.Controls.SelectionFocused[2].Value or 1
				end,
			},

			create("UICorner")({
				Name = "UICorner",
				CornerRadius = UDim.new(0, 5),
			}),

			create("UIListLayout")({
				Name = "UIListLayout",
				FillDirection = Enum.FillDirection.Horizontal,
				HorizontalFlex = Enum.UIFlexAlignment.SpaceBetween,
				Padding = UDim.new(0, 14),
				SortOrder = Enum.SortOrder.LayoutOrder,
				VerticalAlignment = Enum.VerticalAlignment.Center,
			}),

			create("UIPadding")({
				Name = "UIPadding",
				PaddingLeft = UDim.new(0, 10),
				PaddingRight = UDim.new(0, 8),
			}),

			create("Frame")({
				Name = "Leading",
				AutomaticSize = Enum.AutomaticSize.Y,
				BackgroundColor3 = Color3.fromRGB(255, 255, 255),
				BackgroundTransparency = 1,
				BorderColor3 = Color3.fromRGB(0, 0, 0),
				BorderSizePixel = 0,
				Size = UDim2.new(1, -34, 0, 0),

				create("TextLabel")({
					Name = "Title",
					BackgroundColor3 = Color3.fromRGB(255, 255, 255),
					BackgroundTransparency = 1,
					BorderColor3 = Color3.fromRGB(0, 0, 0),
					BorderSizePixel = 0,
					FontFace = Font.new("rbxassetid://12187365364"),
					LayoutOrder = 2,
					LineHeight = 0,
					RichText = true,
					Size = UDim2.new(1, -22, 0, 20),
					TextSize = 15,
					TextTruncate = Enum.TextTruncate.AtEnd,
					TextXAlignment = Enum.TextXAlignment.Left,

					__dynamicKeys = {
						TextColor3 = self.Theme.Text.SelectionPrimary[1],
						TextTransparency = self.Theme.Text.SelectionPrimary[2],
					},
					__contextKeys = {
						TextColor3 = function()
							return properties.Selected and self.Theme.Text.SelectionPrimary[1].Value
								or self.Theme.Text.Primary[1].Value
						end,
						TextTransparency = function()
							return properties.Selected and self.Theme.Text.SelectionPrimary[2].Value
								or self.Theme.Text.Primary[2].Value
						end,
					},
				}),

				create("UIListLayout")({
					Name = "UIListLayout",
					FillDirection = Enum.FillDirection.Horizontal,
					Padding = UDim.new(0, 2),
					SortOrder = Enum.SortOrder.LayoutOrder,
				}),

				create("ImageLabel")({
					Name = "Symbol",
					Visible = false,
					AnchorPoint = Vector2.new(0.5, 0.5),
					BackgroundColor3 = Color3.fromRGB(255, 255, 255),
					BackgroundTransparency = 1,
					BorderColor3 = Color3.fromRGB(0, 0, 0),
					BorderSizePixel = 0,
					Image = "rbxassetid://127049167227557",
					LayoutOrder = 1,
					Position = UDim2.fromScale(0.5, 0.5),
					Size = UDim2.fromOffset(20, 20),

					__dynamicKeys = {
						ImageColor3 = self.Theme.Controls.Selection[1],
						ImageTransparency = self.Theme.Controls.Selection[2],
					},
					__contextKeys = {
						ImageColor3 = function()
							return properties.Selected and self.Theme.Text.SelectionPrimary[1].Value
								or self.Theme.Controls.Selection[1].Value
						end,
						ImageTransparency = function()
							return properties.Selected and self.Theme.Text.SelectionPrimary[2].Value
								or self.Theme.Controls.Selection[2].Value
						end,
					},
				}),
			}),

			create("Frame")({
				Name = "Trailing",
				AutomaticSize = Enum.AutomaticSize.XY,
				BackgroundColor3 = Color3.fromRGB(255, 255, 255),
				BackgroundTransparency = 1,
				BorderColor3 = Color3.fromRGB(0, 0, 0),
				BorderSizePixel = 0,
				LayoutOrder = 1,
				Size = UDim2.fromOffset(20, 16),
			}),
		})
	) :: TextButton

	--// Initialize
	structures.Trailing = structures.Body:FindFirstChild("Trailing") :: Frame
	structures.Leading = structures.Body:FindFirstChild("Leading") :: Frame
	structures.Title = structures.Leading:FindFirstChild("Title") :: TextLabel
	structures.Symbol = structures.Leading:FindFirstChild("Symbol") :: ImageLabel
	structures.Padding = structures.Body:FindFirstChild("UIPadding") :: UIPadding

	local pageComponent = nil

	if properties and properties.Page then
		if type(properties.Page) == "table" and properties.Page.Type == "Page" then
			pageComponent = properties.Page
			structures.Page = pageComponent.Structures.Page
		else
			structures.Page = properties.Page
		end
	else
		pageComponent = Page(self, properties and properties.PageProperties)
		structures.Page = pageComponent.Structures.Page
	end

	structures.Page = structures.Page
		or (function()
			return binder.Apply(
				properties,
				create("ScrollingFrame")({
					Name = "ContentList",
					AutomaticCanvasSize = Enum.AutomaticSize.Y,
					BackgroundColor3 = Color3.fromRGB(255, 255, 255),
					BackgroundTransparency = 1,
					BorderColor3 = Color3.fromRGB(0, 0, 0),
					BorderSizePixel = 0,
					CanvasSize = UDim2.new(),
					ClipsDescendants = false,
					ScrollBarImageColor3 = Color3.fromRGB(0, 0, 0),
					ScrollBarImageTransparency = 0.6,
					ScrollBarThickness = 7,
					Size = UDim2.fromScale(1, 1),

					create("UIListLayout")({
						Name = "UIListLayout",
						Padding = UDim.new(0, 9),
						SortOrder = Enum.SortOrder.LayoutOrder,
					}),

					create("UIPadding")({
						Name = "Margins",
						PaddingBottom = UDim.new(0, 17),
						PaddingLeft = UDim.new(0, 17),
						PaddingRight = UDim.new(0, 17),
						PaddingTop = UDim.new(0, 17),
					}),
				})
			) :: ScrollingFrame
		end)()

	local object
	object = binder.Wrap(properties, {
		Title = function(name: string)
			structures.Title.Text = name
		end,
		Icon = function(icon: string?)
			structures.Symbol.Visible = icon and true or false
			if icon then
				structures.Symbol.Image = icon
			end
		end,
		Indentation = function(indentation: number)
			structures.Padding.PaddingLeft += UDim.new(0, (11 * indentation))
		end,
		Selected = function(selected: boolean)
			if selected then
				for _, tab: types.Tab in pairs(window.Tabs) do
					if tab.__container == object.__container then
						continue
					end

					tab.Selected = false
				end
			end

			structures.Body.Transparency = selected and self.Theme.Controls.SelectionFocused[2].Value or 1

			structures.Title.TextColor3 = selected and self.Theme.Text.SelectionPrimary[1].Value
				or self.Theme.Text.Primary[1].Value
			structures.Title.TextTransparency = selected and self.Theme.Text.SelectionPrimary[2].Value
				or self.Theme.Text.Primary[2].Value

			structures.Symbol.ImageColor3 = selected and self.Theme.Text.SelectionPrimary[1].Value
				or self.Theme.Controls.Selection[1].Value
			structures.Symbol.ImageTransparency = selected and self.Theme.Text.SelectionPrimary[2].Value
				or self.Theme.Controls.Selection[2].Value

			structures.Page.Parent = selected and window and window.__container or nil
		end,
	}, structures.Body)

	object.Navigate = function(self, targetPage: types.Page)
		if not targetPage or type(targetPage) ~= "table" or targetPage.Type ~= "Page" then
			warn("Tab:Navigate expects a Page component.")
			return
		end

		local newPageStructure = targetPage.Structures.Page

		if object.Selected and window and window.__container then
			if structures.Page then
				structures.Page.Parent = nil
			end
			newPageStructure.Parent = window.__container
		end

		structures.Page = newPageStructure

		pageComponent = targetPage
	end

	object.Type = "Tab"
	object.Theme = self.Theme
	object.Structures = structures
	object.__container = structures.Page.__instance or structures.Page
	object.__window = self.__window

	binder.Apply(properties, object)

	if window then
		table.insert(window.Tabs, object)

		if object.Selected then
			window.addToHistory(object.__container)
		end

		structures.Body.MouseButton1Click:Connect(function()
			if object.Selected then
				return
			end

			object.Selected = true

				window.addToHistory(object.__container)
		end)
	end

	if self.Type == "Tab" then
		object.Indentation = self.Indentation + 1
	end

	return object
end


local types = require("@types")

return function(self, properties: types.TextFieldProperties): types.TextField
	--// Imports
	local binder = require("@modules/binder")

	--// Variables
	local structures = require("@structures/TextField")(self)

	--// UI
	properties = properties or {}
	properties.Value = properties.Value ~= nil and properties.Value or ""
	properties.Placeholder = properties.Placeholder or "Placeholder"

	--// Initialize
	structures.Field.TextTruncate = Enum.TextTruncate.AtEnd
	structures.Field.TextXAlignment = Enum.TextXAlignment.Right
	structures.Body.Parent = self.__container or self.__instance or self

	local object
	object = binder.Wrap(properties, {
		Placeholder = function(value: string)
			structures.Field.PlaceholderText = value
		end,
		Value = function(value: string)
			structures.Field.Text = value

			if properties.ValueChanged then
				properties.Value = value
				task.spawn(properties.ValueChanged, object, value)
			end
		end,
	}, structures.Body)

	structures.Field.Focused:Connect(function()
		structures.Body.AutomaticSize = Enum.AutomaticSize.XY
	end)

	structures.Field.FocusLost:Connect(function()
		structures.Body.AutomaticSize = Enum.AutomaticSize.None

		if object.Value ~= structures.Field.Text then
			object.Value = structures.Field.Text
		end
	end)

	object.Type = "TextField"
	object.Theme = self.Theme
	object.Structures = structures

	binder.Apply(properties, object)

	structures.Field:GetPropertyChangedSignal("Text"):Connect(function()
		if properties.TextChanged then
			task.spawn(properties.TextChanged, object, structures.Field.Text or "")
		end
	end)

	return object
end


local types = require("@types")

return function(self, properties: types.TitleStackProperties): types.TitleStack
	--// Imports
	local binder = require("@modules/binder")

	local titleStack = require("@structures/TitleStack")

	--// Variables
	local structures = titleStack(self)

	--// UI
	properties = properties or {}
	properties.Title = properties.Title or "Title"

	structures.Body.Parent = self.__container or self.__instance or self

	--// Initialize
	local object = binder.Wrap(properties, {
		Title = function(value: string)
			structures.Title.Text = value
		end,
		Subtitle = function(value: string)
			structures.Subtitle.Visible = true
			structures.Subtitle.Text = value
		end,
	}, structures.Body)

	object.Type = "TitleStack"
	object.Theme = self.Theme
	object.Structures = structures

	binder.Apply(properties, object)

	return object
end


local types = require("@types")

return function(self, properties: types.ToggleProperties): types.Row
	--// Imports
	local creator = require("@modules/creator")
	local binder = require("@modules/binder")
	local services = require("@modules/services")

	--// References
	local create = creator.Create

	local tweenService = services.TweenService

	--// Variables
	local parent = self.__container or self.__instance or self
	local theme = self.Theme.Controls.Toggle
	local structures = {}

	--// UI
	properties = properties or {}
	properties.Value = properties.Value == true

	structures.Body = binder.Apply(
		properties,
		create("Frame")({
			Name = "Toggle",
			BackgroundColor3 = Color3.fromRGB(255, 255, 255),
			BackgroundTransparency = 1,
			BorderColor3 = Color3.fromRGB(0, 0, 0),
			BorderSizePixel = 0,
			Size = UDim2.fromOffset(28, 16),
			Parent = parent,

			create("ImageButton")({
				Name = "Switch",
				AutoButtonColor = false,
				BackgroundColor3 = Color3.fromRGB(255, 255, 255),
				BackgroundTransparency = 1,
				BorderColor3 = Color3.fromRGB(0, 0, 0),
				BorderSizePixel = 0,
				Image = "rbxassetid://104426531889908",
				ImageColor3 = Color3.fromRGB(0, 0, 0),
				ImageTransparency = 0.91,
				Size = UDim2.fromOffset(28, 16),

				__dynamicKeys = {
					ImageColor3 = theme.SwitchOff[1],
					ImageTransparency = theme.SwitchOff[2],
				},
				__contextKeys = {
					ImageColor3 = function()
						return properties.Value and theme.SwitchOn[1].Value or theme.SwitchOff[1].Value
					end,
					ImageTransparency = function()
						return properties.Value and theme.SwitchOn[2].Value or theme.SwitchOff[2].Value
					end,
				},

				create("ImageLabel")({
					Name = "Knob",
					AnchorPoint = Vector2.new(0, 0.5),
					BackgroundColor3 = Color3.fromRGB(255, 255, 255),
					BackgroundTransparency = 1,
					BorderColor3 = Color3.fromRGB(0, 0, 0),
					BorderSizePixel = 0,
					Image = "rbxassetid://99107881432922",
					Position = UDim2.new(0, 1, 0.5, 0),
					Size = UDim2.fromOffset(14, 14),

					__dynamicKeys = {
						ImageColor3 = theme.Knob[1],
						ImageTransparency = theme.Knob[2],
					},

					create("ImageLabel")({
						Name = "Effects",
						AnchorPoint = Vector2.new(0.5, 0.5),
						BackgroundColor3 = Color3.fromRGB(255, 255, 255),
						BackgroundTransparency = 1,
						BorderColor3 = Color3.fromRGB(0, 0, 0),
						BorderSizePixel = 0,
						Image = "rbxassetid://138042641797315",
						Position = UDim2.fromScale(0.5, 0.5),
						Size = UDim2.fromOffset(16, 16),

						__dynamicKeys = {
							ImageColor3 = theme.KnobEffects[1],
							ImageTransparency = theme.KnobEffects[2],
						},
					}),
				}),

				create("UIGradient")({
					Name = "UIGradient",
					Rotation = 90,

					__dynamicKeys = {
						Color = theme.DepthEffect[1],
					},
				}),
			}),
		})
	) :: Frame

	--// Initialize
	structures.Switch = structures.Body:FindFirstChild("Switch") :: ImageButton
	structures.Knob = structures.Switch:FindFirstChild("Knob") :: ImageLabel

	local object
	local bindings = {
		Value = function(value: boolean, instant: boolean?)
			instant = (instant == nil and true) or false

			local tweenInfo = TweenInfo.new(0.4, Enum.EasingStyle.Exponential, Enum.EasingDirection.Out)
			local knobGoal = { Position = value and UDim2.new(0, 13, 0.5, 0) or UDim2.new(0, 1, 0.5, 0) }
			local switchGoal = {
				ImageColor3 = value and theme.SwitchOn[1].Value or theme.SwitchOff[1].Value,
				ImageTransparency = value and theme.SwitchOn[2].Value or theme.SwitchOff[2].Value,
			}

			if instant then
				tweenService:Create(structures.Knob, tweenInfo, knobGoal):Play()
				tweenService:Create(structures.Switch, tweenInfo, switchGoal):Play()
			else
				structures.Knob.Position = knobGoal.Position
				structures.Switch.ImageColor3 = switchGoal.ImageColor3
				structures.Switch.ImageTransparency = switchGoal.ImageTransparency
			end

			if properties.ValueChanged and instant then
				properties.Value = value
				task.spawn(properties.ValueChanged, object, value)
			end
		end,
	}

	object = binder.Wrap(properties, bindings, structures.Body)

	object.Type = "Toggle"
	object.Theme = self.Theme
	object.Structures = structures

	do -- Input handler
		structures.Switch.MouseButton1Click:Connect(function()
			object.Value = not object.Value
		end)
	end

	bindings.Value(not not properties.Value, false)
	binder.Apply(properties, object)

	return object
end


local types = require("@types")

return function(self, properties: types.StackProperties): types.Stack
	--// Imports
	local creator = require("@modules/creator")
	local binder = require("@modules/binder")

	--// References
	local create = creator.Create

	--// Variables
	local parent = self.__container or self.__instance or self
	local structures = {}

	--// UI
	properties = properties or {}
	properties.Padding = properties.Padding or UDim.new(0, 10)
    properties.VerticalAlignment = properties.VerticalAlignment or Enum.VerticalAlignment.Center
    properties.HorizontalAlignment = properties.HorizontalAlignment or Enum.HorizontalAlignment.Right

	structures.Body = binder.Apply(
		properties,
		create("Frame")({
			Name = "VStack",
			BackgroundTransparency = 1,
			AutomaticSize = Enum.AutomaticSize.XY,
			Parent = parent,

			create("UIListLayout")({
				Name = "UIListLayout",
				FillDirection = Enum.FillDirection.Vertical,
				SortOrder = Enum.SortOrder.LayoutOrder,
				Wraps = true,
			}),
		})
	) :: Frame

	--// Initialize
	structures.Layout = structures.Body:FindFirstChild("UIListLayout") :: UIListLayout

	local object = binder.Wrap(properties, {
		Padding = function(value: UDim)
			structures.Layout.Padding = value
		end,
		HorizontalAlignment = function(value: Enum.HorizontalAlignment)
			structures.Layout.HorizontalAlignment = value
		end,
		VerticalAlignment = function(value: Enum.VerticalAlignment)
			structures.Layout.VerticalAlignment = value
		end,
	}, structures.Body)

	object.Type = "VStack"
	object.Theme = self.Theme
	object.Structures = structures

	binder.Apply(properties, object)

	return object
end


-- We uh
-- We dont talk about this..

local types = require("@types")

return function(self, properties: types.WindowProperties): types.Window
	--// Imports
	local effects = require("@effects")
	local services = require("@modules/services")
	local creator = require("@modules/creator")
	local binder = require("@modules/binder")

	local titleBar, addToHistory = require("@structures/Titlebar")(self)
	local resizeHandler = require("@modules/resizeHandler")

	--// References
	local create = creator.Create

	local userInputService = services.UserInputService
	local tweenService = services.TweenService

	--// Variables
	local parent = self.__container or self.__instance or self
	local window = create("Frame")({
		Name = "Window",
		BackgroundTransparency = 1,
		BorderSizePixel = 0,
		Size = UDim2.fromScale(1, 1),
		AnchorPoint = Vector2.new(0.5, 0.5),
		Position = UDim2.fromScale(0.5, 0.5),
		Parent = parent,
	}).__instance
	local originalSize
	local originalPosition
	local originalPosition2
	local minimizing
	local dragging
	local resizeClient
	local structures = {}

	--// UI
	properties = properties or {}

	properties.Size = properties.Size or UDim2.fromOffset(850, 530)
	properties.Maximized = properties.Maximized == true
	properties.Minimized = properties.Minimized == true
	properties.Searching = properties.Searching ~= false
	properties.Resizable = properties.Resizable ~= false
	properties.Draggable = properties.Draggable ~= false
	properties.Resizable = properties.Resizable ~= false
	properties.Dropshadow = properties.Dropshadow ~= false
	properties.UIBlur = properties.UIBlur ~= false
	properties.Title = properties.Title or "Title"

	structures.Body = binder.Apply(
		properties,
		create("Frame")({
			Name = "Body",
			BorderSizePixel = 0,
			AnchorPoint = Vector2.new(0.5, 0.5),
			Position = UDim2.fromScale(0.5, 0.5),
			Parent = window,

			__dynamicKeys = {
				BackgroundColor3 = self.Theme.Controls.Sidebar[1],
				BackgroundTransparency = self.Theme.Controls.Sidebar[2],
			},

			__contextKeys = {
				BackgroundTransparency = function()
					return properties.UIBlur and self.Theme.Controls.Sidebar[2].Value or 0
				end,
			},

			create("UICorner")({
				Name = "UICorner",
				CornerRadius = UDim.new(0, 10),
			}),

			create("UIListLayout")({
				Name = "UIListLayout",
				FillDirection = Enum.FillDirection.Horizontal,
				Padding = UDim.new(0, 0),
				SortOrder = Enum.SortOrder.LayoutOrder,
			}),

			create("Frame")({
				Name = "Sidebar",
				BackgroundColor3 = Color3.fromRGB(234, 234, 234),
				BackgroundTransparency = 1,
				BorderColor3 = Color3.fromRGB(0, 0, 0),
				BorderSizePixel = 0,
				Size = UDim2.new(0, 200, 1, 0),
				ClipsDescendants = true,

				create("UIPadding")({
					Name = "UIPadding",
				}),

				create("Frame")({
					Name = "Margins",
					BackgroundColor3 = Color3.fromRGB(234, 234, 234),
					BackgroundTransparency = 1,
					BorderColor3 = Color3.fromRGB(0, 0, 0),
					BorderSizePixel = 0,
					Size = UDim2.new(0, 200, 1, 0),
					create("Folder")({
						Name = "LayoutIgnore",

						create("Frame")({
							Name = "Shadow",
							AnchorPoint = Vector2.new(1, 0),
							BorderColor3 = Color3.fromRGB(0, 0, 0),
							BorderSizePixel = 0,
							Position = UDim2.new(1, 2, 0, 0),
							Size = UDim2.new(0, 5, 1, 0),
							ZIndex = 0,
							__dynamicKeys = {
								BackgroundColor3 = self.Theme.Controls.Separator.Shadow[1],
								BackgroundTransparency = self.Theme.Controls.Separator.Shadow[2],
							},

							create("UIGradient")({
								Name = "UIGradient",
								Transparency = NumberSequence.new({
									NumberSequenceKeypoint.new(0, 1),
									NumberSequenceKeypoint.new(1, 0),
								}),
							}),
						}),
					}),

					create("UIPadding")({
						Name = "UIPadding",
						PaddingRight = UDim.new(0, 2),
					}),

					create("Frame")({
						Name = "Toolbar",
						BackgroundColor3 = Color3.fromRGB(255, 255, 255),
						BackgroundTransparency = 1,
						BorderColor3 = Color3.fromRGB(0, 0, 0),
						BorderSizePixel = 0,
						Size = UDim2.new(1, 0, 0, 52),

						create("Frame")({
							Name = "WindowControls",
							AnchorPoint = Vector2.new(0, 0.5),
							BackgroundColor3 = Color3.fromRGB(255, 255, 255),
							BackgroundTransparency = 1,
							BorderColor3 = Color3.fromRGB(0, 0, 0),
							BorderSizePixel = 0,
							Position = UDim2.fromScale(0, 0.5),
							Size = UDim2.fromOffset(92, 38),

							create("UIListLayout")({
								Name = "UIListLayout",
								FillDirection = Enum.FillDirection.Horizontal,
								Padding = UDim.new(0, 8),
								SortOrder = Enum.SortOrder.LayoutOrder,
								VerticalAlignment = Enum.VerticalAlignment.Center,
							}),

							create("UIPadding")({
								Name = "UIPadding",
								PaddingLeft = UDim.new(0, 20),
								PaddingRight = UDim.new(0, 20),
							}),

							create("ImageButton")({
								Name = "Exit",
								AutoButtonColor = false,
								BackgroundColor3 = Color3.fromRGB(255, 255, 255),
								BackgroundTransparency = 1,
								BorderColor3 = Color3.fromRGB(0, 0, 0),
								BorderSizePixel = 0,
								Image = "rbxassetid://132228700346004",
								Size = UDim2.fromOffset(12, 12),

								__dynamicKeys = {
									ImageColor3 = self.Theme.Controls.Exit[1],
									ImageTransparency = self.Theme.Controls.Exit[2],
								},

								create("ImageLabel")({
									Name = "Stroke",
									BackgroundColor3 = Color3.fromRGB(255, 255, 255),
									BackgroundTransparency = 1,
									BorderColor3 = Color3.fromRGB(0, 0, 0),
									BorderSizePixel = 0,
									Image = "rbxassetid://94763505860483",
									Size = UDim2.fromScale(1, 1),

									__dynamicKeys = {
										ImageColor3 = self.Theme.Controls.WindowControlStroke[1],
										ImageTransparency = self.Theme.Controls.WindowControlStroke[2],
									},
								}),

								create("ImageLabel")({
									Name = "Icon",
									AnchorPoint = Vector2.new(0.5, 0.5),
									BackgroundColor3 = Color3.fromRGB(255, 255, 255),
									BackgroundTransparency = 1,
									BorderColor3 = Color3.fromRGB(0, 0, 0),
									BorderSizePixel = 0,
									Image = "rbxassetid://94781753558308",
									Position = UDim2.fromScale(0.5, 0.5),
									Size = UDim2.fromScale(1, 1),
									Visible = false,

									__dynamicKeys = {
										ImageColor3 = self.Theme.Controls.WindowControlIcon[1],
										ImageTransparency = self.Theme.Controls.WindowControlIcon[2],
									},
								}),
							}),

							create("ImageButton")({
								Name = "Minimize",
								AutoButtonColor = false,
								BackgroundColor3 = Color3.fromRGB(255, 255, 255),
								BackgroundTransparency = 1,
								BorderColor3 = Color3.fromRGB(0, 0, 0),
								BorderSizePixel = 0,
								Image = "rbxassetid://132228700346004",
								LayoutOrder = 1,
								Size = UDim2.fromOffset(12, 12),

								__dynamicKeys = {
									ImageColor3 = self.Theme.Controls.Minimize[1],
									ImageTransparency = self.Theme.Controls.Minimize[2],
								},

								create("ImageLabel")({
									Name = "Stroke",
									BackgroundColor3 = Color3.fromRGB(255, 255, 255),
									BackgroundTransparency = 1,
									BorderColor3 = Color3.fromRGB(0, 0, 0),
									BorderSizePixel = 0,
									Image = "rbxassetid://94763505860483",
									Size = UDim2.fromScale(1, 1),

									__dynamicKeys = {
										ImageColor3 = self.Theme.Controls.WindowControlStroke[1],
										ImageTransparency = self.Theme.Controls.WindowControlStroke[2],
									},
								}),

								create("ImageLabel")({
									Name = "Icon",
									AnchorPoint = Vector2.new(0.5, 0.5),
									BackgroundColor3 = Color3.fromRGB(255, 255, 255),
									BackgroundTransparency = 1,
									BorderColor3 = Color3.fromRGB(0, 0, 0),
									BorderSizePixel = 0,
									Image = "rbxassetid://118368309445367",
									Position = UDim2.fromScale(0.5, 0.5),
									Size = UDim2.fromScale(1, 1),
									Visible = false,

									__dynamicKeys = {
										ImageColor3 = self.Theme.Controls.WindowControlIcon[1],
										ImageTransparency = self.Theme.Controls.WindowControlIcon[2],
									},
								}),
							}),

							create("ImageButton")({
								Name = "Zoom",
								AutoButtonColor = false,
								BackgroundColor3 = Color3.fromRGB(255, 255, 255),
								BackgroundTransparency = 1,
								BorderColor3 = Color3.fromRGB(0, 0, 0),
								BorderSizePixel = 0,
								Image = "rbxassetid://132228700346004",
								LayoutOrder = 2,
								Size = UDim2.fromOffset(12, 12),

								__dynamicKeys = {
									ImageColor3 = self.Theme.Controls.Zoom[1],
									ImageTransparency = self.Theme.Controls.Zoom[2],
								},

								create("ImageLabel")({
									Name = "Stroke",
									BackgroundColor3 = Color3.fromRGB(255, 255, 255),
									BackgroundTransparency = 1,
									BorderColor3 = Color3.fromRGB(0, 0, 0),
									BorderSizePixel = 0,
									Image = "rbxassetid://94763505860483",
									Size = UDim2.fromScale(1, 1),

									__dynamicKeys = {
										ImageColor3 = self.Theme.Controls.WindowControlStroke[1],
										ImageTransparency = self.Theme.Controls.WindowControlStroke[2],
									},
								}),

								create("ImageLabel")({
									Name = "Icon",
									AnchorPoint = Vector2.new(0.5, 0.5),
									BackgroundColor3 = Color3.fromRGB(255, 255, 255),
									BackgroundTransparency = 1,
									BorderColor3 = Color3.fromRGB(0, 0, 0),
									BorderSizePixel = 0,
									Image = "rbxassetid://114376524082699",
									Position = UDim2.fromScale(0.5, 0.5),
									Size = UDim2.fromScale(1, 1),
									Visible = false,

									__dynamicKeys = {
										ImageColor3 = self.Theme.Controls.WindowControlIcon[1],
										ImageTransparency = self.Theme.Controls.WindowControlIcon[2],
									},
								}),
							}),
						}),
					}),

					create("ScrollingFrame")({
						Name = "SidebarList",
						AutomaticCanvasSize = Enum.AutomaticSize.Y,
						BackgroundColor3 = Color3.fromRGB(255, 255, 255),
						BackgroundTransparency = 1,
						BorderColor3 = Color3.fromRGB(0, 0, 0),
						BorderSizePixel = 0,
						CanvasSize = UDim2.new(),
						Position = UDim2.fromOffset(0, 52),
						ScrollBarImageColor3 = Color3.fromRGB(0, 0, 0),
						ScrollBarImageTransparency = 0.7,
						ScrollBarThickness = 6,
						Size = UDim2.new(1, 0, 1, -52),

						create("UIListLayout")({
							Name = "UIListLayout",
							Padding = UDim.new(0, 9),
							SortOrder = Enum.SortOrder.LayoutOrder,
							HorizontalAlignment = Enum.HorizontalAlignment.Right,
						}),

						create("UIPadding")({
							Name = "UIPadding",
							PaddingLeft = UDim.new(0, 10),
							PaddingRight = UDim.new(0, 10),
							PaddingBottom = UDim.new(0, 10),
						}),
					}),
				}),
			}),

			create("Frame")({
				Name = "Separator",
				AnchorPoint = Vector2.new(1, 0),
				BorderColor3 = Color3.fromRGB(0, 0, 0),
				BorderSizePixel = 0,
				LayoutOrder = 1,
				Position = UDim2.fromScale(1, 0),
				Size = UDim2.new(0, 1, 1, 0),
				__dynamicKeys = {
					BackgroundColor3 = self.Theme.Controls.Separator.Background[1],
					BackgroundTransparency = self.Theme.Controls.Separator.Background[2],
				},
			}),

			create("Frame")({
				Name = "ContentBody",
				AnchorPoint = Vector2.new(1, 0),
				BorderColor3 = Color3.fromRGB(0, 0, 0),
				BorderSizePixel = 0,
				ClipsDescendants = true,
				LayoutOrder = 2,
				Position = UDim2.fromScale(1, 0),
				Size = UDim2.new(1, -201, 1, 0),

				__dynamicKeys = {
					BackgroundColor3 = self.Theme.Controls.Background[1],
					BackgroundTransparency = self.Theme.Controls.Background[2],
				},

				create("UICorner")({
					Name = "UICorner",
					CornerRadius = UDim.new(0, 10),
				}),

				create("Frame")({
					Name = "Content",
					BackgroundColor3 = Color3.fromRGB(255, 255, 255),
					BackgroundTransparency = 1,
					BorderColor3 = Color3.fromRGB(255, 199, 199),
					BorderMode = Enum.BorderMode.Inset,
					BorderSizePixel = 0,
					ClipsDescendants = true,
					Position = UDim2.fromOffset(0, 52),
					Size = UDim2.new(1, 0, 1, -52),

					create("UIPadding")({
						Name = "Margins",
						PaddingBottom = UDim.new(0, 3),
						PaddingLeft = UDim.new(0, 3),
						PaddingRight = UDim.new(0, 3),
						PaddingTop = UDim.new(0, 3),
					}),
				}),

				create("Frame")({
					Name = "CornerClip",
					AnchorPoint = Vector2.new(0, 1),
					BorderColor3 = Color3.fromRGB(0, 0, 0),
					BorderSizePixel = 0,
					Position = UDim2.fromScale(0, 1),
					Size = UDim2.fromOffset(10, 10),
					ZIndex = -1,

					__dynamicKeys = {
						BackgroundColor3 = self.Theme.Controls.Background[1],
					},
				}),
			}),

			create("Folder")({
				Name = "LayoutIgnore",

				create("TextButton")({
					Name = "TopArea",
					AutoButtonColor = false,
					Active = false,
					BackgroundColor3 = Color3.fromRGB(255, 255, 255),
					BackgroundTransparency = 1,
					BorderColor3 = Color3.fromRGB(0, 0, 0),
					BorderSizePixel = 0,
					Size = UDim2.new(1, 0, 0, 52),
					ZIndex = 0,
					Text = "",
					Modal = false,
				}),

				create("ImageLabel")({
					Name = "Dropshadow",
					AnchorPoint = Vector2.new(0.5, 0.5),
					BackgroundColor3 = Color3.fromRGB(255, 255, 255),
					BackgroundTransparency = 1,
					BorderColor3 = Color3.fromRGB(0, 0, 0),
					BorderSizePixel = 0,
					Image = "rbxassetid://138260268144845",
					ImageTransparency = 0.65,
					Interactable = false,
					Position = UDim2.new(0.5, 0, 0.5, 3),
					ScaleType = Enum.ScaleType.Slice,
					Size = UDim2.new(1, 24, 1, 24),
					SliceCenter = Rect.new(28, 26, 96, 94),
					ZIndex = 0,
				}),
			}),
		})
	) :: Frame

	--// Initialize
	structures.Scale = create("UIScale")({
		Parent = window,
	})
	structures.Cornering = structures.Body:FindFirstChild("UICorner") :: UICorner
	structures.LayoutIgnore = structures.Body:FindFirstChild("LayoutIgnore") :: Folder
	structures.Dropshadow = structures.LayoutIgnore:FindFirstChild("Dropshadow") :: ImageLabel
	structures.Separator = structures.Body:FindFirstChild("Separator") :: Frame
	structures.SidebarMargins = structures.Body:FindFirstChild("Sidebar")
	structures.Sidebar = structures.SidebarMargins:FindFirstChild("Margins") :: Frame
	structures.SidebarList = structures.Sidebar:FindFirstChild("SidebarList") :: Frame
	structures.Toolbar = structures.Sidebar:FindFirstChild("Toolbar") :: Frame
	structures.WindowControls = structures.Toolbar:FindFirstChild("WindowControls") :: Frame
	structures.ContentBody = structures.Body:FindFirstChild("ContentBody") :: Frame
	structures.Content = structures.ContentBody:FindFirstChild("Content") :: Frame
	structures.CornerClip = structures.ContentBody:FindFirstChild("CornerClip") :: Frame

	structures.Titlebar = titleBar
	structures.Titlebar.Body.Parent = structures.ContentBody

	originalSize = structures.Body.Size
	originalPosition = structures.Body.Position

	local bindings = {
		Title = function(value: string)
			structures.Titlebar.Title.Visible = value and true or false

			if value then
				structures.Titlebar.Title.Text = value
			end
		end,
		Subtitle = function(value: string)
			structures.Titlebar.Subtitle.Visible = value and true or false

			if value then
				structures.Titlebar.Subtitle.Text = value
			end
		end,
		Searching = function(value: boolean)
			structures.Titlebar.SearchField.Body.Parent = value and structures.Titlebar.Trailing or nil
			structures.Titlebar.SearchField.Body.Visible = value
		end,
		Draggable = function(value: boolean)
			dragging = not value and false
		end,
		Resizable = function(value: boolean)
			if resizeClient and not properties.Maximized then
				resizeClient.SetEnabled(value)
			end
		end,
		Minimized = function(value: boolean?, tween: boolean?)
			local useTween = tween ~= false

			if value and not minimizing then
				originalPosition2 = structures.Body.Position

				if structures["BlurModel"] then
					structures["BlurModel"].SetVisibility(false)
				end
			end

			local tweenInfo = TweenInfo.new(0.25, Enum.EasingStyle.Exponential, Enum.EasingDirection.Out)
			local bodyTarget = {
				Position = value and UDim2.new(0.5, 0, 0.5, structures.Body.AbsoluteSize.Y * 2) or originalPosition2,
			}
			local scaleTarget = { Scale = value and 0 or 1 }

			if useTween then
				minimizing = true
				tweenService:Create(structures.Body.__instance, tweenInfo, bodyTarget):Play()

				local scaleTween: Tween = tweenService:Create(structures.Scale.__instance, tweenInfo, scaleTarget)

				scaleTween:Play()
				scaleTween.Completed:Once(function()
					minimizing = false

					if structures["BlurModel"] and not properties.Minimized then
						structures["BlurModel"].SetVisibility(true)
					end
				end)
			else
				structures.Body.Position = bodyTarget.Position
				structures.Scale.Scale = scaleTarget.Scale

				if value and structures["BlurModel"] then
					structures["BlurModel"].SetVisibility(false)
				end
			end
		end,
		Maximized = function(value: boolean?, tween: boolean?)
			tween = tween ~= false

			if value then
				originalSize = structures.Body.Size
				originalPosition = structures.Body.Position
				resizeClient.SetEnabled(false)
			else
				dragging = false
			end

			local tweenInfo = TweenInfo.new(0.5, Enum.EasingStyle.Exponential, Enum.EasingDirection.Out)
			local bodyTarget = {
				Size = value and UDim2.fromScale(1, 1) or originalSize,
				Position = value and UDim2.fromScale(0.5, 0.5) or originalPosition,
			}
			local cornerTarget = { CornerRadius = value and UDim.new(0, 0) or UDim.new(0, 10) }

			if tween then
				tweenService:Create(structures.Body.__instance, tweenInfo, bodyTarget):Play()
				tweenService:Create(structures.Cornering, tweenInfo, cornerTarget):Play()
			else
				structures.Body.Size = bodyTarget.Size
				structures.Body.Position = bodyTarget.Position
				structures.Cornering.CornerRadius = cornerTarget.CornerRadius
			end

			if not value then
				resizeClient.SetEnabled(properties.Resizable)
			end
		end,
		Dropshadow = function(value: boolean)
			structures.Dropshadow.Visible = value
		end,
		UIBlur = function(value: boolean)
			if structures["BlurModel"] then
				structures["BlurModel"].Model:Destroy()
				structures["BlurModel"] = nil
			end

			structures.Body.BackgroundTransparency = value and self.Theme.Controls.Sidebar[2].Value or 0

			if value and not properties.Minimized then
				structures.BlurModel = effects.UIBlur(structures.Body)
			end
		end,
	}
	local object = binder.Wrap(properties, bindings, structures.Body)

	object.Type = "Window"
	object.Theme = self.Theme
	object.Structures = structures
	object.Tabs = {}
	object.addToHistory = addToHistory(object)
	object.__container = structures.Content

	do -- Resize handler
		resizeClient = resizeHandler(structures.Body.__instance, Vector2.new(350, 250))

		resizeClient.CreateClient()
	end

	do -- Sidebar button
		local toggled = true

		local function toggle()
			toggled = not toggled

			local marginsTargetSize = toggled and UDim.new(0, 0) or UDim.new(0, -200)
			local sidebarTargetSize = toggled and UDim2.new(0, 200, 1, 0) or UDim2.new(0, 0, 1, 0)
			local contentTargetSize = toggled and UDim2.new(1, -201, 1, 0) or UDim2.new(1, 0, 1, 0)
			local cornerLeftSize = toggled and UDim2.new(0, 10, 1, 0) or UDim2.new(0, 10, 0.5, 0)

			local tweenInfo = TweenInfo.new(0.6, Enum.EasingStyle.Exponential, Enum.EasingDirection.Out)

			structures.Separator.Visible = toggled and true or false
			structures.CornerClip.Visible = toggled and true

			tweenService
				:Create(structures.ContentBody, tweenInfo, {
					Size = contentTargetSize,
				})
				:Play()

			tweenService
				:Create(structures.SidebarMargins:FindFirstChild("UIPadding"), tweenInfo, {
					PaddingLeft = marginsTargetSize,
				})
				:Play()

			local sidebarTween = tweenService:Create(structures.SidebarMargins, tweenInfo, {
				Size = sidebarTargetSize,
			})

			tweenService
				:Create(structures.Titlebar.CornerClipLeft, tweenInfo, {
					Size = cornerLeftSize,
				})
				:Play()

			sidebarTween:Play()

			if not toggled then
				sidebarTween.Completed:Connect(function()
					structures.CornerClip.Visible = false
				end)
			end
		end

		structures.Titlebar.SidebarButton.MouseButton1Click:Connect(toggle)
	end

	do -- Page searching
		local field = structures.Titlebar.SearchField.Field
		local pageCaches = {}

		local function toCache(page, descendants)
			local cache = {}

			for _, child in ipairs(descendants) do
				if child:IsA("GuiObject") then
					cache[child] = child.Visible
				end
			end

			pageCaches[page] = cache
		end

		local function fromCache(page, descendants)
			local cache = pageCaches[page]

			if not cache then
				return
			end

			for _, child in ipairs(descendants) do
				if child:IsA("GuiObject") then
					child.Visible = cache[child] ~= false
				end
			end
		end

		field:GetPropertyChangedSignal("Text"):Connect(function()
			local matches = {}
			local items = {}
			local page = structures.Content:FindFirstChildOfClass("ScrollingFrame")

			if not page then
				return
			end

			local descendants = page:GetDescendants()

			if not pageCaches[page] then
				toCache(page, descendants)
			end

			local query = field.Text:lower()

			if query == "" then
				fromCache(page, descendants)
				return
			end

			for _, child in ipairs(descendants) do
				if child:IsA("GuiObject") then
					local searchIndex = child:GetAttribute("SearchIndex")

					if typeof(searchIndex) == "string" and searchIndex:lower():find(query) then
						table.insert(matches, child)
					end
				end
			end

			for _, match in ipairs(matches) do
				items[match] = true

				local parent = match.Parent

				while parent and parent ~= page do
					if parent:IsA("GuiObject") then
						items[parent] = true
					end

					parent = parent.Parent
				end
			end

			for _, child in ipairs(descendants) do
				if child:IsA("GuiObject") then
					child.Visible = false
				end
			end

			for _, match in ipairs(matches) do
				match.Visible = true

				local parent = match.Parent

				while parent and parent ~= page do
					if parent:IsA("GuiObject") then
						parent.Visible = true
					end

					parent = parent.Parent
				end

				local cache = pageCaches[page]

				for _, descendant in ipairs(match:GetDescendants()) do
					if descendant:IsA("GuiObject") then
						local wasVisible = cache and cache[descendant]
						if wasVisible then
							descendant.Visible = true
						end
					end
				end
			end
		end)
	end

	do -- Window controls
		local exit = structures.WindowControls:FindFirstChild("Exit") :: ImageButton
		local minimize = structures.WindowControls:FindFirstChild("Minimize") :: ImageButton
		local zoom = structures.WindowControls:FindFirstChild("Zoom") :: ImageButton

		local function rollOver()
			exit:FindFirstChild("Icon").Visible = structures.WindowControls.GuiState ~= Enum.GuiState.Hover
			minimize:FindFirstChild("Icon").Visible = structures.WindowControls.GuiState ~= Enum.GuiState.Hover
			zoom:FindFirstChild("Icon").Visible = structures.WindowControls.GuiState ~= Enum.GuiState.Hover
		end

		zoom.MouseButton1Click:Connect(function()
			properties.Maximized = not properties.Maximized
			bindings.Maximized(properties.Maximized, true)
		end)

		minimize.MouseButton1Click:Connect(function()
			properties.Minimized = not properties.Minimized
			bindings.Minimized(properties.Minimized, true)
		end)

		if self.Structures and self.Structures["WindowPill"] then
			local pill: ImageButton = self.Structures["WindowPill"]

			pill.MouseButton1Click:Connect(function()
				properties.Minimized = not properties.Minimized
				bindings.Minimized(properties.Minimized, true)
			end)
		end

		exit.MouseButton1Click:Connect(function()
			bindings.Minimized(true)
			task.delay(0.25, structures.Body.Destroy)
		end)

		structures.WindowControls.MouseEnter:Connect(rollOver)
		structures.WindowControls.MouseLeave:Connect(rollOver)
	end

	do -- Window dragging
		local inputPos = nil
		local startPos = nil
		local connection = nil
		local boundingUi = structures.LayoutIgnore:FindFirstChild("TopArea")

		boundingUi.InputBegan:Connect(function(input)
			if
				(
					input.UserInputType == Enum.UserInputType.MouseButton1
					or input.UserInputType == Enum.UserInputType.Touch
				)
				and properties.Draggable
				and not properties.Maximized
			then
				dragging = true
				inputPos = input.Position
				startPos = structures.Body.Position

				if connection then
					connection:Disconnect()
				end

				connection = input.Changed:Connect(function()
					if input.UserInputState == Enum.UserInputState.End then
						dragging = false
					end
				end)
			end
		end)

		userInputService.InputChanged:Connect(function(input)
			if
				input.UserInputType == Enum.UserInputType.MouseMovement
				or input.UserInputType == Enum.UserInputType.Touch
			then
				if dragging then
					local delta = input.Position - inputPos
					local newPosition = UDim2.new(
						startPos.X.Scale,
						startPos.X.Offset + delta.X,
						startPos.Y.Scale,
						startPos.Y.Offset + delta.Y
					)

					structures.Body.Position = newPosition
				end
			end
		end)
	end

	binder.Apply(properties, object)

	local function recheck() -- Due to roblox resizing issues
		-- If there's a better way to do this please tell me or make a PR
		for i, v in pairs(structures.Body:GetDescendants()) do
			if not pcall(function()
				return v.Size
			end) then
				continue
			end

			local original = v.Size

			v.Size = UDim2.fromOffset(0, 0)
			v.Size = original
		end
	end

	task.defer(recheck)
	task.delay(1, recheck)

	return object
end


--// Imports
local binder = require("@modules/binder")

--// Variables
local components = {
	Window = require("@components/Window"),
	Section = require("@components/Section"),
	Tab = require("@components/Tab"),
	PageSection = require("@components/PageSection"),
	Form = require("@components/Form"),
	Row = require("@components/Row"),
	HStack = require("@components/HStack"),
	VStack = require("@components/VStack"),
	TitleStack = require("@components/TitleStack"),
	Label = require("@components/Label"),
	Symbol = require("@components/Symbol"),
	Toggle = require("@components/Toggle"),
	TextField = require("@components/TextField"),
	KeybindField = require("@components/KeybindField"),
	Slider = require("@components/Slider"),
	Button = require("@components/Button"),
	Stepper = require("@components/Stepper"),
	RadioButtonGroup = require("@components/RadioButtonGroup"),
	PopUpButton = require("@components/PopUpButton"),
	PullDownButton = require("@components/PullDownButton"),
	Page = require("@components/Page"),
	Notification = require("@components/Notification"),
}

--// Initialize
local function wrap(name, make)
	return function(self, ...)
		local result, raw = make(self, ...)

		if
			typeof(result) == "Instance"
			or (typeof(result) == "table" and getmetatable(result) and typeof(getmetatable(result)) == "Instance")
		then
			raw = result
			result = binder.Wrap({}, {}, result)
		end

		if typeof(result) == "table" then
			if result.Type == nil then
				result.Type = name
			end

			if result.Theme == nil and self and self.Theme then
				result.Theme = self.Theme
			end
		end

		binder.Apply(components, result)

		local final = raw
			or (
				typeof(result) == "table"
				and pcall(function()
					return result.__instance
				end)
				and result.__instance
			)

		if final ~= nil then
			return result, final
		end

		return result
	end
end

for name, make in pairs(components) do
	components[name] = wrap(name, make)
end

function components.register(name: string, make: (any, any) -> any)
	components[name] = wrap(name, make)
end

return components


--// Imports
local utility = require("@modules/utility")
local types = require("@types")
local creator = require("@modules/creator")
local binder = require("@modules/binder")
local services = require("@modules/services")

local symbols = require("@modules/symbols")
local components = require("@components/init")

local themes = require("@themes/init")
local accents = require("@themes/accents")

--// References
local create = creator.Create

local tweenService = services.TweenService

--// Variables
local cascade = {
	Themes = themes,
	Accents = accents,
	Symbols = symbols,

	Creator = creator,
	Binder = binder,
	Components = components,
}

local tweenInfo = TweenInfo.new(0.4, Enum.EasingStyle.Exponential, Enum.EasingDirection.Out)
local currentTween: Tween? = nil

--// Functions
local function deepCopy(original, identifier: string?)
	local copy = {}
	for key, value in pairs(original) do
		local vType = typeof(value)
		if vType == "table" then
			if value.Value ~= nil and value.Connect and typeof(value.Connect) == "function" then
				copy[key] = creator.Value(value.Value)
			else
				copy[key] = deepCopy(value)
			end
		else
			copy[key] = value
		end
	end

	if identifier and not original._id then
		original._id = identifier
	end

	return copy
end

local function parseAccent(theme, overrides)
	for key, override in pairs(overrides) do
		local themeObj = theme[key]

		if not themeObj and type(theme) == "table" and type(theme.Controls) == "table" then
			themeObj = theme.Controls[key]
		end

		if not themeObj then
			continue
		end

		if type(themeObj) == "table" and themeObj.Connect then
			themeObj.Value = override
		elseif type(themeObj) == "table" and themeObj[1] and themeObj[1].Connect and typeof(override) == "Color3" then
			themeObj[1].Value = override
		elseif type(themeObj) == "table" and type(override) == "table" then
			parseAccent(themeObj, override)
		end
	end
end

local function updateThemes(target, theme, accent)
	local function deepUpdate(target, new)
		for key, value in pairs(new) do
			if type(value) == "table" and type(target[key]) == "table" and not value.Value then
				deepUpdate(target[key], value)
			elseif target[key] and value and value.Value ~= nil then
				target[key].Value = value.Value
			end
		end
	end
	deepUpdate(target, theme)

	if accent and accent[theme._id] then
		parseAccent(target, accent[theme._id])
	end
end

--// Initialize
cascade.New = function(properties: types.AppProperties): types.App
	if not game:IsLoaded() then
		game.Loaded:Wait()
	end

	properties = properties or {}

	local initialTheme = properties.Theme or themes.Light
	local initialAccent = properties.Accent or accents.Blue

	local currentBaseTheme = initialTheme

	properties.Theme = deepCopy(initialTheme)
	properties.Accent = deepCopy(initialAccent)

	updateThemes(properties.Theme, initialTheme, initialAccent)

	local container = utility.ProtectUI(create("ScreenGui")({
		Name = "Cascade",
		IgnoreGuiInset = true,
		ResetOnSpawn = false,
		ZIndexBehavior = Enum.ZIndexBehavior.Sibling,
		DisplayOrder = 200,

		OnTopOfCoreBlur = true,
	})) :: ScreenGui

	local pill = create("ImageButton")({
		Name = "WindowPill",
		AnchorPoint = Vector2.new(0.5, 0),
		AutoButtonColor = false,
		BackgroundColor3 = Color3.fromRGB(255, 255, 255),
		BackgroundTransparency = 1,
		BorderColor3 = Color3.fromRGB(0, 0, 0),
		BorderSizePixel = 0,
		Image = "rbxassetid://93520763686656",
		ImageTransparency = 0.5,
		Position = UDim2.new(0.5, 0, 0, 10),
		Size = UDim2.fromOffset(180, 5),
		Parent = container.__instance,

		create("UICorner")({
			Name = "UICorner",
			CornerRadius = UDim.new(1, 0),
		}),
	}) :: ImageButton

	pill.MouseEnter:Connect(function()
		if currentTween then
			currentTween:Cancel()
		end

		currentTween = tweenService:Create(pill.__instance, tweenInfo, {
			ImageTransparency = 0.15,
		})

		if currentTween then
			currentTween:Play()
		end
	end)

	pill.MouseLeave:Connect(function()
		if currentTween then
			currentTween:Cancel()
		end

		currentTween = tweenService:Create(pill.__instance, tweenInfo, {
			ImageTransparency = 0.5,
		})

		if currentTween then
			currentTween:Play()
		end
	end)

	local object = binder.Wrap(properties, {
		WindowPill = function(value: boolean)
			pill.Visible = value
		end,
		Theme = function(newTheme)
			currentBaseTheme = newTheme
			updateThemes(properties.Theme, newTheme, properties.Accent)
		end,
		Accent = function(newAccent)
			properties.Accent = deepCopy(newAccent, newAccent._id)
			updateThemes(properties.Theme, currentBaseTheme, newAccent)
		end,
	}, container, { "Theme", "Accent" })

	object.Structures = {
		WindowPill = pill,
	}

	setmetatable(properties, { __index = components })

	binder.Apply(properties, object)
	task.defer(binder.Apply, properties, object)

	return object
end

cascade.Component = function(properties: types.ComponentProperties?): types.ComponentContext
	properties = properties or {}

	local initialTheme = properties.Theme or themes.Light
	local initialAccent = properties.Accent or accents.Blue

	local currentBaseTheme = initialTheme

	properties.Theme = deepCopy(initialTheme)
	properties.Accent = deepCopy(initialAccent)

	updateThemes(properties.Theme, initialTheme, initialAccent)

	local object = binder.Wrap(properties, {
		Theme = function(newTheme)
			currentBaseTheme = newTheme
			updateThemes(properties.Theme, newTheme, properties.Accent)
		end,
		Accent = function(newAccent)
			properties.Accent = deepCopy(newAccent, newAccent._id)
			updateThemes(properties.Theme, currentBaseTheme, newAccent)
		end,
	}, nil, { "Theme", "Accent" })

	if properties.Parent then
		object.__container = properties.Parent
	end

	setmetatable(properties, { __index = components })

	binder.Apply(properties, object)
	task.defer(binder.Apply, properties, object)

	return object
end

cascade.RegisterComponent = function(name: string, make: (self: any, properties: any) -> any)
	components.register(name, make)
end

return cascade


local binder = {}

function binder.Apply(properties: { [string]: any }, object: any, excludes: { [number]: string }?): any
	for property, value in pairs(properties) do
		if excludes and table.find(excludes, property) then
			continue
		end

		pcall(function()
			object[property] = value
		end)
	end

	return object
end

function binder.ReactiveTable(initial, onChange)
	local raw = table.clone(initial or {})
	local proxy = {}

	local mt = {
		__index = function(_, key)
			return raw[key]
		end,
		__newindex = function(_, key, value)
			raw[key] = value
			if onChange then
				onChange(raw)
			end
		end,
		__len = function()
			return #raw
		end,
		__pairs = function()
			return pairs(raw)
		end,
		__ipairs = function()
			return ipairs(raw)
		end,
		__metatable = false,
	}

	return setmetatable(proxy, mt)
end

function binder.Wrap(
	object: { [string]: any },
	bindings: { [string]: (any) -> () },
	instance: Instance?,
	excludeSets: { [number]: any }?
): any
	local proxy = {}

	setmetatable(proxy, {
		__index = function(_, key)
			if object[key] ~= nil then
				return object[key]
			elseif instance then
				local ok, value = pcall(function()
					return instance[key]
				end)

				if ok then
					return value
				end
			end

			return
		end,

		__newindex = function(_, key, value)
			local handler = bindings[key]

			if handler then
				handler(value)

				if not (excludeSets and table.find(excludeSets, key)) then
					object[key] = value
				end
			elseif instance then
				local ok, _ = pcall(function()
					instance[key] = value
				end)

				if not ok then
					object[key] = value
				end
			else
				object[key] = value
			end
		end,
	})

	return proxy
end

return binder