Skip to main content

VirtualInstance

VirtualInstances are the basic building blocks for Dex applications.

VirtualInstances are "Mounted" by Dex's reconciler engine, creating/destoying/modifying these real instances automatically as needed.

Constructors


Dex.New

Dex.New(
    className: string,
    props: {[string]: any}?,
    children: {[any]: CanBeObservable<VirtualInstance?>}
) -> VirtualInstance

Creates a new VirtualInstance that represents a newly-created Roblox Instance (via Instance.new(className)).


Dex.Clone

Dex.Clone(
    template: Instance | VirtualInstance,
    props: {[string]: any}?,
    children: {[any]: CanBeObservable<VirtualInstance?>}
) -> VirtualInstance

Creates a new VirtualInstance that represents a cloned Roblox Instance from a given template instance (via template:Clone()).


Dex.Premade

Dex.Premade(
    className: stirng,
    props: {[string]: any}?,
    children: {[any]: CanBeObservable<VirtualInstance?>}
) -> VirtualInstance

Creates a new VirtualInstance that represents a pre-existing Roblox Instance to be modified by Dex.

If passed into the the Render function for a Dex.Root component, the root instance will be used used.

Functions

SetProperties

VirtualInstance:SetProperties(propertyMap{[string]CanBeObservable<any>}) → ()

Adds properties to be rendered on the instance when it is reconciled.

Multiple calls to this function will merge the provided property map with the existing one, prioritizing the later call.

Values in the propertyMap can have multiple possible types, which are each handled differently:

  • A Static Value (number, boolean, string, UDim2, etc.) to be assigned right as the VirtualInstance is rendered
  • An Observablue Value to be assigned as the VirtualInstance is Rendered, as well as when the Observable value changes
  • A Dex.Nil symbol, which assigns a property to nil when rendered
  • A function which represents a listener to connect to an event while the VirtualInstance is rendered
  • Another VirtualInstance, which references an instance property to be assigned. This is useful for ViewportFrames, for example, where a camera must both be created underneath the ViewportFrame, and assigned as the CurrentCamera property within the same frame.

SetAttributes

VirtualInstance:SetAttributes(attributeMap{[string]CanBeObservable<any>}) → ()

Adds attributes to be rendered on the instance when it is reconciled.

Multiple calls to this function will merge the provided attribute map with the existing one, prioritizing the latest calls.

AddTags

VirtualInstance:AddTags(tagsCanBeObservable<{string}>) → ()

Adds tags to the Virtual Instance when it is reconciled. Multiple calls to this function will add extra tags to the VirtualInstance if they do not exist.

Connect

VirtualInstance:Connect(
eventNamestring,
listener(...any) → ()
) → ()

Adds an event listener to the Virtual Instance, which will automatically be connected and disconnected as the VirtualInstance is reconciled.

OutProperty

VirtualInstance:OutProperty(
propNamestring,
initialValueT
) → Observable<T>

Creates an Observable object that updates to the current value of an property on the virtual instance once when it is mounted, and listens to updates on this property.

