Skip to main content

Blend

Declarative UI system inspired by Fusion.

Functions

New

Blend.New(classNamestring) → (props{[string]any;}) → Observable<Instance>

Creates a new function which will return an observable that, given the props in question, will construct a new instance and assign all props. This is the equivalent of a pipe-able Rx command.

local render = Blend.New "ScreenGui" {
	Parent = game.Players.LocalPlayer.PlayerGui;

	Blend.New "Frame" {
		Size = UDim2.new(1, 0, 1, 0);
		BackgroundTransparency = 0.5;
	};
};

maid:GiveTask(render:Subscribe(function(gui)
	print(gui)
end))

State

Blend.State(
defaultValueT,
checkTypestring | nil
) → ValueObject<T>

Creates a new Blend State which is actually just a ValueObject underneath.

Throttled

Blend.Throttled(observableObservable<T>) → Observable<T>

Throttles the update to the end of the defer lane. Can help optimize scenarios when Compute() can trigger multiple times per a frame.

Generally not needed.

Shared

Blend.Shared(observableObservable<T>) → Observable<T>

Shares this observables state/computation with all down-stream observables. This can be useful when a very expensive computation was done and needs to be shared.

Generally not needed.

Computed

Blend.Computed(...Aseriesofconvertablestates,followedbyafunctionattheend.) → Observable<T>

Takes a list of variables and uses them to compute an observable that will combine into any value. These variables can be any value, and if they can be converted into an Observable, they will be, which will be used to compute the value.

local verbState = Blend.State("hi")
local nameState = Blend.State("alice")

local computed = Blend.Computed(verbState, nameState, function(verb, name)
	return verb .. " " .. name
end)

maid:GiveTask(computed:Subscribe(function(sentence)
	print(sentence)
end)) --> "hi alice"

nameState.Value = "bob" --> "hi bob"
verbState.Value = "bye" --> "bye bob"
nameState.Value = "alice" --> "bye alice"

OnChange

Blend.OnChange(propertyNamestring) → (instanceInstance) → Observable

Short hand to register a propertyEvent changing

Blend.mount(workspace, {
	[Blend.OnChange "Name"] = function(name)
		print(name)
	end;
}) --> Immediately will print "Workspace"

workspace.Name = "Hello" --> Prints "Hello"

OnEvent

Blend.OnEvent(eventNamestring) → (instanceInstance) → Observable

Short hand to register an event from the instance

	Blend.mount(workspace, {
		[Blend.OnEvent "ChildAdded"] = function(child)
			print("Child added", child)
		end;
	})

	local folder = Instance.new("Folder")
	folder.Name = "Hi"
	folder.Parent = workspace --> prints "Child added Hi"

Attached

Blend.Attached(constructorT) → (parentInstance) → Observable<T>

Uses the constructor to attach a class or resource to the actual object for the lifetime of the subscription of that object.

return Blend.New "Frame" {
	Parent = variables.Parent;
	[Blend.Attached(function(parent)
		local maid = Maid.new()

		print("Got", parent)

		maid:GiveTask(function()
			print("Dead!")
		end)

		return maid
	end)] = true;
}

ComputedPairs

Blend.ComputedPairs(
sourceObservable<T> | any,
compute(
keyany,
valueany,
innerMaidMaid
) → Instance | Observable<Instance>
) → Observable<Brio<Instance>>

Similiar to Fusion's ComputedPairs, where the changes are cached, and the lifetime limited.

AccelTween

Blend.AccelTween(
sourceany,--

Source observable (or convertable)

accelerationany--

Source acceleration (or convertable)

) → Observable

Like Blend.Spring, but for AccelTween

Spring

Blend.Spring(
sourceany,
speedany,
damperany
) → Observable?

Converts this arbitrary value into an observable that will initialize a spring and interpolate it between values upon subscription.

local percentVisible = Blend.State(0)
local visibleSpring = Blend.Spring(percentVisible, 30)
local transparency = Blend.Computed(visibleSpring, function(percent)
	return 1 - percent
end);

