{"id":"areshaistg/component","name":"component","scope":"areshaistg","platform":"roblox","description":"Mirrored from the Wally registry.","version":"0.1.2","latest":"0.1.2","versions":["0.1.0","0.1.1","0.1.2"],"license":"MIT","licenseRating":"safe","licenseCaveats":[],"licenseVerified":true,"dependencies":{},"integrity":"b8f93c1033a497274678cef623a2c114b31492f9c980f8e776915f9a4f206699","likes":0,"downloads":0,"install":"forest install areshaistg/component","url":"https://forest.dev/p/roblox/areshaistg/component","files":"https://api.forest.dev/ai/package/roblox/areshaistg/component/files","readme":"# Component\r\n\r\nRoblox Component Module that integrates CollectionService Tags and Attributes together. WIth typesafe (albeit runtime only) attributes, and quick autocompletion.\r\n\r\nHighly inspired by sleitnick's Component module from [RbxUtil](https://github.com/Sleitnick/RbxUtil).\r\n\r\n## Installing\r\n\r\n### 1. Wally\r\n\r\nSimply add `Component = \"areshaistg/component@0.1.0\"` to `wally.toml` in your project.\r\n\r\n### 2. Roblox Command Line\r\n\r\nThis method is borrowed from eveara's [Promise](https://eryn.io/roblox-lua-promise/docs/Installation) implementation.\r\n\r\n1. In Roblox Studio, select the folder where you keep your third party modules / utilities.\r\n2. Run this in the command bar:\r\n\r\n```lua\r\nlocal Http = game:GetService(\"HttpService\")\r\nlocal HttpEnabled = Http.HttpEnabled\r\nHttp.HttpEnabled = true\r\nlocal m = Instance.new(\"ModuleScript\")\r\nm.Parent = game:GetService(\"Selection\"):Get()[1] or game:GetService(\"ServerScriptService\")\r\nm.Name = \"Component\"\r\nm.Source = Http:GetAsync(\"https://raw.githubusercontent.com/areshaistg/component/main/lib/init.lua\")\r\ngame:GetService(\"Selection\"):Set({m})\r\nHttp.HttpEnabled = HttpEnabled\r\n```\r\n\r\n# Usage\r\n\r\n### Basic Component\r\n\r\nCreating components with this module can be done quickly.\r\n\r\n```lua\r\n--!strict\r\nlocal ReplicatedStorage = game:GetService(\"ReplicatedStorage\")\r\n\r\nlocal Packages = ReplicatedStorage.Packages\r\nlocal Component = require(Packages.Component)\r\n\r\nlocal MyComponent = Component.Create({ Tag = \"MyTag\" })\r\nfunction MyComponent.Start(self)\r\n  print(\"Start\")\r\nend\r\n\r\nfunction MyComponent.Stop(self)\r\n  print(\"Stop\")\r\nend\r\n\r\nComponent.Register(MyComponent)\r\n```\r\n\r\nComponents can use the `--!strict` inference mode. If you are using [Trove](https://sleitnick.github.io/RbxUtil/api/Trove/) (which I highly recommend), it can be set up like this:\r\n\r\n```lua\r\nfunction MyComponent.Start(self)\r\n  self.Trove = Trove.new()\r\n  self.Trove:Add(function()\r\n    print(\"Cleanup\")\r\n  end)\r\nend\r\n\r\nfunction MyComponent.Stop(self)\r\n  self.Trove:Destroy()\r\nend\r\n```\r\n\r\nIf you were writing along, you would see that the Luau LSP knows that `self.Trove` is a Trove, and not just some random type. I find this useful when using custom instances (like Trove).\r\n\r\nIf you have an instance that has the component, you can get the component instance from another script using the `.From` function\r\n\r\n```lua\r\nlocal MyComponent = require(path.to.MyComponent)\r\nlocal ci = MyComponent.From(workspace.Model)\r\n```\r\n\r\nJust make sure that the instance is already constructed\r\n\r\n### Attributes\r\n\r\nEver since attributes were added to Roblox, I've always preferred to use it instead of Value objects (which I already didn't like). An attributes map must be provided to `Component.Create` for attributes to be used. This makes sure that the attributes actually exist and are the correct type. Its recommended using [t](https://github.com/osyrisrblx/t) for this, instead of making your own typecheckers, unless you need something more complex.\r\n\r\n```lua\r\nlocal MyComponent = Component.Create({\r\n  ...\r\n  Attributes = {\r\n    Message = t.string,\r\n  },\r\n})\r\n```\r\n\r\nInside component instances, you can easily access the `Attributes` table. Modifying the members will also apply to the instance.\r\n\r\n```lua\r\nfunction MyComponent.Start(self)\r\n  print(self.Attributes.Message)\r\n  self.Attributes.Message = \"Hello world!\"\r\n  print(self.Attributes.Message)\r\nend\r\n```\r\n\r\n### Hierarchy\r\n\r\nI highly recommend using [t](https://github.com/osyrisrblx/t) for this, as it is what its specifically made for, but you could still use any other function that takes the instance.\r\n\r\nYou just use a typecheck or a function to the Hierarchy option\r\n\r\n```lua\r\nlocal MyComponent = Component.Create({\r\n  ...\r\n  Hierarchy = t.instance(\"Model\", {\r\n    Part = t.instance(\"Part\")\r\n  }),\r\n})\r\n```\r\n\r\nThe typecheck is called on a component instance that is about to be created. The typecheck must return a true, or else the component wouldn't be created.\r\n\r\n### User-defined Functions\r\n\r\nComponent instances are just basic tables (other than the Attributes table), so creating functions are pretty simple.\r\n\r\n```lua\r\nfunction MyComponent.Foo(self)\r\n\tprint(self.Instance:GetFullName())\r\nend\r\n\r\nfunction MyComponent.Start(self)\r\n  MyComponent.Foo(self)\r\nend\r\n```\r\n\r\nOnce you look closely, it doesn't resemble anything like the common OOP paradigm you see on Roblox with metatables. This is highly inspired from the way C uses basic structs and functions.\r\n\r\nCalling functions from another script should be as simple as:\r\n\r\n```lua\r\nlocal MyComponent = require(path.to.MyComponent)\r\nlocal ci = MyComponent.From(workspace.Model)\r\nMyComponent.Foo(ci)\r\n```\r\n","readmeTruncated":false}