## Lightweight, highest performance BigInteger library for Luau
### AptInt is the fastest luau implementation of BigInteger, designed for working with numbers over 10,000 digits long.

# Overview
This library provides [arbitrary precision arithmetic](https://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic) capabilities implemented in just Luau. It uses a 2^24 word size to store numbers and can easily be configured to your liking.

This library provides:
- Functionality for all arithmetic operations ([`:AddRaw()` `:SubtractRaw()` `:MultiplyRaw()` `:DivideRaw()` `:PowRaw()` `:ModRaw()` `:sqrt()`](https://github.com/fosterchild1/AptInt/blob/main/docs/usage.md#arithmetic))
- Comparison functions ([`:LowerThanRaw()` `:EqualsRaw()` `:LowerOrEqualToRaw()`](https://github.com/fosterchild1/AptInt/blob/main/docs/usage.md#comparison))
- Metamethod support (`+ - * / ^ % < <= == >= =`)
- Limb-wise [Left shift and right shift](https://github.com/fosterchild1/AptInt/blob/main/docs/usage.md#other)
- Conversion functions ([`:ToString()` `:ToNumber()`](https://github.com/fosterchild1/AptInt/blob/main/docs/usage.md#conversion))
- Extra utilities such as ([`:Abs()` `:Min()` `:Max()`](https://github.com/fosterchild1/AptInt/blob/main/docs/usage.md#extensions))

The implementations are as performant as possible, so they have no safety checks, with the exception of the metamethods.

# Usage
Usage Documentation can be found [here](https://github.com/fosterchild1/AptInt/blob/main/docs/usage.md).
Algorithm choice can be found [here](https://github.com/fosterchild1/AptInt/blob/main/docs/algorithms.md).

# What makes it so fast?
AptInt uses the Karatsuba and Toom-Cook3 algorithms for multiplication, Knuths algorithm D for division, Karatsuba sqrt for finding the square root and more. Alongside these algorithms, it uses many techniques to shave off hundreds of milliseconds of computing time.

It also utilizes the full power of native code generation to get even faster results.

# Benchmarks
Note that these were done on an i7-10750H CPU. The benchmark script can be found in [/bench/](https://github.com/fosterchild1/AptInt/blob/main/bench/bench.luau).
The results are updated every time the performance gets improved. They are also generally ~1.3x faster if running on the roblox server.
For division, we do a 2NxN division. (2N = digit count)

| Digit count | Addition | Subtraction | Multiplication | Division | Square root |
| ---  | --- | --- | --- | --- | --- |
| 1 | 1μs | 1μs | 1μs | 2μs | 29μs |
| 50 | 1μs | 3μs | 4μs | 11μs | 81μs |
| 100 | 2μs | 7μs | 6μs | 24μs | 157μs |
| 500 | 5μs | 9μs | 56μs | 49μs | 311μs |
| 1,000 | 7μs | 13μs | 225μs | 153μs | 468μs |
| 5,000 | 23μs | 30μs | 2ms | 2ms | 2ms |
| 10,000 | 57μs | 74μs | 6ms | 8ms | 5ms |
| 50,000 | 209μs | 243μs | 67ms | 105ms | 67ms |
| 100,000 | 389μs | 396μs | 183ms | 195ms | 145ms |


# Nebula Icon Library 🪐
The Ultimate Icon Library For Roblox Interfaces.

![Image](https://github.com/Nebula-Softworks/Nebula-Icon-Library/blob/master/Nebula%20Icons%20Cover%20Image.png?raw=true)

## [Documentation](https://docs.nebulasoftworks.xyz/nebula-icons)


# Cerebral
**Roblox Player State Management**\
*watch my data for me?*

[About](#about) |
[Supported Platforms](#supported-platforms) |
[Use](#use) |
[Road Map](#road-map)

> [!WARNING]
> Cerebral is in its early stages and is **unstable**. **Do not use in production**

## About
**Cerebral** is a Roblox Player State Management Tool. This tool is created to make managing Player Data through the server as seemeless and error free as possible, so you can spend more time on the fun stuff rather than wondering why your *Money* is not increasing.

## Supported Platforms
**Cerebral** is currently posted on [Wally](https://www.wally.run) under `cerebrallabs/cerebral`. Roblox Store support is planned.

## Use
### Set Up
```luau
local Players = game:GetService("Players")

local Cerebral = require(--[[path to Cerebral]])

Cerebral:DefineAgentAttributes({
    "money" = Cereberal:Create("number"),
    "xp" = Cereberal:Create("number"),
    "is_admin" = Cerebral:Create("boolean"),
    "pet_name" = Cerebral:Create("string"),
})

local function PlayerAdded(player: Player)
    local agent: Cerebral.Agent
    local playerData

    agent = Cerebral:NewAgent(player)
    playerData = -- Some dataStore getter function

    Cerebral:NewAgent(player, playerData)
end

local function RemovePlayer(player: Player)
    Cerebral:RemoveAgent(player)
end

Players.PlayerAdded:Connect(PlayerAdded)
Players.PlayerRemoved:Connect(RemovePlayer)

### Use
Imagine a buy station.
```luau
local Cerebral = require(--[[path to Cerebral]])
local proximitySensor = script.--[[path to proximitySensor]]

local COST = 50

proximitySensor.Triggered:Connect(function(player: Player)
    local playerMoney = Cerebral:GetAgent(player):GetAttribute("money")
    if playerMoney:Get() >= COST then
        playerMoney:Decrement(COST)
        --[[award player whatever this proximitySensor is connected to]]
    else
        --[[notify user "NOT ENOUGH MONEY]]
    end
end)

### Road Map
In no particular order:

#### 1. Add migrations for `ds_data.data` to better allow for the transfer of data models. I want these to act similarly to how postgres migrates its databases.

For instance, if we wish to change the name of a attribute name, like `money` to `coins`, we would have the migration move the attribute to the new name upon the player joining the server.

Additionally, these migrations will (and must) be labeled cardinally. So when a player that has not logged on in a while, their data can migrate thorugh several migrations without breaking anything.

Example:
```luau
-- migration 1
Cerebral:Migrate({version = 1}, function(oldData)
    local newData = oldData
    newData.ds_data.data.coins = oldData.ds_data.data.money
    newData.ds_data.data.money = nil

    return newData
end)

NOTE: Cerebral should store migrations in the data store. Unsure how to go about this, but we want to raise all the flags if a migration is missing.

#### 2. Create more secure default modules.

Take a module that tracks `experience`. `experience` should never be able to decrease. The developer should know this, but adding additoinal protections, like:

```luau
Cerebral:DefineAttributes({
    --                            Module Type | Options
    "experience" = Cerebral:Create("number", { protected = true })
})

would be welcomed. Additionally, adding in the `options` functionality via a table supports forward thinking.


# React-Matter [![CI status][ci-badge]][ci] [![Docs status][docs-badge]][docs]

**React-Matter** is an interface between _[React]_ and _[Matter]_.

It provides access to useful hooks not included in with Matter.

[ci-badge]: https://github.com/matter-ecs/react-matter/actions/workflows/ci.yaml/badge.svg
[docs-badge]: https://github.com/matter-ecs/react-matter/actions/workflows/docs.yaml/badge.svg
[ci]: https://github.com/matter-ecs/react-matter/actions/workflows/ci.yaml
[docs]: https://matter-ecs.github.io/react-matter/
[react]: https://jsdotlua.github.io/react-lua/
[matter]: https://matter-ecs.github.io/matter/

## Installation

React-Matter can be installed with [Wally] by including it as a dependency in
your `wally.toml` file.

```toml
ReactMatter = "matter-ecs/react-matter@0.1.0"

## Building

Before building, you'll need to install all dependencies using [Wally].

You can then sync or build the project with [Rojo]. React-Matter contains
several project files with different builds of the project. The
`default.project.json` is the package build.

[rojo]: https://rojo.space/
[wally]: https://wally.run/

## Contributing

Contributions are welcome, please make a pull request! Check out our
[contribution] guide for further information.

Please read our [code of conduct] when getting involved.

[contribution]: CONTRIBUTING.md
[code of conduct]: CODE_OF_CONDUCT.md

## License

React-Matter is free software available under the MIT license. See the [license]
for details.

[license]: LICENSE.md


# React Lua¶

React Lua is a Lua port of Facebook's [React JS](https://reactjs.org) UI library.

By and large, [React's documentation](https://reactjs.org/docs/getting-started.html) should be able to serve most React Lua users' needs. This documentation site serves as a comprehensive guide to the _differences_ between Roact and React.

If you're new to the React Lua library and want **to start learning the concepts of React**, begin with the [React JS documentation](https://reactjs.org/docs/getting-started.html).

If you want **to find out if a React JS feature is present in React Lua (and if there are any differences to be aware of)**, check out the [API Reference](http://react.luau.page/api-reference/react/).

If you're familiar with React JS and want **to learn where React Lua differs**, start with the [Deviations page](http://react.luau.page/deviations/).

And if you want **to migrate an existing project from Legacy Roact to React Lua**, check out the guide on [Migrating From Legacy Roact](http://react.luau.page/migrating-from-legacy/minimum-requirements/).


# Additional Libraries¶

## ReactIs¶

_Under construction 🔨_

## ReactTestRender¶

_Under construction 🔨_

## ReactDevToolsExtensions¶

_Under construction 🔨_


# ReactRoblox¶

The ReactRoblox package is the entry point for any Roblox-opinionated logic. It can be thought of as the equivalent of the ReactDOM package in React JS.

However, rather than fully implementing all of the features of ReactDOM, it leaves most deprecated APIs out entirely, implementing only the modern and forward-looking portions of the API.

Notable absences are:

  * `render` \- Use `createRoot` (or, depending on the circumstances, `createBlockingRoot` or `createLegacyRoot`) instead
  * `unmountComponentAtNode` \- Use the `unmount` method on the root object returned from `createRoot` instead
  * `findDOMNode` \- Use [refs](https://reactjs.org/docs/refs-and-the-dom.html) instead

## `ReactRoblox.createRoot`¶

Adopted as part of the Concurrent Mode API. Refer to [`ReactDOM.createRoot` documentation](https://reactjs.org/docs/concurrent-mode-reference.html#createroot).

## `ReactRoblox.createBlockingRoot`¶

Adopted as part of the Concurrent Mode API. "Blocking" roots represent a transitional step between synchronous rendering and full concurrent rendering. Refer to [`ReactDOM.createBlockingRoot` documentation](https://reactjs.org/docs/concurrent-mode-adoption.html#migration-step-blocking-mode).

## `ReactRoblox.createLegacyRoot`¶

Adopted as part of the Concurrent Mode API. "Legacy" roots are essentially equivalent to pre-concurrent React behavior. Refer to [`ReactDOM.createLegacyRoot` documentation](https://reactjs.org/docs/concurrent-mode-adoption.html#migration-step-blocking-mode).

### Deviations¶

React documentation provides [a handy chart](https://reactjs.org/docs/concurrent-mode-adoption.html#feature-comparison) that explains the feature differences between the roots. This table lists three deprecated features under legacy roots only:

  * [String Refs](https://reactjs.org/docs/refs-and-the-dom.html#legacy-api-string-refs)
  * [Legacy Context](https://reactjs.org/docs/legacy-context.html)
  * [findDOMNode](https://reactjs.org/docs/strict-mode.html#warning-about-deprecated-finddomnode-usage)

**These features were never implemented in legacy Roact, and have not been ported.** Instead, creating a Legacy Mode root simply tells React Lua to render synchronously. This behavior is most similar to legacy Roact or pre-Concurrent-Mode React JS.

Generally speaking, `ReactRoblox.createRoot` should be used for all new work, while the Blocking and Legacy versions can be used for upgrading existing Roact logic in the event that it does not yet meet the requirements for Concurrent Mode.

## `ReactRoblox.createPortal`¶

Refer to [`ReactDOM.createPortal` documentation](https://reactjs.org/docs/portals.html).

## `ReactRoblox.act`¶

Used for testing code with scheduling logic mocked. This ensures that tests behave consistently and don't batch work unpredictably across frames. `act` executes a function and then plays forward the mock scheduler after it's done, and should be used to wrap any interactions that trigger updates to a React UI.

More info on using `act` can be found [in the migration guide](http://react.luau.page/migrating-from-legacy/adopt-new-features/#reactrobloxact).

Refer to [ReactDOM's `act` testing documentation](https://reactjs.org/docs/test-utils.html#act) for more high-level guidance.

### Deviations¶

In production, `ReactRoblox.act` will not be available. Set the global value `_G.__ROACT_17_INLINE_ACT__` to `true` in order to enable this behavior in tests.

Info

This behavior is still a work in progress, and there may be changes to how React Lua detects whether or not it should provide the `act` function. For now, use the global `__ROACT_17_INLINE_ACT__` to enable it for tests.

## `ReactRoblox.Event`¶

_Roact-only_

Re-exports [`React.Event`](http://react.luau.page/api-reference/react/#reactevent). This is only exposed for backwards compatibility; please prefer to use `React.Event`.

## `ReactRoblox.Change`¶

_Roact-only_

Re-exports [`React.Change`](http://react.luau.page/api-reference/react/#reactchange). This is only exposed for backwards compatibility; please prefer to use `React.Change`.


# RoactCompat¶

The `RoactCompat` package is designed to have the same interface as [legacy Roact](https://roblox.github.io/roact/api-reference/). This should allow easier adoption of React Lua in existing Roact code.

`RoactCompat` is fully compatible with all React Lua logic. In particular, you may wish to use `RoactCompat` in combination with the [`React`](http://react.luau.page/api-reference/react/#react) and [`ReactRoblox`](http://react.luau.page/api-reference/react-roblox/#reactroblox) packages that provide the new interface.

Caution

`RoactCompat` is **not** compatible with legacy Roact in any way. It should be used only as a drop-in replacement for legacy Roact, for the purposes of upgrading existing projects written for legacy Roact.

## `RoactCompat.Component`¶

Re-exports [React.Component](http://react.luau.page/api-reference/react/#ReactComponent).

## `RoactCompat.PureComponent`¶

Re-exports [React.PureComponent](http://react.luau.page/api-reference/react/#ReactPureComponent).

## `RoactCompat.createElement`¶

Re-exports [React.createElement](http://react.luau.page/api-reference/react/#ReactcreateElement).

## `RoactCompat.createContext`¶

Re-exports [React.createContext](http://react.luau.page/api-reference/react/#ReactcreateContext).

## `RoactCompat.createRef`¶

Re-exports [React.createRef](http://react.luau.page/api-reference/react/#ReactcreateRef).

## `RoactCompat.forwardRef`¶

Re-exports [React.forwardRef](http://react.luau.page/api-reference/react/#ReactforwardRef).

## `RoactCompat.mount`¶

    RoactCompat.mount(
        element: ReactElement,
        container: Instance?,
        name: string?
    ): RoactTree

Compatibility method mimicking [legacy `Roact.mount`](https://roblox.github.io/roact/api-reference/#roactmount).

For all intents and purposes, this should function equivalently to legacy Roact's `mount` function. Under the hood, RoactCompat takes the following steps:

  1. Creates a root using [`React.createRoot`](http://react.luau.page/api-reference/react/#reactcreateroot)
     * When `_G.__ROACT_17_COMPAT_LEGACY_ROOT__` is enabled, this will use [`React.createLegacyRoot`](http://react.luau.page/api-reference/react/#reactcreatelegacyroot) instead
  2. Calls `root:render` with the provided element
     * React's roots take complete control of the provided container, deleting all existing children. Legacy Roact does not tamper with existing children of the provided container. To mimic the legacy behavior, we use a [`Portal`](http://react.luau.page/api-reference/react/#reactcreateportal) to mount into the container instead of providing it directly to the root.
     * When `_G.__ROACT_17_INLINE_ACT__` is enabled, the `render` call is automatically wrapped in [`ReactRoblox.act`](http://react.luau.page/api-reference/react-roblox/#reactrobloxact) to ensure that mounting behavior resolves synchronously in tests.
  3. Returns an opaque handle to the root that can be used with `RoactCompat.update` and `RoactCompat.unmount`

## `RoactCompat.update`¶

    RoactCompat.update(tree: RoactTree, element: ReactElement): RoactTree

Compatibility method mimicking [legacy `Roact.update`](https://roblox.github.io/roact/api-reference/#roactupdate).

The first argument should be the value returned from a prior call to `RoactCompat.mount` or `RoactCompat.update`. This function will not work if the argument passed in was created with legacy Roact.

## `RoactCompat.unmount`¶

    RoactCompat.unmount(tree: RoactTreeHandle)

Compatibility method mimicking [legacy `Roact.unmount`](https://roblox.github.io/roact/api-reference/#roactunmount).

## `RoactCompat.createFragment`¶

    RoactCompat.createFragment(elements: { [string | number]: ReactElement }): ReactElement

Compatibility method mimicking [`Roact.createFragment`](https://roblox.github.io/roact/api-reference/#roactcreatefragment). Uses the special component [`React.Fragment`](http://react.luau.page/api-reference/react/#reactfragment) under the hood.

## `RoactCompat.oneChild`¶

    RoactCompat.oneChild(
        children: { [string | number]: ReactElement } | ReactElement | nil
    ): ReactElement

Compatibility method mimicking [`Roact.oneChild`](https://roblox.github.io/roact/api-reference/#roactonechild). This function is similar to [`React.Children.only`](http://react.luau.page/api-reference/react/#reactchildrenonly), but provides additional functionality to unwrap a table that may contain a single element.

## `RoactCompat.setGlobalConfig`¶

    RoactCompat.setGlobalConfig(configValues: { [string]: boolean })

Compatibility method mimicking [`Roact.setGlobalConfig`](https://roblox.github.io/roact/api-reference/#roactsetglobalconfig). **This does not apply to React Lua, so calling this function is a no-op.**

Info

If you need to apply global configuration to React Lua, you can do so by setting global values ([see Configuration docs](http://react.luau.page/configuration/))

## `RoactCompat.Portal`¶

Compatibility component mimicking [`Roact.Portal`](https://roblox.github.io/roact/api-reference/#roactportal). Uses the [React.createPortal](http://react.luau.page/api-reference/react/#reactcreateportal) function under the hood.

## `RoactCompat.Ref`¶

Compatibility field that mimics the special symbol key [`Roact.Ref`](https://roblox.github.io/roact/api-reference/#roactref). In RoactCompat, the `Ref` field is simply equal to the string "ref", which is a reserved prop key in React Lua.

This allows prop tables that are written for legacy Roact:

    Roact.createElement("TextLabel", {
        Text = "Hello",
        [Roact.Ref] = textLabelRef,
    })

...to be equivalent to prop tables written for React Lua, which uses "ref" as a reserved prop name:

    Roact.createElement("TextLabel", {
        Text = "Hello",
        ref = textLabelRef,
    })

## `RoactCompat.Children`¶

Compatibility field that mimics the special symbol key [`Roact.Children`](https://roblox.github.io/roact/api-reference/#roactchildren). In RoactCompat, the `Children` field is simply equal to the string "children", which is a reserved prop key in React Lua.

This allows prop tables that are written for legacy Roact:

    -- forwards the children provided to this component
    Roact.createElement("Frame", nil, self.props[Roact.Children])

...to be equivalent to prop tables written for React Lua, which uses "children" as a reserved prop name:

    -- forwards the children provided to this component
    Roact.createElement("Frame", nil, self.props.children)

Caution

This is not to be confused with [`React.Children`](http://react.luau.page/api-reference/react/#reactchildren), which is a set of utilities for transforming or interacting with sets of children passed to `createElement`.

## `RoactCompat.None`¶

Re-exports [React.None](http://react.luau.page/api-reference/react/#reactnone).

## `RoactCompat.Event`¶

Re-exports [React.Event](http://react.luau.page/api-reference/react/#reactevent).

## `RoactCompat.Change`¶

Re-exports [React.Change](http://react.luau.page/api-reference/react/#reactchange).

## `RoactCompat.createBinding`¶

Re-exports [ReactRoblox.createBinding](http://react.luau.page/api-reference/react/#reactcreatebinding).

## `RoactCompat.joinBindings`¶

Re-exports [ReactRoblox.joinBindings](http://react.luau.page/api-reference/react/#reactjoinbindings).

## `RoactCompat.act`¶

Re-exports [ReactRoblox.act](http://react.luau.page/api-reference/react-roblox/#reactrobloxact).


# React¶

Info

This page is intended to provide _brief_ descriptions, examples, and notes about deviations in behavior or API. For complete feature documentation of upstream-aligned features, follow the `View React Docs` link and consult the React JS docs.

The `React` package is the entry point for most React logic and behavior. Most of its API members align directly to their equivalents in [React JS](https://reactjs.org/docs/react-api.html). Some API members have slightly different behavior, different guidance around their usage, or slightly different function signatures to better accommodate Luau functionality and idioms.

## API Deviations¶

### Not Supported¶

The following API members are notable absences relative to React JS 17.0.1:

  * `React.createFactory` \- Considered legacy and will likely not be included
  * `React.useDebugValue` \- Not yet implemented

Additionally, the following APIs are implemented, but have blocking issues that prevent them from being fully supported or usable:

  * `React.lazy`
  * `React.Suspense`

### Undocumented¶

The `React` packages includes some features that are undocumented in React JS 17.0.1, but are present in its implementation. The following API members may be less stable than the features that are fully documented upstream:

  * `React.createMutableSource`
  * `React.useMutableSource`

### Unique to Roblox¶

`React` also exports a small collection of Lua-exclusive APIs which have no upstream equivalent. These are designed to facilitate better integration with the Luau language and the Roblox engine functionality.

  * `React.None`
  * `React.Event`
  * `React.Change`
  * `React.Tag`
  * `React.useBinding`
  * `React.createBinding`
  * `React.joinBindings`

## `React.Component`¶

[](https://beta.reactjs.org/reference/react/Component)

Luau does not have ES6's class semantics, so class components work slightly differently from React JS in the following ways:

  * Use `Component:extend` in place of ES6 class semantics
  * Implement an `init` method on components instead of a constructor

React-lua also includes the following deviations:

  * Instead of initializing component state by assigning a value to `self.state` in the `init` method, use `setState` as you would elsewhere (this is inherited from Legacy Roact for compatibility and consistency)
  * Error boundaries are not fully supported in React-lua at this time due to a limitation in recursive `pcall` depth

    local MyComponent = React.Component:extend("MyComponent")

    function MyComponent:init()
        self:setState({ expanded = true })
    end

    function MyComponent:render()
        return React.createElement("TextButton", {
            Text = if expanded
                then self.props.text
                else "Click to Expand",
            Size = if expanded
                then UDim2.new(1, 0, 0, 200)
                else UDim2.new(1, 0, 0, 30),
            [React.Event.Activated] = function()
                self:setState(function(expanded)
                    return { expanded = not expanded }
                end)
            end
        })
    end

Check the [deviations guide](http://react.luau.page/deviations/#class-components) for more detailed information.

## `React.PureComponent`¶

[](https://beta.reactjs.org/reference/react/PureComponent)

The same deviations to `React.Component` apply equivalently to `React.PureComponent`. Check the [deviations guide](http://react.luau.page/deviations/#class-components) for more detailed information.

## `React.memo`¶

[](https://beta.reactjs.org/reference/react/memo)

    local MyComponent = React.memo(function MyComponent(props)
        --[[ render using props ]]
    end)

Guidance specified in the [React documentation](https://beta.reactjs.org/reference/react/memo#usage) applies for React Lua as well. Use this only as a performance optimization, and only when relevant to the use case.

## `React.createElement`¶

[](https://beta.reactjs.org/reference/react/createElement)

While the `createElement` API is aligned to React JS, current tooling in Luau does not support an equivalent for JSX. When writing React Lua code, you'll use `createElement` directly much more often than in React JS.

    React.createElement(
        type,
        [props],
        [...children]
    )
    local element = React.createElement(
        "Frame",
        { Size = UDim2.fromScale(1, 1) },
        React.createElement("TextLabel", { Text = "Child1" })
        React.createElement("TextLabel", { Text = "Child2" })
    )

## `React.cloneElement`¶

[](https://beta.reactjs.org/reference/react/cloneElement)

Clone an existing element, using its provided config values (props, `ref`, and `key`) as a starting point.

    local onlyChild = React.Children.only(props.children)
    local cloned = React.cloneElement(onlyChild, { Text = "Cloned" })

## `React.isValidElement`¶

[](https://beta.reactjs.org/reference/react/isValidElement)

Returns `true` if the provided value is a React element; otherwise, returns `false`.

    if React.isValidElement(props.frameContents) then
        return React.createElement("Frame", { Size = UDim2.fromScale(1, 1) }, props.frameContents)
    end

## `React.Children`¶

[](https://beta.reactjs.org/reference/react/Children)

Warning

This field can often be confused with a Legacy Roact API called `Roact.Children`. In the legacy API, `Roact.Children` was a special opaque prop key that could be used to pass children through props tables. In React Lua, the `children` string key is reserved and used instead. Learn more about how to migrate away from `Roact.Children` in the [migration guide](http://react.luau.page/migrating-from-legacy/convert-legacy-conventions/#reserved-keys).

A collection of utilities for manipulating the children provided to a React component via `props.children` or `self.props.children`. The `children` property should always be used as an opaque data structure; manipulate it via `React.Children` utilities rather than accessing it directly.

There are a few notable deviations:

  * React Children values with type "userdata" will be treated as nil in callbacks. This means that a `React.None` child passed to `React.Children.forEach` or `React.Children.map` will be treated the same as a nil value or boolean in the callbacks. `React.Children.count` will not include userdata children in the count.
  * The `context` argument for mapChildren is not passed to the callback. This is typically used to pass `this` in javascript, but does not have an equivalent in Lua.
  * React Children utilities work with tables with string keys as well as arrays

### `React.Children.map`¶

[](https://beta.reactjs.org/reference/react/Children#children-map)

Use `React.Children.map` to transform each member child of the `children` property.

    local ListItem = require(script.Parent.ListItem)

    local function OrderedList(props)
        return React.createElement(
            "Frame",
            { Size = UDim2.fromScale(1, 1) },
            React.Children.map(props.children, function(child, i)
                return React.createElement(ListItem, { layoutOrder = i }, child)
            end)
        )
    end

### `React.Children.forEach`¶

[](https://beta.reactjs.org/reference/react/Children#children-foreach)

Accepts a function that will be called with each member child of the `children` property. Similar to `React.Children.map`, but the provided callback does not return a new child.

    local ListItem = require(script.Parent.ListItem)
    local Separator = require(script.Parent.Separator)

    local function SeparatorList(props)
        local listItems = {}

        React.Children.forEach(props.children, function(child, i)
            table.insert(listItems, React.createElement(ListItem, { layoutOrder = i*2 }, child))
            table.insert(listItems, React.createElement(Separator, { layoutOrder = i*2 + 1 }))
        end)

        return React.createElement(
            "Frame",
            { Size = UDim2.fromScale(1, 1) },
            listItems
        )
    end

### `React.Children.count`¶

[](https://beta.reactjs.org/reference/react/Children#children-count)

Returns the number of child members in the provided `children` object.

    local function List(props)
        print(string.format("Render list with %d children", React.Children.count(props.children)))

        return React.createElement(
            "Frame",
            { Size = UDim2.fromScale(1, 1) },
            props.children,
        )
    end

### `React.Children.only`¶

[](https://beta.reactjs.org/reference/react/Children#children-only)

Asserts that the provided object is a single React element. If the provided object is an array or table of elements, this function will throw; otherwise, it returns the element that was passed into it.

    local function Box(props)
        local element = React.Children.only(props.children)

        return React.createElement(
            "Frame",
            { Size = UDim2.fromOffset(100, 100) },
            element,
        )
    end

### `React.Children.toArray`¶

[](https://beta.reactjs.org/reference/react/Children#children-toarray)

Converts the opaque `children` prop into an array. The resulting value can then be manipulated with typical Lua array semantics or using utility methods that operate on array-like Lua tables.

    local Array = require(Packages.Collections).Array

    local function FilteredList(props)
        local children = React.Children.toArray(props.children)

        return React.createElement(
            "Frame",
            { Size = UDim2.fromScale(1, 1) },
            Array.filter(children, props.filterFn),
        )
    end

## `React.Fragment`¶

[](https://beta.reactjs.org/reference/react/Fragment)

Renders multiple components using a special component called a `Fragment`. Fragments are useful for returning multiple elements from a single component without creating additional UI elements.

    function MyComponent:render()
        return React.createElement(
            React.Fragment,
            nil,
            React.createElement("TextLabel", { Text = "Some text." }),
            React.createElement("TextButton", { Text = "Button" }),
        )
    end

## `React.createRef`¶

[](https://beta.reactjs.org/reference/react/createRef)

Creates a Ref object which can be used to access underlying Instances in the DataModel. Use this as an escape hatch when you need to interact directly with Roblox Instances (or equivalent in other environments).

    local MyComponent = React.Component:extend("MyComponent")

    function MyComponent:init()
        self.inputRef = React.createRef()
    end

    function MyComponent:render()
        return React.createElement("TextBox", { ref = self.inputRef })
    end

    function MyComponent:componentDidMount()
        self.inputRef.current:CaptureFocus()
    end

## `React.forwardRef`¶

[](https://beta.reactjs.org/reference/react/forwardRef)

In some cases, you may want your component to accept a ref and forward it to a child, typically a Roblox host component.

`React.forwardRef` accepts a render function that receives `props` (just like a function component) as well as a `ref` object, and can then assign its ref within the render callback.

    local FancyButton = React.forwardRef(function(props, ref)
        return React.createElement("TextButton", {
            ref = ref,
            Text = props.text,
            [React.Event.Activated] = props.onActivated,
        }, props.children)
    end)

    -- You can now get a ref directly to the TextButton Instance:
    local ref = React.createRef()
    React.createElement(FancyButton, { ref = ref, text = "Click me!" })

## `React.createContext`¶

[](https://beta.reactjs.org/reference/react/createContext)

Creates a Context object. Context is a mechanism for passing information through many levels of the React component tree without needing to explicitly pass it down at each level.

    local MyContext = React.createContext(defaultValue)

### `Context.Provider`¶

[](https://beta.reactjs.org/reference/react/createContext#provider)

The Context object returned from `createContext` includes a `Provider` component, which can be used to pass a context value into the component tree.

    React.createElement(MyContext.Provider, { value = someValue })

### `Context.Consumer`¶

[](https://beta.reactjs.org/reference/react/createContext#consumer)

The Context object returned from `createContext` includes a `Consumer` component, which can be used to retrieve a context value that was provided higher up in the tree.

    React.createElement(MyContext.Consumer, nil, function(value)
        -- render something based on the context value
    end)

## `React.lazy`¶

[](https://beta.reactjs.org/reference/react/lazy)

Warning

Though `React.lazy`'s functionality is implemented, it may not be especially useful without complete support for `React.Suspense`.

Warning

The `lazy` utility is designed for an ecosystem where loading modules can be expensive. **This is rarely a concern in the context of Luau projects.** Since `lazy` relies upon a dynamic call to `require`, tooling like type checking may not work correctly. Use `React.lazy` with caution and intent, and only if it has a measurable performance impact.

Wraps a component in a lazy-loading container that waits until the component is used in a render before calling the function to load it.

    local Component = React.lazy(function()
        return require(script.Parent.Component)
    end)

## `React.Suspense`¶

[](https://beta.reactjs.org/reference/react/Suspense)

Warning

**While `React.Suspense` is technically implemented, it should be considered unusable as of version `17.0.1`.** This is due to a limitation in Luau around recursive `pcall` depth. Future updates to React will unravel the recursive traversal and enable these features. Future version of React eliminate this recursive structure and should enable full use of `Suspense` and error boundaries.

Renders a subtree of children that can yield. If the children suspend while rendering, the `fallback` field provided will be used until the children have resolved their render.

    React.createElement(
        React.Suspense,
            fallback = React.createElement("TextLabel", {
                Text = "Loading...",
            })
        },
        React.createElement(SomeContents)
    )

## Hooks¶

Hooks allow simple function components to introduce stateful behaviors without incurring the overhead or complexity of the full Component lifecycle.

### `React.useState`¶

[](https://beta.reactjs.org/reference/react/useState)

`useState` is a React Hook that creates a state variable that can be used and updated by your component. Updating the state will cause the component to re-render.

    local function ClickCounter(props)
        local count, setCount = React.useState(0)

        return React.createElement("TextButton", {
            Text = string.format("Clicked %d times", count)
            -- Clicking the button updates the count, which re-renders the component
            [React.Event.Activated] = function()
                setCount(count + 1)
            end
        })
    end

Note that Luau does not have syntactic sugar for destructuring like javascript:

    const [value, setValue] = useState(0);

However, it _does_ support multiple return values, so React Lua supports a very similar usage:

    local value, setValue = useState(0)

### `React.useEffect`¶

[](https://beta.reactjs.org/reference/react/useEffect)

`useEffect` is a React Hook that causes a side effect to run after a component's render has completed, allowing synchronization with external systems.

    local UserInputService = game:GetService("UserInputService")
    local LastInputTypeChanged = UserInputService.LastInputTypeChanged

    local function LastInputLabel(props)
        local lastInput, setLastInput = React.useState(Enum.UserInputType.None)

        React.useEffect(function()
            -- Update `lastInput` state when the engine signal fires
            local connection = LastInputTypeChanged:Connect(setLastInput)

            return function()
                connection:Disconnect()
            end
        end, {})

        return React.createElement("TextLabel", {
            Text = string.format("Last input: %s", lastInput)
        })
    end

### `React.useContext`¶

[](https://beta.reactjs.org/reference/react/useContext)

`useContext` is a React Hook that allows a component to read from and subscribe to context values provided from `createContext`.

    local ThemeContext = require(...)

    local function ThemedLabel(props)
        local theme = React.useContext(ThemeContext)

        return React.createElement("TextLabel", {
            TextSize = theme.TextSize,
            TextColor3 = theme.TextColor3,
            -- ...
        })
    end

### `React.useReducer`¶

[](https://beta.reactjs.org/reference/react/useReducer)

`useReducer` is a React Hook that introduces a reducer function to your component for managing complex state. See the [`Rodux` documentation](https://roblox.github.io/rodux/introduction/reducers/) for detailed examples of the reducer pattern in Lua.

    local function reducer(state, action)
        if action.type == "add" then
            return {
                value = state.value + action.value,
                ops = state.ops + 1,
        elseif action.type == "multiply" then
            return {
                value = state.value * action.value,
                ops = state.ops + 1,
        end
    end

    local function Calculator(props)
        local state, dispatch = React.useReducer(reducer, { value = 1, ops = 0 })

        return React.createElement(React.Fragment, nil,
            React.createElement("TextLabel", {
                Text = string.format("value: %d - ops: %d", state.value, state.ops)
            })
            React.createElement("TextButton", {
                Text = "Add 4",
                [React.Event.Activated] = function()
                    dispatch({ type = "add", value = 4 })
                end
            })
            React.createElement("TextButton", {
                Text = "Multiply by 3",
                [React.Event.Activated] = function()
                    dispatch({ type = "multiply", value = 3 })
                end
            })
        )
    end

Just like the `useState` hook, we use Luau's multiple returns to approximate JavaScript's destructuring. The following JS:

    const [state, dispatch] = useReducer(reducer, initialState);

Becomes:

    local state, dispatch = useReducer(reducer, initialState)

### `React.useCallback`¶

[](https://beta.reactjs.org/reference/react/useCallback)

`useCallback` is a React Hook that allows a component to cache a function definition between re-renders.

    local ItemTile = require(...)
    local equipItem = require(...)

    local function EquippableItemTile(props)
        local onClick = React.useCallback(function()
            equipItem(props.itemId)
        end, { props.itemId })

        return React.createElement(ItemTile, {
            text = props.itemName,
            onTileClicked = onClick,
        })
    end

### `React.useMemo`¶

[](https://beta.reactjs.org/reference/react/useMemo)

`useMemo` is a React Hook that caches a computed value between re-renders.

    local function filterByCategory(todos, category)
        -- ...
        return filteredTodos
    end

    local function FilteredTodoList(props)
        local filteredTodos = React.useMemo(function()
            return filterByCategory(props.todos, props.selectedCategory)
        end, { props.todos, props.selectedCategory })

        return React.createElement(TodoList, {
            items = filteredTodos,
        })
    end

### `React.useRef`¶

[](https://beta.reactjs.org/reference/react/useRef)

`useRef` is a React Hook that stores a value that's not needed for rendering. In other words, refs are arbitrary value containers that do no invoke re-renders when they change.

Refs can be used for a variety of purposes, including assigning them to the `ref` field of an element to get a reference to the underlying Roblox `Instance`.

    local function TextBoxWithButton(props)
        local textBoxRef = React.useRef(nil)

        return React.createElement(React.Fragment, nil,
            React.createElement("TextBox", { ref = textBoxRef }),
            React.createElement("TextButton", {
                Text = "->",
                [React.Event.Activated] = function()
                    textBoxRef.current:CaptureFocus()
                end
            }),
        )
    end

### `React.useImperativeHandle`¶

[](https://beta.reactjs.org/reference/react/useImperativeHandle)

`useImperativeHandle` is a React Hook that provides a way to customize a handle that's exposed as a ref.

This allows a ref to be defined around a narrower or more convenient interface rather than a direct reference to the underlying `Instance`, and can be used to expose a customized ref interface from a function or class component.

    local ControllableScrollingFrame = React.forwardRef(function(props, ref)
        local innerRef = React.useRef(nil)

        React.useImperativeHandle(ref, function()
            return {
                scrollToTop = function()
                    innerRef.current.CanvasPosition = Vector2.new(0, 0)
                end
        end, {})

        return React.createElement("ScrollingFrame", {
            ref = innerRef
            -- ...
        })
    end)

    -- Another component will be able to access this interface via a ref:
    local function TodoListApp(props)
        local scrollingFrameRef = React.useRef(nil)

        return React.createElement(ControllableScrollingFrame,
                ref = scrollingFrameRef
            },
            React.createElement(TodoList, {
                items = props.todoItems,
            }),
            React.createElement("TextButton", {
                Text = "Back to top",
                [React.Event.Activated] = function()
                    scrollingFrameRef.current.scrollToTop()
                end
            })
        )
    end

### `React.useLayoutEffect`¶

[](https://beta.reactjs.org/reference/react/useLayoutEffect)

`useLayoutEffect` is an alternative version of `useEffect` that fires after the component runs its render function, but before the Roblox `Instance` hierarchy is reconciled with the new properties.

Caution

Use this hook sparingly. While `useEffect` runs asynchronously after a render operation is completed, `useLayoutEffect` runs _during_ an update in between rendering and reconciliation: this can introduce performance issues if used carelessly.

In React JS, `useLayoutEffect` is most often used to measure and position elements before the browser repaints them. It's not yet clear how this use case translates to Roblox usage, and this hook should be used with caution until performance is investigated in detail and best practices emerge.

### `React.useBinding`¶

A hook introduced in React Lua that creates a `Binding` object. Bindings are isolated containers that automatically update. Creates and returns a binding and its associated updater function as multiple return values, similar to `useState`.

    local function DisplaysSize(props)
        local absSize, setAbsSize = React.useBinding(Vector2.new(0, 0))
        return React.createElement(React.Fragment, nil,
            React.createElement("ImageLabel", {
                Image = props.image,
                [React.Change.AbsoluteSize] = function(rbx)
                    setAbsSize(rbx.AbsoluteSize)
                end,
            }),
            React.createElement("TextLabel", {
                Text = absSize:map(function(value)
                    return "X = " .. tostring(value.X) .. "; Y = " .. tostring(value.Y)
                end)
        )
    end

A `Binding` has the following API:

#### `getValue`¶

Warning

Using `getValue` inside a component's `render` method is likely to result in using stale values! Using the unwrapped value directly won't allow React to subscribe to a binding's updates. To guarantee that a bound value will update, use the binding itself for your prop value or use the `map` method to map the value to a new one.

Returns the internal value of the binding. This is helpful when updating a binding relative to its current value.

    local function UpdateOnClick()
        local count, setCount = React.useBinding(0)

        return React.createElement("TextButton", {
            Text = count,
            [React.Event.Activated] = function()
                setCount(count:getValue() + 1)
            end,
        })
    end

#### `map`¶

Returns a new binding that maps the existing binding's value to something else. For example, `map` can be used to transform an animation progress value like `0.4` into a property that can be consumed by a Roblox Instance like `UDim2.new(0.4, 0, 1, 0)`.

In function components, the `useBinding` hook provides equivalent functionality, and guarantees that it will return the same binding and updater objects on subsequent calls (just like `useRef` does).

    local function UpdateOnClick()
        local count, setCount = React.useBinding(0)

        return React.createElement("TextButton", {
            Text = count:map(function(value)
                return string.format("Clicked %d times", value)
            end),
            [React.Event.Activated] = function()
                setCount(count:getValue() + 1)
            end,
        })
    end

## `React.Profiler`¶

Refer to [React Profiler API documentation](https://beta.reactjs.org/reference/react/Profiler).

## `React.StrictMode`¶

Refer to [React StrictMode API documentation](https://beta.reactjs.org/reference/react/StrictMode).

## `React.createMutableSource`¶

Refer to [relevant React RFC](https://github.com/reactjs/rfcs/pull/147).

## `React.useMutableSource`¶

Refer to [relevant React RFC](https://github.com/reactjs/rfcs/pull/147).

## Roblox and Luau¶

The `React` package shipped from React Lua includes certain APIs designed specifically to account for nuances of the Luau language and to more easily leverage Roblox engine features.

These APIs are unique to React Lua and do not have equivalents in React JS.

### `React.None`¶

A placeholder value that can be used to remove fields from a table (by changing the value to nil) when merging tables. This allows state fields to be nil-able despite lua treating table fields with `nil` values as semantically equivalent to absent fields.

`React.None` can be used to remove values from React class component state via these uses:

  * When returning a table from the updater function passed to a class component's [`setState`](http://react.luau.page/api-reference/react/) method

        self:setState(function(_prevState)
            return { myStateValue = React.None }
        end)

  * When passing a table directly to a class component's `setState` method

        self:setState({ myStateValue = React.None })

  * When returning a table from a component's `getDerivedStateFromProps` implementation

        function MyComponent.getDerivedStateFromProps(props, state)
            return {
                value = if props.someCondition
                    then state.value
                    else React.None
        end

Caution

`React.None` should be used sparingly; component state fields can generally be expressed more clearly with enumerated values or reasonable defaults than with nil-able values.

Additionally, `React.None` is not intended to be used as a prop value, and may be reverted to nil by internal React logic in some cases if it's provided as one.

### `React.Event`¶

A special key that can be used to interact with [events on Roblox Instance objects](https://developer.roblox.com/en-us/api-reference/function/Instance/GetPropertyChangedSignal). Index into `React.Event` with the name of an Event that's defined for the given host Instance class in order to get a special prop key that connects to that event:

    React.createElement("ImageButton", {
        [React.Event.MouseButton1Click] = function(rbx, x, y)
            print(rbx, "clicked at position", x, y)
        end,
    })

The event connection will be automatically created when the host element is mounted and automatically disconnected when the element is unmounted.

Info

Event callbacks receive the Roblox Instance as the first parameter, followed by any parameters yielded by the event.

### `React.Change`¶

A special key that can be used to interact with the [`GetPropertyChangedSignal` method on Roblox Instance objects](https://developer.roblox.com/en-us/api-reference/function/Instance/GetPropertyChangedSignal). Index into `React.Change` with the name of the property to get a special prop key that connects to the change signal of an Instance with that property:

    React.createElement("ScrollingFrame", {
        [React.Change.CanvasPosition] = function(rbx)
            print("ScrollingFrame scrolled to", rbx.CanvasPosition)
        end,
    })

The change signal connection will be automatically created when the host element is mounted and automatically disconnected when the element is unmounted.

### `React.Tag`¶

    local button = React.createElement("TextButton", {
        [React.Tag] = "confirm-button"
        Text = "Confirm",
        -- ...
    })

A special key that can be used to apply [`CollectionService`](https://developer.roblox.com/en-us/api-reference/class/CollectionService) tags to a host component.

Multiple tags can be provided as a single space-delimited string. For example:

    [React.Tag] = "some-tag some-other-tag"

will apply "some-tag" and "some-other-tag" as `CollectionService` tags to the underlying Roblox Instance when the component is mounted.

### `React.createBinding`¶

Creates a binding object. This function can be used outside of React function components and works similarly to `useBinding`.

Use `createBinding` when you'd like to use a binding within a class component:

    local DisplaysSize = React.Component:extend("DisplaysSize")

    function DisplaysSize:init()
        self.absSize, self.setAbsSize = React.createBinding(Vector2.new(0, 0))
    end

    function DisplaysSize:render()
        return React.createElement(React.Fragment, nil,
            React.createElement("ImageLabel", {
                Image = self.props.image,
                [React.Change.AbsoluteSize] = function(rbx)
                    self.setAbsSize(rbx.AbsoluteSize)
                end,
            }),
            React.createElement("TextLabel", {
                Text = self.absSize:map(function(value)
                    return "X = " .. tostring(value.X) .. "; Y = " .. tostring(value.Y)
                end)
        )
    end

### `React.joinBindings`¶

Combines a map or array of bindings into a single binding. The new binding's value will have the same keys as the input table of bindings. Each time any of the input bindings update, the resulting binding will update as well with a new value.

This capability can be used to create a single binding value that responds to changes from several input bindings:

    local function Flex()
        local aSize, setASize = React.useBinding(Vector2.new())
        local bSize, setBSize = React.useBinding(Vector2.new())

        return React.createElement(
            "Frame",
                Size = React.joinBindings({aSize, bSize}):map(function(sizes)
                    local sum = Vector2.new()

                    for _, size in sizes do
                        sum += size
                    end

                    return UDim2.new(0, sum.X, 0, sum.Y)
                end),
            },
            React.createElement("Frame", {
                Size = UDim2.new(1, 0, 0, 30),
                [React.Change.AbsoluteSize] = function(instance)
                    setASize(instance.Size)
                end,
            }),
            React.createElement("Frame", {
                Size = UDim2.new(1, 0, 0, 30),
                Position = aSize:map(function(size)
                    return UDim2.new(0, 0, 0, size.Y)
                end),
                [React.Change.AbsoluteSize] = function(instance)
                    setBSize(instance.Size)
                end,
            })
        )
    end


A reactive state management library for Luau, inspired by Solid and Vue.

## Features

- **Concise & Declarative:** Write UI and logic that is easy to read and understand
- **Deferred Updates:** Updates are batched and processed efficiently on the next `RunService.Heartbeat`
- **Reactive Children Binding:** Dynamically manage and update child Instances based on state changes
- **Built-in Spring/Tween Support:** Easily animate state changes for smooth and engaging user experiences

## Basic Usage: Reactive Counter

This example demonstrates a simple counter button. The button's text updates automatically when the `count` state changes.

```luau
-- Assuming Flux is located in ReplicatedStorage
local Flux = require(game.ReplicatedStorage.Flux)
local new = Flux.new
local state = Flux.state

local function Counter()
    -- Create a reactive state variable initialized to 0
    local count = state(0)

    -- Create a TextButton Instance
    return new "TextButton" {
        -- The Text property is a function that depends on 'count'.
        -- Automatically updates the button's text when 'count' changes.
        Text = function()
            return "Count: " .. count
        end,

        -- When the button is activated (clicked)
        Activated = function()
            -- Update the 'count' state. Updates dependent properties (like Text).
            count(count + 1)
        end,

        -- Example of setting initial properties
        Size = UDim2.new(0, 100, 0, 30),
        Position = UDim2.new(0.5, -50, 0.5, -15),
end

-- To use this component:
-- local myCounter = Counter()
-- myCounter.Parent = someGuiElement

## Comprehensive Usage: Dynamic UI with Effects and Children

```luau
-- Assuming Flux is located in ReplicatedStorage
local Flux = require(game.ReplicatedStorage.Flux)
local new = Flux.new
local state = Flux.state
local tween = Flux.tween

-- 1. State for Tweening a Color
-- This state will smoothly transition its Color3 value.
local tweenColorState = tween(Color3.new(0, 0, 0), TweenInfo.new(1))

-- 2. State Bound to an Instance Property
-- This state reflects game.Lighting.TimeOfDay and updates when it changes.
local timeState = state(game.Lighting, "TimeOfDay")

-- 3. State for Managing Reactive Children
-- This state will hold a list of child UI elements.
local showChildren = state(false)
local dynamicChildren = Flux.compute(function()
    if showChildren() then
        return {
            new "UITextSizeConstraint" { MaxTextSize = 18 },
            new "UIPadding" { PaddingLeft = UDim.new(0, 5) },
    else
        return -- Return nothing to remove children
    end
end)

-- Create a TextLabel with various reactive bindings
local label
label = new "TextLabel" {
    Parent = script.Parent, -- Parent is assigned last for performance reasons

    -- Static properties
    AutomaticSize = Enum.AutomaticSize.XY,
    TextColor3 = Color3.new(1, 1, 1),

    -- Bind BackgroundColor3 to our tweening color state
    BackgroundColor3 = tweenColorState,

    -- Text property is computed based on timeState and showChildren
    -- It updates automatically when timeState changes
    Text = function()
        -- Conditional dependencies must retrieve value via state() to be tracked
        local conditionalText = if showChildren() then "Visible" else "Hidden"
        return `Time: {timeState} - Children: {conditionalText}`
    end,

    -- RBXScriptSignal connection for the Destroying event
    Destroying = function()
        print("Label is being destroyed!")
    end,

    -- Define children, implicitly sets LayoutOrder to the numeric index for GuiObjects
    new "UICorner" {
        CornerRadius = UDim.new(0, 8), -- Slightly rounded corners
    },

    -- Bind dynamic children
    dynamicChildren,

    -- Initialize Attributes
    [Flux.Attribute] = {
        lastUpdateTimestamp = 0, -- Initial attribute value
    },

    -- Handle Property and Attribute change events
    [Flux.Event] = {
        -- Listen to changes in the Text property
        Text = function()
            print("Label Text Changed to:", label.Text)
            -- Update an attribute reactively
            label:SetAttribute("lastUpdateTimestamp", os.time())
        end,

        -- Listen to changes in a specific attribute
        [Flux.Attribute] = {
            lastUpdateTimestamp = function()
                print("Attribute 'lastUpdateTimestamp' Changed to:", label:GetAttribute("lastUpdateTimestamp"))
            end,
        },
    },

    -- Define resources to be cleaned up when the label is destroyed
    [Flux.Clean] = {
        timeState,
    },

-- 4. State Bound to an Instance Attribute
-- This state reflects the 'lastUpdateTimestamp' attribute of the label.
local attributeState = state(label, "Attribute.lastUpdateTimestamp")
local disconnectAttributeWatcher = attributeState:Connect(function(newValue)
    print(`Attribute 'lastUpdateTimestamp' via state:Connect(): {newValue}`)
end)

-- Initial interactions
print("Initial attribute value:", attributeState()) --> 0

-- Simulate some interactions
task.wait(2)
print("--- Simulating changes ---")

-- Parent the children (triggers reactive children update and Text update)
showChildren(true)
task.wait(1)

-- Change game time (triggers timeState update, which updates label.Text)
game.Lighting.ClockTime = 12
task.wait(1)

-- Start the color tween
tweenColorState(Color3.fromRGB(0, 128, 255)) -- Tween to a blue color
task.wait(2)

-- Deparent the children
showChildren(false)
task.wait(1)

-- Manually change an attribute (triggers attributeState and Flux.Event.Attribute.lastUpdateTimestamp)
label:SetAttribute("lastUpdateTimestamp", os.time() + 100)

task.wait(1)
-- label:Destroy() -- This would trigger Flux.Clean and the Destroying event

## Core Concepts

A brief look into how Flux achieves its reactivity.

- **Reactive States (`Flux.state`):**
  - These are the foundation. When you create a state, Flux wraps your value in an object that can track dependencies and dependents.
  - When you get a state's value (`myState()`), Flux registers this access if it happens within a reactive context (like a `Flux.compute` function or a property function).
  - When you set a state's value (`myState(newValue)`), Flux notifies all its dependents that they need to update.

- **Computed States (`Flux.compute`):**
  - Functions that depend on one or more states are re-evaluated automatically when those states change.
  - `Flux.compute` creates an explicit reactive computation.
  - Property functions (e.g., `Text = function() return "Name: " .. nameState end`) in `Flux.new` or `Flux.edit` implicitly create computations. Flux detects which states are accessed within these functions and subscribes to their changes.

- **Deferred Updates:**
  - By default (`Flux.deferUpdates(true)`), when a state changes, it doesn't immediately trigger updates down the chain. Instead, it schedules the update for the next `RunService.Heartbeat` event.
  - This batching mechanism is crucial for performance. If multiple states change in the same frame, UI elements and computations are only re-evaluated once with the latest values, preventing redundant work and layout thrashing.

- **Reactive Children Management:**
  - When you assign a state to a numeric index (e.g., `[1] = childrenState`) in `Flux.new` or `Flux.edit`, Flux monitors this state.
  - If `childrenState`'s value changes to an Instance, that Instance becomes a child.
  - If it changes to an array of Instances, those Instances become children.
  - If it changes to `nil` or an empty array, the previously managed children are removed.
  - This allows for dynamic lists of UI elements that respond to your application's state.

- **Automatic Cleanup:**
  - The `Flux.Clean` symbol provides a declarative way to manage the lifecycle of states, connections, or other Instances tied to a specific UI component.
  - When the component Instance is destroyed, everything listed in its `Flux.Clean` table is also cleaned up (states are destroyed, connections disconnected, etc.), preventing memory leaks.

## API Overview

Flux provides a concise API for managing state and creating reactive UIs.

### Core Functions

```luau
Flux.state(initialValue: T? | Instance? | State<T>?, propertyName: string?): State<T>

- Creates a new reactive state.
- If `initialValue` is an `Instance` and `propertyName` is provided, it binds the state to the Instance's property. If `propertyName` starts with `"Attribute."` (e.g., `"Attribute.MyCustomAttribute"`), it binds to the specified Instance attribute.
- Examples: `state(workspace, "Gravity")`, `state(myInstance, "Attribute.Value")`.
- Calling `state()` (e.g., `myState()`) gets the current value.
- Calling `state(newValue)` (e.g., `myState(10)`) sets the value and triggers updates.

```luau
Flux.compute<T>(computation: () -> T): State<T>

- Creates a derived state whose value is computed by the given function.
- Automatically tracks dependencies on other states used within the computation.
- The computation re-runs automatically when any of its dependencies change.

```luau
Flux.tween<T>(state: T | State<T> | Function, tweenInfo: Stateful<TweenInfo>): State<T>

- Applies a tween to a state. When the state's value is set, it will tween to the new value using the provided `TweenInfo`.
- Can take a raw value, existing state, or a computation function directly.

```luau
Flux.new(className: string): (properties: table) -> Instance

- A factory function for creating Roblox Instances with reactive property bindings.
- Example: `local frame = Flux.new "Frame" { Size = state(UDim2.new(0,100,0,100)) }`

```luau
Flux.edit(instance: Instance, properties: table): Instance

- Applies reactive property bindings to an existing Roblox Instance.

```luau
Flux.deferUpdates(shouldDefer: boolean)

- Controls whether state updates should be deferred to the next `RunService.Heartbeat`.
- Pass `true` (default) to defer updates, improving performance by batching changes.
- Pass `false` for immediate updates (can be less performant for many rapid changes).

```luau
Flux.isState(object: any): boolean

- Returns `true` if the given object is a Flux state, `false` otherwise.

```luau
Flux.raw(object: any): any

- Returns the raw underlying value of a state, or the object itself if it's not a state.

```luau
Flux.rawVariadic(...: any): ...any

- Returns the raw underlying values for multiple arguments.

### Special Symbols for `Flux.new` and `Flux.edit`

When defining properties in `Flux.new` or `Flux.edit`:

```luau
[Flux.Attribute] = { attributeName = valueOrState, ... }

- Defines or binds Instance attributes.

```luau
[Flux.Event] = { eventName = callback, [Flux.Attribute] = { attributeName = callback } }

- Connects to Instance events (e.g., `Activated`, `TextChanged`) or property/attribute change signals.

```luau
[Flux.Clean] = { stateToClean, connectionToDisconnect, instanceToDestroy, ... }

- An array of resources that will be cleaned up (e.g., states destroyed, connections disconnected, instances destroyed) when the primary Instance created/edited is destroyed.

### State Object Methods

```luau
state:Connect(callback: (newValue: T) -> ()) -> Function

- Registers a callback function that fires whenever the state's value changes.
- Returns a `disconnect` function to stop listening.

```luau
state:Destroy()

- Manually cleans up the state, removing its bindings and connections. This is often handled automatically by `Flux.Clean`.


# Hydrogen

## A Framework for Roblox designed to handle things that you would rather not.

## WARNING: Hey There! Please note that Hydrogen is NOT finished and contains MANY issues and no official documentation

## These will come with due time after the project has been battle-tested, however feel free to use Hydrogen if you figure it out!

## Install

### With wally

```toml
    hydrogen = "teamhydrogen/hydrogen@0.2.6"

### With pesde

```sh
pesde add teamhydrogen/hydrogen
pesde install

### In File

pesde.toml:

```toml
[dependencies]
hydrogen = { name = "teamhydrogen/hydrogen", version = "^0.2.6"}

## Usage:

These documents will be very brief as it is just a readme

```lua
Hydrogen.Start(Config: {
    ModuleDirectory: any,
    ModuleSuffix: string?,
    RunLifecycles: boolean? | { "PlayerAdded" | "PlayerRemoving" | "CharacterAdded" | "Heartbeat" | "RenderStepped" }?,
})

ModuleDirectory: Where your modules are stored on Server and Client
ModuleSuffix: What your modules end in, Defaults to "Handler"
RunLifecycles: True for all, select what you can use automatically as a function without needing extra connections

This will load your modules and other Hydrogen aspects like lifecycles and sound, Players will need to be sorted yourself.

## Lifecycles

Lifecycles set in Hydrogen.Start can be ran with the following

```lua
local Module = {}

function Module.CONNECTION(Args)
end

return Module

For example:

```lua
local Module = {}

function Module.PlayerAdded(Player: Player)
end

return Module

This will run every time a player is added

## PlayerHandler

This handles player data and saving, being a wrapper for [ProfileStore](https://devforum.roblox.com/t/profilestore-save-your-player-data-easy-datastore-module/3190543) allowing you to set, get and even handle custom functions when data is updated

This will go more in-depth in the real documentation, however for a README I want to keep it short.

The basics are that you set data with

```lua
PlayerHandler:SetPlayerData(Player, {DATA})

Data is a table with a key and what you want to set the key to

```lua
PlayerHandler:SetPlayerData(Player, {Coins = 300}) -- Sets coins to 300

Note: You can also run :expect() at the end of SetPlayerData to return the new data that has been set.

You get data with

```lua
PlayerHandler:GetPlayerData(Player):expect() -- Returns a promise, expect being most likely what you would want

## SoundHandler

Plays sounds on Server and/or Client, tries to make sounds completely handled by Client.


# CuteSignal

CuteSignal is a lightweight, fast signal module built for Roblox Luau.

## Documentation

- Docs home: https://00202210.github.io/CuteSignal/
- API reference: https://00202210.github.io/CuteSignal/classes/signal
- Performance notes: https://00202210.github.io/CuteSignal/guide/performance

## Source

- Module file: `CuteSignal.luau`


# ClassicHeadConversion

* ClassicHeadConversion tries to convert roblox dynamic heads to their classic face and head counterparts.
* Head to the example [script](/example.server.luau) for an example on how to use it!
> This was originally made for my game [Super Sonic Robloxia Adventure](https://www.roblox.com/games/10417853509/Super-Sonic-Robloxia-Adventure/) as it is a Classic Roblox styled Sonic fan game and it uses Roblox's classic face system to change the face of a player via a decal in the player's head

> [!IMPORTANT]
> This project is pretty much now obsolete because of Dogutsune's [Facial Unification](https://github.com/Dawgra/Facial-Unification/releases) module, which doesnt require HttpsService and does a much better job then my system.
>Keep in mind my version doesnt change the head shape, it did in the legacy version, i'll maybe make a modified version of the legacy one with httpsservice support.
> You need to enable Allow HTTP Requests in File > Experience Settings > Security

> [!WARNING]
> The model on the roblox asset store is legacy and won't be updated, you can only grab it from here.
> You can either clone this repository, or grab an .rbxm file from the latest [release](https://github.com/Conikku/ClassicHeadConversion/releases/latest) instead

> [!NOTE]
> There is a legacy version of this repository listed within the [legacy](/legacy) directory, however it is not advised to use this version as it is no longer supported/maintained. It also uses `require` with a number... which is not good design.

## Contribution

Want to contribute? Send a pull request if there are any bugs!

### Plugin to help contribute:

To contribute to the list of faces in the [json](/Faces.json) file, you can get the DynamicToClassic plugin to help!
You can get the DynamicToClassic Devtool Plugin [here](https://create.roblox.com/marketplace/asset/15407420885/DynamicToClassicHead-Devtool).


### About Me

Heya! The name's Conikku! I'm a developer with a passion for creating games, websites, and open-source tools! Welcome to my personal corner of the internet where I showcase my work and share my interests!

I am 21 years old and I am a pansexualPansexuality is a sexual orientation where a person feels attraction to others regardless of their gender or sex. Pansexual individuals are often described as being attracted to people based on personality, connection, or other traits rather than gender identity. furry who's genderfluid Genderfluid describes someone whose gender identity changes over time, shifting between different genders or expressions. It falls under the broader genderqueer or nonbinary umbrella, which includes identities that don't fit strictly into male or female categories. I am under the umbrella "Gender nonconforming": Refers to people whose appearance, behavior, or interests don't align with traditional expectations for their assigned gender. It's about expressing oneself in ways that don't fit typical male or female norms, without necessarily relating to a specific gender identity. and a **ambivert** Ambivert refers to someone who has a balance of introvert and extrovert traits. They can enjoy socializing but also need alone time to recharge, depending on their mood or situation. Introvert describes someone who feels most energized by spending time alone or in calm environments. They often prefer deep conversations over large social gatherings and may need quiet time to recharge. Extrovert describes someone who gains energy from being around others and engaging in social activities. They often enjoy group settings, talking, and staying active with people. so I mostly prefer quiet moments, but I sometimes can be too energetic, but I still like spending time with others no matter how quiet or loud (well for the latter- sometimes not...). I am (biologically) a male and my pronouns are he/him and I have AuADHD AuADHD refers to individuals who are both autistic and have ADHD, meaning they experience traits from both conditions. The combination can create unique strengths and challenges, such as intense focus on interests alongside difficulties with attention, routine, or sensory processing. Autism is a neurodevelopmental condition that affects how a person experiences social interaction, communication, and sensory input, often leading to unique patterns of thinking and behavior. It exists on a spectrum, meaning each autistic person's abilities and challenges can vary widely. ADHD (Attention-Deficit/Hyperactivity Disorder) is a neurodevelopmental disorder that impacts attention, impulse control, and activity levels. People with ADHD may have difficulty focusing, sitting still, or managing time, but often show high creativity and energy. and **Fragile X Syndrome**Fragile X Syndrome is a genetic disorder caused by a mutation in the FMR1 gene on the X chromosome, leading to a lack of the FMRP protein needed for normal brain development. It often results in intellectual disability, developmental delays, and behavioral or learning challenges..

I've been game developing since 2016, starting with Scratch and Roblox, I don't use scratch no more but I still make games on Roblox! I've always been invested in early internet culture, I was even there for a bit of it since I've been using the web since I was just 4 years old. I've always been intrested in anthro animals ever since I was 4. I've always loved designing furry ocs on games, especially Roblox. I started playing Roblox in 2012, and I'm still playing to this day!

### Hobbies

  * Game Development (Roblox/LuaU, Godot)
  * Web Development (still learning)
  * Character Design (and sometimes art)
  * UI, Sound, and Level Design
  * Playing games
  * Video Editing and Graphic Design
  * 3D Animation and Rendering

### Fave Media, Games & Interests

  * Media: Sonic the Hedgehog (series), Femtanyl, Pokemon,
  * Games: Roblox (see interests for Roblox games), Fortnite (mainly Save the World), GMod, Tower Unite, Skate., Minecraft, Sonic Generations, Sonic X Shadow Generations, Tower Unite
  * Interests: Nico's Nextbots, Regretevator, Disaster games (NDS, UDS, SEWH), Social games

### TIME & COUNTDOWNS

#### Countdown to my Birthday (Oct 1st)

🎉 IT'S MY BIRTHDAY! 🎉

Click to Celebrate!

#### How long I've been alive

### Favorite Music Artists

Click an image to play a sample!

Michael Jackson

Favorite: Off the Wall

Femtanyl

Favorite: WORLDWID3

Linkin Park

Favorite: BURN IT DOWN

Green Day

Favorite: Basket Case

nicopatty

Favorite: shop

Saint Pepsi

Favorite: Enjoy Yourself

coldrain

Favorite: Bloody Power Fame

Ken Ashcorp

Favorite: On the Rocks

Frizk

Favorite: not asking 4 much

Hydraa

Favorite: Rocksteady

Fearofdark

Favorite: Surfing on a Sine Wave

Inbirth

Favorite: Sweet Tooth

nelward

Favorite: Sleepwalk

Jane Remover

Favorite: Dancing with your eyes...

MAN WITH A MISSION

Favorite: Remember Me

ONE OK ROCK

Favorite: Vandalize

### Character Hyperfixations

Click an image to learn more!

Tails

Sonic the Hedgehog

[](https://sonic.fandom.com/wiki/Miles_%22Tails%22_Prower)

Tails Doll

Sonic R

[](https://sonic.fandom.com/wiki/Tails_Doll)

Taokaka

Blazblue

[](https://blazblue.wiki/wiki/Taokaka)

Raven Team Leader

Fortnite

[](https://fortnite.fandom.com/wiki/Raven_Team_Leader)

Camille

Fortnite

[](https://fortnite.fandom.com/wiki/Camille)

Kimiko Five-Tails

Fortnite

[](https://fortnite.fandom.com/wiki/Kimiko_Five-Tails)

Meow Skulls

Fortnite

[](https://fortnite.fandom.com/wiki/Meow_Skulls)

Token

Femtanyl

[](https://femtanyl.fandom.com/wiki/Token)

Zeraora

Pokémon

[](https://pokemon.fandom.com/wiki/Zeraora)

Nyan Cat

Christopher Torres

[](https://en.wikipedia.org/wiki/Nyan_Cat)

Noob

Roblox

[](https://roblox.fandom.com/wiki/Noob)

BillyBloxxer (Guest)

Roblox

[](https://roblox.fandom.com/wiki/Guest)

1x1x1x1

Roblox

[](https://roblox.fandom.com/wiki/Player:1x1x1x1)

Gnarpy

Regretevator (Roblox)

[](https://regretevator.fandom.com/wiki/Gnarpy)

### FAQ

#### What was the inspiration for this site?

When I first brought conikku.com, I brought it off google sites (now defunct) so I had to use the website builder, I made the site black and white (like it is now), I liked it so when I started remaking this site with actual HTML I kept the theming but added onto it by adding some animations and more stuff like the about me and the open/collapse elements for my favorite music artists and such.

#### What got you into learning HTML?

Originally before I started working on remaking conikku.com, I wanted to make a website that estimated how much VBucks you can grind from Fortnite save the world to get a item before it left the shop. I decided to learn HTML and CSS to make it with the help of w3schools and youtube tutorials. I am still learning but it's helped me a lot to understand. I also learned a bit of javascript (yes I know... some people don't like it but I honestly think php is harder) to have some of the elements of this site work (for example: the ability to use the scroll wheel to scroll the page of buttons on the bottom of the screen and the music player).

#### Do you have any pets?

Yes! I have a cat and her name is **Mow Mow** (pronounced Meow Meow). She loves me to death, she'll follow me everywhere I go and usually stays in my room when I'm here. She also has a sister that just roams the house. We were originally only going to adopt her sister but the shelter told us that they were bonded so we got both, but then her sister (my cat) just became bonded with me and they barely interact now, they still sometimes play with each other at times, but it's rare.

#### When did you learn Luau?

I honestly think I still am a beginner and still learning, But I Have made some pretty optimized and modular code that I'm still proud of. I sometimes suck at OOP (Object Orientated Programming), but I think I still do a pretty good job with it, which is why there's a few games I've worked on, most of the time I only work on games I come up with myself. If you want to learn Roblox Development i'd recommend looking at the docs roblox provides, and for advanced scripting i'd recommend watching BrawlDev's Advanced Scripting Tutorial Guide Series.

#### What's your favorite food?

It's kinda a hard question since I'll eat almost anything, but i'd say a comfort food of mines is probably mac and cheese! A good classic!

#### Why do you usually have a DNI for the roblox sonic community on most of your socials?

It's because... well quite simply... I just don't like how toxic the community is. I was once like this, but then a certain Roblox Sonic community gave me a reality check, and changed how I handle drama, which is to never take sides. Before I react, I try to get both sides of the story, and even then I still chose not to side with anyone, it's honestly made me a much better person and has helped me not get into drama with others as often as I used to. Also I want to give a shoutout to bear2126 for being a very good role model of mines, he also helped me improve as a person for the same reason as avoiding getting into drama as much as possible. He's really like the only person from that community I respect. I still make sonic games on roblox, but I distance myself away from the community as much as possible.

### SOCIALS

[ ](https://bsky.app/profile/conikku.com) [ ](https://github.com/Conikku) [ ](https://namemc.com/profile/Conikku.1) [ ](https://www.roblox.com/users/155829351/profile) [ ](https://x.com/Conikku) [ ](https://www.youtube.com/@Conikku)

[ PORTFOLIO ](https://www.conikku.com/portfolio.html) [ GUESTBOOK ](https://conikku.atabook.org/) [ STRAWPAGE ](https://conikku.straw.page)

#### My website button

<

Copy Code

[](https://tokenpaws.conikku.com) [](https://femtanyl03.neocities.org) [ ](https://cobalt.tools "save what you love") [](https://vert.sh "the file converter you'll love") [](https://catcut.snaz.in "in-browser media editing") [](https://bitwarden.com) [](https://send.cyberjake.xyz "simple, private file sharing") [](https://wikipedia.com) [](https://nekoweb.org/) [](https://cyber.dabamos.de/88x31/) [](https://www.w3schools.com/html/default.asp) [](https://frutigeraeroarchive.org/) [](https://bigrat.monster/) [](https://crouton.net/)


# **Modula**
Modula is a strictly typed, lightweight, and Promise driven module loader for Roblox. It automatically requires all ModuleScripts from a directory or a table, then executes their lifecycle methods (e.g. Init, OnStart) in order. Modula ensures that every Init Promise resolves before any OnStart method runs providing a clean, predictable, and fully asynchronous startup for your entire system.

## Features

- **Bulk Loading**: Load entire folders or tables of modules in one call.
- **Selective Filtering**: Load only specific modules by matching name patterns.
- **Custom Lifecycle Names**: Redefine lifecycle method names (e.g. use "Initialize" and "StartUp" instead of "Init" and "OnStart") to match your project’s naming conventions.
- **Composable Callbacks**: Implement additional logic with :andThen() allowing for staged or conditional startup sequences once all modules are finished loading.
- **Priority Loading**: Assign an Optional Priority value to modules to control execution order (higher number = earlier load).

> [!CAUTION]
> When passing a directory, you must specify a Depth option in your config table ("Children" or "Descendants"). If you pass a table of ModuleScripts instead the Depth option is not required.

## Name Filtering

```lua
-- Load all modules that end with “Service”
MatchName = "Service$"

-- Load all modules that start with “UI”
MatchName = "^UI"

-- Load all modules that contain “Controller”
MatchName = "Controller"

-- Load only exact “Inventory” module
MatchName = "^Inventory$"

## Usage Example

Basic Usage
```lua
local Modula = require(path.to.Modula)

-- Load all modules ending with "Service" from the Services directory
Modula:Load(ScriptService.Source.Services, {
    Depth = "Descendants",
    MatchName = "Service$"
})

Using a Callback

```lua
local LoadedServices = Modula:Load(ScriptService.Source.Services, {
    Depth = "Descendants",
    MatchName = "Service$"
})

LoadedService:andThen(function(Services)
    warn("[Server]: Loaded Services ", Services)
end):catch(warn)

By default, Modula looks for lifecycle methods named Init and OnStart but you can override these in the config if your project uses different names.

```lua
Modula:Load(ScriptService.Source.Services, {
    Depth = "Descendants",
    MatchName = "Service$",
    InitName = "Setup",       -- // Custom initialization method name
    StartName = "Begin"       -- // Custom startup method name
})

Loading from a Table of Modules

```lua
local ModulesToLoad = {
    ScriptService.Source.Services.Main.DataService,
    ScriptService.Source.Services.Main.OtherService,

Modula:Load(ModulesToLoad, {
    InitName = "Setup",
    StartName = "Begin"
})

> [!Note]
> Each modules lifecycle runs concurrently through Promises but the execution model remains single threaded.

## Module Example

```lua
local Promise = require(pathtopromise)

local OtherService = {}
OtherService.Priority = 3 -- // Optional Priority (Default is 1)

function OtherService.Init()
    print("INITIALISED OTHER SERVICE")

    return Promise.delay(3):andThen(function() -- // Optional but useful for Services that might take some time to initialise (e.g Data or PlayerServices)
        print("OTHER SERVICE INIT COMPLETE")
    end)
end

function OtherService.OnStart()
    print("STARTED OTHER SERVICE")
end

return OtherService

> [!Tip]
> Modules are not required to implement every lifecycle method. A module may define only Init, only OnStart or neither. This is especially useful for lightweight or component-style modules that do not require explicit initialization or startup logic.

## Installation
You can download the latest version from the [Releases](https://github.com/Levnth/Modula/releases) page.
Alternatively, if you use Wally you can find wally.toml name on the latest release.

For any problems, Contact me on Discord (@oglev) or open a new issue.


# catboygirl maid

The fastest, and simplest maid out there for luau & roblox.

```luau
local RunService = game:GetService("RunService")
local maid = require("@maid")

local garbage = {}

maid.insert(garbage, RunService.PostSimulation:Connect(function()
    print("meow :3")
end))

print(typeof(maid[1])) --> "RBXScriptConnection"

maid.clear(garbage)
print(maid[1]) --> nil

local part_maid = maid.create()
local decal = Instance.new("Decal")
local part = Instance.new("Part")
local has_destroyed_part = false

part.Destroying:Connect(function()
    has_destroyed_part = true
end)

part_maid:insert(part)
part_maid:insert(decal)

print(part_maid.values[1]) --> Part
print(part_maid.values[2]) --> Decal

maid:remove(part)

print(part_maid.values[1]) --> Decal
print(part_maid.values[2]) --> nil
print(has_destroyed_part) --> true


# Radio System

  [&labelColor=302d41&style=for-the-badge)](https://discord.gg/Eb384Xw)
  [&labelColor=302d41&style=for-the-badge)](https://mit-license.org/)
  [&labelColor=302d41&style=for-the-badge)](https://github.com/Redon-Tech/radio-system/releases)
  [&labelColor=302d41&style=for-the-badge)](https://github.com/Redon-Tech/radio-system/commits/main)

# Overview

A radio system made by Redon Tech that is highly custamizable and easy to setup, featuring both text and voice communications allowing for less travel between services in order to communicate effectively.

# Features

- Channels
- Voice Communications
- Highly Customizable
- API

# Planned Features

- Audio API

# Installation
Read the [Setup Guide](https://radio.redon.tech/setup/) for more information.

# Documentation
[Visit the official documentation](https://radio.redon.tech/)

# Developer

## ToDo

| Status   | Name           | Description                                         |
| -------- | -------------- | --------------------------------------------------- |
| Complete | UI Design/Code | The UI for the radio system.                        |
| Complete | Chat           | Chat                                                |
| Complete | Voice          | Voice                                               |
| Complete | API            | API to send chat messages to the radio from scripts |


# Client Wrapper

Please take a note of where your client API wrapper is located, this guide will assume that the wrapper is in ReplicatedStorage.

## Setting Up

Setting up is pretty simple. Just require the script and call `.init()`.

  1. Create a `LocalScript` in `StaterGui` or in `StaterPlayer`
  2. Paste the following code:

         local ReplicatedStorage = game:GetService("ReplicatedStorage")
         local clientAPI = require(ReplicatedStorage:WaitForChild("Radio System Client API")).init()

  3. Hit 'Play', check for any errors.

It Errors

  1. Try debugging it yourself.
  2. If you can not figure out why, feel free to create a support thread.
  3. Remember, be patient, and please understand that the API is meant to be used by those who know how to program.

## API Reference

### cleanup

**The most important function of them all** Call this function once you are done with the API, it will clean up all connections for you.

    () -> nil

#### Example Usage

    clientAPI:cleanup()

### ScriptConnection

Our version of a `RBXMScriptConnection`, it just provides a way to disconnect from a function.

#### Methods

  * `disconnect()` \- Disconnects the function

#### Example Usage

    local connection = ...
    task.wait(10)
    connection:disconnect()

### clientMessageRecieved

Calls the function whenever we receieve a message from another player or we sent a message.

    (
        func: (channelId: number, player: Player, message: string) -> nil
    ) -> ScriptConnection

#### Parameters

  * `func: (channelId: number, player: Player, message: string) -> nil` \- a function that accepts a number, Player, and string as its parameters and returns nil.

#### Example Usage

    local connection = clientAPI:clientMessageRecieved(function(channelId: number, player: Player, message: string)
        print(channelId, player, message)
    end)

    task.wait(10)

    connection:disconnect()

### systemMessageRecieved

Calls the function whenever we receieve a message from the system which is usually called by the server API.

    (
        func: (channelId: number, message: {
            text: string,
            headerText: string?,
            backgroundColor3: Color3?,
            icon: string?,
            iconColor3: Color3?,
            iconRounded: boolean?,
            sideText: string?,
            sideAccent: Color3?,
        }) -> nil
    ) -> ScriptConnection

#### Parameters

  * `func: (channelId: number, message: ...) -> nil` \- a function that accepts a number and message as its parameters and returns nil.

#### Example Usage

    clientAPI:systemMessageRecieved(function(channelId: number, message: {...any})
        print(channelId, message)
    end)

### panicButtonActivated

Calls the function whenever we recieve a panic button activation.

`channelId` is true if the panic button was activated on all channels.

    (
        func: (channelId: number | boolean, player: Player, message: string) -> nil
    ) -> ScriptConnection

#### Parameters

  * `func: (channelId: number | boolean, player: Player, message: string) -> nil` \- a function that accepts a number or boolean, player, and message as its parameters and returns nil.

#### Example Usage

    clientAPI:panicButtonActivated(function(channelId: number | boolean, player: Player, message: string)
        if channelId == true then
            print("Panic Button Activated on all channels")
        else
            print(channelId, player, message)
        end
    end)

### messageHistoryRecieved

Calls the function whenever we recieve a channels history, usually calls whenver the player recieves the GUI.

    (
        func: (channelId: number, history: {}) -> nil
    ) -> ScriptConnection

#### Parameters

  * `func: (channelId: number, history: {}) -> nil` \- a function that accepts a number and table as its parameters and returns nil.

#### Example Usage

    clientAPI:clientMessageRecieved(function(channelId: number, history: {...any})
        print(channelId, history)
    end)

### voiceRecieve

Calls the function whenever any player (including the local player) starts to send voice communications.

    (
        func: (channelId: number, player: Player) -> nil
    ) -> ScriptConnection

#### Parameters

  * `func: (channelId: number, player: Player) -> nil` \- a function that accepts a number and Player as its parameters and returns nil.

#### Example Usage

    clientAPI:clientMessageRecieved(function(channelId: number, player: Player)
        print(channelId, player)
    end)

### textActivateChanged

Calls the function whenever we the player activated or deactivated the text chat.

    (
        func: (active: boolean) -> nil
    ) -> ScriptConnection

#### Parameters

  * `func: (active: boolean) -> nil` \- a function that accepts a boolean as its parameters and returns nil.

#### Example Usage

    clientAPI:clientMessageRecieved(function(active: boolean)
        print(active)
    end)

### voiceActivateChanged

Calls the function whenever we the player activated or deactivated the voice chat.

    (
        func: (active: boolean) -> nil
    ) -> ScriptConnection

#### Parameters

  * `func: (active: boolean) -> nil` \- a function that accepts a boolean as its parameters and returns nil.

#### Example Usage

    clientAPI:clientMessageRecieved(function(active: boolean)
        print(active)
    end)

### getEnabled

Returns wether or not the radio is currently enabled

    (): boolean

#### Example Usage

    print(clientAPI:getEnabled())

### setEnabled

Tells the radio to disable or enable

    (
        enabled: boolean
    ) -> nil

#### Parameters

  * `enabled: boolean` \- a true or false.

#### Example Usage

    clientAPI:setEnabled(false)

Back to top


# Server Wrapper

Please take a note of where your server API wrapper is located, this guide will assume that the wrapper is in ServerScriptService.

## Setting Up

Setting up is pretty simple. Just require the script and call `.init()`.

  1. Create a `Script`
  2. Paste the following code:

         local ServerScriptService = game:GetService("ServerScriptService")
         local serverAPI = require(ServerScriptService:WaitForChild("Radio System Server API")).init()

  3. Hit 'Play', check for any errors.

It Errors

  1. Try debugging it yourself.
  2. If you can not figure out why, feel free to create a support thread.
  3. Remember, be patient, and please understand that the API is meant to be used by those who know how to program.

## API Reference

### cleanup

**The most important function of them all** Call this function once you are done with the API, it will clean up all connections for you.

    () -> nil

#### Example Usage

    serverAPI:cleanup()

### ScriptConnection

Our version of a `RBXMScriptConnection`, it just provides a way to disconnect from a function.

#### Methods

  * `disconnect()` \- Disconnects the function

#### Example Usage

    local connection = ...
    task.wait(10)
    connection:disconnect()

### receivedClientMessage

Calls the function whenever we receieve a message from a player.

    (
        func: (player: Player, message: string, channelId: number) -> nil
    ) -> ScriptConnection

#### Parameters

  * `func: (player: Player, message: string, channelId: number) -> nil` \- a function that accepts a Player, string, number as its parameters and returns nil.

#### Example Usage

    local connection = serverAPI:receivedClientMessage(function(player: Player, message: string, channelId: number)
        print(player, message, channelId)
    end)

    task.wait(10)

    connection:disconnect()

### receivedActivateVoice

Calls the function whenever a player **tries** to use the voice channel.

    (
        func: (player: Player, channelId: number) -> nil
    ) -> ScriptConnection

#### Parameters

  * `func: (player: Player, channelId: number) -> nil` \- a function that accepts a Player and number as its parameters and returns nil.

#### Example Usage

    serverAPI:receivedActivateVoice(function(player: Player, channelId: number)
        print(player, channelId)
    end)

### receivedPanic

Calls the function whenever a player successfully uses the panic button.

    (
        func: (player: Player, channelId: number) -> nil
    ) -> ScriptConnection

#### Parameters

  * `func: (player: Player, channelId: number) -> nil` \- a function that accepts a Player and number as its parameters and returns nil.

#### Example Usage

    serverAPI:receivedPanic(function(player: Player, channelId: number)
        print(player, channelId)
    end)

### authorizedClient

Calls the function whenever the server sends authorized channels to a client.

    (
        func: (player: Player, authorizedChannels: {number}) -> nil
    ) -> ScriptConnection

#### Parameters

  * `func: (player: Player, authorizedChannels: {number}) -> nil` \- a function that accepts a Player and table as its parameters and returns nil.

#### Example Usage

    serverAPI:clientMessageRecieved(function(player: Player, authorizedChannels: {number})
        print(player, authorizedChannels)
    end)

### channelAddPlayer

Calls the function whenever a channel adds a player to itself.

    (
        func: (id: number, player: Player) -> nil
    ) -> ScriptConnection

#### Parameters

  * `func: (id: number, player: Player) -> nil` \- a function that accepts a numbe and Player as its parameters and returns nil.

#### Example Usage

    serverAPI:clientMessageRecieved(function(id: number, player: Player)
        print(id, player)
    end)

### channelRemovePlayer

Calls the function whenever a channel removes a player to itself.

    (
        func: (id: number, player: Player) -> nil
    ) -> ScriptConnection

#### Parameters

  * `func: (id: number, player: Player) -> nil` \- a function that accepts a numbe and Player as its parameters and returns nil.

#### Example Usage

    serverAPI:clientMessageRecieved(function(id: number, player: Player)
        print(id, player)
    end)

### createSystemMessage

Creates a system message in the specified channel. System messages are not currently stored in channel history.

    (
        channelId: number,
        message: {
            text: string,
            headerText: string?,
            backgroundColor3: Color3?,
            icon: string?,
            iconColor3: Color3?,
            iconRounded: boolean?,
            sideText: string?,
            sideAccent: Color3?,
    ) -> nil

#### Parameters

  * `channelId: number` \- the channel id to send the message to
  * `message: ...` \- the message data to send

#### Example Usage

    serverAPI:createSystemMessage(1, {
        text = "Hello, World!",
        sideText = "test",
    })

### activatePlayersVoice

Attempts to activate/deactivate a players voice communications

    (
        channelId: number,
        player: Player
    ) -> nil

#### Parameters

  * `channelId: number` \- the channel id to use
  * `player: Player` \- the player to attempt this on

#### Example Usage

    serverAPI:activatePlayersVoice(1, game.Players.parker02311)

Back to top


# Overview

The API is just a simple bindable event for both the server and client, but to make it easier to communicate with the API we have provided API wrappers.

# Requirements

  * The API wrapper for either the client or server1
  * A knowledge on how to code

# Support

Our maintainers will provide basic support for API usage, we will not teach you how to code.

[Client API Wrapper](https://radio.redon.tech/guide/api/client/) [Server API Wrapper](https://radio.redon.tech/guide/api/server/)

  1. You can download the rbxmx files from [GitHub](https://github.com/Redon-Tech/Radio-System/releases/latest) ↩

Back to top


# better-view-selector

A simplified plugin replacement for the view selector plugin in Roblox studio.

This plugin overrides the default View Selector plugin in favour of a much simpler display that harkens back to the legacy view selector.

This plugin supports also comes with some very nifty support for showing a selected object's local space axes. By toggling StudioService.UseLocalSpace (by pressing ctrl + L while using the studio draggers), you can swap between this mode.

[Creator Store](https://create.roblox.com/store/asset/16349581373)

### Examples

Object/Local Space:

World Space:


## What is red?
red is a lightweight, easy-to-use, and efficient event-driven library for Roblox.
red provides a simple API that allows you to create and manage events and actions in your game.

## Benefits
- **Simple API**: red is designed to be easy to use and understand, making it perfect for developers of all skill levels.
- **Lightweight**: red is a lightweight library, meaning that it won't slow down your game or take up unnecessary resources.
- **Type Safety**: red is typed and provides type safety, making it easier to catch errors and bugs in your code.

## Features
- **Stores**: The store is how you will dispatch and listen for events in your game.
- **Actions**: Actions are a way to perform side effects in response to events.
- **Middleware**: Middleware allows you to intercept and modify events before they are dispatched.

## Getting Started
### Installing as a wally dependency
Add the below line to your wally.toml file
```toml
red = "dig1t/red@2.2.10"
### Roblox Studio
Download the rbxl file from the [releases](https://github.com/dig1t/red/releases) tab.

Once the place file is open, you can find the package inside `ReplicatedStorage.Packages`.