{"id":"w1nthinker/virtualized-ui","name":"virtualized-ui","scope":"w1nthinker","platform":"roblox","description":"virtualized UIGrid- and UIListLayout","version":"0.2.0","latest":"0.2.0","versions":["0.1.2","0.1.3","0.2.0"],"license":"MIT","licenseRating":"safe","licenseCaveats":[],"licenseVerified":true,"dependencies":{},"integrity":"4f832537a0467bedd31f3eb8042b8b1def25f1fa85cd4f2d7af7936d6f4b183e","likes":0,"downloads":0,"install":"forest install w1nthinker/virtualized-ui","url":"https://forest.dev/p/roblox/w1nthinker/virtualized-ui","files":"https://api.forest.dev/ai/package/roblox/w1nthinker/virtualized-ui/files","readme":"# VirtualizedUI\nvirtualized UIGrid- and UIListLayout\n\n## Installation\n\n[install with wally](https://wally.run/package/w1nthinker/virtualized-ui)\n\n[get from creator store](https://create.roblox.com/store/asset/90730916541451/VirtualizedUI)\n\n[edit showcase game](https://www.roblox.com/games/start?placeId=85879577952024&launchData=%7B%22creatorStoreAssetId%22%3A79483342482432%7D)\n\n## Example\n[play showcase game](https://www.roblox.com/games/start?placeId=85879577952024&launchData=%7B%22creatorStoreAssetId%22%3A79483342482432%7D)\n\nhttps://github.com/user-attachments/assets/0bb80816-c83c-4ea3-a037-220a2298b65f\n\nSee `example/native.luau` for a full setup, and `example/benchmark.luau` for the performance + correctness harness.\n\n## Info\nVirtualizedUI is distributed as a Wally package and as a plain Luau module.\n\nVirtual List & Grid, that have all the properties one can dream of from UIListLayout & UIGridLayout.\nWorks on every viewport size.\n\nInstall the package with Wally or copy `src/init.luau` into your game.\nCreate an issue for feedback & improvements.\n\n- made with & for the new type solver\n- fully strict typed\n- optimized & instant up to engine limits\n\n## Batching mutations\n\nEvery mutation (`AddItem`, `RemoveItem`, `SortData`, `SetLayout`, `ReloadData`) triggers one\nsynchronous update. When applying many at once, wrap them so only a single update runs:\n\n```lua\ngrid:BeginUpdates()\nfor _, item in newItems do\n\tgrid:AddItem(item)\nend\ngrid:EndUpdates() -- one update, not one per item\n```\n\n`BeginUpdates`/`EndUpdates` are reference-counted, so nesting is safe.\n\n## Data mutation contract\n\nThe grid rebinds a frame's data only when it recycles the frame or when you tell it to. If you\nmutate an item **in place** (e.g. `data[i].label = \"...\"`) without adding/removing/reloading,\ncall `Refresh()` (or `ReloadData()`) to push the change to any on-screen frame:\n\n```lua\ndata[i].label = \"updated\"\ngrid:Refresh()\n```\n\n## Performance\n\nThe visible-item update skips frames whose position and bound data can't have changed, so a scroll\nthat crosses one row rebinds only the items that actually moved instead of every visible item.\nCanvas size is only written when it actually changes. `example/benchmark.luau` is a client-side\nharness (needs `PlayerGui`) that times a scroll sweep and sub-row jitter while asserting frame\npositions, indices, and data stay correct across every mutation path:\n\n```lua\nrequire(game.ReplicatedStorage.VirtualizedUIBenchmark).run()\n-- or: run({ itemCount = 10000, steps = 300 })\n```\n","readmeTruncated":false}