Blend.mount(frame, {
	BackgroundTransparency = visibleSpring;
})

toPropertyObservable

Blend.toPropertyObservable(valueany) → Observable?

Converts this arbitrary value into an observable suitable for use in properties.

toNumberObservable

Blend.toNumberObservable(valuenumber | any) → Observable<number>?

Converts this arbitrary value into an observable that emits numbers.

toEventObservable

Blend.toEventObservable(valueany) → Observable?

Converts this arbitrary value into an observable that can be used to emit events.

toEventHandler

Blend.toEventHandler(valueany) → function?

Converts this arbitrary value into an event handler, which can be subscribed to

Children

Blend.Children(
parentInstance,
valueany
) → Observable

Mounts children to the parent and returns an object which will cleanup and delete all children when removed.

Note that this effectively recursively mounts children and their values, which is the heart of the reactive tree.

Blend.New "ScreenGui" {
	Parent = game.Players.LocalPlayer.PlayerGui;
	[Blend.Children] = {
		Blend.New "Frame" {
			Size = UDim2.new(1, 0, 1, 0);
			BackgroundTransparency = 0.5;
		};
	};
};

Note since 6.14 you don't need to be explicit about Blend.Children. Any number-based index in the mounting process will be automatically inferred as children to mount.

Blend.New "ScreenGui" {
	Parent = game.Players.LocalPlayer.PlayerGui;

	Blend.New "Frame" {
		Size = UDim2.new(1, 0, 1, 0);
		BackgroundTransparency = 0.5;
	};
};

Rules:

  • { Instance } - Tables of instances are all parented to the parent
  • Brio will last for the lifetime of the brio
  • Brio<Observable> will last for the lifetime of the brio
    • Brio<Signal> will also act as above
    • Brio<Promise> will also act as above
    • Brio<{ Instance } will also act as above
  • Observable will parent to the parent
    • Signal will act as Observable
    • ValueObject will act as an Observable
    • Promise will act as an Observable
  • will parent all instances to the parent
  • Observables may emit non-observables (in form of Computed/Dynamic)
    • Observable<Brio> will last for the lifetime of the brio, and parent the instance.
    • Observable<Observable> occurs when computed returns a value.
  • ValueObject will switch to the current value
  • function - Will be invoked as func(parent) and then the standard scheme will be applied

Cleanup:

  • Instances will be cleaned up on unsubscribe

Tags

Blend.Tags(
parentInstance,
valueany
) → Observable

Allows you to add CollectionService tags to a Blend object.

Blend.New "ScreenGui" {
	[Blend.Tags] = { "Hide", "ScreenGui" };
};

Find

Blend.Find(classNamestring) → function

Mounts Blend objects into an existing instance.

tip

Normally specifying ClassName as a property breaks mounting, since you can't write to ClassName. However, if you specify ClassName here, it will only listen to changes on children with that class name.

If multiple instances are named the same thing, then this will bind to both.

tip

This explicitly listens for any children underneath the mounted instance with the name passed in here. This is fine for small amounts of instances, like in most Gui hierarchies. However, it will be way less performance friendly for large class hierarchies.

maid:GiveTask(Blend.mount(frame, {
	Size = UDim2.new(0.5, 0, 0.5, 0);

	Blend.Find "UIScale" {
		Scale = 2;
	};
}))
tip

Instance

Blend.Instance(parentInstance) → Observable<Instance>

An event emitter that emits the instance that was actually created. This is useful for a variety of things.

Using this to track an instance

local currentCamera = Blend.State()

return Blend.New "ViewportFrame" {
	CurrentCamera = currentCamera;
	[Blend.Children] = {
		self._current;
		Blend.New "Camera" {
			[Blend.Instance] = currentCamera;
		};
	};
};

Note that since 6.14 you should also be able to just use the reification scheme of Blend.Children implicitly in Blend.mount to get somewhat equivalent behavior.

Blend.mount(frame, {
	-- Array indexed methods get treated as children-constructors, which get the parent
	-- in them;

	function(parent)
		print("Got parent!", parent)
	end;
})

