{"id":"jadonbp/ui","name":"ui","scope":"jadonbp","platform":"roblox","description":"Schema-driven UI for Roblox: pages as plain data with automatic lifecycle and cleanup, navigation, input on every platform, animation, stores and binding, theming, components, sound, viewports, and 2D particles","version":"1.2.0","latest":"1.2.0","versions":["1.0.0","1.0.1","1.0.2","1.0.3","1.1.0","1.1.1","1.1.2","1.2.0"],"license":"MIT","licenseRating":"safe","licenseCaveats":[],"licenseVerified":true,"dependencies":{},"integrity":"c483eda97c145b2e2ccc1cf7238af8a81e7df6030cef6d2c230d790c2f660d6c","likes":0,"downloads":0,"install":"forest install jadonbp/ui","url":"https://forest.dev/p/roblox/jadonbp/ui","files":"https://api.forest.dev/ai/package/roblox/jadonbp/ui/files","readme":"# UI\r\n\r\nSchema-driven UI for Roblox, written in Luau. A page is a ModuleScript that returns a plain table describing it; the library builds it, shows and hides it, and cleans up everything it set up while shown. Client-only singleton.\r\n\r\nIt covers page lifecycle and layers (pages, overlays, modals), navigation hosts with back history, input on every platform (mouse, touch, gamepad selection, drag and drop, holds, keybinds), animation and transitions, stores and two-way binding, theming on native UI Styling, components (virtualized grids and lists, tabs, sliders, toggles, progress bars, text inputs, toasts, tooltips, confirm dialogs), UI sound, viewport previews, and 2D particles.\r\n\r\n## Install\r\n\r\n```toml\r\n[dependencies]\r\nUI = \"jadonbp/ui@1.0.0\"\r\n```\r\n\r\n## Use\r\n\r\n```lua\r\n-- Client loader\r\nlocal UI = require(ReplicatedStorage.Packages.UI)\r\n\r\nUI.Configure({ Pages = ReplicatedStorage.Client.UI.Pages })\r\nUI.Initialize()\r\n\r\nUI:Show(\"Inventory\", { Tab = \"Hats\" })\r\n```\r\n\r\n```lua\r\n-- ReplicatedStorage.Client.UI.Pages.Inventory (plain data: no require of UI, no setup at load)\r\nreturn {\r\n\tFrame = function()\r\n\t\treturn Players.LocalPlayer.PlayerGui:WaitForChild(\"Main\").Inventory\r\n\tend,\r\n\tLayer = { Type = \"Page\" },\r\n\tTransition = \"Slide\",\r\n\r\n\tBehaviors = {\r\n\t\tClose = {\r\n\t\t\tOnActivated = function(page)\r\n\t\t\t\tpage:Hide()\r\n\t\t\tend,\r\n\t\t},\r\n\t},\r\n\tButtons = {\r\n\t\tClose = { Target = \"Header.Close\", Behavior = \"Close\" },\r\n\t},\r\n\r\n\tBindings = {\r\n\t\tCount = { Target = \"Header.Count\", Property = \"Text\", Store = InventoryCount },\r\n\t},\r\n\r\n\tOnShow = function(page, data)\r\n\t\t-- Everything connected here is cleaned up when the page hides\r\n\t\tpage:Observe(Coins, function(page, coins)\r\n\t\t\tpage.Frame.Header.Coins.Text = tostring(coins)\r\n\t\tend)\r\n\tend,\r\n}\r\n```\r\n\r\nConfigure is called with a dot (`UI.Configure`, `UI.Initialize`); everything else uses a colon (`UI:Show`, `UI:Hide`, `UI:Back`, `UI:Confirm`, `UI:Toast`).\r\n\r\nGlobal switches are stores: `UI.Stores.ReducedMotion:Set(true)` and `UI.Stores.UISounds:Set(false)`.\r\n\r\n## Sound\r\n\r\nA theme carries its sound set in `Values.Sounds`, referenced anywhere a sound is expected as `\"$Name\"`. A sound is an asset id or a spec:\r\n\r\n```lua\r\nSounds = {\r\n\tClick = { Id = \"rbxassetid://1\", Volume = 0.6 },\r\n\t-- Variants play in turn, one per play (round-robin)\r\n\tHover = { Ids = { \"rbxassetid://2\", \"rbxassetid://3\", \"rbxassetid://4\" }, PitchVariance = 0.03 },\r\n\tError = \"\", -- empty until the sound exists: plays nothing, reports nothing\r\n},\r\n```\r\n\r\nGive either `Id` or `Ids`, not both. `Volume`, `PlaybackSpeed`, `PitchVariance`, `MinInterval` and `Looped` apply to whichever variant plays. The throttle (`MinInterval`, 0.05 s by default) is per sound, so a slot's variants share it.\r\n\r\n## License\r\n\r\nMIT\r\n","readmeTruncated":false}