{"id":"fewkz/froact","name":"froact","scope":"fewkz","platform":"roblox","description":" Wrapper around Roact & Roact Hooks to simplify UI development","version":"0.2.2","latest":"0.2.2","versions":["0.1.0","0.1.1","0.1.2","0.1.3","0.1.4","0.2.0","0.2.1","0.2.2"],"license":"MIT","licenseRating":"safe","licenseCaveats":[],"licenseVerified":true,"dependencies":{},"integrity":"8365f15e54a94ef05a4b24f14cdcf99ab491251f5033b2e9d77773e0fb107364","likes":0,"downloads":0,"install":"forest install fewkz/froact","url":"https://forest.dev/p/roblox/fewkz/froact","files":"https://api.forest.dev/ai/package/roblox/fewkz/froact/files","readme":"# froact\n\nFroact is a wrapper around [Roact](https://github.com/Roblox/roact) and\n[Roact Hooks](https://github.com/Kampfkarren/roact-hooks) to make UI development\neasier via utilies and improved types.\n\n## Adding froact\n\nYou can download the latest release of froact as a rbxm file from\nhttps://github.com/fewkz/froact/releases.\n\nFroact can be added to your project via [Wally](https://wally.run/) by adding\nthis line under dependencies.\n\n```toml\nfroact = \"fewkz/froact@0.2.0\"\n```\n\n## How to use\n\nFroact needs to be configured in order to be used:\n\n```lua\nlocal baseFroact = require(path.to.froact)\nlocal froact = baseFroact.configure({\n    Roact = Roact,\n    Hooks = Hooks.new(Roact),\n    defaultProperties = {\n        { class = \"GuiObject\", property = \"BorderSizePixel\", value = 0 }\n    },\n})\n```\n\nConfiguration is where you give froact a reference to Roact and RoactHooks. You\ncan also set default properties to be applied to all elements froact creates.\nFor a good starting config, see\n[fluf-example-game/src/FroactConfig.lua](https://github.com/fewkz/fluf-example-game/blob/main/src/FroactConfig.lua).\n\nThis configured version of froact should be used, not the base froact module.\n\n## Features\n\n`froact.c` lets you create a functional component.\n\n```lua\nlocal Timer = froact.c({ pure = true, name = \"Timer\" }, function(props, hooks)\n    local count, setCount = hooks.useState(0)\n    hooks.useEffect(function()\n        local thread = task.spawn(function()\n            while true do\n                task.wait(1)\n                setCount(function(count)\n                    return count + 1\n                end)\n            end\n        end)\n        return function()\n            task.cancel(thread)\n        end)\n    end, {})\n    return froact.TextLabel({\n        Text = \"It's been \"..count..\" seconds\"\n    })\nend)\n```\n\nThe first parameter configures the component. It supports `pure` to make the\ncomponent a `PureComponent`, which only re-renders if it's properties or state\nchange. It also supports `name` which is the name of the Roact component. Froact\nalso uses the name of the component when generating a name with `froact.list`.\n\nFroact is designed to be used by calling the component directly, rather than\nusing `Roact.createElement`. Froact is designed to give you full luau type\nchecking support this way.\n\n```lua\ntype ReverseLabelProps = { text: string, layoutOrder: number? }\nlocal ReverseLabel = froact.c({ name = \"ReverseLabel\" }, function(props: ReverseLabelProps, hooks)\n    local reversed = string.reverse(props.text)\n    return froact.TextLabel({ Text = reversed, LayoutOrder = props.layoutOrder })\nend)\nlocal element = ReverseLabel({\n    layoutOrder = \"five\" -- Luau would warn against this\n    -- Luau will warn that text was not specified\n})\n```\n\n`froact.list` takes an array of elements and returns a Roact fragment with\ngenerated keys for each element. If the `setOrder` config is enabled, it will\nset the `LayoutOrder` of elements. If an element is not an instance component,\nit will instead assign `layoutOrder` to props.\n\nIf the `orderByName` config is enabled, keys will be prefixed by a number that\ncan be sorted by a `UIListLayout` with `SortOrder.Name`. This makes the tree in\nthe explorer easier to read in studio.\n\nThe key of elements can be set to the value of a prop using the `key` config.\n\n```lua\nlocal list1 = froact.list({ setOrder = true }, {\n    froact.UIListLayout({ SortOrder = Enum.SortOrder.LayoutOrder }), -- Gets named UIListLayout\n    froact.TextLabel({ Text = \"This line is first\" }), -- Gets named TextLabel 1\n    froact.TextLabel({ Text = \"This line is second\" }), -- Gets named TextLabel 2\n    Timer({}) -- Gets named Timer, since `name` was defined on it.\n    ReverseLabel({ text = \"This line is last\" }) -- Gets named ReverseLabel, and has `layoutOrder` set.\n})\nlocal list2 = froact.list({ orderByName = true, key = \"text\" }, {\n    froact.UIListLayout({ SortOrder = Enum.SortOrder.Name }), -- Gets named UIListLayout\n    froact.TextLabel({ Text = \"First line\" }), -- Gets named 1 | First line\n    froact.TextLabel({ Text = \"Second line\" }), -- Gets named 2 | Second line\n})\n```\n\nYou can connect to the events of an instance component via the `onEventName`\nprop.\n\n```lua\nlocal element = froact.TextButton({\n    onActivated = function()\n        print(\"Button was pressed\")\n    end \n})\n```\n\nYou can connect to when a property of an instance component changes via the\n`bindPropertyName` prop. Froact only has bind props for `Text`, `TextBounds`,\nand all `Absolute...` properties. Binds for `TextBounds` and `Absolute...`\nproperties will trigger as soon as the element is mounted.\n\n```lua\nlocal element = froact.TextBox({\n    bindText = function(rbx)\n        print(\"Text was changed to\", rbx.Text)\n    end \n})\n```\n\nTo assign a ref to an element, you can use the `ref` prop\n\n```lua\nlocal ref = froact.Roact.createRef()\nlocal element = froact.TextLabel({ ref = ref })\n```\n\nFroact has support for turning template-based UI into components. This is useful\nwhen gradually porting an existing codebase to Roact, or for having legacy UI\nstill work without having to recode it.\n\n```lua\nlocal HealthBarTemplate = froact.template({ name = \"HealthBar\" }, function(name, parent, onUpdate)\n    local rbx = ReplicatedStorage.UI.HealthBar:Clone()\n    rbx.Name = name\n    rbx.Parent = parent\n    onUpdate(function(props: { percent: number })\n        rbx.Percent.Size = UDim2.fromScale(props.percent, 0)\n    end)\n    return function()\n        rbx:Destroy()\n    end\n})\n-- Can be used like an ordinary component!\nlocal element = froact.ScreenGui({}, HealthBarTemplate({ percent = 0.5 }))\nfroact.Roact.mount(element, Players.LocalPlayer.PlayerGui, \"HealthBar\")\n```\n\nTemplates do not support hooks by default, so if you want to add functionality\nyou should wrap the template in another froact component.\n\n# froact testing\n\nGenerated by [Rojo](https://github.com/rojo-rbx/rojo) 7.2.1.\n\n## Getting Started\n\nTo build the place from scratch, use:\n\n```bash\nrojo build -o \"testing.rbxl\" testing.project.json\n```\n\nNext, open `testing.rbxl` in Roblox Studio and start the Rojo server:\n\n```bash\nrojo serve testing.project.json\n```\n\nFor more help, check out [the Rojo documentation](https://rojo.space/docs).\n\n## Issues\n\nIf you run into issues where, you're creating an element like:\n`TextButton({ onActivated = function(rbx) end })`, and Luau is unable to infer\n`rbx` as `TextButton`, you may want to set the following parameters to `True`:\nhttps://github.com/fewkz/froact/blob/0b749d9a2cfb90eb03780e29f2bcbb7e587f8628/generate.py#L26-L29\nThis will fix Luau not being able to infer the parameter correctly, but may\ndrastically increase the size of `froactful.lua`, the added convenience is\ndefinitely worth it however. The distributed version of froact has these set to\n`False` by default.\n","readmeTruncated":false}