Flux
Reactive UI library for Roblox and Luau, including fine-grained signals, declarative instances, layout, motion, Flux.Clock, and Flux.Sync.
local count = Flux.signal(0)
Flux.new "TextButton" {
Parent = gui,
Text = function() return `Clicked {count()} times` end,
Activated = function() count(count() + 1) end,
}Types
Node type
type Node<T> = Graph.Node<T>State type
type State<T> = Graph.State<T>Reactive type
type Reactive<T> = Graph.Reactive<T>Unwrap type
type Unwrap<T> = Graph.Unwrap<T>Owner type
type Owner = Graph.OwnerCleanable type
type Cleanable = Graph.CleanableProps type
type Props<ClassName, Extra = {}> = Type.Merge<Type.Properties<Type.Resolve<ClassName>>, Extra>Child type
Children type
type Children = { Child }Component type
type Component<P, I = Instance> = (props: P) -> IPartial type
type Partial<T> = Edit.Partial<T>Pick type
type Pick<T, G> = Edit.Pick<T, G>Omit type
type Omit<T, G> = Edit.Omit<T, G>Async type
type Async<T> = Async.Async<T>AsyncState type
type AsyncState = Async.AsyncStateContext type
type Context<T> = Graph.Context<T>Selector type
type Selector<K> = Conditional.Selector<K>Spring type
type Spring<T> = Motion.Spring<T>SyncSignal type
type SyncSignal<T = any> = Sync.SyncSignal<T>SyncValidator type
type SyncValidator<T> = Sync.Validator<T>HoverOptions type
type HoverOptions = Interact.HoverOptionsBreakpoint type
type Breakpoint = Responsive.BreakpointInput type
type Input = Responsive.InputPlatform type
type Platform = Responsive.PlatformTextSize type
type TextSize = Responsive.TextSizeDisplaySize type
type DisplaySize = Responsive.DisplaySizeLength type
type Length = Layout.LengthReactiveLength type
type ReactiveLength = Layout.ReactiveLengthInsets type
type Insets = Layout.InsetsAlign type
type Align = Layout.AlignFlexAlign type
type FlexAlign = Layout.FlexAlignLineAlign type
type LineAlign = Layout.LineAlignDirection type
type Direction = Layout.DirectionFlexMode type
type FlexMode = Layout.FlexModePaddingSides type
type PaddingSides = Layout.PaddingSidesCornerSides type
type CornerSides = Layout.CornerSidesListConfig type
type ListConfig = Layout.ListConfigGridConfig type
type GridConfig = Layout.GridConfigStrokeConfig type
type StrokeConfig = Layout.StrokeConfigGradientConfig type
type GradientConfig = Layout.GradientConfigSizeConstraintConfig type
type SizeConstraintConfig = Layout.SizeConstraintConfigTextSizeConstraintConfig type
type TextSizeConstraintConfig = Layout.TextSizeConstraintConfigProperties
Color from Motion
Flux.Color: ColorPerceptual Color3 utilities in Oklab (lighten, saturate, mix, rotateHue, and WCAG contrast/readable).
Defaults Read Only from Edit
Flux.Defaults: { [string]: { [string]: unknown } }Mutable table of per-class default properties applied by Flux.new.
Find from Edit
Flux.Find: FindInstance selectors (Child, Descendant, Ancestor, Path, Query) for hydrating trees inside Flux.edit.
Flags from Edit
Flux.Flags: FlagsGlobal behavior flags (Flags.defaults toggles per-class defaults in Flux.new).
Sync Module
Flux.Sync: SyncNetwork-synchronized signals replicated from the server to clients once per frame. Use sig:of(player) for per-player values and pass a validate callback to allow client writes.
otherwise Read Only from Conditional
Flux.otherwise: anyCatch-all branch key for Flux.switch maps when source matches no explicit key.
Flux.switch(state) {
loading = function() return Spinner {} end,
[Flux.otherwise] = function(value) return Label { text = value } end,
}Functions
edit
Flux.edit<T>(instance: T & Instance)Applies reactive properties, events, children, and directives to an existing Instance. Bindings created inside a Flux.scope disconnect when the scope is destroyed.
Flux.edit(existingLabel) { Text = function() return `HP {health()}` end }new
Flux.new<T>(className: T | keyof<Type.Creatable>)Creates a Roblox Instance of className with its per-class defaults and applies a table of properties, events, children, and directives. When called inside a Flux.scope, the instance is destroyed with the scope.
Flux.new "Frame" {
Size = UDim2.fromScale(1, 1),
BackgroundTransparency = function() return if hovered() then 0 else 0.5 end,
_attr_Kind = "Panel",
_tag_Interactive = true,
Flux.new "UICorner" {},
}signal from Graph
Flux.signal(initial: any, equals: any): anyCreates a writable signal holding initial, using equals (default ==) to skip unchanged writes. Signals aren't owned by enclosing scopes and are garbage-collected once unreferenced.
local count = Flux.signal(0)
count(count() + 1)computed from Graph
Flux.computed(fn: any, equals: any): anyCreates a lazily cached computed node derived from fn. Re-evaluates only when read after a dependency changes, and uses equals (default ==) to stop propagation when the result is unchanged.
local total = Flux.computed(function()
return price() * quantity()
end)effect from Graph
Flux.effect(fn: (...any) -> ...any): anySchedules fn to run on the next flush and re-run whenever any node it reads changes. Owned by the enclosing scope or stopped manually with node:Destroy().
Flux.effect(function() print("count is", count()) end)createSignal from Graph
Flux.createSignal<T>(initial: T, equals: ((T, T: any) -> boolean)?): (() -> T, (value: T, force: boolean?) -> T)Creates a lightweight signal without a node wrapper and returns (getter, setter). Faster and smaller than Flux.signal, with no methods (Destroy, onObserved, etc.).
local count, setCount = Flux.createSignal(0)
Flux.effect(function()
print(count())
end)
setCount(count() + 1)createMemo from Graph
Flux.createMemo<T>(fn: () -> T, equals: ((T, T) -> boolean)?): () -> TCreates a lightweight computed without a node wrapper and returns its tracked getter function. Owned by the active scope or reaction like Flux.computed.
local count, setCount = Flux.createSignal(1)
local doubled = Flux.createMemo(function()
return count() * 2
end)createEffect from Graph
Flux.createEffect(fn: (...any) -> ...any)Creates a lightweight effect without returning a node wrapper. Owned by the active scope or reaction like Flux.effect.
local count, setCount = Flux.createSignal(0)
Flux.createEffect(function()
print("count is", count())
end)getter from Graph
Flux.getter(node: any): anyReturns a plain function that reads node with tracking, avoiding wrapper __call overhead in hot loops.
local count = Flux.signal(0)
local getCount = Flux.getter(count)
Flux.effect(function()
print(getCount())
end)setter from Graph
Flux.setter(node: any): anyReturns a plain function that writes node (setter(value, force)), avoiding wrapper __call overhead in hot loops.
scope from Graph
Runs fn in a new owner scope and returns (scope, result). Calling scope:Destroy() tears down every computed, effect, instance, and cleanup created inside fn.
local scope, frame = Flux.scope(function() return Flux.new "Frame" { Parent = gui } end)
scope:Destroy() -- destroys the frame and everything bound to itflush from Graph
Flux.flush()Runs all queued effects immediately instead of waiting for the next frame.
cleanup from Graph
Flux.cleanup(obj: Cleanable)Registers obj to be disposed via Flux.dispose before the running reaction re-runs and when its owner is destroyed. Cleanup functions receive (previousValue, isDestroyed).
Flux.effect(function()
local connection = button.Activated:Connect(onClick)
Flux.cleanup(connection)
end)dispose from Graph
Flux.dispose(obj: Cleanable?)Tears down obj immediately (functions, instances, connections, threads, objects with Destroy/Disconnect methods, or arrays of cleanables). Runs untracked and warns on error instead of throwing.
local connections = { part.Touched:Connect(onTouched), part.Destroying:Connect(onGone) }
Flux.dispose(connections)getOwner from Graph
Flux.getOwner(): Owner?Returns the active reactive owner, or nil at the root. Pass it to Flux.withOwner to attach deferred work to the same scope.
withOwner from Graph
Flux.withOwner(node: any, fn: () -> ...any): ...anyRuns fn with owner (from Flux.getOwner, a node, or nil for unowned roots) as the active owner and restores its captured context. If owner is already destroyed, anything created inside fn is disposed as soon as fn finishes.
read from Graph
Flux.read(object: any): anyReads a Reactive value (node, getter function, or plain value) and subscribes the running reaction if it's dynamic.
local function Label(props: { text: Flux.Reactive<string> })
return Flux.new "TextLabel" { Text = function() return string.upper(Flux.read(props.text)) end }
endraw from Graph
Flux.raw(object: any): anyReads a Reactive value (node, getter function, or plain value) without subscribing the running reaction.
untrack from Graph
Flux.untrack(fn: (() -> ...any)?): ...anyRuns fn without dependency tracking and returns its result. Called with no arguments (Flux.untrack()), it suspends tracking for the rest of the current reaction body or until Flux.retrack().
Flux.effect(function()
local id = selected() -- tracked
local name = Flux.untrack(function() return names()[id] end) -- not tracked
end)retrack from Graph
Flux.retrack()Resumes tracking after a bare Flux.untrack() in the same function body.
Flux.untrack()
local snapshot = rows()
Flux.retrack()isNode from Graph
Flux.isNode(object: any): booleanReturns true if object is a Flux node.
isReactive from Graph
Flux.isReactive(): booleanReturns true if called inside a tracking computed or effect.
on from Bind
Flux.on<D, R>(deps: any, fn: (input: any, prevInput: any?, prevResult: R?) -> R, defer: boolean?): (prevResult: R?) -> R?Wraps fn so a computed or effect tracks only deps and runs fn(input, prevInput, prevResult) untracked. Pass defer = true to skip the initial run and fire only when deps change.
listen from Bind
Flux.listen<T>(node: Graph.Node<T>, fn: (value: T) -> ()): () -> ()Subscribes fn to updates of node with RBXScriptSignal:Connect semantics and returns an unsubscribe function. Fires on each flush after node changes, spawning fn(value) on its own thread via task.spawn so callbacks may yield freely.
context from Graph
Flux.context(default: any): anyCreates a context with the given default value for passing data down a component tree without prop drilling.
local Theme = Flux.context("dark")
Theme:provide("light", function() return App {} end) -- App and everything it builds reads "light"bindContext from Graph
Flux.bindContext<A..., R...>(fn: (A...) -> R...): (A...) -> R...Wraps fn so every call sees the context values active when bindContext was called. Event handlers in Flux.new/Flux.edit do this automatically.
local onClick = Flux.bindContext(function()
print(ThemeContext:get()) -- the value provided where onClick was made
end)async from Async
Flux.async(source: any, fetcher: any, initialValue: any): Async<any>Runs yielding work off the reactive graph and exposes its progress as .data, .error, .loading, and .state nodes. fetcher(value, previous, refetching) runs untracked whenever source is truthy, and stale in-flight results are discarded automatically.
local profile = Flux.async(userId, function(id) return Players:GetNameFromUserIdAsync(id) end)
Flux.new "TextLabel" { Text = function() return profile.data() or "Loading" end }selector from Conditional
Flux.selector<S, K>(source: S, equals: ((sourceValue: Graph.Unwrap<S>, key: K) -> boolean)?): Selector<K>Creates a keyed selector that tracks which key matches source in O(1) (or O(observed keys) with a custom equals comparator).
store from Store
Flux.store<T>(initialState: T): TWraps a plain table in a deep reactive proxy that tracks each read key, nested table, and array length independently. Values that already have a metatable (such as Flux nodes or class instances) are left untouched.
split from Edit
Flux.split(props: any, keys: any, ...: any): ...anyPartitions props into one table per keys group plus a final table holding every remaining key, leaving props untouched. Pass a schema table or an annotated key-literal array ({ "label" | "onClick" }) to preserve exact Pick/Omit types on a single group.
local OWN: { "label" | "onClick" } = { "label", "onClick" }
local own, rest = Flux.split(props, OWN)safe from Graph
Flux.safe<T>(tryFn: () -> T, fallback: T | (err: unknown) -> T, equals: ((a: T, b: T) -> boolean)?): Node<T>Creates a computed that evaluates tryFn and returns fallback (a static value or an untracked (err) -> T function) if tryFn throws. Automatically recovers when tracked dependencies change.
property from Bind
Flux.property<I, K>(instance: I & Instance, property: K | "Name"): Graph.Node<Type.PropertyType<I, K>>Creates a node mirroring an Instance property, an attribute ($Name or _attr_Name), or a CollectionService tag (#Tag or _tag_Tag). Disconnects automatically when the node or its owning scope is destroyed.
local text = Flux.property(textBox, "Text")
local health = Flux.property(character, "$Health")
local isEnemy = Flux.property(character, "#Enemy")model from Bind
Flux.model<N>(node: N): Graph.Unwrap<N>Wraps a reactive node for two-way binding on an Instance property, attribute, or tag. Updates the instance from node and writes changes back to node when the instance fires its changed signal.
isModel from Bind
Flux.isModel(value: unknown): booleanReturns true when value is a Flux.model wrapper.
modelNode from Bind
Flux.modelNode(value: unknown): Graph.Node<any>?Returns the underlying node from a Flux.model wrapper, or nil if value is not a model.
local node = Flux.modelNode(props.value)
if node then
node:set(text)
endshow from Conditional
Flux.show<T, F>(condition: unknown, component: (value: () -> any) -> T, fallback: ((value: () -> any) -> F)?): Node<T | F>Mounts component while condition is truthy, or fallback when falsy, in its own child scope. Rebuilds only when truthiness flips (use Flux.showKeyed to rebuild on every identity change).
showKeyed from Conditional
Flux.showKeyed<T, F>(condition: unknown, component: (value: () -> any) -> T, fallback: ((value: () -> any) -> F)?): Node<T | F>Mounts component while condition is truthy (or fallback when falsy) and remounts in a fresh scope whenever condition changes identity.
switch from Conditional
Flux.switch<S>(source: S)Mounts the branch factory matching source's current value in its own child scope. Use [Flux.otherwise] in map as a catch-all branch for unmatched values.
presence from Conditional
Flux.presence<T>(condition: unknown, component: (exiting: Node<boolean>, done: () -> ()) -> T): Node<T?>Mounts component(exiting, done) while condition is truthy and keeps it mounted while exiting() is true until done() is called. If condition turns truthy again before done() runs, exiting flips back to false without remounting.
pick from Conditional
Flux.pick(condition: unknown, whenTrue: any, whenFalse: any?): Node<any>Derives a node returning whenTrue while condition is truthy and whenFalse otherwise. Only the active branch is read, and no branch scope is created.
fallback from Conditional
Flux.fallback<V, D>(value: V, default: D): Node<NonNil<Graph.Unwrap<V>> | Graph.Unwrap<D>>Derives a node returning value when non-nil, or default when value is nil. Preserves false instead of replacing it like or.
forValue from Conditional
Flux.forValue<L, U>(list: L, mapFn: (index: Node<number>, value: Item<L>) -> U): Node<{ U }>Maps list by item identity, running mapFn(index, value) once per unique value and updating index when an item moves. Values must be unique (use Flux.forIndex for primitive or duplicate values).
forIndex from Conditional
Flux.forIndex<L, U>(list: L, mapFn: (index: number, item: Node<Item<L>>) -> U): Node<{ U }>Maps list by numeric index, running mapFn(index, item) once per slot and updating item in place when the value at that index changes.
spring from Motion
Flux.spring<A>(target: A, frequency: Reactive<number>?, damping: Reactive<number>?, initialVelocity: any?): Spring<Unwrap<A>>Creates a node that animates toward target using an analytic harmonic oscillator (frequency in Hz and damping ratio both default to 1 and may be reactive). Retargets preserve current velocity.
local size = Flux.spring(function() return if open() then 300 else 0 end, 4)tween from Motion
Flux.tween<A>(target: A, tweenInfo: Reactive<TweenInfo>?): Graph.Node<Unwrap<A>>Creates a node that eases toward target over a TweenInfo curve. When target or tweenInfo changes, the tween restarts from its current value without waiting for DelayTime.
padding from Layout
Flux.padding(value: Length | PaddingSides | Graph.Node<any> | (() -> Length | Insets)): UIPaddingCreates a UIPadding from a single length, a { top, bottom, left, right, x, y } table, or a reactive source. Plain number values are interpreted as offset pixels.
corner from Layout
Flux.corner(radius: ReactiveLength | CornerSides?): UICornerCreates a UICorner from an offset pixel radius, a UDim, or a per-corner { topLeft, topRight, bottomLeft, bottomRight, top, bottom, left, right, radius } table.
stroke from Layout
Flux.stroke(config: StrokeConfig?): UIStrokeCreates a UIStroke with static or reactive thickness, color, transparency, mode, joins, position, and offset.
aspectRatio from Layout
Flux.aspectRatio(ratio: Reactive<number>, aspectType: Reactive<"fit" | "scale" | Enum.AspectType>?, dominantAxis: Reactive<"width" | "height" | Enum.DominantAxis>?): UIAspectRatioConstraintCreates a UIAspectRatioConstraint with ratio, aspectType ("fit" or "scale"), and dominantAxis ("width" or "height").
list from Layout
Flux.list(config: ListConfig?): UIListLayoutCreates a UIListLayout with SortOrder = LayoutOrder and flexbox-style gap, direction, align (cross-axis), justify (main-axis), and wraps options.
grid from Layout
Flux.grid(config: GridConfig?): UIGridLayoutCreates a UIGridLayout with SortOrder = LayoutOrder and cell, gap, fill, align, justify, and maxCells options.
flex from Layout
Flux.flex(mode: Reactive<FlexMode | Enum.UIFlexMode>?): UIFlexItemCreates a UIFlexItem with mode ("fill" by default, "grow", "shrink", or "none").
gradient from Layout
Flux.gradient(config: GradientConfig?): UIGradientCreates a UIGradient from single values, evenly spaced stop arrays, or sequences for color and transparency.
sizeConstraint from Layout
Flux.sizeConstraint(config: SizeConstraintConfig?): UISizeConstraintCreates a UISizeConstraint from min/max Vector2 bounds or per-axis minWidth, minHeight, maxWidth, and maxHeight bounds.
textSizeConstraint from Layout
Flux.textSizeConstraint(config: TextSizeConstraintConfig?): UITextSizeConstraintCreates a UITextSizeConstraint bounding text size between min and max pixels.
Metamethods
__call
Flux.__call(_: any, obj: any, propertyName: string?): Graph.Node<any>Terse untyped constructor for a signal (Flux(value)), computed (Flux(fn)), or instance property node (Flux(instance, key)). Use Flux.signal, Flux.computed, and Flux.property when you want strict type inference.
local size = Flux(frame, "AbsoluteSize")Clock
Shared time source for timers, frame callbacks, and deterministic test stepping. Call Clock.manual(true) and Clock.step(seconds) in tests to advance timers, motion, and frame flushes in order.
now from Clock
Flux.Clock.now(): numberSeconds on a monotonic clock, for measuring intervals: os.clock() in a game, virtual time on a manual clock.
wall from Clock
Flux.Clock.wall(): numberUnix time in seconds, for dates and countdowns shared between players: workspace:GetServerTimeNow() in a game, 2026-01-01T00:00:00Z + now() on a manual clock.
delay from Clock
Flux.Clock.delay<A...>(seconds: number?, fn: ((A...) -> ...any) | thread, ...: A...): threadRuns fn(...) (or resumes a thread) after seconds, like task.delay. Returns the thread, for cancel.
wait Yields from Clock
Flux.Clock.wait(seconds: number?): numberYields the running thread for seconds (default: one frame), like task.wait, and returns the time it waited. On a manual clock it waits for a step to pass the deadline, so it needs a coroutine to yield.
defer from Clock
Flux.Clock.defer<A...>(fn: ((A...) -> ...any) | thread, ...: A...): threadRuns fn(...) (or resumes a thread) once the current work finishes, like task.defer. On a manual clock it waits for drain() (which every step frame calls). Returns the thread, for cancel.
cancel from Clock
Flux.Clock.cancel(thread: thread)Cancels a thread from delay, defer or a wait, like task.cancel.
connect from Clock
Flux.Clock.connect(phase: Phase, fn: (dt: number) -> ()): () -> ()Calls fn(dt) every frame at phase ("PreRender", "RenderStepped" or "Heartbeat"). Returns a function that disconnects it. A manual clock calls it from step instead of the engine's frames.
manual from Clock
Flux.Clock.manual(on: boolean)Toggles manual clock mode for tests (headless Luau is always manual). Disabling manual mode clears pending tasks via Clock.reset().
isManual from Clock
Flux.Clock.isManual(): booleanTests only: whether the clock is manual.
step from Clock
Flux.Clock.step(seconds: number, frameLength: number?)Tests only: advances a manual clock by seconds, in frames of at most frameLength seconds (default 1/60). step(0) runs one frame of zero length: due timers, subscribers, a Flux step and the deferred work.
drain from Clock
Flux.Clock.drain()Tests only: runs deferred work until none is left, including work it defers in turn. Errors after 10000 calls, when deferred work keeps deferring more.
reset from Clock
Flux.Clock.reset()Tests only: drops every pending timer, wait, deferred call and manual subscriber. now keeps its value.
Interact
Read-only interaction state nodes (hover, press, selected, focused) and pointer hit-testing helpers (pointIn, sunk, covered).
pointIn from Interact
Flux.Interact.pointIn(x: number, y: number, object: GuiObject): booleanWhether the point (x, y) lies within object's absolute bounds (inclusive, ignoring rotation). Coordinates are inset-relative, matching InputObject.Position and AbsolutePosition.
sunk from Interact
Flux.Interact.sunk(x: number, y: number, object: GuiObject, token: any?): booleanReturns true when input at (x, y) would be claimed by an Active or input-sinking GUI rendered above object (or while the Roblox escape menu is open). Pass the InputObject as token to share the hit-test query across multiple controls on the same input event.
covered from Interact
Flux.Interact.covered(x: number, y: number, object: GuiObject, token: any?): booleanReturns true when input at (x, y) would be claimed by an Active or input-sinking GUI above object that is not a descendant of object.
hover from Interact
Flux.Interact.hover(object: GuiObject, options: HoverOptions?): Graph.Node<boolean>Returns a read-only boolean node that is true while a pointer or touch contact is inside object with no input-claiming GUI above it. Pass { within = true } on containers so child controls inside object do not count as covering it.
press from Interact
Flux.Interact.press(object: GuiObject): Graph.Node<boolean>Returns a read-only boolean node that is true while object is held down by pointer, touch, or gamepad/keyboard activation (ButtonA/Enter). Stays true until that input ends anywhere on screen.
selected from Interact
Flux.Interact.selected(object: GuiObject): Graph.Node<boolean>Returns a read-only boolean node tracking whether object is currently GuiService.SelectedObject.
focused from Interact
Flux.Interact.focused(textBox: TextBox): Graph.Node<boolean>Returns a read-only boolean node tracking whether textBox currently has keyboard focus.
Motion
Advances active Flux.spring and Flux.tween nodes. Stepped automatically each frame, or manually in tests via Motion.step(dt).
step from Motion
Flux.Motion.step(dt: number?)Advances every active spring and tween by dt seconds (or the time since the last step). Wired to RunService automatically in Roblox, so you only call this in tests (Flux.Motion.step(1 / 60)).
Responsive
Reactive nodes for viewport size, UI scale, breakpoints, device platform, active input mode, and accessibility settings.
config Read Only from Responsive
Flux.Responsive.config: ConfigDefault responsive configuration shared by derived nodes. Mutate once at startup before building UI.
platform Read Only from Responsive
Flux.Responsive.platform: Graph.Node<Platform>Active device class ("vr", "console", "pc", or "mobile"), updated live on the client ("pc" off-client).
viewport Read Only from Responsive
Flux.Responsive.viewport: Graph.Node<Vector2>The active camera's ViewportSize as a node, live on the client.
scale Read Only from Responsive
Flux.Responsive.scale: Graph.Node<number>UI scale factor derived from viewport (1.0 at config.reference).
breakpoint Read Only from Responsive
Flux.Responsive.breakpoint: Graph.Node<Breakpoint>Size class ("phone" | "tablet" | "desktop") derived from viewport width.
displaySize Read Only from Responsive
Flux.Responsive.displaySize: Graph.Node<DisplaySize>Physical screen size class ("Small", "Medium", or "Large") mirroring GuiService.ViewportDisplaySize.
input Read Only from Responsive
Flux.Responsive.input: Graph.Node<Input>Active input mode ("keyboard", "touch", or "gamepad") tracking UserInputService.PreferredInput on the client.
textSize Read Only from Responsive
Flux.Responsive.textSize: Graph.Node<TextSize>Player's preferred text size ("Medium", "Large", "Larger", or "Largest") from GuiService.PreferredTextSize. Roblox scales rendered text automatically, so use this to adjust surrounding container spacing rather than multiplying TextSize.
reducedMotion Read Only from Responsive
Flux.Responsive.reducedMotion: Graph.Node<boolean>Tracks GuiService.ReducedMotionEnabled (true when the player prefers reduced motion).
preferredTransparency Read Only from Responsive
Flux.Responsive.preferredTransparency: Graph.Node<number>Tracks GuiService.PreferredTransparency from 0 (opaque backgrounds) to 1 (default).
scaleOf from Responsive
Flux.Responsive.scaleOf(partial: PartialConfig?): Graph.Node<number>Factory escape hatch: a scale node with per-surface config (merged over defaults).
breakpointOf from Responsive
Flux.Responsive.breakpointOf(partial: PartialConfig?): Graph.Node<Breakpoint>Factory escape hatch: a breakpoint node with per-surface thresholds.
Store
Array mutation (insert, remove, move), snapshot diffing (reconcile), unwrapping (unwrap), and teardown (Destroy) for Flux.store proxies.
insert from Store
Flux.Store.insert(proxy: any, posOrValue: any, value: any?)Inserts value into a store array (appending with 2 arguments, or inserting at posOrValue with 3) and notifies length and index observers.
remove from Store
Flux.Store.remove(proxy: any, pos: number?): anyRemoves and returns the element at pos (defaulting to the last element) from a store array and notifies length and index observers.
move from Store
Flux.Store.move(proxy: any, from: number, to: number)Moves the element at 1-based index from to to in a single tracked step without tearing down nested item proxies.
reconcile from Store
Flux.Store.reconcile<T>(proxy: T, newData: T, key: string?): TDiffs newData into the store proxy in place, firing only changed leaf nodes and reusing unchanged nested proxies. Pass key to match array elements by element[key] instead of array index.
unwrap from Store
Flux.Store.unwrap<T>(proxy: T): TReturns the raw, unproxied backing table of a store for untracked reads or serialization.
Destroy from Store
Flux.Store.Destroy<T>(proxy: T)Tears down a store and all of its nested proxies, disposing their per-key nodes via Flux.dispose while leaving the raw backing table intact.