You can also use this to execute code against an instance.

return Blend.New "Frame" {
	[Blend.Instance] = function(frame)
		print("We got a new frame!")
	end;
};

Note that if you subscribe twice to the resulting observable, the internal function will execute twice.

Single

Blend.Single(Observable<Instance | Brio<Instance>>) → Observable<Brio<Instance>>

Ensures the computed version of a value is limited by lifetime instead of multiple. Used in conjunction with Blend.Children and Blend.Computed.

warning

In general, cosntructing new instances like this is a bad idea, so it's recommended against it.

local render = Blend.New "ScreenGui" {
	Parent = game.Players.LocalPlayer.PlayerGui;
	[Blend.Children] = {
		Blend.Single(Blend.Computed(percentVisible, function()
			-- you generally would not want to do this anyway because this reconstructs a new frame
			-- every frame.

			Blend.New "Frame" {
				Size = UDim2.new(1, 0, 1, 0);
				BackgroundTransparency = 0.5;
			};
		end)
	};
};

maid:GiveTask(render:Subscribe(function(gui)
	print(gui)
end))

_observeChildren

Blend._observeChildren(
valueany,
parentInstance
) → Observable<Instance>

Observes children and ensures that the value is cleaned up afterwards.

mount

Blend.mount(
instanceInstance,
propstable
) → Maid

Mounts the instance to the props. This handles mounting children, and events.

The contract is that the props table is turned into observables. Note the following.

  • Keys of strings are turned into properties
    • If this can be turned into an observable, it will be used to subscribe to this event
    • Otherwise, we assign directly
  • Keys of functions are invoked on the instance in question
    • `(instance, value) -> Observable
    • If this returns an observable (or can be turned into one), we subscribe the event immediately
  • Keys of numbers (array components) are treated as implicit children
  • If the key is Blend.Children then we invoke mountChildren on it.
maid:GiveTask(Blend.mount(frame, {
	BackgroundTransparency = 1;

	-- All items named InventoryFrame
	Blend.Find "Frame" {
		Name = "InventoryFrame"

		-- Apply the following properties
		Blend.New "UIScale" {
			Scale = 0.5;
		};
	};
}))
Show raw api
{
    "functions": [
        {
            "name": "New",
            "desc": "Creates a new function which will return an observable that, given the props\nin question, will construct a new instance and assign all props. This is the\nequivalent of a pipe-able Rx command.\n\n```lua\nlocal render = Blend.New \"ScreenGui\" {\n\tParent = game.Players.LocalPlayer.PlayerGui;\n\n\tBlend.New \"Frame\" {\n\t\tSize = UDim2.new(1, 0, 1, 0);\n\t\tBackgroundTransparency = 0.5;\n\t};\n};\n\nmaid:GiveTask(render:Subscribe(function(gui)\n\tprint(gui)\nend))\n```",
            "params": [
                {
                    "name": "className",
                    "desc": "",
                    "lua_type": "string"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "(props: { [string]: any; }) -> Observable<Instance>"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 53,
                "path": "src/blend/src/Shared/Blend/Blend.lua"
            }
        },
        {
            "name": "State",
            "desc": "Creates a new Blend State which is actually just a ValueObject underneath.",
            "params": [
                {
                    "name": "defaultValue",
                    "desc": "",
                    "lua_type": "T"
                },
                {
                    "name": "checkType",
                    "desc": "",
                    "lua_type": "string | nil"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "ValueObject<T>"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 85,
                "path": "src/blend/src/Shared/Blend/Blend.lua"
            }
        },
        {
            "name": "Throttled",
            "desc": "Throttles the update to the end of the defer lane. Can help optimize scenarios when\nCompute() can trigger multiple times per a frame.\n\nGenerally not needed.",
            "params": [
                {
                    "name": "observable",
                    "desc": "",
                    "lua_type": "Observable<T>"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "Observable<T>"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 98,
                "path": "src/blend/src/Shared/Blend/Blend.lua"
            }
        },
        {
            "name": "Shared",
            "desc": "Shares this observables state/computation with all down-stream observables. This can be useful\nwhen a very expensive computation was done and needs to be shared.\n\nGenerally not needed.",
            "params": [
                {
                    "name": "observable",
                    "desc": "",
                    "lua_type": "Observable<T>"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "Observable<T>"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 113,
                "path": "src/blend/src/Shared/Blend/Blend.lua"
            }
        },
        {
            "name": "Computed",
            "desc": "Takes a list of variables and uses them to compute an observable that\nwill combine into any value. These variables can be any value, and if they\ncan be converted into an Observable, they will be, which will be used to compute\nthe value.\n\n```lua\nlocal verbState = Blend.State(\"hi\")\nlocal nameState = Blend.State(\"alice\")\n\nlocal computed = Blend.Computed(verbState, nameState, function(verb, name)\n\treturn verb .. \" \" .. name\nend)\n\nmaid:GiveTask(computed:Subscribe(function(sentence)\n\tprint(sentence)\nend)) --> \"hi alice\"\n\nnameState.Value = \"bob\" --> \"hi bob\"\nverbState.Value = \"bye\" --> \"bye bob\"\nnameState.Value = \"alice\" --> \"bye alice\"\n```",
            "params": [
                {
                    "name": "...",
                    "desc": "",
                    "lua_type": "A series of convertable states, followed by a function at the end."
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "Observable<T>"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 162,
                "path": "src/blend/src/Shared/Blend/Blend.lua"
            }
        },
        {
            "name": "OnChange",
            "desc": "Short hand to register a propertyEvent changing\n\n```lua\nBlend.mount(workspace, {\n\t[Blend.OnChange \"Name\"] = function(name)\n\t\tprint(name)\n\tend;\n}) --> Immediately will print \"Workspace\"\n\nworkspace.Name = \"Hello\" --> Prints \"Hello\"\n```",
            "params": [
                {
                    "name": "propertyName",
                    "desc": "",
                    "lua_type": "string"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "(instance: Instance) -> Observable"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 212,
                "path": "src/blend/src/Shared/Blend/Blend.lua"
            }
        },
        {
            "name": "OnEvent",
            "desc": "Short hand to register an event from the instance\n\n```lua\n\tBlend.mount(workspace, {\n\t\t[Blend.OnEvent \"ChildAdded\"] = function(child)\n\t\t\tprint(\"Child added\", child)\n\t\tend;\n\t})\n\n\tlocal folder = Instance.new(\"Folder\")\n\tfolder.Name = \"Hi\"\n\tfolder.Parent = workspace --> prints \"Child added Hi\"\n```",
            "params": [
                {
                    "name": "eventName",
                    "desc": "",
                    "lua_type": "string"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "(instance: Instance) -> Observable"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 238,
                "path": "src/blend/src/Shared/Blend/Blend.lua"
            }
        },
        {
            "name": "Attached",
            "desc": "Uses the constructor to attach a class or resource to the actual object\nfor the lifetime of the subscription of that object.\n\n```lua\nreturn Blend.New \"Frame\" {\n\tParent = variables.Parent;\n\t[Blend.Attached(function(parent)\n\t\tlocal maid = Maid.new()\n\n\t\tprint(\"Got\", parent)\n\n\t\tmaid:GiveTask(function()\n\t\t\tprint(\"Dead!\")\n\t\tend)\n\n\t\treturn maid\n\tend)] = true;\n}\n```",
            "params": [
                {
                    "name": "constructor",
                    "desc": "",
                    "lua_type": "T"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "(parent: Instance) -> Observable<T>"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 270,
                "path": "src/blend/src/Shared/Blend/Blend.lua"
            }
        },
        {
            "name": "ComputedPairs",
            "desc": "Similiar to Fusion's ComputedPairs, where the changes are cached, and the lifetime limited.",
            "params": [
                {
                    "name": "source",
                    "desc": "",
                    "lua_type": "Observable<T> | any"
                },
                {
                    "name": "compute",
                    "desc": "",
                    "lua_type": "(key: any, value: any, innerMaid: Maid) -> Instance | Observable<Instance>"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "Observable<Brio<Instance>>"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 294,
                "path": "src/blend/src/Shared/Blend/Blend.lua"
            }
        },
        {
            "name": "AccelTween",
            "desc": "Like Blend.Spring, but for AccelTween",
            "params": [
                {
                    "name": "source",
                    "desc": "Source observable (or convertable)",
                    "lua_type": "any"
                },
                {
                    "name": "acceleration",
                    "desc": "Source acceleration (or convertable)",
                    "lua_type": "any"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "Observable"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 347,
                "path": "src/blend/src/Shared/Blend/Blend.lua"
            }
        },
        {
            "name": "Spring",
            "desc": "Converts this arbitrary value into an observable that will initialize a spring\nand interpolate it between values upon subscription.\n\n```lua\nlocal percentVisible = Blend.State(0)\nlocal visibleSpring = Blend.Spring(percentVisible, 30)\nlocal transparency = Blend.Computed(visibleSpring, function(percent)\n\treturn 1 - percent\nend);\n\nBlend.mount(frame, {\n\tBackgroundTransparency = visibleSpring;\n})\n```",
            "params": [
                {
                    "name": "source",
                    "desc": "",
                    "lua_type": "any"
                },
                {
                    "name": "speed",
                    "desc": "",
                    "lua_type": "any"
                },
                {
                    "name": "damper",
                    "desc": "",
                    "lua_type": "any"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "Observable?"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 412,
                "path": "src/blend/src/Shared/Blend/Blend.lua"
            }
        },
        {
            "name": "toPropertyObservable",
            "desc": "Converts this arbitrary value into an observable suitable for use in properties.",
            "params": [
                {
                    "name": "value",
                    "desc": "",
                    "lua_type": "any"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "Observable?"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 471,
                "path": "src/blend/src/Shared/Blend/Blend.lua"
            }
        },
        {
            "name": "toNumberObservable",
            "desc": "Converts this arbitrary value into an observable that emits numbers.",
            "params": [
                {
                    "name": "value",
                    "desc": "",
                    "lua_type": "number | any"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "Observable<number>?"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 498,
                "path": "src/blend/src/Shared/Blend/Blend.lua"
            }
        },
        {
            "name": "toEventObservable",
            "desc": "Converts this arbitrary value into an observable that can be used to emit events.",
            "params": [
                {
                    "name": "value",
                    "desc": "",
                    "lua_type": "any"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "Observable?"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 512,
                "path": "src/blend/src/Shared/Blend/Blend.lua"
            }
        },
        {
            "name": "toEventHandler",
            "desc": "Converts this arbitrary value into an event handler, which can be subscribed to",
            "params": [
                {
                    "name": "value",
                    "desc": "",
                    "lua_type": "any"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "function?"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 528,
                "path": "src/blend/src/Shared/Blend/Blend.lua"
            }
        },
        {
            "name": "Children",
            "desc": "Mounts children to the parent and returns an object which will cleanup and delete\nall children when removed.\n\nNote that this effectively recursively mounts children and their values, which is\nthe heart of the reactive tree.\n\n```lua\nBlend.New \"ScreenGui\" {\n\tParent = game.Players.LocalPlayer.PlayerGui;\n\t[Blend.Children] = {\n\t\tBlend.New \"Frame\" {\n\t\t\tSize = UDim2.new(1, 0, 1, 0);\n\t\t\tBackgroundTransparency = 0.5;\n\t\t};\n\t};\n};\n```\n\nNote since 6.14 you don't need to be explicit about [Blend.Children]. Any number-based\nindex in the mounting process will be automatically inferred as children to mount.\n\n```lua\nBlend.New \"ScreenGui\" {\n\tParent = game.Players.LocalPlayer.PlayerGui;\n\n\tBlend.New \"Frame\" {\n\t\tSize = UDim2.new(1, 0, 1, 0);\n\t\tBackgroundTransparency = 0.5;\n\t};\n};\n```\n\nRules:\n\n* `{ Instance }` - Tables of instances are all parented to the parent\n* Brio<Instance> will last for the lifetime of the brio\n* Brio<Observable<Instance>> will last for the lifetime of the brio\n\t* Brio<Signal<Instance>> will also act as above\n\t* Brio<Promise<Instance>> will also act as above\n\t* Brio<{ Instance } will also act as above\n* Observable<Instance> will parent to the parent\n\t* Signal<Instance> will act as Observable<Instance>\n\t* ValueObject<Instance> will act as an Observable<Instance>\n\t* Promise<Instance> will act as an Observable<Instance>\n*  will parent all instances to the parent\n* Observables may emit non-observables (in form of Computed/Dynamic)\n\t* Observable<Brio<Instance>> will last for the lifetime of the brio, and parent the instance.\n\t* Observable<Observable<Instance>> occurs when computed returns a value.\n* ValueObject<Instance> will switch to the current value\n* function - Will be invoked as `func(parent)` and then the standard scheme will be applied\n\nCleanup:\n* Instances will be cleaned up on unsubscribe",
            "params": [
                {
                    "name": "parent",
                    "desc": "",
                    "lua_type": "Instance"
                },
                {
                    "name": "value",
                    "desc": "",
                    "lua_type": "any"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "Observable"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 612,
                "path": "src/blend/src/Shared/Blend/Blend.lua"
            }
        },
        {
            "name": "Tags",
            "desc": "Allows you to add [CollectionService] tags to a Blend object.\n\n```lua\nBlend.New \"ScreenGui\" {\n\t[Blend.Tags] = { \"Hide\", \"ScreenGui\" };\n};\n```",
            "params": [
                {
                    "name": "parent",
                    "desc": "",
                    "lua_type": "Instance"
                },
                {
                    "name": "value",
                    "desc": "",
                    "lua_type": "any"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "Observable"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 641,
                "path": "src/blend/src/Shared/Blend/Blend.lua"
            }
        },
        {
            "name": "Find",
            "desc": "Mounts Blend objects into an existing instance.\n\n:::tip\nNormally specifying ClassName as a property breaks mounting, since you\ncan't write to ClassName. However, if you specify ClassName here, it will only\nlisten to changes on children with that class name.\n:::\n\nIf multiple instances are named the same thing, then this will\nbind to both.\n\n:::tip\nThis explicitly listens for any children underneath the mounted\ninstance with the name passed in here. This is fine for small amounts\nof instances, like in most Gui hierarchies. However, it will be way less\nperformance friendly for large class hierarchies.\n:::\n\n```lua\nmaid:GiveTask(Blend.mount(frame, {\n\tSize = UDim2.new(0.5, 0, 0.5, 0);\n\n\tBlend.Find \"UIScale\" {\n\t\tScale = 2;\n\t};\n}))\n```\n\n:::tip\n\n:::",
            "params": [
                {
                    "name": "className",
                    "desc": "",
                    "lua_type": "string"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "function"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 712,
                "path": "src/blend/src/Shared/Blend/Blend.lua"
            }
        },
        {
            "name": "Instance",
            "desc": "An event emitter that emits the instance that was actually created. This is\nuseful for a variety of things.\n\nUsing this to track an instance\n\n```lua\nlocal currentCamera = Blend.State()\n\nreturn Blend.New \"ViewportFrame\" {\n\tCurrentCamera = currentCamera;\n\t[Blend.Children] = {\n\t\tself._current;\n\t\tBlend.New \"Camera\" {\n\t\t\t[Blend.Instance] = currentCamera;\n\t\t};\n\t};\n};\n```\n\nNote that since 6.14 you should also be able to just use the reification scheme of\n[Blend.Children] implicitly in [Blend.mount] to get somewhat equivalent behavior.\n\n```lua\nBlend.mount(frame, {\n\t-- Array indexed methods get treated as children-constructors, which get the parent\n\t-- in them;\n\n\tfunction(parent)\n\t\tprint(\"Got parent!\", parent)\n\tend;\n})\n```\n\nYou can also use this to execute code against an instance.\n\n```lua\nreturn Blend.New \"Frame\" {\n\t[Blend.Instance] = function(frame)\n\t\tprint(\"We got a new frame!\")\n\tend;\n};\n```\n\nNote that if you subscribe twice to the resulting observable, the internal function\nwill execute twice.",
            "params": [
                {
                    "name": "parent",
                    "desc": "",
                    "lua_type": "Instance"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "Observable<Instance>"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 835,
                "path": "src/blend/src/Shared/Blend/Blend.lua"
            }
        },
        {
            "name": "Single",
            "desc": "Ensures the computed version of a value is limited by lifetime instead\nof multiple. Used in conjunction with [Blend.Children] and [Blend.Computed].\n\n:::warning\nIn general, cosntructing new instances like this is a bad idea, so it's recommended against it.\n:::\n\n```lua\nlocal render = Blend.New \"ScreenGui\" {\n\tParent = game.Players.LocalPlayer.PlayerGui;\n\t[Blend.Children] = {\n\t\tBlend.Single(Blend.Computed(percentVisible, function()\n\t\t\t-- you generally would not want to do this anyway because this reconstructs a new frame\n\t\t\t-- every frame.\n\n\t\t\tBlend.New \"Frame\" {\n\t\t\t\tSize = UDim2.new(1, 0, 1, 0);\n\t\t\t\tBackgroundTransparency = 0.5;\n\t\t\t};\n\t\tend)\n\t};\n};\n\nmaid:GiveTask(render:Subscribe(function(gui)\n\tprint(gui)\nend))\n```",
            "params": [
                {
                    "name": "Observable<Instance",
                    "desc": "",
                    "lua_type": "| Brio<Instance>>"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "Observable<Brio<Instance>>"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 875,
                "path": "src/blend/src/Shared/Blend/Blend.lua"
            }
        },
        {
            "name": "_observeChildren",
            "desc": "Observes children and ensures that the value is cleaned up\nafterwards.",
            "params": [
                {
                    "name": "value",
                    "desc": "",
                    "lua_type": "any"
                },
                {
                    "name": "parent",
                    "desc": "",
                    "lua_type": "Instance"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "Observable<Instance>"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 905,
                "path": "src/blend/src/Shared/Blend/Blend.lua"
            }
        },
        {
            "name": "mount",
            "desc": "Mounts the instance to the props. This handles mounting children, and events.\n\nThe contract is that the props table is turned into observables. Note the following.\n\n* Keys of strings are turned into properties\n\t* If this can be turned into an observable, it will be used to subscribe to this event\n\t* Otherwise, we assign directly\n* Keys of functions are invoked on the instance in question\n\t* `(instance, value) -> Observable\n\t* If this returns an observable (or can be turned into one), we subscribe the event immediately\n* Keys of numbers (array components) are treated as implicit children\n* If the key is [Blend.Children] then we invoke mountChildren on it.\n\n```lua\nmaid:GiveTask(Blend.mount(frame, {\n\tBackgroundTransparency = 1;\n\n\t-- All items named InventoryFrame\n\tBlend.Find \"Frame\" {\n\t\tName = \"InventoryFrame\"\n\n\t\t-- Apply the following properties\n\t\tBlend.New \"UIScale\" {\n\t\t\tScale = 0.5;\n\t\t};\n\t};\n}))\n```",
            "params": [
                {
                    "name": "instance",
                    "desc": "",
                    "lua_type": "Instance"
                },
                {
                    "name": "props",
                    "desc": "",
                    "lua_type": "table"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "Maid"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 1122,
                "path": "src/blend/src/Shared/Blend/Blend.lua"
            }
        }
    ],
    "properties": [],
    "types": [],
    "name": "Blend",
    "desc": "Declarative UI system inspired by Fusion.",
    "source": {
        "line": 5,
        "path": "src/blend/src/Shared/Blend/Blend.lua"
    }
}