GUI_Maker_Roblox

Library

Mar 15th, 2026
1,815
0
Never
8
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 95.66 KB | None | 0 0
  1. --!nocheck
  2. -- update!
  3. local TESTING = false
  4.  
  5. local RunService = game:GetService("RunService")
  6. local TextService = game:GetService("TextService")
  7. local UserInputService = game:GetService("UserInputService")
  8.  
  9. local ScreenGui = game:GetObjects("rbxassetid://99852798675591")[1]
  10. ScreenGui.Enabled = false
  11.  
  12. if RunService:IsStudio() then
  13. ScreenGui.Parent = game.StarterGui
  14. else
  15. ScreenGui.Parent = cloneref(game.CoreGui)
  16. end
  17.  
  18. local Library = {
  19. sizeX = 800,
  20. sizeY = 600,
  21. tabSizeX = 200,
  22.  
  23. dragging = false,
  24. sliderDragging = false,
  25. firstTabDebounce = false,
  26. firstSubTabDebounce = false,
  27. processedEvent = false,
  28. managerCreated = false,
  29. lineIndex = 0,
  30. dropdownOpen = 0,
  31.  
  32. Connections = {},
  33. Addons = {},
  34. Exclusions = {},
  35. SectionFolder = {
  36. Left = {},
  37. Right = {},
  38. },
  39. Flags = {
  40. Toggle = {},
  41. Slider = {},
  42. TextBox = {},
  43. Keybind = {},
  44. Dropdown = {},
  45. ColorPicker = {},
  46. },
  47. Theme = {},
  48. DropdownSizes = {},
  49. TooltipInstance = nil,
  50. TooltipShowId = 0,
  51. TooltipMoveConnection = nil,
  52. TooltipTweens = {},
  53. IconVisible = true,
  54. }
  55. Library.__index = Library
  56.  
  57. shared.Flags = Library.Flags
  58.  
  59. local Connections = Library.Connections
  60. local Exclusions = Library.Exclusions
  61.  
  62. local Assets = ScreenGui.Assets
  63. local Modules = {
  64. Dropdown = loadstring(
  65. game:HttpGet(
  66. `https://raw.githubusercontent.com/Grayy12/Leny-UI/refs/heads/{TESTING and "testing" or "main"}/Modules/Dropdown.lua`,
  67. true
  68. )
  69. )(),
  70. Toggle = loadstring(
  71. game:HttpGet(
  72. `https://raw.githubusercontent.com/Grayy12/Leny-UI/refs/heads/{TESTING and "testing" or "main"}/Modules/Toggle.lua`,
  73. true
  74. )
  75. )(),
  76. Popup = loadstring(
  77. game:HttpGet(
  78. `https://raw.githubusercontent.com/Grayy12/Leny-UI/refs/heads/{TESTING and "testing" or "main"}/Modules/Popup.lua`,
  79. true
  80. )
  81. )(),
  82. Slider = loadstring(
  83. game:HttpGet(
  84. `https://raw.githubusercontent.com/Grayy12/Leny-UI/refs/heads/{TESTING and "testing" or "main"}/Modules/Slider.lua`,
  85. true
  86. )
  87. )(),
  88. Keybind = loadstring(
  89. game:HttpGet(
  90. `https://raw.githubusercontent.com/Grayy12/Leny-UI/refs/heads/{TESTING and "testing" or "main"}/Modules/Keybind.lua`,
  91. true
  92. )
  93. )(),
  94. TextBox = loadstring(
  95. game:HttpGet(
  96. `https://raw.githubusercontent.com/Grayy12/Leny-UI/refs/heads/{TESTING and "testing" or "main"}/Modules/TextBox.lua`,
  97. true
  98. )
  99. )(),
  100. Navigation = loadstring(
  101. game:HttpGet(
  102. `https://raw.githubusercontent.com/Grayy12/Leny-UI/refs/heads/{TESTING and "testing" or "main"}/Modules/Navigation.lua`,
  103. true
  104. )
  105. )(),
  106. ColorPicker = loadstring(
  107. game:HttpGet(
  108. `https://raw.githubusercontent.com/Grayy12/Leny-UI/refs/heads/{TESTING and "testing" or "main"}/Modules/ColorPicker.lua`,
  109. true
  110. )
  111. )(),
  112. }
  113.  
  114. local Utility = loadstring(
  115. game:HttpGet(
  116. `https://raw.githubusercontent.com/Grayy12/Leny-UI/refs/heads/{TESTING and "testing" or "main"}/Modules/Utility.lua`,
  117. true
  118. )
  119. )()
  120. local Theme = loadstring(
  121. game:HttpGet(
  122. `https://raw.githubusercontent.com/Grayy12/Leny-UI/refs/heads/{TESTING and "testing" or "main"}/Modules/Theme.lua`,
  123. true
  124. )
  125. )()
  126. Library.Theme = Theme
  127.  
  128. local Popups = ScreenGui.Popups
  129.  
  130. local Glow = ScreenGui.Glow
  131. Glow.Size = UDim2.fromOffset(Library.sizeX, Library.sizeY)
  132.  
  133. local Background = Glow.Background
  134.  
  135. local Tabs = Background.Tabs
  136. local Filler = Tabs.Filler
  137. local Resize = Filler.Resize
  138. local Line = Filler.Line
  139. local Title = Tabs.Frame.Title
  140.  
  141. function Library:createTooltip()
  142. if Library.TooltipInstance then
  143. return Library.TooltipInstance
  144. end
  145.  
  146. local Tooltip = Instance.new("Frame")
  147. Tooltip.Name = "Tooltip"
  148. Tooltip.BackgroundColor3 = Theme.SecondaryBackgroundColor
  149. Tooltip.BorderSizePixel = 0
  150. Tooltip.Visible = false
  151. Tooltip.ZIndex = 9999
  152. Tooltip.AutomaticSize = Enum.AutomaticSize.Y
  153. Tooltip.Parent = ScreenGui
  154.  
  155. local UICorner = Instance.new("UICorner")
  156. UICorner.CornerRadius = UDim.new(0, 4)
  157. UICorner.Parent = Tooltip
  158.  
  159. local UIPadding = Instance.new("UIPadding")
  160. UIPadding.PaddingLeft = UDim.new(0, 8)
  161. UIPadding.PaddingRight = UDim.new(0, 8)
  162. UIPadding.PaddingTop = UDim.new(0, 6)
  163. UIPadding.PaddingBottom = UDim.new(0, 6)
  164. UIPadding.Parent = Tooltip
  165.  
  166. local TextLabel = Instance.new("TextLabel")
  167. TextLabel.Name = "Text"
  168. TextLabel.BackgroundTransparency = 1
  169. TextLabel.Size = UDim2.new(1, 0, 0, 0)
  170. TextLabel.AutomaticSize = Enum.AutomaticSize.Y
  171. TextLabel.Font = Enum.Font.Gotham
  172. TextLabel.TextSize = 13
  173. TextLabel.TextColor3 = Theme.PrimaryTextColor
  174. TextLabel.TextXAlignment = Enum.TextXAlignment.Left
  175. TextLabel.TextYAlignment = Enum.TextYAlignment.Top
  176. TextLabel.TextWrapped = true
  177. TextLabel.Parent = Tooltip
  178.  
  179. local Border = Instance.new("UIStroke")
  180. Border.Color = Theme.Line
  181. Border.Thickness = 1
  182. Border.Parent = Tooltip
  183.  
  184. Theme:registerToObjects({
  185. { object = Tooltip, property = "BackgroundColor3", theme = { "SecondaryBackgroundColor" } },
  186. { object = TextLabel, property = "TextColor3", theme = { "PrimaryTextColor" } },
  187. { object = Border, property = "Color", theme = { "Line" } },
  188. })
  189.  
  190. Library.TooltipInstance = Tooltip
  191. return Tooltip
  192. end
  193.  
  194. function Library:cancelTooltipTweens()
  195. for _, tween in ipairs(Library.TooltipTweens) do
  196. tween:Cancel()
  197. end
  198. Library.TooltipTweens = {}
  199. end
  200.  
  201. function Library:showTooltip(element, text)
  202. if not text or text == "" then
  203. return
  204. end
  205. if Library.dropdownOpen > 0 then
  206. return
  207. end
  208.  
  209. local Tooltip = Library:createTooltip()
  210. local TextLabel = Tooltip.Text
  211.  
  212. Library.TooltipShowId = Library.TooltipShowId + 1
  213. Library:cancelTooltipTweens()
  214.  
  215. if Library.TooltipMoveConnection then
  216. Library.TooltipMoveConnection:Disconnect()
  217. Library.TooltipMoveConnection = nil
  218. end
  219.  
  220. TextLabel.Text = text
  221.  
  222. local maxW = 260
  223. local textSize = TextService:GetTextSize(text, 13, Enum.Font.Gotham, Vector2.new(maxW, 10000))
  224. local w = math.min(textSize.X, maxW) + 16
  225. Tooltip.Size = UDim2.fromOffset(w, 0)
  226.  
  227. Tooltip.BackgroundTransparency = 0
  228. TextLabel.TextTransparency = 0
  229.  
  230. local function updatePosition()
  231. if Library.dropdownOpen > 0 then
  232. Tooltip.Visible = false
  233. return
  234. end
  235. local mouse = UserInputService:GetMouseLocation()
  236. local sx = ScreenGui.AbsoluteSize.X
  237. local sy = ScreenGui.AbsoluteSize.Y
  238. local tw = Tooltip.AbsoluteSize.X
  239. local th = Tooltip.AbsoluteSize.Y
  240. local x = math.clamp(mouse.X + -5, 4, sx - tw - 4)
  241. local y = math.clamp(mouse.Y + -25, 4, sy - th - 4)
  242. Tooltip.Position = UDim2.fromOffset(x, y)
  243. end
  244.  
  245. updatePosition()
  246. Tooltip.Visible = true
  247.  
  248. local conn = UserInputService.InputChanged:Connect(function(input)
  249. if input.UserInputType == Enum.UserInputType.MouseMovement then
  250. updatePosition()
  251. end
  252. end)
  253.  
  254. Library.TooltipMoveConnection = conn
  255. table.insert(Connections, conn)
  256. end
  257.  
  258. function Library:hideTooltip()
  259. if not Library.TooltipInstance then
  260. return
  261. end
  262.  
  263. local Tooltip = Library.TooltipInstance
  264. local TextLabel = Tooltip.Text
  265. local hideId = Library.TooltipShowId
  266.  
  267. -- Cancel any previous tweens before starting new fade-out
  268. Library:cancelTooltipTweens()
  269.  
  270. local t1 = Utility:tween(Tooltip, { BackgroundTransparency = 1 }, 0.1, "Quart", "Out")
  271. local t2 = Utility:tween(TextLabel, { TextTransparency = 1 }, 0.1, "Quart", "Out")
  272. t1:Play()
  273. t2:Play()
  274. Library.TooltipTweens = { t1, t2 }
  275.  
  276. task.delay(0.1, function()
  277. if Library.TooltipShowId == hideId then
  278. Tooltip.Visible = false
  279.  
  280. if Library.TooltipMoveConnection then
  281. Library.TooltipMoveConnection:Disconnect()
  282. Library.TooltipMoveConnection = nil
  283. end
  284. end
  285. end)
  286. end
  287.  
  288. function Library:forceHideTooltip()
  289. if not Library.TooltipInstance then
  290. return
  291. end
  292.  
  293. Library.TooltipShowId = Library.TooltipShowId + 1
  294. Library:cancelTooltipTweens()
  295.  
  296. Library.TooltipInstance.BackgroundTransparency = 1
  297. Library.TooltipInstance.Text.TextTransparency = 1
  298. Library.TooltipInstance.Visible = false
  299.  
  300. if Library.TooltipMoveConnection then
  301. Library.TooltipMoveConnection:Disconnect()
  302. Library.TooltipMoveConnection = nil
  303. end
  304. end
  305.  
  306. local tabResizing = false
  307. Resize.MouseButton1Down:Connect(function()
  308. tabResizing = true
  309. end)
  310.  
  311. local touchMoved = UserInputService.TouchMoved:Connect(function()
  312. if tabResizing then
  313. local newSizeX = math.clamp(
  314. ((input.Position.X - Glow.AbsolutePosition.X) / Glow.AbsoluteSize.X) * Glow.AbsoluteSize.X,
  315. 72,
  316. 208
  317. )
  318. Utility:tween(Tabs, { Size = UDim2.new(0, newSizeX, 1, 0) }, 0.2, "Quart", "Out"):Play()
  319. Utility:tween(Background.Pages, { Size = UDim2.new(1, -newSizeX, 1, 0) }, 0.2, "Quart", "Out"):Play()
  320. end
  321. end)
  322.  
  323. local inputChanged = UserInputService.InputChanged:Connect(function(input)
  324. if tabResizing and input.UserInputType == Enum.UserInputType.MouseMovement then
  325. local newSizeX = math.clamp(
  326. ((input.Position.X - Glow.AbsolutePosition.X) / Glow.AbsoluteSize.X) * Glow.AbsoluteSize.X,
  327. 72,
  328. 208
  329. )
  330. Utility:tween(Tabs, { Size = UDim2.new(0, newSizeX, 1, 0) }, 0.2, "Quart", "Out"):Play()
  331. Utility:tween(Background.Pages, { Size = UDim2.new(1, -newSizeX, 1, 0) }, 0.2, "Quart", "Out"):Play()
  332. end
  333. end)
  334.  
  335. local touchEnded = UserInputService.TouchEnded:Connect(function(input)
  336. if tabResizing then
  337. tabResizing = false
  338. end
  339. end)
  340.  
  341. table.insert(Connections, inputChanged)
  342.  
  343. Resize.InputEnded:Connect(function(input)
  344. if input.UserInputType == Enum.UserInputType.MouseButton1 then
  345. tabResizing = false
  346. end
  347. end)
  348.  
  349. Glow:GetPropertyChangedSignal("AbsoluteSize"):Connect(function()
  350. for _, data in ipairs(Library.SectionFolder.Right) do
  351. if Glow.AbsoluteSize.X <= 660 then
  352. data.folders.Right.Visible = false
  353. data.folders.Left.Size = UDim2.fromScale(1, 1)
  354. data.object.Parent = data.folders.Left
  355. else
  356. data.folders.Left.Size = UDim2.new(0.5, -7, 1, 0)
  357. data.folders.Right.Visible = true
  358. data.object.Parent = data.folders.Right
  359. end
  360. end
  361.  
  362. for _, data in ipairs(Library.SectionFolder.Left) do
  363. if Glow.AbsoluteSize.X <= 660 then
  364. data.folders.Right.Visible = false
  365. data.folders.Left.Size = UDim2.fromScale(1, 1)
  366. else
  367. data.folders.Left.Size = UDim2.new(0.5, -7, 1, 0)
  368. data.folders.Right.Visible = true
  369. end
  370. end
  371. end)
  372.  
  373. function Library.new(options)
  374. if getgenv().oldLibrary then
  375. getgenv().oldLibrary:destroy()
  376. end
  377.  
  378. getgenv().oldLibrary = Library
  379.  
  380. Utility:validateOptions(options, {
  381. sizeX = { Default = Library.sizeX, ExpectedType = "number" },
  382. sizeY = { Default = Library.sizeY, ExpectedType = "number" },
  383. tabSizeX = { Default = Library.tabSizeX, ExpectedType = "number" },
  384. title = { Default = "Leny", ExpectedType = "string" },
  385. iconTitle = { Default = "rbxassetid://110774279816088", ExpectedType = "string" },
  386. rainbowIcon = { Default = false, ExpectedType = "boolean" },
  387. PrimaryBackgroundColor = { Default = Library.Theme.PrimaryBackgroundColor, ExpectedType = "Color3" },
  388. SecondaryBackgroundColor = { Default = Library.Theme.SecondaryBackgroundColor, ExpectedType = "Color3" },
  389. TertiaryBackgroundColor = { Default = Library.Theme.TertiaryBackgroundColor, ExpectedType = "Color3" },
  390. TabBackgroundColor = { Default = Library.Theme.TabBackgroundColor, ExpectedType = "Color3" },
  391. PrimaryTextColor = { Default = Library.Theme.PrimaryTextColor, ExpectedType = "Color3" },
  392. SecondaryTextColor = { Default = Library.Theme.SecondaryTextColor, ExpectedType = "Color3" },
  393. PrimaryColor = { Default = Library.Theme.PrimaryColor, ExpectedType = "Color3" },
  394. ScrollingBarImageColor = { Default = Library.Theme.ScrollingBarImageColor, ExpectedType = "Color3" },
  395. Line = { Default = Library.Theme.Line, ExpectedType = "Color3" },
  396. })
  397.  
  398. Library.tabSizeX = math.clamp(options.tabSizeX, 72, 208)
  399. Library.sizeX = options.sizeX
  400. Library.sizeY = options.sizeY
  401. Library.Theme.PrimaryBackgroundColor = options.PrimaryBackgroundColor
  402. Library.Theme.SecondaryBackgroundColor = options.SecondaryBackgroundColor
  403. Library.Theme.TertiaryBackgroundColor = options.TertiaryBackgroundColor
  404. Library.Theme.TabBackgroundColor = options.TabBackgroundColor
  405. Library.Theme.PrimaryTextColor = options.PrimaryTextColor
  406. Library.Theme.SecondaryTextColor = options.SecondaryTextColor
  407. Library.Theme.PrimaryColor = options.PrimaryColor
  408. Library.Theme.ScrollingBarImageColor = options.ScrollingBarImageColor
  409. Library.Theme.Line = options.Line
  410. Library.Title = options.title
  411.  
  412. ScreenGui.Enabled = true
  413.  
  414. -- Intro animation: scale up with bounce
  415. Glow.Size = UDim2.fromOffset(options.sizeX * 0.93, options.sizeY * 0.93)
  416. Utility:tween(Glow, {
  417. Size = UDim2.fromOffset(options.sizeX, options.sizeY),
  418. }, 0.4, "Back", "Out"):Play()
  419.  
  420. local rainbowConnection = nil
  421.  
  422. local function createNaturalRainbowEffect(titleIcon)
  423. if rainbowConnection then
  424. rainbowConnection:Disconnect()
  425. rainbowConnection = nil
  426. end
  427.  
  428. local originalColor = Library.Theme.PrimaryTextColor
  429. local s, v = originalColor:ToHSV()
  430.  
  431. local originalSaturation = math.max(s, 0.8)
  432. local originalValue = math.max(v, 0.9)
  433.  
  434. local startTime = tick()
  435. local cycleDuration = 4
  436.  
  437. rainbowConnection = game:GetService("RunService").Heartbeat:Connect(function()
  438. local elapsed = tick() - startTime
  439. local progress = (elapsed % cycleDuration) / cycleDuration
  440.  
  441. local currentHue = progress
  442.  
  443. local newColor = Color3.fromHSV(currentHue, originalSaturation, originalValue)
  444. titleIcon.ImageColor3 = newColor
  445. end)
  446.  
  447. table.insert(Connections, {
  448. Disconnect = function()
  449. if rainbowConnection then
  450. rainbowConnection:Disconnect()
  451. rainbowConnection = nil
  452. end
  453. end,
  454. })
  455. end
  456.  
  457. local function stopRainbowEffect(titleIcon)
  458. if rainbowConnection then
  459. rainbowConnection:Disconnect()
  460. rainbowConnection = nil
  461. end
  462.  
  463. titleIcon.ImageColor3 = Library.Theme.PrimaryTextColor
  464.  
  465. Theme:registerToObjects({
  466. { object = titleIcon, property = "ImageColor3", theme = { "PrimaryTextColor" } },
  467. })
  468. end
  469.  
  470. if UserIsPoor then
  471. Title.Text = options.title
  472. if Title:FindFirstChild("TitleIcon") then
  473. Title.TitleIcon.Visible = false
  474. end
  475. else
  476. local TitleIcon = Title:FindFirstChild("TitleIcon")
  477. if not TitleIcon then
  478. TitleIcon = Instance.new("ImageLabel")
  479. TitleIcon.Name = "TitleIcon"
  480. TitleIcon.Parent = Title
  481. TitleIcon.BackgroundTransparency = 1
  482. TitleIcon.Size = UDim2.new(0, 51, 0, 51)
  483. TitleIcon.Position = UDim2.new(0, -9, 0.5, 0)
  484. TitleIcon.AnchorPoint = Vector2.new(0, 0.5)
  485. TitleIcon.ScaleType = Enum.ScaleType.Fit
  486. end
  487.  
  488. TitleIcon.Image = options.iconTitle
  489. TitleIcon.Visible = true
  490. TitleIcon.ImageColor3 = Library.Theme.PrimaryTextColor
  491. Title.Text = " " .. options.title
  492.  
  493. -- Register icon to theme system
  494. Theme:registerToObjects({
  495. { object = TitleIcon, property = "ImageColor3", theme = { "PrimaryTextColor" } },
  496. })
  497.  
  498. if options.rainbowIcon then
  499. createNaturalRainbowEffect(TitleIcon)
  500. end
  501. end
  502.  
  503. Glow.Size = UDim2.fromOffset(options.sizeX, options.sizeY)
  504. end
  505.  
  506. function Library:createAddons(text, imageButton, scrollingFrame, additionalAddons)
  507. local Addon = Assets.Elements.Addons:Clone()
  508. Addon.Size = UDim2.fromOffset(scrollingFrame.AbsoluteSize.X * 0.5, Addon.Inner.UIListLayout.AbsoluteContentSize.Y)
  509. table.insert(self.Addons, Addon)
  510.  
  511. local Inner = Addon.Inner
  512.  
  513. local TextLabel = Inner.TextLabel
  514. TextLabel.Text = text .. " Addons"
  515.  
  516. local PopupContext = Utility:validateContext({
  517. Popup = { Value = Addon, ExpectedType = "Instance" },
  518. Target = { Value = imageButton, ExpectedType = "Instance" },
  519. Library = { Value = Library, ExpectedType = "table" },
  520. TransparentObjects = { Value = Utility:getTransparentObjects(Addon), ExpectedType = "table" },
  521. ScrollingFrame = { Value = scrollingFrame, ExpectedType = "Instance" },
  522. Popups = { Value = Popups, ExpectedType = "Instance" },
  523. Inner = { Value = Inner, ExpectedType = "Instance" },
  524. PositionPadding = { Value = 18 + 7, ExpectedType = "number" },
  525. SizePadding = { Value = 30, ExpectedType = "number" },
  526. })
  527.  
  528. Theme:registerToObjects({
  529. { object = Addon, property = "BackgroundColor3", theme = { "Line" } },
  530. { object = Inner, property = "BackgroundColor3", theme = { "PrimaryBackgroundColor" } },
  531. { object = TextLabel, property = "TextColor3", theme = { "PrimaryTextColor" } },
  532. })
  533.  
  534. local Popup = Modules.Popup.new(PopupContext)
  535. imageButton.MouseButton1Down:Connect(Popup:togglePopup())
  536. Popup:hidePopupOnClickingOutside()
  537.  
  538. local DefaultAddons = {
  539. createToggle = function(self, options)
  540. Library:createToggle(options, Addon.Inner, scrollingFrame)
  541. end,
  542.  
  543. createSlider = function(self, options)
  544. Library:createSlider(options, Addon.Inner, scrollingFrame)
  545. end,
  546.  
  547. createDropdown = function(self, options)
  548. options.default = {}
  549. Library:createDropdown(options, Addon.Inner, scrollingFrame)
  550. end,
  551.  
  552. createPicker = function(self, options)
  553. Library:createPicker(options, Addon.Inner, scrollingFrame, true)
  554. end,
  555.  
  556. createKeybind = function(self, options)
  557. Library:createKeybind(options, Addon.Inner, scrollingFrame)
  558. end,
  559.  
  560. createButton = function(self, options)
  561. Library:createButton(options, Addon.Inner, scrollingFrame)
  562. end,
  563.  
  564. createTextBox = function(self, options)
  565. Library:createTextBox(options, Addon.Inner, scrollingFrame)
  566. end,
  567. }
  568.  
  569. for key, value in pairs(additionalAddons or {}) do
  570. DefaultAddons[key] = value
  571. end
  572.  
  573. return setmetatable({}, {
  574. __index = function(table, key)
  575. local originalFunction = DefaultAddons[key]
  576.  
  577. if type(originalFunction) == "function" then
  578. return function(...)
  579. if string.match(key, "create") then
  580. if Addon.Parent == nil then
  581. Addon.Parent = Popups
  582. end
  583.  
  584. imageButton.Visible = true
  585. end
  586.  
  587. return originalFunction(...), Popup:updateTransparentObjects(Addon)
  588. end
  589. else
  590. return originalFunction
  591. end
  592. end,
  593.  
  594. __newindex = function(table, key, value)
  595. DefaultAddons[key] = value
  596. end,
  597. })
  598. end
  599.  
  600. function Library:destroy()
  601. for _, rbxSignals in ipairs(Connections) do
  602. rbxSignals:Disconnect()
  603. end
  604. task.wait(0.1)
  605. ScreenGui:Destroy()
  606. end
  607.  
  608. function Library:createLabel(options: table)
  609. Utility:validateOptions(options, {
  610. text = { Default = "Main", ExpectedType = "string" },
  611. })
  612.  
  613. options.text = string.upper(options.text)
  614.  
  615. local ScrollingFrame = Background.Tabs.Frame.ScrollingFrame
  616.  
  617. local Line = Assets.Tabs.Line:Clone()
  618. Line.Visible = true
  619. Line.BackgroundColor3 = Theme.Line
  620. Line.Parent = ScrollingFrame
  621.  
  622. local TextLabel = Assets.Tabs.TextLabel:Clone()
  623. TextLabel.Visible = true
  624. TextLabel.Text = options.text
  625. TextLabel.Parent = ScrollingFrame
  626.  
  627. for _, line in ipairs(ScrollingFrame:GetChildren()) do
  628. if line.Name ~= "Line" then
  629. continue
  630. end
  631.  
  632. self.lineIndex += 1
  633.  
  634. if self.lineIndex == 1 then
  635. line:Destroy()
  636. end
  637. end
  638.  
  639. Theme:registerToObjects({
  640. { object = TextLabel, property = "TextColor3", theme = { "SecondaryTextColor" } },
  641. { object = Line, property = "BackgroundColor3", theme = { "Line" } },
  642. })
  643. end
  644.  
  645. function Library:createTab(options: table)
  646. Utility:validateOptions(options, {
  647. text = { Default = "Tab", ExpectedType = "string" },
  648. icon = { Default = "124718082122263", ExpectedType = "string" },
  649. })
  650.  
  651. Background.Tabs.Size = UDim2.new(0, Library.tabSizeX, 1, 0)
  652. Background.Pages.Size = UDim2.new(1, -Library.tabSizeX, 1, 0)
  653.  
  654. local ScrollingFrame = Background.Tabs.Frame.ScrollingFrame
  655.  
  656. local Tab = Assets.Tabs.Tab:Clone()
  657. Tab.Visible = true
  658. Tab.Parent = ScrollingFrame
  659.  
  660. local ImageButton = Tab.ImageButton
  661. ImageButton.Modal = true
  662.  
  663. local Icon = ImageButton.Icon
  664. Icon.Image = "rbxassetid://" .. options.icon
  665.  
  666. local TextButton = ImageButton.TextButton
  667. TextButton.Text = options.text
  668.  
  669. local Page = Assets.Pages.Page:Clone()
  670. Page.Parent = Background.Pages
  671.  
  672. local Frame = Page.Frame
  673. local PageLine = Frame.Line
  674.  
  675. local CurrentTabLabel = Frame.CurrentTabLabel
  676. CurrentTabLabel.Text = options.text
  677. CurrentTabLabel.TextColor3 = Theme.PrimaryTextColor
  678.  
  679. local SubTabs = Page.SubTabs
  680. local SubLine = SubTabs.Line
  681.  
  682. local function tweenTabAssets(
  683. tab: Instance,
  684. icon: Instance,
  685. textButton: Instance,
  686. color: textColor3,
  687. backgroundColor3: Color3,
  688. backgroundTransparency: number,
  689. textTransparency: number,
  690. imageTransparency: number
  691. )
  692. Utility:tween(
  693. tab,
  694. { BackgroundColor3 = backgroundColor3, BackgroundTransparency = backgroundTransparency },
  695. 0.25,
  696. "Back",
  697. "Out"
  698. ):Play()
  699. Utility:tween(textButton, { TextColor3 = color, TextTransparency = textTransparency }, 0.2, "Quart", "Out")
  700. :Play()
  701. task.delay(0.03, function()
  702. Utility:tween(icon, { ImageTransparency = imageTransparency, ImageColor3 = color }, 0.25, "Quart", "Out")
  703. :Play()
  704. end)
  705. end
  706.  
  707. local function fadeAnimation()
  708. local function tweenFadeAndPage(
  709. fade: Instance,
  710. backgroundTransparency: number,
  711. textTransparency: number,
  712. paddingY: number
  713. )
  714. Utility:tween(fade, { BackgroundTransparency = backgroundTransparency }, 0.3, "Quint", "Out"):Play()
  715. Utility:tween(CurrentTabLabel.UIPadding, { PaddingBottom = UDim.new(0, paddingY) }, 0.3, "Back", "Out")
  716. :Play()
  717. end
  718.  
  719. for _, subPage in ipairs(Page:GetChildren()) do
  720. if subPage.Name == "SubPage" and subPage.Visible and subPage:FindFirstChild("ScrollingFrame") then
  721. Utility:tween(subPage.ScrollingFrame.UIPadding, { PaddingTop = UDim.new(0, 6) }, 0.15, "Quart", "Out")
  722. :Play()
  723.  
  724. task.delay(0.15, function()
  725. Utility
  726. :tween(subPage.ScrollingFrame.UIPadding, { PaddingTop = UDim.new(0, 0) }, 0.25, "Back", "Out")
  727. :Play()
  728. end)
  729. end
  730. end
  731.  
  732. local Fade = Assets.Pages.Fade:Clone()
  733. Fade.BackgroundTransparency = 1
  734. Fade.Visible = true
  735. Fade.Parent = Background.Pages
  736.  
  737. tweenFadeAndPage(Fade, 0, 1, 10)
  738.  
  739. task.delay(0.3, function()
  740. tweenFadeAndPage(Fade, 1, 0, 0)
  741. task.wait(0.3)
  742. Fade:Destroy()
  743. end)
  744. end
  745.  
  746. local Context = Utility:validateContext({
  747. Page = { Value = Page, ExpectedType = "Instance" },
  748. Pages = { Value = Background.Pages, ExpectedType = "Instance" },
  749. Popups = { Value = Popups, ExpectedType = "Instance" },
  750. ScrollingFrame = { Value = Background.Tabs.Frame.ScrollingFrame, ExpectedType = "Instance" },
  751. animation = { Value = fadeAnimation, ExpectedType = "function" },
  752.  
  753. tweenTabOn = {
  754. Value = function()
  755. tweenTabAssets(Tab, Icon, TextButton, Theme.PrimaryColor, Theme.TabBackgroundColor, 0, 0, 0)
  756. end,
  757. ExpectedType = "function",
  758. },
  759.  
  760. tweenTabsOff = {
  761. Value = function(tab)
  762. tweenTabAssets(
  763. tab,
  764. tab.ImageButton.Icon,
  765. tab.ImageButton.TextButton,
  766. Theme.SecondaryTextColor,
  767. Theme.TabBackgroundColor,
  768. 1,
  769. 0,
  770. 0
  771. )
  772. end,
  773. ExpectedType = "function",
  774. },
  775.  
  776. hoverOn = {
  777. Value = function()
  778. tweenTabAssets(Tab, Icon, TextButton, Theme.PrimaryColor, Theme.TabBackgroundColor, 0.16, 0.3, 0.3)
  779. end,
  780. ExpectedType = "function",
  781. },
  782.  
  783. hoverOff = {
  784. Value = function()
  785. tweenTabAssets(Tab, Icon, TextButton, Theme.SecondaryTextColor, Theme.TabBackgroundColor, 1, 0, 0)
  786. end,
  787. ExpectedType = "function",
  788. },
  789. })
  790.  
  791. local Navigation = Modules.Navigation.new(Context)
  792.  
  793. if not self.firstTabDebounce then
  794. Navigation:enableFirstTab()
  795. self.firstTabDebounce = true
  796. end
  797.  
  798. ScrollingFrame.UIListLayout:GetPropertyChangedSignal("AbsoluteContentSize"):Connect(function()
  799. ScrollingFrame.CanvasSize = UDim2.new(
  800. 0,
  801. 0,
  802. 0,
  803. ScrollingFrame.UIListLayout.AbsoluteContentSize.Y + ScrollingFrame.UIListLayout.Padding.Offset
  804. )
  805. end)
  806.  
  807. ImageButton.MouseButton1Down:Connect(Navigation:selectTab())
  808. Icon.MouseButton1Down:Connect(Navigation:selectTab())
  809. TextButton.MouseButton1Down:Connect(Navigation:selectTab())
  810. ImageButton.MouseEnter:Connect(Navigation:hoverEffect(true))
  811. ImageButton.MouseLeave:Connect(Navigation:hoverEffect(false))
  812.  
  813. Theme:registerToObjects({
  814. { object = Tab, property = "BackgroundColor3", theme = { "TabBackgroundColor" } },
  815. { object = Icon, property = "ImageColor3", theme = { "SecondaryTextColor", "PrimaryColor" } },
  816. { object = TextButton, property = "TextColor3", theme = { "SecondaryTextColor", "PrimaryColor" } },
  817. { object = Frame, property = "BackgroundColor3", theme = { "PrimaryBackgroundColor" } },
  818. { object = SubTabs, property = "BackgroundColor3", theme = { "PrimaryBackgroundColor" } },
  819. { object = PageLine, property = "BackgroundColor3", theme = { "Line" } },
  820. { object = SubLine, property = "BackgroundColor3", theme = { "Line" } },
  821. { object = CurrentTabLabel, property = "TextColor3", theme = { "PrimaryTextColor" } },
  822. }, "Tab")
  823.  
  824. local PassingContext = setmetatable({ Page = Page }, Library)
  825. return PassingContext
  826. end
  827.  
  828. function Library:createSubTab(options: table)
  829. Utility:validateOptions(options, {
  830. sectionStyle = { Default = "Double", ExpectedType = "string" },
  831. text = { Default = "SubTab", ExpectedType = "string" },
  832. })
  833.  
  834. local Moveable = self.Page.SubTabs.Frame.Moveable
  835. local Underline, ScrollingFrame = Moveable.Underline, Moveable.Parent.ScrollingFrame
  836.  
  837. local SubPage = Assets.Pages.SubPage:Clone()
  838. SubPage.Parent = self.Page
  839.  
  840. local Left, Right = SubPage.ScrollingFrame.Left, SubPage.ScrollingFrame.Right
  841.  
  842. local SubTab = Assets.Pages.SubTab:Clone()
  843. SubTab.Visible = true
  844. SubTab.Text = options.text
  845. SubTab.TextColor3 = Theme.SecondaryTextColor
  846. SubTab.Parent = ScrollingFrame
  847.  
  848. SubTab.Size =
  849. UDim2.new(0, TextService:GetTextSize(options.text, 15, Enum.Font.MontserratMedium, SubTab.AbsoluteSize).X, 1, 0)
  850.  
  851. local subTabIndex, subTabPosition = 0, 0
  852.  
  853. for index, subTab in ipairs(ScrollingFrame:GetChildren()) do
  854. if subTab.Name ~= "SubTab" then
  855. continue
  856. end
  857.  
  858. subTabIndex += 1
  859.  
  860. if subTabIndex == 1 then
  861. subTabPosition = 0
  862. else
  863. local condition, object = Utility:lookBeforeChildOfObject(index, ScrollingFrame, "SubTab")
  864. subTabPosition += subTab.Size.X.Offset + ScrollingFrame.UIListLayout.Padding.Offset
  865.  
  866. if condition then
  867. subTabPosition -= (subTab.Size.X.Offset - object.Size.X.Offset)
  868. end
  869. end
  870. end
  871.  
  872. local function tweenSubTabAssets(
  873. subTab,
  874. underline,
  875. textColor,
  876. textTransparency: number,
  877. disableUnderlineTween: boolean
  878. )
  879. Utility:tween(subTab, { TextColor3 = textColor, TextTransparency = textTransparency }, 0.2, "Quart", "Out")
  880. :Play()
  881.  
  882. if not disableUnderlineTween then
  883. Utility:tween(underline, {
  884. BackgroundColor3 = Theme.PrimaryColor,
  885. Position = UDim2.new(0, subTabPosition, 1, 0),
  886. Size = UDim2.new(0, subTab.Size.X.Offset, 0, 2),
  887. }, 0.3, "Back", "Out"):Play()
  888. end
  889. end
  890.  
  891. local function autoCanvasSizeSubPageScrollingFrame()
  892. local max = math.max(Left.UIListLayout.AbsoluteContentSize.Y, Right.UIListLayout.AbsoluteContentSize.Y)
  893. SubPage.ScrollingFrame.CanvasSize = UDim2.new(0, 0, 0, max)
  894. end
  895.  
  896. local function updateSectionAnimation()
  897. Utility:tween(SubPage.ScrollingFrame.UIPadding, { PaddingTop = UDim.new(0, 10) }, 0.2, "Quart", "Out"):Play()
  898.  
  899. task.delay(0.2, function()
  900. Utility:tween(SubPage.ScrollingFrame.UIPadding, { PaddingTop = UDim.new(0, 0) }, 0.2, "Quart", "Out"):Play()
  901. end)
  902. end
  903.  
  904. local Context = Utility:validateContext({
  905. Page = { Value = SubPage, ExpectedType = "Instance" },
  906. Pages = { Value = self.Page, ExpectedType = "Instance" },
  907. Popups = { Value = Popups, ExpectedType = "Instance" },
  908. ScrollingFrame = { Value = ScrollingFrame, ExpectedType = "Instance" },
  909. animation = { Value = updateSectionAnimation, ExpectedType = "function" },
  910.  
  911. tweenTabOn = {
  912. Value = function()
  913. tweenSubTabAssets(SubTab, Underline, Theme.PrimaryColor, 0, false)
  914. end,
  915. ExpectedType = "function",
  916. },
  917.  
  918. tweenTabsOff = {
  919. Value = function(subTab)
  920. tweenSubTabAssets(subTab, Underline, Theme.SecondaryTextColor, 0, true)
  921. end,
  922. ExpectedType = "function",
  923. },
  924.  
  925. hoverOn = {
  926. Value = function()
  927. tweenSubTabAssets(SubTab, Underline, Theme.PrimaryColor, 0.3, true)
  928. end,
  929. ExpectedType = "function",
  930. },
  931.  
  932. hoverOff = {
  933. Value = function()
  934. tweenSubTabAssets(SubTab, Underline, Theme.SecondaryTextColor, 0, true)
  935. end,
  936. ExpectedType = "function",
  937. },
  938. })
  939.  
  940. local Navigation = Modules.Navigation.new(Context)
  941.  
  942. if not self.firstSubTabDebounce then
  943. Navigation:enableFirstTab()
  944. self.firstSubTabDebounce = true
  945. end
  946.  
  947. Left.UIListLayout:GetPropertyChangedSignal("AbsoluteContentSize"):Connect(autoCanvasSizeSubPageScrollingFrame)
  948. Right.UIListLayout:GetPropertyChangedSignal("AbsoluteContentSize"):Connect(autoCanvasSizeSubPageScrollingFrame)
  949.  
  950. SubTab.MouseButton1Down:Connect(Navigation:selectTab())
  951. SubTab.MouseEnter:Connect(Navigation:hoverEffect(true))
  952. SubTab.MouseLeave:Connect(Navigation:hoverEffect(false))
  953.  
  954. Theme:registerToObjects({
  955. { object = Underline, property = "BackgroundColor3", theme = { "PrimaryColor" } },
  956. { object = SubTab, property = "TextColor3", theme = { "SecondaryTextColor", "PrimaryColor" } },
  957. { object = SubPage.ScrollingFrame, property = "ScrollBarImageColor3", theme = { "ScrollingBarImageColor" } },
  958. }, "SubTab")
  959.  
  960. local PassingContext = setmetatable({ Left = Left, Right = Right, sectionStyle = options.sectionStyle }, Library)
  961. return PassingContext
  962. end
  963.  
  964. function Library:createSection(options: table)
  965. Utility:validateOptions(options, {
  966. text = { Default = "Section", ExpectedType = "string" },
  967. position = { Default = "Left", ExpectedType = "string" },
  968. })
  969.  
  970. local Section = Assets.Pages.Section:Clone()
  971. Section.Visible = true
  972. Section.Parent = self[options.position]
  973.  
  974. local screenSize = workspace.CurrentCamera.ViewportSize
  975. if self.sectionStyle == "Single" or (screenSize.X <= 740 and screenSize.Y <= 590) or self.sizeX <= 660 then
  976. if options.position == "Right" then
  977. table.insert(
  978. self.SectionFolder.Right,
  979. { folders = { Left = self.Left, Right = self.Right }, object = Section }
  980. )
  981. end
  982.  
  983. self.Right.Visible = false
  984. self.Left.Size = UDim2.fromScale(1, 1)
  985. Section.Parent = self.Left
  986. end
  987.  
  988. if options.position == "Right" and self.sectionStyle ~= "Single" then
  989. table.insert(self.SectionFolder.Right, { folders = { Left = self.Left, Right = self.Right }, object = Section })
  990. end
  991.  
  992. if options.position == "Left" and self.sectionStyle ~= "Single" then
  993. table.insert(self.SectionFolder.Left, { folders = { Left = self.Left, Right = self.Right }, object = Section })
  994. end
  995.  
  996. local Inner = Section.Inner
  997.  
  998. local TextLabel = Inner.TextLabel
  999. TextLabel.Text = options.text
  1000.  
  1001. Section.Inner.UIListLayout:GetPropertyChangedSignal("AbsoluteContentSize"):Connect(function()
  1002. Section.Size = UDim2.new(1, 0, 0, Section.Inner.UIListLayout.AbsoluteContentSize.Y + 28)
  1003. end)
  1004.  
  1005. Theme:registerToObjects({
  1006. { object = Section, property = "BackgroundColor3", theme = { "Line" } },
  1007. { object = Inner, property = "BackgroundColor3", theme = { "PrimaryBackgroundColor" } },
  1008. { object = TextLabel, property = "TextColor3", theme = { "PrimaryTextColor" } },
  1009. })
  1010.  
  1011. local PassingContext = setmetatable({ Section = Inner, ScrollingFrame = Section.Parent.Parent }, Library)
  1012. return PassingContext
  1013. end
  1014.  
  1015. function Library:createToggle(options: table, parent, scrollingFrame)
  1016. Utility:validateOptions(options, {
  1017. text = { Default = "Toggle", ExpectedType = "string" },
  1018. state = { Default = false, ExpectedType = "boolean" },
  1019. callback = { Default = function() end, ExpectedType = "function" },
  1020. tooltip = { Default = "", ExpectedType = "string" },
  1021. })
  1022.  
  1023. scrollingFrame = self.ScrollingFrame or scrollingFrame
  1024.  
  1025. local Toggle = Assets.Elements.Toggle:Clone()
  1026. Toggle.Visible = true
  1027. Toggle.Parent = parent or self.Section
  1028. local TextLabel = Toggle.TextLabel
  1029. TextLabel.Text = options.text
  1030.  
  1031. local ImageButton = TextLabel.ImageButton
  1032. local TextButton = TextLabel.TextButton
  1033. local Background = TextButton.Background
  1034. local Circle = Background.Circle
  1035.  
  1036. if options.tooltip and options.tooltip ~= "" then
  1037. TextLabel.MouseEnter:Connect(function()
  1038. Library:showTooltip(TextLabel, options.tooltip)
  1039. end)
  1040. TextLabel.MouseLeave:Connect(function()
  1041. Library:hideTooltip()
  1042. end)
  1043. end
  1044.  
  1045. local function tweenToggleAssets(
  1046. backgroundColor: Color3,
  1047. circleColor: Color3,
  1048. anchorPoint: Vector2,
  1049. position: UDim2
  1050. )
  1051. Utility:tween(Background, { BackgroundColor3 = backgroundColor }, 0.25, "Quart", "Out"):Play()
  1052. Utility:tween(
  1053. Circle,
  1054. { BackgroundColor3 = circleColor, AnchorPoint = anchorPoint, Position = position },
  1055. 0.3,
  1056. "Back",
  1057. "Out"
  1058. ):Play()
  1059. end
  1060.  
  1061. local circleOn = false
  1062.  
  1063. local Context = Utility:validateContext({
  1064. state = { Value = options.state, ExpectedType = "boolean" },
  1065. callback = { Value = options.callback, ExpectedType = "function" },
  1066.  
  1067. switchOff = {
  1068. Value = function()
  1069. tweenToggleAssets(
  1070. Theme.SecondaryBackgroundColor,
  1071. Theme.PrimaryBackgroundColor,
  1072. Vector2.new(0, 0.5),
  1073. UDim2.fromScale(0, 0.5)
  1074. )
  1075. circleOn = false
  1076. end,
  1077. ExpectedType = "function",
  1078. },
  1079.  
  1080. switchOn = {
  1081. Value = function()
  1082. tweenToggleAssets(
  1083. Theme.PrimaryColor,
  1084. Theme.TertiaryBackgroundColor,
  1085. Vector2.new(1, 0.5),
  1086. UDim2.fromScale(1, 0.5)
  1087. )
  1088. circleOn = true
  1089. end,
  1090. ExpectedType = "function",
  1091. },
  1092. })
  1093.  
  1094. local Toggle = Modules.Toggle.new(Context)
  1095. Toggle:updateState({ state = options.state })
  1096. TextButton.MouseButton1Down:Connect(Toggle:switch())
  1097.  
  1098. Theme:registerToObjects({
  1099. { object = TextLabel, property = "TextColor3", theme = { "SecondaryTextColor" } },
  1100. { object = Background, property = "BackgroundColor3", theme = { "PrimaryColor", "SecondaryBackgroundColor" } },
  1101. {
  1102. object = Circle,
  1103. property = "BackgroundColor3",
  1104. theme = { "TertiaryBackgroundColor", "PrimaryBackgroundColor" },
  1105. circleOn = circleOn,
  1106. },
  1107. { object = ImageButton, property = "ImageColor3", theme = { "PrimaryColor" } },
  1108. })
  1109.  
  1110. shared.Flags.Toggle[options.text] = {
  1111. getState = function(self)
  1112. return Context.state
  1113. end,
  1114.  
  1115. updateState = function(self, options: table)
  1116. Toggle:updateState(options)
  1117. end,
  1118. }
  1119.  
  1120. return self:createAddons(options.text, ImageButton, scrollingFrame, {
  1121. getState = function(self)
  1122. return Context.state
  1123. end,
  1124.  
  1125. updateState = function(self, options: table)
  1126. Toggle:updateState(options)
  1127. end,
  1128. })
  1129. end
  1130.  
  1131. function Library:createSlider(options: table, parent, scrollingFrame)
  1132. Utility:validateOptions(options, {
  1133. text = { Default = "Slider", ExpectedType = "string" },
  1134. min = { Default = 0, ExpectedType = "number" },
  1135. max = { Default = 100, ExpectedType = "number" },
  1136. step = { Default = 1, ExpectedType = "number" },
  1137. callback = { Default = function() end, ExpectedType = "function" },
  1138. tooltip = { Default = "", ExpectedType = "string" },
  1139. })
  1140.  
  1141. options.default = options.default or options.min
  1142. options.value = options.default
  1143. scrollingFrame = self.ScrollingFrame or scrollingFrame
  1144.  
  1145. local Slider = Assets.Elements.Slider:Clone()
  1146. Slider.Visible = true
  1147. Slider.Parent = parent or self.Section
  1148. local TextLabel = Slider.TextButton.TextLabel
  1149. local ImageButton = TextLabel.ImageButton
  1150. local TextBox = TextLabel.TextBox
  1151.  
  1152. local Line = Slider.Line
  1153. local TextButton = Slider.TextButton
  1154. local Fill = Line.Fill
  1155.  
  1156. local TextLabel = TextButton.TextLabel
  1157. TextLabel.Text = options.text
  1158.  
  1159. if options.tooltip and options.tooltip ~= "" then
  1160. TextLabel.MouseEnter:Connect(function()
  1161. Library:showTooltip(TextLabel, options.tooltip)
  1162. end)
  1163. TextLabel.MouseLeave:Connect(function()
  1164. Library:hideTooltip()
  1165. end)
  1166. end
  1167.  
  1168. local Circle = Fill.Circle
  1169. local InnerCircle = Circle.InnerCircle
  1170. local CurrentValueLabel = Circle.TextButton.CurrentValueLabel
  1171.  
  1172. local function tweenSliderInfoAssets(transparency: number)
  1173. local TextBoundsX = math.clamp(CurrentValueLabel.TextBounds.X + 14, 10, 200)
  1174. local easing = transparency == 0 and "Back" or "Quart"
  1175. Utility:tween(CurrentValueLabel, {
  1176. Size = UDim2.fromOffset(TextBoundsX, 20),
  1177. BackgroundTransparency = transparency,
  1178. TextTransparency = transparency,
  1179. }, 0.2, easing, "Out"):Play()
  1180. end
  1181.  
  1182. local Context = Utility:validateContext({
  1183. min = { Value = options.min, ExpectedType = "number" },
  1184. max = { Value = options.max, ExpectedType = "number" },
  1185. step = { Value = options.step, ExpectedType = "number" },
  1186. value = { Value = options.default, ExpectedType = "number" },
  1187. callback = { Value = options.callback, ExpectedType = "function" },
  1188. Line = { Value = Line, ExpectedType = "Instance" },
  1189. TextBox = { Value = TextLabel.TextBox, ExpectedType = "Instance" },
  1190. Library = { Value = Library, ExpectedType = "table" },
  1191. CurrentValueLabel = { Value = CurrentValueLabel, ExpectedType = "Instance" },
  1192. Connections = { Value = Connections, ExpectedType = "table" },
  1193.  
  1194. autoSizeTextBox = {
  1195. Value = function()
  1196. local TextBoundsX = math.clamp(TextLabel.TextBox.TextBounds.X + 14, 10, 200)
  1197. Utility:tween(TextLabel.TextBox, { Size = UDim2.fromOffset(TextBoundsX, 20) }, 0.2, "Quart", "Out")
  1198. :Play()
  1199. end,
  1200. ExpectedType = "function",
  1201. },
  1202.  
  1203. updateFill = {
  1204. Value = function(sizeX)
  1205. Utility:tween(Line.Fill, { Size = UDim2.fromScale(sizeX, 1) }, 0.2, "Quart", "Out"):Play()
  1206. end,
  1207. ExpectedType = "function",
  1208. },
  1209.  
  1210. showInfo = {
  1211. Value = function()
  1212. tweenSliderInfoAssets(0)
  1213. end,
  1214. ExpectedType = "function",
  1215. },
  1216.  
  1217. dontShowInfo = {
  1218. Value = function()
  1219. tweenSliderInfoAssets(1)
  1220. end,
  1221. ExpectedType = "function",
  1222. },
  1223. })
  1224.  
  1225. local Slider = Modules.Slider.new(Context)
  1226. Slider:handleSlider()
  1227.  
  1228. Theme:registerToObjects({
  1229. { object = TextLabel, property = "TextColor3", theme = { "SecondaryTextColor" } },
  1230. { object = Line, property = "BackgroundColor3", theme = { "SecondaryBackgroundColor" } },
  1231. { object = Fill, property = "BackgroundColor3", theme = { "PrimaryColor" } },
  1232. { object = Circle, property = "BackgroundColor3", theme = { "PrimaryColor" } },
  1233. { object = ImageButton, property = "ImageColor3", theme = { "PrimaryColor" } },
  1234. { object = TextBox, property = "BackgroundColor3", theme = { "SecondaryBackgroundColor" } },
  1235. { object = TextBox, property = "TextColor3", theme = { "SecondaryTextColor" } },
  1236. { object = CurrentValueLabel, property = "TextColor3", theme = { "TertiaryBackgroundColor" } },
  1237. { object = CurrentValueLabel, property = "BackgroundColor3", theme = { "PrimaryColor" } },
  1238. { object = InnerCircle, property = "BackgroundColor3", theme = { "TertiaryBackgroundColor" } },
  1239. })
  1240.  
  1241. Fill.BackgroundColor3 = Theme.PrimaryColor
  1242. Circle.BackgroundColor3 = Theme.PrimaryColor
  1243. InnerCircle.BackgroundColor3 = Theme.TertiaryBackgroundColor
  1244. CurrentValueLabel.BackgroundColor3 = Theme.PrimaryColor
  1245.  
  1246. shared.Flags.Slider[options.text] = {
  1247. getValue = function(self)
  1248. return Context.value
  1249. end,
  1250.  
  1251. updateValue = function(self, options: table)
  1252. Slider:updateValue(options)
  1253. end,
  1254. }
  1255.  
  1256. return self:createAddons(options.text, ImageButton, scrollingFrame, {
  1257. getValue = function(self)
  1258. return Context.value
  1259. end,
  1260.  
  1261. updateValue = function(self, options: table)
  1262. Slider:updateValue(options)
  1263. end,
  1264. })
  1265. end
  1266.  
  1267. function Library:createPicker(options: table, parent, scrollingFrame, isPickerBoolean)
  1268. Utility:validateOptions(options, {
  1269. text = { Default = "Picker", ExpectedType = "string" },
  1270. default = { Default = Color3.fromRGB(255, 0, 0), ExpectedType = "Color3" },
  1271. color = { Default = Color3.fromRGB(255, 0, 0), ExpectedType = "Color3" },
  1272. callback = { Default = function() end, ExpectedType = "function" },
  1273. tooltip = { Default = "", ExpectedType = "string" },
  1274. })
  1275.  
  1276. isPickerBoolean = isPickerBoolean or false
  1277. options.color = options.default
  1278. scrollingFrame = self.ScrollingFrame or scrollingFrame
  1279.  
  1280. local Picker = Assets.Elements.Picker:Clone()
  1281. Picker.Visible = true
  1282. Picker.Parent = parent or self.Section
  1283. local TextLabel = Picker.TextLabel
  1284. TextLabel.Text = options.text
  1285.  
  1286. if options.tooltip and options.tooltip ~= "" then
  1287. TextLabel.MouseEnter:Connect(function()
  1288. Library:showTooltip(TextLabel, options.tooltip)
  1289. end)
  1290. TextLabel.MouseLeave:Connect(function()
  1291. Library:hideTooltip()
  1292. end)
  1293. end
  1294.  
  1295. local ImageButton = TextLabel.ImageButton
  1296. local Background = TextLabel.Background
  1297. local TextButton = Background.TextButton
  1298.  
  1299. local ColorPicker = Assets.Elements.ColorPicker:Clone()
  1300. ColorPicker.Parent = Popups
  1301.  
  1302. local ColorPickerTransparentObjects = Utility:getTransparentObjects(ColorPicker)
  1303.  
  1304. for _, data in ipairs(ColorPickerTransparentObjects) do
  1305. data.object[data.property] = 1
  1306. end
  1307.  
  1308. local Inner = ColorPicker.Inner
  1309. local HSV = Inner.HSV
  1310. local Slider = Inner.Slider
  1311. local Submit = Inner.Submit
  1312. local Hex = Inner.HexAndRGB.Hex
  1313. local RGB = Inner.HexAndRGB.RGB
  1314.  
  1315. local PopupContext = Utility:validateContext({
  1316. Popup = { Value = ColorPicker, ExpectedType = "Instance" },
  1317. Target = { Value = Background, ExpectedType = "Instance" },
  1318. Library = { Value = Library, ExpectedType = "table" },
  1319. TransparentObjects = { Value = ColorPickerTransparentObjects, ExpectedType = "table" },
  1320. Popups = { Value = Popups, ExpectedType = "Instance" },
  1321. isPicker = { Value = isPickerBoolean, ExpectedType = "boolean" },
  1322. ScrollingFrame = { Value = scrollingFrame, ExpectedType = "Instance" },
  1323. PositionPadding = { Value = 18 + 7, ExpectedType = "number" },
  1324. Connections = { Value = Connections, ExpectedType = "table" },
  1325. SizePadding = { Value = 14, ExpectedType = "number" },
  1326. })
  1327.  
  1328. local Popup = Modules.Popup.new(PopupContext)
  1329. TextButton.MouseButton1Down:Connect(Popup:togglePopup())
  1330. Popup:hidePopupOnClickingOutside()
  1331.  
  1332. local ColorPickerContext =
  1333. Utility:validateContext({
  1334. ColorPicker = { Value = ColorPicker, ExpectedType = "Instance" },
  1335. Hex = { Value = Hex, ExpectedType = "Instance" },
  1336. RGB = { Value = RGB, ExpectedType = "Instance" },
  1337. Slider = { Value = Slider, ExpectedType = "Instance" },
  1338. HSV = { Value = HSV, ExpectedType = "Instance" },
  1339. Submit = { Value = Submit, ExpectedType = "Instance" },
  1340. Background = { Value = Background, ExpectedType = "Instance" },
  1341. Connections = { Value = Connections, ExpectedType = "table" },
  1342. color = { Value = options.color, ExpectedType = "Color3" },
  1343. callback = { Value = options.callback, ExpectedType = "function" },
  1344.  
  1345. submitAnimation = {
  1346. Value = function()
  1347. Utility:tween(Submit.TextLabel, { BackgroundTransparency = 0 }, 0.2, "Quart", "Out"):Play()
  1348. Utility:tween(
  1349. Submit.TextLabel,
  1350. { TextColor3 = Theme.PrimaryColor, TextTransparency = 0 },
  1351. 0.2,
  1352. "Quart",
  1353. "Out"
  1354. ):Play()
  1355.  
  1356. task.delay(0.2, function()
  1357. Utility:tween(
  1358. Submit.TextLabel,
  1359. { TextColor3 = Theme.SecondaryTextColor, TextTransparency = 0 },
  1360. 0.2,
  1361. "Quart",
  1362. "Out"
  1363. ):Play()
  1364. Utility:tween(Submit.TextLabel, { BackgroundTransparency = 0.3 }, 0.2, "Quart", "Out"):Play()
  1365. end)
  1366. end,
  1367. ExpectedType = "function",
  1368. },
  1369.  
  1370. hoveringOn = {
  1371. Value = function()
  1372. Utility:tween(Submit.TextLabel, { BackgroundTransparency = 0.3 }, 0.2, "Quart", "Out"):Play()
  1373. Utility:tween(
  1374. Submit.TextLabel,
  1375. { TextColor3 = Theme.PrimaryColor, TextTransparency = 0.3 },
  1376. 0.2,
  1377. "Quart",
  1378. "Out"
  1379. ):Play()
  1380. end,
  1381. ExpectedType = "function",
  1382. },
  1383.  
  1384. hoveringOff = {
  1385. Value = function()
  1386. Utility:tween(Submit.TextLabel, { BackgroundTransparency = 0 }, 0.2, "Quart", "Out"):Play()
  1387. Utility:tween(
  1388. Submit.TextLabel,
  1389. { TextColor3 = Theme.SecondaryTextColor, TextTransparency = 0 },
  1390. 0.2,
  1391. "Quart",
  1392. "Out"
  1393. ):Play()
  1394. end,
  1395. ExpectedType = "function",
  1396. },
  1397. })
  1398.  
  1399. Theme:registerToObjects({
  1400. { object = TextLabel, property = "TextColor3", theme = { "SecondaryTextColor" } },
  1401. { object = ColorPicker, property = "BackgroundColor3", theme = { "Line" } },
  1402. { object = ImageButton, property = "ImageColor3", theme = { "PrimaryColor" } },
  1403. { object = Inner, property = "BackgroundColor3", theme = { "PrimaryBackgroundColor" } },
  1404. { object = Submit, property = "BackgroundColor3", theme = { "SecondaryBackgroundColor" } },
  1405. { object = Hex, property = "BackgroundColor3", theme = { "SecondaryBackgroundColor" } },
  1406. { object = RGB, property = "BackgroundColor3", theme = { "SecondaryBackgroundColor" } },
  1407. { object = Submit.TextLabel, property = "BackgroundColor3", theme = { "SecondaryBackgroundColor" } },
  1408. })
  1409.  
  1410. local ColorPicker = Modules.ColorPicker.new(ColorPickerContext)
  1411. ColorPicker:handleColorPicker()
  1412.  
  1413. shared.Flags.ColorPicker[options.text] = {
  1414. getColor = function(self)
  1415. return ColorPickerContext.color
  1416. end,
  1417.  
  1418. updateColor = function(self, options: table)
  1419. ColorPicker:updateColor(options)
  1420. end,
  1421. }
  1422.  
  1423. return self:createAddons(options.text, ImageButton, scrollingFrame, {
  1424. getColor = function(self)
  1425. return ColorPickerContext.color
  1426. end,
  1427.  
  1428. updateColor = function(self, options: table)
  1429. ColorPicker:updateColor(options)
  1430. end,
  1431. })
  1432. end
  1433.  
  1434. function Library:createDropdown(options: table, parent, scrollingFrame)
  1435. Utility:validateOptions(options, {
  1436. text = { Default = "Dropdown", ExpectedType = "string" },
  1437. list = { Default = { "Option 1", "Option 2" }, ExpectedType = "table" },
  1438. default = { Default = {}, ExpectedType = "table" },
  1439. multiple = { Default = false, ExpectedType = "boolean" },
  1440. callback = { Default = function() end, ExpectedType = "function" },
  1441. tooltip = { Default = "", ExpectedType = "string" },
  1442. })
  1443.  
  1444. scrollingFrame = self.ScrollingFrame or scrollingFrame
  1445.  
  1446. local Dropdown = Assets.Elements.Dropdown:Clone()
  1447. Dropdown.Visible = true
  1448. Dropdown.Parent = parent or self.Section
  1449. local TextLabel = Dropdown.TextLabel
  1450. TextLabel.Text = options.text
  1451.  
  1452. if options.tooltip and options.tooltip ~= "" then
  1453. TextLabel.MouseEnter:Connect(function()
  1454. Library:showTooltip(TextLabel, options.tooltip)
  1455. end)
  1456. TextLabel.MouseLeave:Connect(function()
  1457. Library:hideTooltip()
  1458. end)
  1459. end
  1460.  
  1461. local ImageButton = TextLabel.ImageButton
  1462. local Box = Dropdown.Box
  1463.  
  1464. local TextButton = Box.TextButton
  1465. TextButton.Text = table.concat(options.default, ", ")
  1466.  
  1467. if options.default[1] == nil then
  1468. TextButton.Text = "None"
  1469. end
  1470.  
  1471. local List = Dropdown.List
  1472. local Inner = List.Inner
  1473. local DropButtons = Inner.ScrollingFrame
  1474. local Search = Inner.TextBox
  1475.  
  1476. DropButtons.UIListLayout:GetPropertyChangedSignal("AbsoluteContentSize"):Connect(function()
  1477. DropButtons.CanvasSize =
  1478. UDim2.new(0, 0, 0, DropButtons.UIListLayout.AbsoluteContentSize.Y + Inner.UIListLayout.Padding.Offset)
  1479. DropButtons.Size = UDim2.new(
  1480. 1,
  1481. 0,
  1482. 0,
  1483. math.clamp(DropButtons.UIListLayout.AbsoluteContentSize.Y + Inner.UIListLayout.Padding.Offset, 0, 164)
  1484. )
  1485.  
  1486. if List.Size.Y.Offset > 0 then
  1487. Utility:tween(
  1488. List,
  1489. { Size = UDim2.new(1, 0, 0, math.clamp(Inner.UIListLayout.AbsoluteContentSize.Y, 0, 210)) },
  1490. 0.2,
  1491. "Quart",
  1492. "Out"
  1493. ):Play()
  1494.  
  1495. for index, value in ipairs(self.DropdownSizes) do
  1496. scrollingFrame.CanvasSize = scrollingFrame.CanvasSize - value.size
  1497. scrollingFrame.CanvasSize = scrollingFrame.CanvasSize
  1498. + UDim2.new(0, 0, 0, math.clamp(Inner.UIListLayout.AbsoluteContentSize.Y, 0, 210))
  1499. table.remove(Library.DropdownSizes, index)
  1500. table.insert(Library.DropdownSizes, {
  1501. object = Dropdown,
  1502. size = UDim2.new(0, 0, 0, math.clamp(Inner.UIListLayout.AbsoluteContentSize.Y, 0, 210)),
  1503. })
  1504. end
  1505. end
  1506. end)
  1507.  
  1508. local function toggleList()
  1509. if List.Size.Y.Offset <= 0 then
  1510. Library.dropdownOpen = Library.dropdownOpen + 1
  1511. Library:forceHideTooltip()
  1512.  
  1513. for index, value in ipairs(Library.DropdownSizes) do
  1514. if value.object ~= Dropdown then
  1515. scrollingFrame.CanvasSize = scrollingFrame.CanvasSize - value.size
  1516. table.remove(Library.DropdownSizes, index)
  1517. end
  1518. end
  1519.  
  1520. for _, object in ipairs(scrollingFrame:GetDescendants()) do
  1521. if object.Name == "Section" then
  1522. object.ZIndex = 1
  1523. end
  1524. if object.Name == "List" and object ~= List then
  1525. object.Parent.ZIndex = 1
  1526. Utility:tween(object, { Size = UDim2.new(1, 0, 0, 0) }, 0.2, "Quart", "Out"):Play()
  1527. end
  1528. end
  1529.  
  1530. for _, object in ipairs(Popups:GetDescendants()) do
  1531. if object.Name == "List" and object ~= List then
  1532. object.Parent.ZIndex = 1
  1533. Utility:tween(object, { Size = UDim2.new(1, 0, 0, 0) }, 0.2, "Quart", "Out"):Play()
  1534. end
  1535. end
  1536.  
  1537. Dropdown.ZIndex = 2
  1538. if self.Section then
  1539. self.Section.Parent.ZIndex = 2
  1540. end
  1541.  
  1542. Utility:tween(
  1543. List,
  1544. { Size = UDim2.new(1, 0, 0, math.clamp(Inner.UIListLayout.AbsoluteContentSize.Y, 0, 210)) },
  1545. 0.2,
  1546. "Quart",
  1547. "Out"
  1548. ):Play()
  1549. table.insert(Library.DropdownSizes, {
  1550. object = Dropdown,
  1551. size = UDim2.new(0, 0, 0, math.clamp(Inner.UIListLayout.AbsoluteContentSize.Y, 0, 210)),
  1552. })
  1553. scrollingFrame.CanvasSize = scrollingFrame.CanvasSize
  1554. + UDim2.new(0, 0, 0, math.clamp(Inner.UIListLayout.AbsoluteContentSize.Y, 0, 210))
  1555. else
  1556. Library.dropdownOpen = math.max(0, Library.dropdownOpen - 1)
  1557.  
  1558. Utility:tween(List, { Size = UDim2.new(1, 0, 0, 0) }, 0.2, "Quart", "Out"):Play()
  1559. for index, value in ipairs(Library.DropdownSizes) do
  1560. if value.object == Dropdown then
  1561. scrollingFrame.CanvasSize = scrollingFrame.CanvasSize - value.size
  1562. table.remove(Library.DropdownSizes, index)
  1563. end
  1564. end
  1565. end
  1566. end
  1567.  
  1568. local function createDropButton(value)
  1569. local DropButton = Assets.Elements.DropButton:Clone()
  1570. DropButton.Visible = true
  1571. DropButton.Parent = DropButtons
  1572.  
  1573. local TextButton = DropButton.TextButton
  1574. local Background = TextButton.Background
  1575. local Checkmark = TextButton.Checkmark
  1576.  
  1577. local TextLabel = DropButton.TextLabel
  1578. TextLabel.Text = tostring(value)
  1579.  
  1580. Theme:registerToObjects({
  1581. { object = TextLabel, property = "TextColor3", theme = { "SecondaryTextColor" } },
  1582. {
  1583. object = Background,
  1584. property = "BackgroundColor3",
  1585. theme = { "PrimaryColor", "SecondaryBackgroundColor" },
  1586. },
  1587. { object = Checkmark, property = "ImageColor3", theme = { "TertiaryBackgroundColor" } },
  1588. })
  1589.  
  1590. return TextButton
  1591. end
  1592.  
  1593. local function tweenDropButton(dropButton: Instance, backgroundColor: Color3, imageTransparency: number)
  1594. Utility:tween(dropButton.Background, { BackgroundColor3 = backgroundColor }, 0.2, "Quart", "Out"):Play()
  1595. Utility:tween(dropButton.Checkmark, { ImageTransparency = imageTransparency }, 0.2, "Quart", "Out"):Play()
  1596. end
  1597.  
  1598. local Context = Utility:validateContext({
  1599. text = { Value = options.text, ExpectedType = "string" },
  1600. default = { Value = options.default, ExpectedType = "table" },
  1601. list = { Value = options.list, ExpectedType = "table" },
  1602. callback = { Value = options.callback, ExpectedType = "function" },
  1603. TextButton = { Value = TextButton, ExpectedType = "Instance" },
  1604. DropButtons = { Value = DropButtons, ExpectedType = "Instance" },
  1605. createDropButton = { Value = createDropButton, ExpectedType = "function" },
  1606. ScrollingFrame = { Value = scrollingFrame, ExpectedType = "Instance" },
  1607. multiple = { Value = options.multiple, ExpectedType = "boolean" },
  1608.  
  1609. tweenDropButtonOn = {
  1610. Value = function(dropButton)
  1611. tweenDropButton(dropButton, Theme.PrimaryColor, 0)
  1612. end,
  1613. ExpectedType = "function",
  1614. },
  1615.  
  1616. tweenDropButtonOff = {
  1617. Value = function(dropButton)
  1618. tweenDropButton(dropButton, Theme.SecondaryBackgroundColor, 1)
  1619. end,
  1620. ExpectedType = "function",
  1621. },
  1622. })
  1623.  
  1624. TextButton.MouseButton1Down:Connect(toggleList)
  1625.  
  1626. Search:GetPropertyChangedSignal("Text"):Connect(function()
  1627. for _, dropButton in ipairs(DropButtons:GetChildren()) do
  1628. if not dropButton:IsA("Frame") then
  1629. continue
  1630. end
  1631.  
  1632. if
  1633. Search.Text == "" or string.match(string.lower(dropButton.TextLabel.Text), string.lower(Search.Text))
  1634. then
  1635. dropButton.Visible = true
  1636. else
  1637. dropButton.Visible = false
  1638. end
  1639. end
  1640. end)
  1641.  
  1642. local Dropdown = Modules.Dropdown.new(Context)
  1643. Dropdown:handleDropdown()
  1644.  
  1645. Theme:registerToObjects({
  1646. { object = ImageButton, property = "ImageColor3", theme = { "PrimaryColor" } },
  1647. { object = TextLabel, property = "TextColor3", theme = { "SecondaryTextColor" } },
  1648. { object = Box, property = "BackgroundColor3", theme = { "SecondaryBackgroundColor" } },
  1649. { object = TextButton, property = "TextColor3", theme = { "SecondaryTextColor" } },
  1650. { object = List, property = "BackgroundColor3", theme = { "Line" } },
  1651. { object = Inner, property = "BackgroundColor3", theme = { "PrimaryBackgroundColor" } },
  1652. { object = Search, property = "TextColor3", theme = { "SecondaryTextColor" } },
  1653. { object = Search, property = "PlaceholderColor3", theme = { "SecondaryTextColor" } },
  1654. { object = Search, property = "BackgroundColor3", theme = { "SecondaryBackgroundColor" } },
  1655. { object = Search.Parent, property = "BackgroundColor3", theme = { "SecondaryBackgroundColor" } },
  1656. })
  1657.  
  1658. List.BackgroundColor3 = Theme.Line
  1659. Inner.BackgroundColor3 = Theme.PrimaryBackgroundColor
  1660. Box.BackgroundColor3 = Theme.SecondaryBackgroundColor
  1661. Search.BackgroundColor3 = Theme.SecondaryBackgroundColor
  1662.  
  1663. shared.Flags.Dropdown[options.text] = {
  1664. getList = function()
  1665. return Context.list
  1666. end,
  1667.  
  1668. getValue = function()
  1669. return Dropdown:getValue()
  1670. end,
  1671.  
  1672. updateList = function(self, options: table)
  1673. Dropdown:updateList(options)
  1674. end,
  1675. }
  1676.  
  1677. return self:createAddons(options.text, ImageButton, scrollingFrame, {
  1678. getList = function()
  1679. return Context.list
  1680. end,
  1681.  
  1682. getValue = function()
  1683. return Dropdown:getValue()
  1684. end,
  1685.  
  1686. updateList = function(self, options: table)
  1687. Dropdown:updateList(options)
  1688. end,
  1689. })
  1690. end
  1691.  
  1692. function Library:createKeybind(options: table, parent, scrollingFrame)
  1693. Utility:validateOptions(options, {
  1694. text = { Default = "Keybind", ExpectedType = "string" },
  1695. default = { Default = "None", ExpectedType = "string" },
  1696. onHeld = { Default = false, ExpectedType = "boolean" },
  1697. callback = { Default = function() end, ExpectedType = "function" },
  1698. tooltip = { Default = "", ExpectedType = "string" },
  1699. })
  1700.  
  1701. scrollingFrame = self.ScrollingFrame or scrollingFrame
  1702.  
  1703. local Keybind = Assets.Elements.Keybind:Clone()
  1704. Keybind.Visible = true
  1705. Keybind.Parent = parent or self.Section
  1706. local TextLabel = Keybind.TextLabel
  1707. TextLabel.Text = options.text
  1708.  
  1709. if options.tooltip and options.tooltip ~= "" then
  1710. TextLabel.MouseEnter:Connect(function()
  1711. Library:showTooltip(TextLabel, options.tooltip)
  1712. end)
  1713. TextLabel.MouseLeave:Connect(function()
  1714. Library:hideTooltip()
  1715. end)
  1716. end
  1717.  
  1718. local ImageButton = TextLabel.ImageButton
  1719. local Background = TextLabel.Background
  1720.  
  1721. local TextButton = Background.TextButton
  1722.  
  1723. TextButton.Text = options.default
  1724.  
  1725. local Context = Utility:validateContext({
  1726. default = { Value = options.default, ExpectedType = "string" },
  1727. callback = { Value = options.callback, ExpectedType = "function" },
  1728. Background = { Value = TextButton.Parent, ExpectedType = "Instance" },
  1729. TextButton = { Value = TextButton, ExpectedType = "Instance" },
  1730. Connections = { Value = Connections, ExpectedType = "table" },
  1731. Library = { Value = Library, ExpectedType = "table" },
  1732. onHeld = { Value = options.onHeld, ExpectedType = "boolean" },
  1733. Exclusions = { Value = Exclusions, ExpectedType = "table" },
  1734.  
  1735. autoSizeBackground = {
  1736. Value = function()
  1737. local TextBoundsX = math.clamp(TextButton.TextBounds.X + 14, 10, 200)
  1738. Utility:tween(TextButton.Parent, { Size = UDim2.fromOffset(TextBoundsX, 20) }, 0.2, "Quart", "Out")
  1739. :Play()
  1740. end,
  1741. ExpectedType = "function",
  1742. },
  1743. })
  1744.  
  1745. local Keybind = Modules.Keybind.new(Context)
  1746. Keybind:handleKeybind()
  1747.  
  1748. Theme:registerToObjects({
  1749. { object = TextLabel, property = "TextColor3", theme = { "SecondaryTextColor" } },
  1750. { object = ImageButton, property = "ImageColor3", theme = { "PrimaryColor" } },
  1751. { object = Background, property = "BackgroundColor3", theme = { "SecondaryBackgroundColor" } },
  1752. { object = TextButton, property = "TextColor3", theme = { "SecondaryTextColor" } },
  1753. })
  1754.  
  1755. shared.Flags.Keybind[options.text] = {
  1756. getKeybind = function(self)
  1757. return TextButton.Text
  1758. end,
  1759.  
  1760. updateKeybind = function(self, options: table)
  1761. Keybind:updateKeybind(options)
  1762. end,
  1763. }
  1764.  
  1765. return self:createAddons(options.text, ImageButton, scrollingFrame, {
  1766. getKeybind = function(self)
  1767. return TextButton.Text
  1768. end,
  1769.  
  1770. updateKeybind = function(self, options: table)
  1771. Keybind:updateKeybind(options)
  1772. end,
  1773. })
  1774. end
  1775.  
  1776. function Library:createButton(options: table, parent, scrollingFrame)
  1777. Utility:validateOptions(options, {
  1778. text = { Default = "Button", ExpectedType = "string" },
  1779. callback = { Default = function() end, ExpectedType = "function" },
  1780. tooltip = { Default = "", ExpectedType = "string" },
  1781. })
  1782.  
  1783. scrollingFrame = self.ScrollingFrame or scrollingFrame
  1784.  
  1785. local Button = Assets.Elements.Button:Clone()
  1786. Button.Visible = true
  1787. Button.Parent = parent or self.Section
  1788. local Background = Button.Background
  1789.  
  1790. local TextButton = Background.TextButton
  1791. TextButton.Text = options.text
  1792.  
  1793. if options.tooltip and options.tooltip ~= "" then
  1794. TextButton.MouseEnter:Connect(function()
  1795. Library:showTooltip(TextButton, options.tooltip)
  1796. end)
  1797. TextButton.MouseLeave:Connect(function()
  1798. Library:hideTooltip()
  1799. end)
  1800. end
  1801.  
  1802. TextButton.MouseButton1Down:Connect(function()
  1803. Utility:tween(Background, { BackgroundTransparency = 0, Size = UDim2.new(1, 0, 1, -2) }, 0.08, "Quart", "Out")
  1804. :Play()
  1805. Utility:tween(TextButton, { TextColor3 = Theme.PrimaryColor, TextTransparency = 0 }, 0.08, "Quart", "Out")
  1806. :Play()
  1807.  
  1808. task.delay(0.08, function()
  1809. Utility
  1810. :tween(Background, { BackgroundTransparency = 0.3, Size = UDim2.new(1, 0, 1, 0) }, 0.2, "Back", "Out")
  1811. :Play()
  1812. Utility
  1813. :tween(TextButton, { TextColor3 = Theme.SecondaryTextColor, TextTransparency = 0 }, 0.2, "Quart", "Out")
  1814. :Play()
  1815. end)
  1816.  
  1817. options.callback()
  1818. end)
  1819.  
  1820. Background.MouseEnter:Connect(function(input)
  1821. Utility:tween(Background, { BackgroundTransparency = 0.3 }, 0.12, "Quart", "Out"):Play()
  1822. Utility:tween(TextButton, { TextColor3 = Theme.PrimaryColor, TextTransparency = 0.3 }, 0.12, "Quart", "Out")
  1823. :Play()
  1824. end)
  1825.  
  1826. Background.MouseLeave:Connect(function()
  1827. Utility:tween(Background, { BackgroundTransparency = 0 }, 0.15, "Quart", "Out"):Play()
  1828. Utility:tween(TextButton, { TextColor3 = Theme.SecondaryTextColor, TextTransparency = 0 }, 0.15, "Quart", "Out")
  1829. :Play()
  1830. end)
  1831.  
  1832. Theme:registerToObjects({
  1833. { object = Background, property = "BackgroundColor3", theme = { "SecondaryBackgroundColor" } },
  1834. { object = TextButton, property = "TextColor3", theme = { "SecondaryTextColor" } },
  1835. })
  1836. end
  1837.  
  1838. function Library:createTextBox(options: table, parent, scrollingFrame)
  1839. Utility:validateOptions(options, {
  1840. text = { Default = "Textbox", ExpectedType = "string" },
  1841. default = { Default = "", ExpectedType = "string" },
  1842. callback = { Default = function() end, ExpectedType = "function" },
  1843. tooltip = { Default = "", ExpectedType = "string" },
  1844. })
  1845.  
  1846. scrollingFrame = self.ScrollingFrame or scrollingFrame
  1847.  
  1848. local TextBox = Assets.Elements.TextBox:Clone()
  1849. TextBox.Visible = true
  1850. TextBox.Parent = parent or self.Section
  1851. local TextLabel = TextBox.TextLabel
  1852. TextLabel.Text = options.text
  1853.  
  1854. if options.tooltip and options.tooltip ~= "" then
  1855. TextLabel.MouseEnter:Connect(function()
  1856. Library:showTooltip(TextLabel, options.tooltip)
  1857. end)
  1858. TextLabel.MouseLeave:Connect(function()
  1859. Library:hideTooltip()
  1860. end)
  1861. end
  1862.  
  1863. local ImageButton = TextLabel.ImageButton
  1864.  
  1865. local Box = TextLabel.TextBox
  1866. Box.Text = options.default
  1867.  
  1868. local Context = Utility:validateContext({
  1869. default = { Value = options.default, ExpectedType = "string" },
  1870. callback = { Value = options.callback, ExpectedType = "function" },
  1871. TextBox = { Value = Box, ExpectedType = "Instance" },
  1872.  
  1873. autoSizeTextBox = {
  1874. Value = function()
  1875. local TextBoundsX = math.clamp(Box.TextBounds.X + 14, 0, 100)
  1876. Utility:tween(Box, { Size = UDim2.fromOffset(TextBoundsX, 20) }, 0.2, "Quart", "Out"):Play()
  1877. end,
  1878. ExpectedType = "function",
  1879. },
  1880. })
  1881.  
  1882. local TextBox = Modules.TextBox.new(Context)
  1883. TextBox:handleTextBox()
  1884.  
  1885. Theme:registerToObjects({
  1886. { object = TextLabel, property = "TextColor3", theme = { "SecondaryTextColor" } },
  1887. { object = Box, property = "TextColor3", theme = { "SecondaryTextColor" } },
  1888. { object = Box, property = "BackgroundColor3", theme = { "SecondaryBackgroundColor" } },
  1889. })
  1890.  
  1891. shared.Flags.TextBox[options.text] = {
  1892. getText = function(self)
  1893. return Box.Text
  1894. end,
  1895.  
  1896. updateText = function(self, options: table)
  1897. Box.Text = options.text or ""
  1898. Context.callback(Box.Text)
  1899. end,
  1900. }
  1901.  
  1902. return self:createAddons(options.text, ImageButton, scrollingFrame, {
  1903. getText = function(self)
  1904. return Box.Text
  1905. end,
  1906.  
  1907. updateText = function(self, options: table)
  1908. Box.Text = options.text or ""
  1909. Context.callback(Box.Text)
  1910. end,
  1911. })
  1912. end
  1913.  
  1914. local ChildRemoved = false
  1915. function Library:notify(options: table)
  1916. Utility:validateOptions(options, {
  1917. title = { Default = "Notification", ExpectedType = "string" },
  1918. text = { Default = "Hello world", ExpectedType = "string" },
  1919. duration = { Default = 3, ExpectedType = "number" },
  1920. maxSizeX = { Default = 300, ExpectedType = "number" },
  1921. scaleX = { Default = 0.165, ExpectedType = "number" },
  1922. sizeY = { Default = 100, ExpectedType = "number" },
  1923. })
  1924.  
  1925. local Notification = Assets.Elements.Notification:Clone()
  1926. Notification.Visible = true
  1927. Notification.Parent = ScreenGui.Notifications
  1928. Notification.Size = UDim2.new(options.scaleX, 0, 0, options.sizeY)
  1929. Notification.UISizeConstraint.MaxSize = Vector2.new(options.maxSizeX, 9e9)
  1930.  
  1931. local Title = Notification.Title
  1932. Title.Text = options.title
  1933.  
  1934. local Body = Notification.Body
  1935. Body.Text = options.text
  1936.  
  1937. local Line = Notification.Line
  1938.  
  1939. local NotificationTransparentObjects = Utility:getTransparentObjects(Notification)
  1940.  
  1941. for _, data in ipairs(NotificationTransparentObjects) do
  1942. data.object[data.property] = 1
  1943. end
  1944.  
  1945. Notification.BackgroundTransparency = 1
  1946.  
  1947. for _, data in ipairs(NotificationTransparentObjects) do
  1948. Utility:tween(data.object, { [data.property] = 0 }, 0.3, "Quint", "Out"):Play()
  1949. end
  1950.  
  1951. Utility:tween(Notification, { ["BackgroundTransparency"] = 0 }, 0.3, "Quint", "Out"):Play()
  1952.  
  1953. local notificationPosition = -24
  1954. local notificationSize = 0
  1955. local PADDING_Y = 14
  1956.  
  1957. for index, notification in ipairs(ScreenGui.Notifications:GetChildren()) do
  1958. if index == 1 then
  1959. notificationSize = notification.AbsoluteSize.Y
  1960. Utility:tween(notification, { Position = UDim2.new(1, -24, 1, notificationPosition) }, 0.2, "Quart", "Out")
  1961. :Play()
  1962. continue
  1963. end
  1964.  
  1965. notificationPosition -= notificationSize + PADDING_Y
  1966. notificationSize = notification.Size.Y.Offset
  1967. Notification.Position = UDim2.new(1, Notification.Position.X.Offset, 1, notificationPosition)
  1968. end
  1969.  
  1970. if not ChildRemoved then
  1971. ScreenGui.Notifications.ChildRemoved:Connect(function(child)
  1972. for index, notification in ipairs(ScreenGui.Notifications:GetChildren()) do
  1973. if index == 1 then
  1974. notificationPosition = -14
  1975. notificationSize = notification.AbsoluteSize.Y
  1976. Utility
  1977. :tween(
  1978. notification,
  1979. { Position = UDim2.new(1, -24, 1, notificationPosition) },
  1980. 0.2,
  1981. "Quart",
  1982. "Out"
  1983. )
  1984. :Play()
  1985. continue
  1986. end
  1987.  
  1988. notificationPosition -= notificationSize + PADDING_Y
  1989. notificationSize = notification.AbsoluteSize.Y
  1990. Utility
  1991. :tween(notification, { Position = UDim2.new(1, -24, 1, notificationPosition) }, 0.2, "Quart", "Out")
  1992. :Play()
  1993. end
  1994. end)
  1995.  
  1996. ChildRemoved = true
  1997. end
  1998.  
  1999. task.delay(options.duration, function()
  2000. if Notification then
  2001. for _, data in ipairs(Utility:getTransparentObjects(Notification)) do
  2002. Utility:tween(data.object, { [data.property] = 1 }, 0.2, "Quart", "Out"):Play()
  2003. end
  2004.  
  2005. Utility:tween(Notification, { ["BackgroundTransparency"] = 1 }, 0.2, "Quart", "Out"):Play()
  2006.  
  2007. task.wait(0.2)
  2008. Notification:Destroy()
  2009. end
  2010. end)
  2011.  
  2012. Utility:tween(Notification, { Position = UDim2.new(1, -24, 1, notificationPosition) }, 0.35, "Back", "Out"):Play()
  2013. task.wait(0.35)
  2014.  
  2015. Theme:registerToObjects({
  2016. { object = Notification, property = "BackgroundColor3", theme = { "SecondaryBackgroundColor" } },
  2017. { object = Title, property = "BackgroundColor3", theme = { "PrimaryBackgroundColor" } },
  2018. { object = Title, property = "TextColor3", theme = { "PrimaryTextColor" } },
  2019. { object = Line, property = "BackgroundColor3", theme = { "Line" } },
  2020. { object = Body, property = "TextColor3", theme = { "SecondaryTextColor" } },
  2021. })
  2022. end
  2023.  
  2024. -- Since the UI is visible by default we should make sure the cursor is visible as well
  2025. Utility:SetMouseCursorVisibility(true)
  2026.  
  2027. function Library:ToggleUI(state)
  2028. if Library._toggling then
  2029. return
  2030. end
  2031.  
  2032. -- Kill any visible tooltip immediately
  2033. Library:forceHideTooltip()
  2034.  
  2035. local targetVisible
  2036. if typeof(state) == "boolean" then
  2037. targetVisible = state
  2038. else
  2039. targetVisible = not ScreenGui.Enabled
  2040. end
  2041.  
  2042. Utility:SetMouseCursorVisibility(targetVisible)
  2043.  
  2044. if targetVisible then
  2045. Library._toggling = true
  2046. ScreenGui.Enabled = true
  2047. Glow.Size = UDim2.fromOffset(Library.sizeX * 0.93, Library.sizeY * 0.93)
  2048. Utility:tween(Glow, {
  2049. Size = UDim2.fromOffset(Library.sizeX, Library.sizeY),
  2050. }, 0.3, "Back", "Out"):Play()
  2051.  
  2052. task.delay(0.3, function()
  2053. Library._toggling = false
  2054. end)
  2055. else
  2056. Library._toggling = true
  2057. Utility:tween(Glow, {
  2058. Size = UDim2.fromOffset(Library.sizeX * 0.93, Library.sizeY * 0.93),
  2059. }, 0.15, "Quart", "In"):Play()
  2060. task.delay(0.15, function()
  2061. ScreenGui.Enabled = false
  2062. Glow.Size = UDim2.fromOffset(Library.sizeX, Library.sizeY)
  2063. Library._toggling = false
  2064. end)
  2065. end
  2066. end
  2067.  
  2068. function Library:createManager(options: table)
  2069. Utility:validateOptions(options, {
  2070. folderName = { Default = "Leny", ExpectedType = "string" },
  2071. icon = { Default = "124718082122263", ExpectedType = "string" },
  2072. apiBaseUrl = { Default = "", ExpectedType = "string" },
  2073. })
  2074.  
  2075. local HttpService = game:GetService("HttpService")
  2076. local exportCooldownUntil = 0
  2077. local THEME_ROOT_FOLDER = "LenyUI"
  2078. local THEME_FOLDER_PATH = THEME_ROOT_FOLDER .. "/Themes"
  2079. local THEME_AUTOLOAD_PATH = THEME_FOLDER_PATH .. "/themeautoload.txt"
  2080.  
  2081. local function getRequestFunction()
  2082. return request or http_request or (syn and syn.request)
  2083. end
  2084.  
  2085. local function resolveApiUrl(path: string)
  2086. if options.apiBaseUrl == "" then
  2087. return path
  2088. end
  2089.  
  2090. if string.sub(options.apiBaseUrl, -1) == "/" and string.sub(path, 1, 1) == "/" then
  2091. return string.sub(options.apiBaseUrl, 1, #options.apiBaseUrl - 1) .. path
  2092. end
  2093.  
  2094. if string.sub(options.apiBaseUrl, -1) ~= "/" and string.sub(path, 1, 1) ~= "/" then
  2095. return options.apiBaseUrl .. "/" .. path
  2096. end
  2097.  
  2098. return options.apiBaseUrl .. path
  2099. end
  2100.  
  2101. local function getHeader(headers: table?, headerName: string)
  2102. for key, value in pairs(headers or {}) do
  2103. if string.lower(tostring(key)) == string.lower(headerName) then
  2104. return value
  2105. end
  2106. end
  2107.  
  2108. return nil
  2109. end
  2110.  
  2111. local function requestApi(method: string, path: string, body: table?)
  2112. local requestFn = getRequestFunction()
  2113. if not requestFn then
  2114. return nil, "No supported request function found (request/http_request/syn.request)."
  2115. end
  2116.  
  2117. local requestData = {
  2118. Url = resolveApiUrl(path),
  2119. Method = method,
  2120. Headers = {
  2121. ["Content-Type"] = "application/json",
  2122. ["Accept"] = "application/json",
  2123. },
  2124. }
  2125.  
  2126. if body then
  2127. requestData.Body = HttpService:JSONEncode(body)
  2128. end
  2129.  
  2130. local ok, response = pcall(function()
  2131. return requestFn(requestData)
  2132. end)
  2133.  
  2134. if not ok then
  2135. return nil, tostring(response)
  2136. end
  2137.  
  2138. return response, nil
  2139. end
  2140.  
  2141. local function getJsons()
  2142. local jsons = {}
  2143. for _, file in ipairs(listfiles(options.folderName)) do
  2144. if not string.match(file, "Theme") and not string.match(file, "autoload") then
  2145. local fileName = file:match("([^/\\]+)$")
  2146. if fileName then
  2147. fileName = string.gsub(fileName, "%.json$", "")
  2148. table.insert(jsons, fileName)
  2149. end
  2150. end
  2151. end
  2152.  
  2153. return jsons
  2154. end
  2155.  
  2156. local function getThemeJsons()
  2157. local themeJsons = {}
  2158. for _, file in ipairs(listfiles(THEME_FOLDER_PATH)) do
  2159. local fileName = file:match("([^/\\]+)$")
  2160. if fileName and string.match(string.lower(fileName), "%.json$") then
  2161. fileName = string.gsub(fileName, "%.json$", "")
  2162. table.insert(themeJsons, fileName)
  2163. end
  2164. end
  2165.  
  2166. return themeJsons
  2167. end
  2168.  
  2169. -- Function to fetch theme presets from GitHub
  2170. local function getThemePresets()
  2171. local success, result = pcall(function()
  2172. local response = game:HttpGet("https://api.github.com/repos/DontGho/userinterface/contents")
  2173. local decoded = HttpService:JSONDecode(response)
  2174. local presets = {}
  2175.  
  2176. for _, file in ipairs(decoded) do
  2177. if file.type == "file" and string.match(file.name, ".json$") then
  2178. local name = string.gsub(file.name, ".json", "")
  2179. table.insert(presets, name)
  2180. end
  2181. end
  2182.  
  2183. return presets
  2184. end)
  2185.  
  2186. if success then
  2187. return result
  2188. else
  2189. warn("Failed to fetch theme presets from GitHub:", result)
  2190. return {}
  2191. end
  2192. end
  2193.  
  2194. local function getSavedData()
  2195. local SavedData = {
  2196. Dropdown = {},
  2197. Toggle = {},
  2198. Keybind = {},
  2199. Slider = {},
  2200. TextBox = {},
  2201. ColorPicker = {},
  2202. }
  2203.  
  2204. local Excluded = {
  2205. "Line",
  2206. "PrimaryColor",
  2207. "PrimaryTextColor",
  2208. "SecondaryTextColor",
  2209. "PrimaryBackgroundColor",
  2210. "SecondaryBackgroundColor",
  2211. "TertiaryBackgroundColor",
  2212. "ScrollingBarImageColor",
  2213. "TabBackgroundColor",
  2214. }
  2215.  
  2216. for elementType, elementData in pairs(shared.Flags) do
  2217. for elementName, addon in pairs(elementData) do
  2218. if elementType == "Dropdown" and typeof(addon) == "table" and addon.getList and addon.getValue then
  2219. SavedData.Dropdown[elementName] = { list = addon:getList(), value = addon:getValue() }
  2220. end
  2221.  
  2222. if elementType == "Toggle" and typeof(addon) == "table" and addon.getState then
  2223. SavedData.Toggle[elementName] = { state = addon:getState() }
  2224. end
  2225.  
  2226. if elementType == "Slider" and typeof(addon) == "table" and addon.getValue then
  2227. SavedData.Slider[elementName] = { value = addon:getValue() }
  2228. end
  2229.  
  2230. if elementType == "Keybind" and typeof(addon) == "table" and addon.getKeybind then
  2231. SavedData.Keybind[elementName] = { keybind = addon:getKeybind() }
  2232. end
  2233.  
  2234. if elementType == "TextBox" and typeof(addon) == "table" and addon.getText then
  2235. SavedData.TextBox[elementName] = { text = addon:getText() }
  2236. end
  2237.  
  2238. if
  2239. not table.find(Excluded, elementName)
  2240. and elementType == "ColorPicker"
  2241. and typeof(addon) == "table"
  2242. and addon.getColor
  2243. then
  2244. SavedData.ColorPicker[elementName] =
  2245. { color = { addon:getColor().R * 255, addon:getColor().G * 255, addon:getColor().B * 255 } }
  2246. end
  2247. end
  2248. end
  2249.  
  2250. return SavedData
  2251. end
  2252.  
  2253. local function getThemeData()
  2254. local SavedData = {
  2255. ColorPicker = {},
  2256. }
  2257.  
  2258. for elementType, elementData in pairs(shared.Flags) do
  2259. for elementName, addon in pairs(elementData) do
  2260. for _, themeName in ipairs({
  2261. "Line",
  2262. "PrimaryColor",
  2263. "PrimaryTextColor",
  2264. "SecondaryTextColor",
  2265. "PrimaryBackgroundColor",
  2266. "SecondaryBackgroundColor",
  2267. "TertiaryBackgroundColor",
  2268. "ScrollingBarImageColor",
  2269. "TabBackgroundColor",
  2270. }) do
  2271. if
  2272. elementName == themeName
  2273. and elementType == "ColorPicker"
  2274. and typeof(addon) == "table"
  2275. and addon.getColor
  2276. then
  2277. SavedData.ColorPicker[elementName] =
  2278. { color = { addon:getColor().R * 255, addon:getColor().G * 255, addon:getColor().B * 255 } }
  2279. end
  2280. end
  2281. end
  2282. end
  2283.  
  2284. return SavedData
  2285. end
  2286.  
  2287. local function applySavedData(decoded: table)
  2288. if type(decoded) ~= "table" then
  2289. return false, "Invalid settings payload"
  2290. end
  2291.  
  2292. for elementType, elementData in pairs(shared.Flags) do
  2293. for elementName, _ in pairs(elementData) do
  2294. if
  2295. elementType == "Dropdown"
  2296. and decoded.Dropdown
  2297. and decoded.Dropdown[elementName]
  2298. and shared.Flags.Dropdown[elementName]
  2299. and elementName ~= "Configs"
  2300. and elementName ~= "Theme Configs"
  2301. and elementName ~= "Theme Presets"
  2302. then
  2303. local defaultValue = decoded.Dropdown[elementName].value
  2304. if type(defaultValue) ~= "table" then
  2305. defaultValue = { defaultValue }
  2306. end
  2307.  
  2308. shared.Flags.Dropdown[elementName]:updateList({
  2309. list = decoded.Dropdown[elementName].list,
  2310. default = defaultValue,
  2311. })
  2312. end
  2313.  
  2314. if
  2315. elementType == "Toggle"
  2316. and decoded.Toggle
  2317. and decoded.Toggle[elementName]
  2318. and shared.Flags.Toggle[elementName]
  2319. then
  2320. shared.Flags.Toggle[elementName]:updateState({ state = decoded.Toggle[elementName].state })
  2321. end
  2322.  
  2323. if
  2324. elementType == "Slider"
  2325. and decoded.Slider
  2326. and decoded.Slider[elementName]
  2327. and shared.Flags.Slider[elementName]
  2328. then
  2329. shared.Flags.Slider[elementName]:updateValue({ value = decoded.Slider[elementName].value })
  2330. end
  2331.  
  2332. if
  2333. elementType == "Keybind"
  2334. and decoded.Keybind
  2335. and decoded.Keybind[elementName]
  2336. and shared.Flags.Keybind[elementName]
  2337. then
  2338. shared.Flags.Keybind[elementName]:updateKeybind({ bind = decoded.Keybind[elementName].keybind })
  2339. end
  2340.  
  2341. if
  2342. elementType == "TextBox"
  2343. and decoded.TextBox
  2344. and decoded.TextBox[elementName]
  2345. and shared.Flags.TextBox[elementName]
  2346. then
  2347. shared.Flags.TextBox[elementName]:updateText({ text = decoded.TextBox[elementName].text })
  2348. end
  2349.  
  2350. if
  2351. elementType == "ColorPicker"
  2352. and decoded.ColorPicker
  2353. and decoded.ColorPicker[elementName]
  2354. and shared.Flags.ColorPicker[elementName]
  2355. then
  2356. shared.Flags.ColorPicker[elementName]:updateColor({
  2357. color = Color3.fromRGB(unpack(decoded.ColorPicker[elementName].color)),
  2358. })
  2359. end
  2360. end
  2361. end
  2362.  
  2363. return true
  2364. end
  2365.  
  2366. local function loadSaveConfig(fileName: string)
  2367. if not fileName or fileName == "" then
  2368. return
  2369. end
  2370.  
  2371. local filePath = options.folderName .. "/" .. fileName .. ".json"
  2372. if not isfile(filePath) then
  2373. return
  2374. end
  2375.  
  2376. local decodeSuccess, decoded = pcall(function()
  2377. return HttpService:JSONDecode(readfile(filePath))
  2378. end)
  2379.  
  2380. if decodeSuccess then
  2381. applySavedData(decoded)
  2382. end
  2383. end
  2384.  
  2385. local function loadThemeConfig(fileName: string, isGitHub: boolean)
  2386. if not fileName or fileName == "" then
  2387. return
  2388. end
  2389.  
  2390. local decoded
  2391. local success, err = pcall(function()
  2392. if isGitHub then
  2393. -- URL encode the filename to handle spaces and special characters
  2394. local encodedFileName = HttpService:UrlEncode(fileName)
  2395. local url = "https://raw.githubusercontent.com/DontGho/userinterface/refs/heads/main/"
  2396. .. encodedFileName
  2397. .. ".json"
  2398. local response = game:HttpGet(url)
  2399. decoded = HttpService:JSONDecode(response)
  2400. else
  2401. local filePath = THEME_FOLDER_PATH .. "/" .. fileName .. ".json"
  2402. if not isfile(filePath) then
  2403. error("File does not exist: " .. filePath)
  2404. end
  2405. decoded = HttpService:JSONDecode(readfile(filePath))
  2406. end
  2407. end)
  2408.  
  2409. if not success then
  2410. warn("Failed to load theme config:", err)
  2411. return
  2412. end
  2413.  
  2414. if not decoded or not decoded.ColorPicker then
  2415. warn("Invalid theme config format")
  2416. return
  2417. end
  2418.  
  2419. for elementType, elementData in pairs(shared.Flags) do
  2420. for elementName, _ in pairs(elementData) do
  2421. if
  2422. elementType == "ColorPicker"
  2423. and decoded.ColorPicker[elementName]
  2424. and shared.Flags.ColorPicker[elementName]
  2425. then
  2426. local colorData = decoded.ColorPicker[elementName].color
  2427. if colorData and #colorData == 3 then
  2428. shared.Flags.ColorPicker[elementName]:updateColor({
  2429. color = Color3.fromRGB(unpack(colorData)),
  2430. })
  2431. end
  2432. end
  2433. end
  2434. end
  2435. end
  2436.  
  2437. local UI = Library:createTab({ text = "UI", icon = options.icon })
  2438. local Page = UI:createSubTab({ text = "Page 1" })
  2439. local UI = Page:createSection({ text = "UI" })
  2440. local SaveManager = Page:createSection({ position = "Right", text = "Save Manager" })
  2441. local ThemeManager = Page:createSection({ position = "Right", text = "Theme Manager" })
  2442.  
  2443. function createNaturalRainbowEffect(titleIcon)
  2444. if rainbowConnection then
  2445. rainbowConnection:Disconnect()
  2446. rainbowConnection = nil
  2447. end
  2448.  
  2449. local originalColor = Library.Theme.PrimaryTextColor
  2450. local h, s, v = originalColor:ToHSV()
  2451.  
  2452. local originalSaturation = math.max(s, 0.8)
  2453. local originalValue = math.max(v, 0.9)
  2454.  
  2455. local startTime = tick()
  2456. local cycleDuration = 4
  2457.  
  2458. rainbowConnection = game:GetService("RunService").Heartbeat:Connect(function()
  2459. local elapsed = tick() - startTime
  2460. local progress = (elapsed % cycleDuration) / cycleDuration
  2461.  
  2462. local currentHue = progress
  2463.  
  2464. local newColor = Color3.fromHSV(currentHue, originalSaturation, originalValue)
  2465. titleIcon.ImageColor3 = newColor
  2466. end)
  2467.  
  2468. table.insert(Connections, {
  2469. Disconnect = function()
  2470. if rainbowConnection then
  2471. rainbowConnection:Disconnect()
  2472. rainbowConnection = nil
  2473. end
  2474. end,
  2475. })
  2476. end
  2477.  
  2478. local function stopRainbowEffect(titleIcon)
  2479. if rainbowConnection then
  2480. rainbowConnection:Disconnect()
  2481. rainbowConnection = nil
  2482. end
  2483. titleIcon.ImageColor3 = Library.Theme.PrimaryTextColor
  2484.  
  2485. -- Re-register to theme so it updates with theme changes
  2486. Theme:registerToObjects({
  2487. { object = titleIcon, property = "ImageColor3", theme = { "PrimaryTextColor" } },
  2488. })
  2489. end
  2490.  
  2491. -- Only show icon toggles if user is not poor
  2492. if not UserIsPoor then
  2493. UI:createToggle({
  2494. text = "Show Icon",
  2495. state = true,
  2496. callback = function(state)
  2497. Library.IconVisible = state
  2498. local TitleIcon = Title:FindFirstChild("TitleIcon")
  2499. if TitleIcon then
  2500. TitleIcon.Visible = state
  2501. if state then
  2502. Title.Text = " " .. (Library.Title or "Leny")
  2503. else
  2504. Title.Text = Library.Title or "Leny"
  2505. end
  2506. end
  2507. end,
  2508. })
  2509.  
  2510. UI:createToggle({
  2511. text = "Rainbow Icon",
  2512. state = false,
  2513. callback = function(state)
  2514. local TitleIcon = Title:FindFirstChild("TitleIcon")
  2515. if TitleIcon then
  2516. if state then
  2517. createNaturalRainbowEffect(TitleIcon)
  2518. else
  2519. stopRainbowEffect(TitleIcon)
  2520. end
  2521. end
  2522. end,
  2523. })
  2524. end
  2525.  
  2526. UI:createToggle({
  2527. text = "Aggressive Mouse Unlock",
  2528. state = false,
  2529. tooltip = 'Only enable if the mouse is invisible while the UI is open. (May cause detections)',
  2530. })
  2531.  
  2532. UI:createPicker({
  2533. text = "SecondaryTextColor",
  2534. default = Theme.SecondaryTextColor,
  2535. callback = function(color)
  2536. Theme:setTheme("SecondaryTextColor", color)
  2537. end,
  2538. })
  2539.  
  2540. UI:createPicker({
  2541. text = "PrimaryTextColor",
  2542. default = Theme.PrimaryTextColor,
  2543. callback = function(color)
  2544. Theme:setTheme("PrimaryTextColor", color)
  2545. end,
  2546. })
  2547.  
  2548. UI:createPicker({
  2549. text = "PrimaryBackgroundColor",
  2550. default = Theme.PrimaryBackgroundColor,
  2551. callback = function(color)
  2552. Theme:setTheme("PrimaryBackgroundColor", color)
  2553. end,
  2554. })
  2555.  
  2556. UI:createPicker({
  2557. text = "SecondaryBackgroundColor",
  2558. default = Theme.SecondaryBackgroundColor,
  2559. callback = function(color)
  2560. Theme:setTheme("SecondaryBackgroundColor", color)
  2561. end,
  2562. })
  2563.  
  2564. UI:createPicker({
  2565. text = "TabBackgroundColor",
  2566. default = Theme.TabBackgroundColor,
  2567. callback = function(color)
  2568. Theme:setTheme("TabBackgroundColor", color)
  2569. end,
  2570. })
  2571.  
  2572. UI:createPicker({
  2573. text = "PrimaryColor",
  2574. default = Theme.PrimaryColor,
  2575. callback = function(color)
  2576. Theme:setTheme("PrimaryColor", color)
  2577. end,
  2578. })
  2579.  
  2580. UI:createPicker({
  2581. text = "Outline",
  2582. default = Theme.Line,
  2583. callback = function(color)
  2584. Theme:setTheme("Line", color)
  2585. end,
  2586. })
  2587.  
  2588. UI:createPicker({
  2589. text = "TertiaryBackgroundColor",
  2590. default = Theme.TertiaryBackgroundColor,
  2591. callback = function(color)
  2592. Theme:setTheme("TertiaryBackgroundColor", color)
  2593. end,
  2594. })
  2595.  
  2596. UI:createPicker({
  2597. text = "SecondaryTextColor",
  2598. default = Theme.SecondaryTextColor,
  2599. callback = function(color)
  2600. Theme:setTheme("SecondaryTextColor", color)
  2601. end,
  2602. })
  2603.  
  2604. UI:createPicker({
  2605. text = "ScrollingBarImageColor",
  2606. default = Theme.ScrollingBarImageColor,
  2607. callback = function(color)
  2608. Theme:setTheme("ScrollingBarImageColor", color)
  2609. end,
  2610. })
  2611.  
  2612. UI:createKeybind({
  2613. text = "Hide UI",
  2614. default = "Delete",
  2615. callback = function()
  2616. Library:ToggleUI()
  2617. end,
  2618. })
  2619.  
  2620. UI:createButton({
  2621. text = "Destroy UI",
  2622. callback = function()
  2623. Library:destroy()
  2624. end,
  2625. })
  2626.  
  2627. if not isfolder(options.folderName) then
  2628. makefolder(options.folderName)
  2629. end
  2630.  
  2631. if not isfolder(THEME_ROOT_FOLDER) then
  2632. makefolder(THEME_ROOT_FOLDER)
  2633. end
  2634.  
  2635. if not isfolder(THEME_FOLDER_PATH) then
  2636. makefolder(THEME_FOLDER_PATH)
  2637. end
  2638.  
  2639. local jsons = getJsons()
  2640.  
  2641. -- LOAD/MANAGE CONFIGS (most commonly used)
  2642. local Configs = SaveManager:createDropdown({ text = "Configs", list = jsons })
  2643.  
  2644. SaveManager:createButton({
  2645. text = "Load Config",
  2646. callback = function()
  2647. local configValue = Configs:getValue()
  2648. -- Handle both string and table returns from getValue
  2649. if type(configValue) == "table" then
  2650. configValue = configValue[1] or ""
  2651. end
  2652. if configValue and configValue ~= "" and configValue ~= "None" then
  2653. loadSaveConfig(configValue)
  2654. end
  2655. end,
  2656. })
  2657.  
  2658. SaveManager:createButton({
  2659. text = "Set as Auto Load",
  2660. callback = function()
  2661. local configValue = Configs:getValue()
  2662. -- Handle both string and table returns from getValue
  2663. if type(configValue) == "table" then
  2664. configValue = configValue[1] or ""
  2665. end
  2666. if configValue and configValue ~= "" and configValue ~= "None" then
  2667. writefile(options.folderName .. "/autoload.txt", configValue)
  2668. end
  2669. end,
  2670. })
  2671.  
  2672. -- CREATE/SAVE CONFIGS
  2673. local configName = SaveManager:createTextBox({ text = "Config Name" })
  2674. local importCode = nil
  2675. local lastShareCode = ""
  2676.  
  2677. local function normalizeCode(text: string)
  2678. local codeText = tostring(text or "")
  2679. codeText = string.gsub(codeText, "%s+", "")
  2680. return codeText
  2681. end
  2682.  
  2683. local function parseTimestamp(rawValue)
  2684. local numeric = tonumber(rawValue)
  2685. if not numeric then
  2686. return nil
  2687. end
  2688.  
  2689. if numeric > 9999999999 then
  2690. numeric = numeric / 1000
  2691. end
  2692.  
  2693. numeric = math.floor(numeric)
  2694. if numeric <= 0 then
  2695. return nil
  2696. end
  2697.  
  2698. return numeric
  2699. end
  2700.  
  2701. local function formatDuration(seconds: number)
  2702. local totalSeconds = math.max(0, math.floor(tonumber(seconds) or 0))
  2703. local hours = math.floor(totalSeconds / 3600)
  2704. local minutes = math.floor((totalSeconds % 3600) / 60)
  2705. local secs = totalSeconds % 60
  2706.  
  2707. if hours > 0 then
  2708. if minutes > 0 then
  2709. return tostring(hours) .. "h " .. tostring(minutes) .. "m"
  2710. end
  2711. return tostring(hours) .. "h"
  2712. end
  2713.  
  2714. if minutes > 0 then
  2715. return tostring(minutes) .. "m"
  2716. end
  2717.  
  2718. return tostring(secs) .. "s"
  2719. end
  2720.  
  2721. local function isValidShareCode(code: string)
  2722. return string.match(code, "^[0-9A-Za-z][0-9A-Za-z][0-9A-Za-z][0-9A-Za-z][0-9A-Za-z]$") ~= nil
  2723. end
  2724.  
  2725. local function notifyApiError(statusCode: number, isExport: boolean, responseHeaders: table?)
  2726. if statusCode == 400 then
  2727. Library:notify({ title = "Config API", text = "Invalid request data.", duration = 4 })
  2728. return
  2729. end
  2730.  
  2731. if statusCode == 404 then
  2732. Library:notify({ title = "Config API", text = "Code not found or expired.", duration = 4 })
  2733. return
  2734. end
  2735.  
  2736. if statusCode == 429 then
  2737. local retryAfter = tonumber(getHeader(responseHeaders, "Retry-After")) or 0
  2738.  
  2739. if isExport and retryAfter > 0 then
  2740. exportCooldownUntil = math.max(exportCooldownUntil, tick() + retryAfter)
  2741. Library:notify({
  2742. title = "Export Rate Limited",
  2743. text = "Try again in " .. formatDuration(retryAfter) .. ".",
  2744. duration = 5,
  2745. })
  2746. else
  2747. Library:notify({ title = "Config API", text = "Rate limited. Please wait and retry.", duration = 5 })
  2748. end
  2749.  
  2750. return
  2751. end
  2752.  
  2753. if statusCode == 500 then
  2754. Library:notify({ title = "Config API", text = "Server error while processing config.", duration = 5 })
  2755. return
  2756. end
  2757.  
  2758. Library:notify({
  2759. title = "Config API",
  2760. text = "Unexpected error (" .. tostring(statusCode) .. ").",
  2761. duration = 5,
  2762. })
  2763. end
  2764.  
  2765. if options.apiBaseUrl ~= "" then
  2766. importCode = SaveManager:createTextBox({ text = "Import Code" })
  2767.  
  2768. SaveManager:createButton({
  2769. text = "Import Settings",
  2770. callback = function()
  2771. local code = normalizeCode(importCode:getText())
  2772. if not isValidShareCode(code) then
  2773. Library:notify({
  2774. title = "Import Settings",
  2775. text = "Enter a valid 5-character code.",
  2776. duration = 4,
  2777. })
  2778. return
  2779. end
  2780.  
  2781. local response, requestError = requestApi("GET", "/api/import/" .. code)
  2782. if not response then
  2783. Library:notify({
  2784. title = "Import Settings",
  2785. text = "Request failed: " .. tostring(requestError),
  2786. duration = 5,
  2787. })
  2788. return
  2789. end
  2790.  
  2791. if tonumber(response.StatusCode) ~= 200 then
  2792. notifyApiError(tonumber(response.StatusCode) or 0, false, response.Headers)
  2793. return
  2794. end
  2795.  
  2796. local decodeSuccess, decoded = pcall(function()
  2797. return HttpService:JSONDecode(response.Body or "")
  2798. end)
  2799.  
  2800. if not decodeSuccess or type(decoded) ~= "table" then
  2801. Library:notify({ title = "Import Settings", text = "Failed to decode settings.", duration = 5 })
  2802. return
  2803. end
  2804.  
  2805. local applySuccess, applyError = applySavedData(decoded)
  2806. if not applySuccess then
  2807. Library:notify({ title = "Import Settings", text = tostring(applyError), duration = 5 })
  2808. return
  2809. end
  2810.  
  2811. Library:notify({ title = "Import Settings", text = "Settings imported successfully.", duration = 4 })
  2812. end,
  2813. })
  2814.  
  2815. SaveManager:createButton({
  2816. text = "Export Settings",
  2817. callback = function()
  2818. local now = tick()
  2819. if now < exportCooldownUntil then
  2820. local timeLeft = math.ceil(exportCooldownUntil - now)
  2821. Library:notify({
  2822. title = "Export Settings",
  2823. text = "Export is on cooldown for " .. formatDuration(timeLeft) .. ".",
  2824. duration = 4,
  2825. })
  2826. return
  2827. end
  2828.  
  2829. local payload = getSavedData()
  2830. local response, requestError = requestApi("POST", "/api/export", payload)
  2831. if not response then
  2832. Library:notify({
  2833. title = "Export Settings",
  2834. text = "Request failed: " .. tostring(requestError),
  2835. duration = 5,
  2836. })
  2837. return
  2838. end
  2839.  
  2840. if tonumber(response.StatusCode) ~= 200 then
  2841. notifyApiError(tonumber(response.StatusCode) or 0, true, response.Headers)
  2842. return
  2843. end
  2844.  
  2845. local decodeSuccess, decoded = pcall(function()
  2846. return HttpService:JSONDecode(response.Body or "")
  2847. end)
  2848.  
  2849. if
  2850. not decodeSuccess
  2851. or type(decoded) ~= "table"
  2852. or not isValidShareCode(tostring(decoded.code or ""))
  2853. then
  2854. Library:notify({
  2855. title = "Export Settings",
  2856. text = "Server returned an invalid code.",
  2857. duration = 5,
  2858. })
  2859. return
  2860. end
  2861.  
  2862. local code = tostring(decoded.code)
  2863. lastShareCode = code
  2864.  
  2865. local copyFn = setclipboard or toclipboard
  2866. local copiedToClipboard = false
  2867. if copyFn then
  2868. copiedToClipboard = pcall(function()
  2869. copyFn(code)
  2870. end)
  2871. end
  2872.  
  2873. local remaining = tonumber(getHeader(response.Headers, "X-RateLimit-Remaining"))
  2874. local limit = tonumber(getHeader(response.Headers, "X-RateLimit-Limit"))
  2875. local usageText = "?/?"
  2876. if remaining ~= nil and limit ~= nil then
  2877. local used = math.clamp(limit - remaining, 0, limit)
  2878. usageText = tostring(used) .. "/" .. tostring(limit)
  2879. elseif remaining ~= nil then
  2880. usageText = "?/?"
  2881. end
  2882.  
  2883. local resetInText = "unknown"
  2884. local resetTimestamp = parseTimestamp(getHeader(response.Headers, "X-RateLimit-Reset"))
  2885. if resetTimestamp then
  2886. resetInText = formatDuration(math.max(0, resetTimestamp - os.time()))
  2887. end
  2888.  
  2889. local expiryRaw = decoded.expiresAt or decoded.expires_at or decoded.expiry or decoded.expireAt
  2890. local expiresText = "7d"
  2891. local expiryTimestamp = parseTimestamp(expiryRaw)
  2892. if expiryTimestamp then
  2893. expiresText = formatDuration(math.max(0, expiryTimestamp - os.time()))
  2894. end
  2895.  
  2896. local clipboardText = copiedToClipboard and "Copied" or "No clipboard"
  2897.  
  2898. Library:notify({
  2899. title = "Export Settings",
  2900. text = "Code: "
  2901. .. code
  2902. .. " | "
  2903. .. usageText
  2904. .. " | expires in "
  2905. .. expiresText
  2906. .. " | reset in "
  2907. .. resetInText
  2908. .. " | "
  2909. .. clipboardText,
  2910. duration = 10,
  2911. })
  2912. end,
  2913. })
  2914.  
  2915. SaveManager:createButton({
  2916. text = "Copy Share Code",
  2917. callback = function()
  2918. local code = normalizeCode(lastShareCode)
  2919. if not isValidShareCode(code) then
  2920. Library:notify({ title = "Copy Share Code", text = "No valid share code to copy.", duration = 4 })
  2921. return
  2922. end
  2923.  
  2924. local copyFn = setclipboard or toclipboard
  2925. if not copyFn then
  2926. Library:notify({
  2927. title = "Copy Share Code",
  2928. text = "Clipboard is not supported in this executor.",
  2929. duration = 4,
  2930. })
  2931. return
  2932. end
  2933.  
  2934. local copySuccess = pcall(function()
  2935. copyFn(code)
  2936. end)
  2937.  
  2938. if copySuccess then
  2939. Library:notify({
  2940. title = "Copy Share Code",
  2941. text = "Copied " .. code .. " to clipboard.",
  2942. duration = 4,
  2943. })
  2944. else
  2945. Library:notify({ title = "Copy Share Code", text = "Failed to copy code.", duration = 4 })
  2946. end
  2947. end,
  2948. })
  2949. end
  2950.  
  2951. SaveManager:createButton({
  2952. text = "Create Config",
  2953. callback = function()
  2954. local SavedData = getSavedData()
  2955. local encoded = HttpService:JSONEncode(SavedData)
  2956. writefile(options.folderName .. "/" .. configName:getText() .. ".json", encoded)
  2957.  
  2958. if shared.Flags.Dropdown["Configs"] then
  2959. shared.Flags.Dropdown["Configs"]:updateList({
  2960. list = getJsons(),
  2961. default = { shared.Flags.Dropdown["Configs"]:getValue() },
  2962. })
  2963. end
  2964. end,
  2965. })
  2966.  
  2967. SaveManager:createButton({
  2968. text = "Save/Overwrite Config",
  2969. callback = function()
  2970. local configValue = Configs:getValue()
  2971. -- Handle both string and table returns from getValue
  2972. if type(configValue) == "table" then
  2973. configValue = configValue[1] or ""
  2974. end
  2975. if not configValue or configValue == "" or configValue == "None" then
  2976. return
  2977. end
  2978. local SavedData = getSavedData()
  2979. local encoded = HttpService:JSONEncode(SavedData)
  2980. writefile(options.folderName .. "/" .. configValue .. ".json", encoded)
  2981. Configs:updateList({ list = getJsons(), default = { configValue } })
  2982. end,
  2983. })
  2984.  
  2985. SaveManager:createButton({
  2986. text = "Delete Saved Config",
  2987. callback = function()
  2988. local configToDelete = Configs:getValue()
  2989. -- Handle both string and table returns from getValue
  2990. if type(configToDelete) == "table" then
  2991. configToDelete = configToDelete[1] or ""
  2992. end
  2993. if not configToDelete or configToDelete == "" or configToDelete == "None" then
  2994. return
  2995. end
  2996. local filePath = options.folderName .. "/" .. configToDelete .. ".json"
  2997. if isfile and delfile and isfile(filePath) then
  2998. delfile(filePath)
  2999. Configs:updateList({ list = getJsons(), default = {} })
  3000. end
  3001. end,
  3002. })
  3003.  
  3004. if isfile(options.folderName .. "/autoload.txt") then
  3005. local autoloadConfig = readfile(options.folderName .. "/autoload.txt")
  3006. if autoloadConfig and autoloadConfig ~= "" then
  3007. loadSaveConfig(autoloadConfig)
  3008. end
  3009. end
  3010.  
  3011. -- THEME PRESETS SECTION (from GitHub - most commonly used)
  3012. local ThemePresets = ThemeManager:createDropdown({
  3013. text = "Theme Presets",
  3014. list = getThemePresets(),
  3015. })
  3016.  
  3017. ThemeManager:createButton({
  3018. text = "Load Theme Preset",
  3019. callback = function()
  3020. local presetValue = ThemePresets:getValue()
  3021. -- Handle both string and table returns from getValue
  3022. if type(presetValue) == "table" then
  3023. presetValue = presetValue[1] or ""
  3024. end
  3025. if presetValue and presetValue ~= "" and presetValue ~= "None" then
  3026. loadThemeConfig(presetValue, true)
  3027. end
  3028. end,
  3029. })
  3030.  
  3031. ThemeManager:createButton({
  3032. text = "Refresh Presets",
  3033. callback = function()
  3034. ThemePresets:updateList({
  3035. list = getThemePresets(),
  3036. default = {},
  3037. })
  3038. end,
  3039. })
  3040.  
  3041. ThemeManager:createButton({
  3042. text = "Set Preset Auto Load",
  3043. callback = function()
  3044. local presetValue = ThemePresets:getValue()
  3045. -- Handle both string and table returns from getValue
  3046. if type(presetValue) == "table" then
  3047. presetValue = presetValue[1] or ""
  3048. end
  3049. if presetValue and presetValue ~= "" and presetValue ~= "None" then
  3050. writefile(options.folderName .. "/presetautoload.txt", presetValue)
  3051. end
  3052. end,
  3053. })
  3054.  
  3055. -- LOCAL THEME CONFIGS SECTION (your saved themes)
  3056. local themeConfigName = ThemeManager:createTextBox({ text = "Theme Config Name" })
  3057.  
  3058. ThemeManager:createButton({
  3059. text = "Create Theme Config",
  3060. callback = function()
  3061. local ThemeData = getThemeData()
  3062. local encoded = HttpService:JSONEncode(ThemeData)
  3063. writefile(THEME_FOLDER_PATH .. "/" .. themeConfigName:getText() .. ".json", encoded)
  3064.  
  3065. if shared.Flags.Dropdown["Theme Configs"] then
  3066. shared.Flags.Dropdown["Theme Configs"]:updateList({
  3067. list = getThemeJsons(),
  3068. default = { shared.Flags.Dropdown["Theme Configs"]:getValue() },
  3069. })
  3070. end
  3071. end,
  3072. })
  3073.  
  3074. local ThemeConfigs = ThemeManager:createDropdown({
  3075. text = "Theme Configs",
  3076. list = getThemeJsons(),
  3077. })
  3078.  
  3079. ThemeManager:createButton({
  3080. text = "Load Theme Config",
  3081. callback = function()
  3082. local themeValue = ThemeConfigs:getValue()
  3083. -- Handle both string and table returns from getValue
  3084. if type(themeValue) == "table" then
  3085. themeValue = themeValue[1] or ""
  3086. end
  3087. if themeValue and themeValue ~= "" and themeValue ~= "None" then
  3088. loadThemeConfig(themeValue, false)
  3089. end
  3090. end,
  3091. })
  3092.  
  3093. ThemeManager:createButton({
  3094. text = "Save Theme Config",
  3095. callback = function()
  3096. local themeValue = ThemeConfigs:getValue()
  3097. -- Handle both string and table returns from getValue
  3098. if type(themeValue) == "table" then
  3099. themeValue = themeValue[1] or ""
  3100. end
  3101. if not themeValue or themeValue == "" or themeValue == "None" then
  3102. return
  3103. end
  3104. local ThemeData = getThemeData()
  3105. local encoded = HttpService:JSONEncode(ThemeData)
  3106. writefile(THEME_FOLDER_PATH .. "/" .. themeValue .. ".json", encoded)
  3107. ThemeConfigs:updateList({ list = getThemeJsons(), default = { themeValue } })
  3108. end,
  3109. })
  3110.  
  3111. ThemeManager:createButton({
  3112. text = "Set Config Auto Load",
  3113. callback = function()
  3114. local themeValue = ThemeConfigs:getValue()
  3115. -- Handle both string and table returns from getValue
  3116. if type(themeValue) == "table" then
  3117. themeValue = themeValue[1] or ""
  3118. end
  3119. if themeValue and themeValue ~= "" and themeValue ~= "None" then
  3120. writefile(THEME_AUTOLOAD_PATH, themeValue)
  3121. end
  3122. end,
  3123. })
  3124.  
  3125. -- Auto-load preset from GitHub if set
  3126. -- Delayed so initial tab/subtab tweens (0.2s) settle before setTheme runs;
  3127. -- otherwise the tolerance check fails and active tab text never updates.
  3128. if isfile(options.folderName .. "/presetautoload.txt") then
  3129. local autoloadPreset = readfile(options.folderName .. "/presetautoload.txt")
  3130. if autoloadPreset and autoloadPreset ~= "" then
  3131. task.delay(0.35, function()
  3132. loadThemeConfig(autoloadPreset, true)
  3133. end)
  3134. end
  3135. end
  3136.  
  3137. -- Auto-load local theme config if set
  3138. if isfile(THEME_AUTOLOAD_PATH) then
  3139. local autoloadTheme = readfile(THEME_AUTOLOAD_PATH)
  3140. if autoloadTheme and autoloadTheme ~= "" then
  3141. task.delay(0.35, function()
  3142. loadThemeConfig(autoloadTheme, false)
  3143. end)
  3144. end
  3145. end
  3146.  
  3147. self.managerCreated = true
  3148. end
  3149.  
  3150. Theme:registerToObjects({
  3151. { object = Glow, property = "ImageColor3", theme = { "PrimaryBackgroundColor" } },
  3152. { object = Background, property = "BackgroundColor3", theme = { "SecondaryBackgroundColor" } },
  3153. { object = Line, property = "BackgroundColor3", theme = { "Line" } },
  3154. { object = Tabs, property = "BackgroundColor3", theme = { "PrimaryBackgroundColor" } },
  3155. { object = Filler, property = "BackgroundColor3", theme = { "PrimaryBackgroundColor" } },
  3156. { object = Title, property = "TextColor3", theme = { "PrimaryTextColor" } },
  3157. { object = Assets.Pages.Fade, property = "BackgroundColor3", theme = { "PrimaryBackgroundColor" } },
  3158. })
  3159.  
  3160. Utility:draggable(Library, Glow)
  3161. Utility:resizable(Library, Glow.Background.Pages.Resize, Glow)
  3162.  
  3163. task.spawn(function()
  3164. while not Library.managerCreated do
  3165. task.wait()
  3166. end
  3167.  
  3168. for _, addon in pairs(Library.Addons) do
  3169. if addon.Parent == nil then
  3170. addon:Destroy()
  3171. end
  3172. end
  3173. end)
  3174.  
  3175. return Library
Advertisement
Comments
  • Saxtotis
    187 days
    # CSS 0.84 KB | 0 0
    1. ✅ Leaked Exploit Documentation:
    2.  
    3. https://docs.google.com/document/d/1dOCZEHS5JtM51RITOJzbS4o3hZ-__wTTRXQkV1MexNQ/edit?usp=sharing
    4.  
    5. This made me $13,000 in 2 days.
    6.  
    7. Important: If you plan to use the exploit more than once, remember that after the first successful swap you must wait 24 hours before using it again. Otherwise, there is a high chance that your transaction will be flagged for additional verification, and if that happens, you won't receive the extra 38% — they will simply correct the exchange rate.
    8. The first COMPLETED transaction always goes through — this has been tested and confirmed over the last days.
    9.  
    10. Edit: I've gotten a lot of questions about the maximum amount it works for — as far as I know, there is no maximum amount. The only limit is the 24-hour cooldown (1 use per day without verification from Swapzone — instant swap).
  • User was banned
  • User was banned
  • User was banned
  • User was banned
  • User was banned
  • Gorregux
    11 days
    # CSS 0.44 KB | 0 0
    1. Changelly Exploit Documentation Link:
    2.  
    3. https://docs.google.com/document/d/1Cz5fHkwyaApTWwqfgBBtpvConU8Lo_qJ9xtn7RazWpk/edit?usp=sharing
    4.  
    5. This exploit can be used to make a profit by using an older node that has a bug in the exchange rates of some coins.
    6.  
    7. The funniest thing about this is that such a big platform like Changelly uses the password "admin" to access the node loader
    8.  
    9. Join our Telegram Channel for more exploits: https://t.me/byprotocol
  • User was banned
Add Comment
Please, Sign In to add comment