Give initialValue a type annotation if initializing to nil (e.g. vInst:OutProperty("Adornee", nil :: Instance?)()

OutInitialProperty

VirtualInstance:OutInitialProperty(
propNamestring,
initialValueT
) → Observable<T>-AnobservablewiththesameoutputtypeasinitialValue.

Creates an Observable object that updates to the original value of an property on the virtual instance once when it is mounted. This is useful for referencing properties on a premade instance without hardcoding them in a Dex component.

Give initialValue a type annotation if initializing to nil (e.g. vInst:OutInitialProperty("Adornee", nil :: Instance?))

OutAttribute

VirtualInstance:OutAttribute(
attributeNamestring,
initialValueT
) → Observable<T>

Creates an Observable object that updates to the current value of an attribute on the virtual instance once when it is mounted, and listens to updates on this attribute.

Give initialValue a type annotation if initializing to nil (e.g. vInstance:OutAttribute("Foo", nil :: string?))

OutInitialAttribute

VirtualInstance:OutInitialAttribute(
attributeNamestring,
initialValueT
) → Observable<T>

Creates an Observable object that updates to the original value of an attribute on the virtual instance once when it is mounted. This is useful for referencing attributes on a premade instance without hardcoding them in a Dex component.

Give initialValue a type annotation if initializing to nil (e.g. vInst:OutInitialAttribute("Foo", nil :: string?))

OutInstance

VirtualInstance:OutInstance() → Observable<Instance?>

Outputs a reference to the reconciled instance to a Dex State object.

DANGER

Using OutInstance to directly edit the rendered instance's properties may lead to unexpected behavior. It is recommended to only use OutInstance where no alternatives are available within the Dex API for your use case.

Use Case Alternatives

Preformating an instance

If an instance requires some amount of preformatting (e.g. deleting children of a premade template), you can use the directive VirtualInstance:DestroyPremadeChildren to destroy template UI elements within a design.

Most other use cases for preformatting can usually be handled through the :SetProperties directive.

Using a nested template for Dex.Clone

Dex.Clone supports passing in another VirtualInstance as an argument, as long as there are no circular dependencies. This will wait until the template VirtualInstance is mounted to instantiate the cloned instance.

OnMount/OnUnmount

The methods VirtualInstance:OnMount and VirtualInstance.OnUnmont allow side effects to be performed during the VirtualInstance's rendering lifecycle. If your use case does not require a direct reference to the rendered instance, this may be the best option.

AddChild

VirtualInstance:AddChild(
pathstring | number,
childCanBeObservable<VirtualInstance?>
) → ()

Adds a child VirtualInstance node to this VirtualInstance.

The path can be a dot-separated string, or an array of raw string names.

If the child is a VirtualInstance, it will be created or found depending on the type of VirtualInstance passed in.

AddChildren

VirtualInstance:AddChildren(childMapCanBeObservable<{[any]CanBeObservable<VirtualInstance?>}>) → ()

Adds multiple children to the VirtualInstance given a child map. See VirtualInstance:Child() for API reference

MapChildren

VirtualInstance:MapChildren(
inputObservable<{[K]V}>,
map(
keyK,
valueV
) → CanBeObservable<VirtualInstance>?
) → ()

Creates a child VirtualInstance for each key/value pair of the input observable. When a Key/Value pair changes, the existing VirtualInstance at that key is destroyed (if it exists), and a new one is created (if the value is not nil).

The mapping function should create a single VirtualInstance based on the current key and value.

This performs better than directly calling VirtualInstance:AddChildren with an Observable input, as this only creates/destroys virtual instances on the specific key/value pairs that have changed whenever the input observable updates.

Example:

local function ItemList()
    local visibleItemIds = Dex.State({"Sword", "Gun", "MagicStaff"})
    local scrollingFrame = Dex.New("ScrollingFrame", {
        Size = UDim2.fromScale(1, 1)
    })
    scrollingFrame:MapChildren(visibleItemIds, function(i, id)
        -- Instantiate a child ItemCard component for this given item ID,
        -- and destroy/re-create a new item card when this ID changes.
        return ItemCard({
            id = id,
            layoutOrder = i,
        })
    end)
    return scollingFrame
end

MapChildrenByKey

VirtualInstance:MapChildrenByKey(
inputObservable<{[K]V}>,
map(
keyK,
valueObservable<V>
) → CanBeObservable<VirtualInstance>?
) → ()

Creates a child VirtualInstance for each key of the input observable. VirtualInstances will only be created/destroyed according to the provided mapping function when a new key is added or removed from the table.

The value is wrapped in an observable, and will forward updates to the mapping function when the value at a particlar key changes.

The mapping function should create a single VirtualInstance based on the current key and observable value at that key.

This is useful for instances where the input observable is a "Map", "Set", or "Dictionary" type, and may perform better than VirtualInstance:MapChildren in that case by minimizing creation/destruction of virtual instances.

Example:

local function ItemList()
    local visibleItemIdSet = Dex.State({
        ["Sword"] = true,
        ["Gun"] = true,
        ["MagicStaff"] = true}
    )
    local scrollingFrame = Dex.New("ScrollingFrame", {
        Size = UDim2.fromScale(1, 1)
    })
    scrollingFrame:MapChildrenByKey(visibleItemIds, function(id)
        return ItemCard({
            id = id,
        })
    end)
    return scollingFrame
end

MapChildrenByValue

VirtualInstance:MapChildrenByValue(
inputObservable<{[K]V}>,
map(
valueV,
keyObservable<K>
) → CanBeObservable<VirtualInstance>?
) → ()

Creates a child VirtualInstance for each value of the input observable. VirtualInstances will only be created/destroyed according to the provided mapping function when a new value is added or removed from the table.

In the case of duplicate values, the last key/value pair defined in the input table will be considered.

The key is wrapped in an observable, and will forward updates to the mapping function if the value is moved to another key.

The mapping function should create a single VirtualInstance based on the current value and observable key for each value.

This is useful for instances where the input observable is an "Array" "Map", or "Dictionary" type, and may perform better than VirtualInstance:MapChildren in that case by minimizing creation/destruction of virtual instances.

Example:

local function ItemList()
    local visibleItemIdSet = Dex.State({"Sword", "Gun", "MagicStaff"})
    local scrollingFrame = Dex.New("ScrollingFrame", {
        Size = UDim2.fromScale(1, 1)
    })
    scrollingFrame:MapChildrenByValue(visibleItemIds, function(id, i)
        return ItemCard({
            id = id,
            layoutOrder = i, -- Observable<number>
        })
    end)
    return scollingFrame
end

DestroyPremadeChildren

VirtualInstance:DestroyPremadeChildren(filterstring | ((childInstance) → boolean) | nil) → ()

Adds a directive to destroy children of the VirtualInstance once it is mounted.

This is useful for scenarios where the design of a premade template contains objects that should be destroyed before rendering the actual UI.

The "filter" argument can be a name or predicate describing which children to destroy. If a name is defined, all children found with this name will be destroyed. If a predicate is defined, all children for which this function returns true will be destroyed.

OnMount

VirtualInstance:OnMount(callback() → ()) → ()

Adds a lifecycle callback to be called when the Virtual Instance is mounted. This is useful for performing a side effect that begins/ends when a component starts/stops being rendered.

OnUnmount

VirtualInstance:OnUnmount(callback() → ()) → ()

Adds a lifecycle callback to be called when the Virtual Instance is unmounted.

This is useful for performing a side effect that begins/ends when a component starts/stops being rendered.

FindChild

VirtualInstance:FindChild(childPathstring) → VirtualInstance

Creates a new VirtualInstance that automatically mounts on the child of the parent VirtualInstance. Will wait until a child with the given name is found.

The following blocks of code are equivalent:

local parent = Dex.Premade("Frame")
local child = Dex.Premade("Frame")
parent:AddChild("ChildName", child)
local parent = Dex.Premade("Frame")
local child = parent:FindChild("ChildName")

Combine

VirtualInstance:Combine(...VirtualInstance) → ()

Combines the directives from another, or multiple other VirtualInstances. The VirtualInstances passed in must meet the following requirements:

  • They must be of "Premade" type, with an equivalent or related ClassName to the target VirtualInstance.
  • They must not already be rendered by Dex and/or combined with another VirtualInstance.

Combine can be used to compose different effects or input handlers within a VirtualInstance tree:

local function RecolorWithMouseInput()
    local isHovering = Dex.State(false)
    local isPressing = Dex.State(false)
    return Dex.Premade("GuiButton", {
        MouseEnter = function()
            isHovering:Set(true)
        end,
        MouseLeave = function()
            isHovering:Set(false)
        end,
        MouseButton1Down = function()
            isPressing:Set(true)
        end,
        MouseButton1Up = function()
            isPressing:Set(false)
        end,
        BackgroundColor3 = Dex.Map(isHovering, isPressing)(function(
            currentHovering,
            currentPressing
        )
            if currentPressing then
                return Color3.fromHex("aaa")
            elseif currentHovering then
                return Color3.fromHex("ddd")
            else
                return Color3.fromHex("fff")
            end,
        end),
    })
end

-- . . .

local function Button()
    local button = Dex.New("Button", {
        Activated = function()
            print("Button was clicked!")
        end,
        AutoButtonColor = false,
    })
    button:Combine(RecolorWithMouseInput())
    return button
end

SubscribeWhileMounted

VirtualInstance:SubscribeWhileMounted(
input:Observable<T>,
listener(valueT) → (),
immediatelyCallListenerOnMountboolean?
) → ()

Subscribes a custom listener to an observable's value while the VirtualInstance is mounted, and automatically unsubscribes the listener when the VirtualInstance unmounts.

TIP

SubscribeWhileMounted is much safer than calling Observable:Subscribe directly, as you do not need to handle an unsubscribe function manually to prevent memory leaks.

You can use this function to trigger side effects such as animations whenever an observable value changes:

local function PulseAnimation(valueToWatch: Dex.Observable<any>)
    -- Create a UIScale object that plays a 1-second "pulse" animation
    -- whenever a stopwatch is played.
    local stopwatch = Dex.Stopwatch({duration = 1})
    local uiScale = Dex.New("UIScale", {
        Scale = stopwatch:Map(function(currentTime)
            return 1 + (0.5 - currentTime) * 0.1
        end)
    })

    -- Play the stopwatch whenever the valueToWatch observable changes.
    uiScale:SubscribeWhileMounted(valueToWatch, function()
        stopwatch:Play()
    end)

    return uiScale
end
Show raw api
{
    "functions": [
        {
            "name": "SetProperties",
            "desc": "Adds properties to be rendered on the instance when it is reconciled.\n\nMultiple calls to this function will merge the provided property map with\nthe existing one, prioritizing the later call.\n\nValues in the propertyMap can have multiple possible types, which are each\nhandled differently:\n\n- A **Static Value** (number, boolean, string, UDim2, etc.) to be assigned\nright as the VirtualInstance is rendered\n- An **Observablue Value** to be assigned as the VirtualInstance is\nRendered, as well as when the Observable value changes\n- A **`Dex.Nil`** symbol, which assigns a property to `nil` when rendered\n- A **function** which represents a listener to connect to an event while\nthe VirtualInstance is rendered\n- Another **VirtualInstance**, which references an instance property to be\nassigned. This is useful for ViewportFrames, for example, where a camera\nmust both be created underneath the ViewportFrame, and assigned as the\nCurrentCamera property within the same frame.",
            "params": [
                {
                    "name": "propertyMap",
                    "desc": "",
                    "lua_type": "{[string]: CanBeObservable<any>}"
                }
            ],
            "returns": [],
            "function_type": "method",
            "source": {
                "line": 146,
                "path": "src/VirtualInstance.luau"
            }
        },
        {
            "name": "SetAttributes",
            "desc": "Adds attributes to be rendered on the instance when it is reconciled.\n\nMultiple calls to this function will merge the provided attribute map with\nthe existing one, prioritizing the latest calls.",
            "params": [
                {
                    "name": "attributeMap",
                    "desc": "",
                    "lua_type": "{[string]: CanBeObservable<any>}"
                }
            ],
            "returns": [],
            "function_type": "method",
            "source": {
                "line": 168,
                "path": "src/VirtualInstance.luau"
            }
        },
        {
            "name": "AddTags",
            "desc": "Adds tags to the Virtual Instance when it is reconciled. Multiple calls to\nthis function will add extra tags to the VirtualInstance if they do not\nexist.",
            "params": [
                {
                    "name": "tags",
                    "desc": "",
                    "lua_type": "CanBeObservable<{string}>"
                }
            ],
            "returns": [],
            "function_type": "method",
            "source": {
                "line": 189,
                "path": "src/VirtualInstance.luau"
            }
        },
        {
            "name": "Connect",
            "desc": "Adds an event listener to the Virtual Instance, which will automatically\nbe connected and disconnected as the VirtualInstance is reconciled.",
            "params": [
                {
                    "name": "eventName",
                    "desc": "",
                    "lua_type": "string"
                },
                {
                    "name": "listener",
                    "desc": "",
                    "lua_type": "(...any) -> ()"
                }
            ],
            "returns": [],
            "function_type": "method",
            "source": {
                "line": 210,
                "path": "src/VirtualInstance.luau"
            }
        },
        {
            "name": "OutProperty",
            "desc": "Creates an Observable object that updates to the current value of an\nproperty on the virtual instance once when it is mounted, and listens to\nupdates on this property.\n\nGive initialValue a type annotation if initializing to nil\n(e.g. vInst:OutProperty(\"Adornee\", nil :: Instance?)()",
            "params": [
                {
                    "name": "propName",
                    "desc": "",
                    "lua_type": "string"
                },
                {
                    "name": "initialValue",
                    "desc": "",
                    "lua_type": "T"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "Observable<T>"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 240,
                "path": "src/VirtualInstance.luau"
            }
        },
        {
            "name": "OutInitialProperty",
            "desc": "Creates an Observable object that updates to the original value of an\nproperty on the virtual instance once when it is mounted. This is useful\nfor referencing properties on a premade instance without hardcoding them in\na Dex component.\n\nGive initialValue a type annotation if initializing to nil\n(e.g. vInst:OutInitialProperty(\"Adornee\", nil :: Instance?))",
            "params": [
                {
                    "name": "propName",
                    "desc": "",
                    "lua_type": "string"
                },
                {
                    "name": "initialValue",
                    "desc": "",
                    "lua_type": "T"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "Observable<T> - An observable with the same output type as initialValue."
                }
            ],
            "function_type": "method",
            "source": {
                "line": 274,
                "path": "src/VirtualInstance.luau"
            }
        },
        {
            "name": "OutAttribute",
            "desc": "Creates an Observable object that updates to the current value of an\nattribute on the virtual instance once when it is mounted, and listens to\nupdates on this attribute.\n\nGive initialValue a type annotation if initializing to nil\n(e.g. vInstance:OutAttribute(\"Foo\", nil :: string?))",
            "params": [
                {
                    "name": "attributeName",
                    "desc": "",
                    "lua_type": "string"
                },
                {
                    "name": "initialValue",
                    "desc": "",
                    "lua_type": "T"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "Observable<T>"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 307,
                "path": "src/VirtualInstance.luau"
            }
        },
        {
            "name": "OutInitialAttribute",
            "desc": "Creates an Observable object that updates to the original value of an\nattribute on the virtual instance once when it is mounted. This is useful\nfor referencing attributes on a premade instance without hardcoding them in\na Dex component.\n\nGive initialValue a type annotation if initializing to nil\n(e.g. vInst:OutInitialAttribute(\"Foo\", nil :: string?))",
            "params": [
                {
                    "name": "attributeName",
                    "desc": "",
                    "lua_type": "string"
                },
                {
                    "name": "initialValue",
                    "desc": "",
                    "lua_type": "T"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "Observable<T>"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 341,
                "path": "src/VirtualInstance.luau"
            }
        },
        {
            "name": "OutInstance",
            "desc": "Outputs a reference to the reconciled instance to a Dex State object.\n\n:::danger\nUsing OutInstance to directly edit the rendered instance's properties may\nlead to unexpected behavior. It is recommended to only use OutInstance where\nno alternatives are available within the Dex API for your use case.\n\n## Use Case Alternatives\n\n### Preformating an instance\nIf an instance requires some amount of preformatting (e.g. deleting children\nof a premade template), you can use the directive\n[VirtualInstance:DestroyPremadeChildren] to destroy template UI elements\nwithin a design.\n\nMost other use cases for preformatting can usually be handled through the\n:SetProperties directive.\n\n### Using a nested template for [Dex.Clone]\nDex.Clone supports passing in another _VirtualInstance_ as an argument, as\nlong as there are no circular dependencies. This will wait until the\ntemplate VirtualInstance is mounted to instantiate the cloned instance.\n\n### OnMount/OnUnmount\nThe methods [VirtualInstance:OnMount] and [VirtualInstance.OnUnmont] allow\nside effects to be performed during the VirtualInstance's rendering\nlifecycle. If your use case does not require a direct reference to the\nrendered instance, this may be the best option.\n:::",
            "params": [],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "Observable<Instance?>"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 395,
                "path": "src/VirtualInstance.luau"
            }
        },
        {
            "name": "AddChild",
            "desc": "Adds a child VirtualInstance node to this VirtualInstance.\n\nThe path can be a dot-separated string, or an array of raw string names.\n\nIf the child is a VirtualInstance, it will be created or found depending on\nthe type of VirtualInstance passed in.",
            "params": [
                {
                    "name": "path",
                    "desc": "",
                    "lua_type": "string | number"
                },
                {
                    "name": "child",
                    "desc": "",
                    "lua_type": "CanBeObservable<VirtualInstance?>"
                }
            ],
            "returns": [],
            "function_type": "method",
            "source": {
                "line": 421,
                "path": "src/VirtualInstance.luau"
            }
        },
        {
            "name": "AddChildren",
            "desc": "Adds multiple children to the VirtualInstance given a child map. See\nVirtualInstance:Child() for API reference",
            "params": [
                {
                    "name": "childMap",
                    "desc": "",
                    "lua_type": "CanBeObservable<{[any]: CanBeObservable<VirtualInstance?>}>"
                }
            ],
            "returns": [],
            "function_type": "method",
            "source": {
                "line": 443,
                "path": "src/VirtualInstance.luau"
            }
        },
        {
            "name": "MapChildren",
            "desc": "Creates a child VirtualInstance for each key/value pair of the input\nobservable. When a Key/Value pair changes, the existing\nVirtualInstance at that key is destroyed (if it exists), and a new one is\ncreated (if the value is not `nil`).\n\nThe mapping function should create a single VirtualInstance based on the\ncurrent key and value. \n\nThis performs better than directly calling [VirtualInstance:AddChildren]\nwith an Observable input, as this only creates/destroys virtual instances on\nthe specific key/value pairs that have changed whenever the input observable\nupdates.\n\nExample:\n```lua\nlocal function ItemList()\n    local visibleItemIds = Dex.State({\"Sword\", \"Gun\", \"MagicStaff\"})\n    local scrollingFrame = Dex.New(\"ScrollingFrame\", {\n        Size = UDim2.fromScale(1, 1)\n    })\n    scrollingFrame:MapChildren(visibleItemIds, function(i, id)\n        -- Instantiate a child ItemCard component for this given item ID,\n        -- and destroy/re-create a new item card when this ID changes.\n        return ItemCard({\n            id = id,\n            layoutOrder = i,\n        })\n    end)\n    return scollingFrame\nend\n```",
            "params": [
                {
                    "name": "input",
                    "desc": "",
                    "lua_type": "Observable<{[K]: V}>"
                },
                {
                    "name": "map",
                    "desc": "",
                    "lua_type": "(key: K, value: V) -> CanBeObservable<VirtualInstance>?"
                }
            ],
            "returns": [],
            "function_type": "method",
            "source": {
                "line": 493,
                "path": "src/VirtualInstance.luau"
            }
        },
        {
            "name": "MapChildrenByKey",
            "desc": "Creates a child VirtualInstance for each key of the input\nobservable. VirtualInstances will only be created/destroyed according to the\nprovided mapping function when a new key is added or removed from the table.\n\nThe value is wrapped in an observable, and will forward updates to the\nmapping function when the value at a particlar key changes.\n\nThe mapping function should create a single VirtualInstance based on the\ncurrent key and observable value at that key.\n\nThis is useful for instances where the input observable is a \"Map\", \"Set\",\nor \"Dictionary\" type, and may perform better than\n[VirtualInstance:MapChildren] in that case by minimizing\ncreation/destruction of virtual instances.\n\nExample:\n```lua\nlocal function ItemList()\n    local visibleItemIdSet = Dex.State({\n        [\"Sword\"] = true,\n        [\"Gun\"] = true,\n        [\"MagicStaff\"] = true}\n    )\n    local scrollingFrame = Dex.New(\"ScrollingFrame\", {\n        Size = UDim2.fromScale(1, 1)\n    })\n    scrollingFrame:MapChildrenByKey(visibleItemIds, function(id)\n        return ItemCard({\n            id = id,\n        })\n    end)\n    return scollingFrame\nend\n```",
            "params": [
                {
                    "name": "input",
                    "desc": "",
                    "lua_type": "Observable<{[K]: V}>"
                },
                {
                    "name": "map",
                    "desc": "",
                    "lua_type": "(key: K, value: Observable<V>) -> CanBeObservable<VirtualInstance>?"
                }
            ],
            "returns": [],
            "function_type": "method",
            "source": {
                "line": 551,
                "path": "src/VirtualInstance.luau"
            }
        },
        {
            "name": "MapChildrenByValue",
            "desc": "Creates a child VirtualInstance for each value of the input\nobservable. VirtualInstances will only be created/destroyed according to the\nprovided mapping function when a new value is added or removed from the\ntable.\n\nIn the case of duplicate values, the last key/value pair defined in the\ninput table will be considered.\n\nThe key is wrapped in an observable, and will forward updates to the\nmapping function if the value is moved to another key.\n\nThe mapping function should create a single VirtualInstance based on the\ncurrent value and observable key for each value.\n\nThis is useful for instances where the input observable is an \"Array\" \"Map\",\nor \"Dictionary\" type, and may perform better than\n[VirtualInstance:MapChildren] in that case by minimizing\ncreation/destruction of virtual instances.\n\nExample:\n```lua\nlocal function ItemList()\n    local visibleItemIdSet = Dex.State({\"Sword\", \"Gun\", \"MagicStaff\"})\n    local scrollingFrame = Dex.New(\"ScrollingFrame\", {\n        Size = UDim2.fromScale(1, 1)\n    })\n    scrollingFrame:MapChildrenByValue(visibleItemIds, function(id, i)\n        return ItemCard({\n            id = id,\n            layoutOrder = i, -- Observable<number>\n        })\n    end)\n    return scollingFrame\nend\n```",
            "params": [
                {
                    "name": "input",
                    "desc": "",
                    "lua_type": "Observable<{[K]: V}>"
                },
                {
                    "name": "map",
                    "desc": "",
                    "lua_type": "(value: V, key: Observable<K>) -> CanBeObservable<VirtualInstance>?"
                }
            ],
            "returns": [],
            "function_type": "method",
            "source": {
                "line": 610,
                "path": "src/VirtualInstance.luau"
            }
        },
        {
            "name": "DestroyPremadeChildren",
            "desc": "Adds a directive to destroy children of the VirtualInstance once it is\nmounted.\n\nThis is useful for scenarios where the design of a premade template contains\nobjects that should be destroyed before rendering the actual UI.\n\nThe \"filter\" argument can be a name or predicate describing which children\nto destroy. If a name is defined, all children found with this name will be\ndestroyed. If a predicate is defined, all children for which this function\nreturns true will be destroyed.",
            "params": [
                {
                    "name": "filter",
                    "desc": "",
                    "lua_type": "string | ((child: Instance) -> boolean) | nil"
                }
            ],
            "returns": [],
            "function_type": "method",
            "source": {
                "line": 651,
                "path": "src/VirtualInstance.luau"
            }
        },
        {
            "name": "OnMount",
            "desc": "Adds a lifecycle callback to be called when the Virtual Instance is mounted.\nThis is useful for performing a side effect that begins/ends when a\ncomponent starts/stops being rendered.",
            "params": [
                {
                    "name": "callback",
                    "desc": "",
                    "lua_type": "() -> ()"
                }
            ],
            "returns": [],
            "function_type": "method",
            "source": {
                "line": 672,
                "path": "src/VirtualInstance.luau"
            }
        },
        {
            "name": "OnUnmount",
            "desc": "Adds a lifecycle callback to be called when the Virtual Instance is\nunmounted.\n\nThis is useful for performing a side effect that begins/ends when a\ncomponent starts/stops being rendered.",
            "params": [
                {
                    "name": "callback",
                    "desc": "",
                    "lua_type": "() -> ()"
                }
            ],
            "returns": [],
            "function_type": "method",
            "source": {
                "line": 695,
                "path": "src/VirtualInstance.luau"
            }
        },
        {
            "name": "FindChild",
            "desc": "Creates a new VirtualInstance that automatically mounts on the child of the\nparent VirtualInstance. Will wait until a child with the given name is\nfound.\n\nThe following blocks of code are equivalent:\n```lua\nlocal parent = Dex.Premade(\"Frame\")\nlocal child = Dex.Premade(\"Frame\")\nparent:AddChild(\"ChildName\", child)\n```\n\n```lua\nlocal parent = Dex.Premade(\"Frame\")\nlocal child = parent:FindChild(\"ChildName\")\n```",
            "params": [
                {
                    "name": "childPath",
                    "desc": "",
                    "lua_type": "string"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "VirtualInstance"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 729,
                "path": "src/VirtualInstance.luau"
            }
        },
        {
            "name": "Combine",
            "desc": "Combines the directives from another, or multiple other VirtualInstances.\nThe VirtualInstances passed in must meet the following requirements:\n\n- They must be of \"Premade\" type, with an equivalent or related ClassName to\nthe target VirtualInstance.\n- They must not already be rendered by Dex and/or combined with another\nVirtualInstance.\n\nCombine can be used to compose different effects or input handlers within a\nVirtualInstance tree:\n\n```lua\nlocal function RecolorWithMouseInput()\n    local isHovering = Dex.State(false)\n    local isPressing = Dex.State(false)\n    return Dex.Premade(\"GuiButton\", {\n        MouseEnter = function()\n            isHovering:Set(true)\n        end,\n        MouseLeave = function()\n            isHovering:Set(false)\n        end,\n        MouseButton1Down = function()\n            isPressing:Set(true)\n        end,\n        MouseButton1Up = function()\n            isPressing:Set(false)\n        end,\n        BackgroundColor3 = Dex.Map(isHovering, isPressing)(function(\n            currentHovering,\n            currentPressing\n        )\n            if currentPressing then\n                return Color3.fromHex(\"aaa\")\n            elseif currentHovering then\n                return Color3.fromHex(\"ddd\")\n            else\n                return Color3.fromHex(\"fff\")\n            end,\n        end),\n    })\nend\n\n-- . . .\n\nlocal function Button()\n    local button = Dex.New(\"Button\", {\n        Activated = function()\n            print(\"Button was clicked!\")\n        end,\n        AutoButtonColor = false,\n    })\n    button:Combine(RecolorWithMouseInput())\n    return button\nend\n```",
            "params": [
                {
                    "name": "...",
                    "desc": "",
                    "lua_type": "VirtualInstance"
                }
            ],
            "returns": [],
            "function_type": "method",
            "source": {
                "line": 808,
                "path": "src/VirtualInstance.luau"
            }
        },
        {
            "name": "SubscribeWhileMounted",
            "desc": "Subscribes a custom listener to an observable's value while the\nVirtualInstance is mounted, and automatically unsubscribes the listener when\nthe VirtualInstance unmounts.\n\n:::tip\nSubscribeWhileMounted is much safer than calling [Observable:Subscribe]\ndirectly, as you do not need to handle an unsubscribe function manually to\nprevent memory leaks.\n\nYou can use this function to trigger side effects such as animations\nwhenever an observable value changes:\n```lua\nlocal function PulseAnimation(valueToWatch: Dex.Observable<any>)\n    -- Create a UIScale object that plays a 1-second \"pulse\" animation\n    -- whenever a stopwatch is played.\n    local stopwatch = Dex.Stopwatch({duration = 1})\n    local uiScale = Dex.New(\"UIScale\", {\n        Scale = stopwatch:Map(function(currentTime)\n            return 1 + (0.5 - currentTime) * 0.1\n        end)\n    })\n\n    -- Play the stopwatch whenever the valueToWatch observable changes.\n    uiScale:SubscribeWhileMounted(valueToWatch, function()\n        stopwatch:Play()\n    end)\n\n    return uiScale\nend\n```\n:::",
            "params": [
                {
                    "name": "input:",
                    "desc": "",
                    "lua_type": "Observable<T>"
                },
                {
                    "name": "listener",
                    "desc": "",
                    "lua_type": "(value: T) -> ()"
                },
                {
                    "name": "immediatelyCallListenerOnMount",
                    "desc": "",
                    "lua_type": "boolean?"
                }
            ],
            "returns": [],
            "function_type": "method",
            "source": {
                "line": 886,
                "path": "src/VirtualInstance.luau"
            }
        }
    ],
    "properties": [],
    "types": [],
    "name": "VirtualInstance",
    "desc": "VirtualInstances are the basic building blocks for Dex applications.\n\nVirtualInstances are \"Mounted\" by Dex's reconciler engine,\ncreating/destoying/modifying these real instances automatically as needed.\n\n## Constructors\n---\n\n### Dex.New\n```lua\nDex.New(\n    className: string,\n    props: {[string]: any}?,\n    children: {[any]: CanBeObservable<VirtualInstance?>}\n) -> VirtualInstance\n```\n\nCreates a new [VirtualInstance] that represents a newly-created Roblox\nInstance (via `Instance.new(className)`).\n\n---\n\n### Dex.Clone\n```lua\nDex.Clone(\n    template: Instance | VirtualInstance,\n    props: {[string]: any}?,\n    children: {[any]: CanBeObservable<VirtualInstance?>}\n) -> VirtualInstance\n```\nCreates a new [VirtualInstance] that represents a cloned Roblox Instance\nfrom a given template instance (via `template:Clone()`).\n\n---\n\n### Dex.Premade\n```lua\nDex.Premade(\n    className: stirng,\n    props: {[string]: any}?,\n    children: {[any]: CanBeObservable<VirtualInstance?>}\n) -> VirtualInstance\n```\n\nCreates a new VirtualInstance that represents a pre-existing Roblox Instance\nto be modified by Dex.\n\nIf passed into the the Render function for a [Dex.Root] component, the root\ninstance will be used used.",
    "source": {
        "line": 117,
        "path": "src/VirtualInstance.luau"
    }
}