mirror of
https://github.com/rojo-rbx/rojo.git
synced 2026-10-23 14:01:37 +00:00
update docs
This commit is contained in:
parent
0b1e8c89dc
commit
7b73720143
586 changed files with 5616 additions and 1325 deletions
50
.cursor/rules/vide/api/animation.md
Normal file
50
.cursor/rules/vide/api/animation.md
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
# Animation
|
||||
|
||||
## spring() <Badge type="tip" text="STABLE"><a href="/vide/api/reactivity-core#Scopes">REACTIVE</a></Badge>
|
||||
|
||||
Returns a new source with a value always moving torwards the input source value.
|
||||
|
||||
- **Type**
|
||||
|
||||
```luau
|
||||
function spring<T>(
|
||||
source: () -> T & Animatable,
|
||||
period: number = 1,
|
||||
damping_ratio: number = 1
|
||||
): (() -> T, SpringControl<T>)
|
||||
|
||||
type Animatable = number | CFrame | Color3 | UDim | UDim2 | Vector2 | Vector3 | Rect
|
||||
|
||||
type SpringControl<T> = ({
|
||||
position: T?,
|
||||
velocity: T?,
|
||||
impulse: T?
|
||||
}) -> ()
|
||||
```
|
||||
|
||||
- **Details**
|
||||
|
||||
Creates a reactive scope internally to detect source updates.
|
||||
|
||||
The movement is physically simulated according to a
|
||||
[spring](https://en.wikipedia.org/wiki/Simple_harmonic_motion).
|
||||
|
||||
`period` is the amount of time in seconds it takes for the spring to
|
||||
complete one full cycle if undamped.
|
||||
|
||||
`damping_ratio` is the amount of resistance applied to the spring.
|
||||
|
||||
- \>1 = Overdamped - slowly reaches target without any overshoot.
|
||||
- 1 = Critically damped - reaches target without any overshoot.
|
||||
- <1 = Underdamped - reaches target with some overshoot.
|
||||
- 0 = Undamped - never stabilizes, oscillates forever.
|
||||
|
||||
By default, the spring solver is ran at 120 Hz in
|
||||
[`Heartbeat`](https://create.roblox.com/docs/reference/engine/classes/RunService#Heartbeat).
|
||||
You can change when the solver runs by calling `vide.step(dt)`, which will
|
||||
advance the simulation time by `dt` seconds and automatically stop the
|
||||
solver running in heartbeat.
|
||||
|
||||
::: warning
|
||||
Large periods or damping ratios can break the spring.
|
||||
:::
|
||||
152
.cursor/rules/vide/api/creation.md
Normal file
152
.cursor/rules/vide/api/creation.md
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
# Element Creation
|
||||
|
||||
## create()
|
||||
|
||||
Creates a new UI element, applying any given properties.
|
||||
|
||||
- **Type**
|
||||
|
||||
```luau
|
||||
function create(class: string): (Properties) -> Instance
|
||||
function create(instance: Instance): (Properties) -> Instance
|
||||
|
||||
type Properties = Map<string|number, unknown>
|
||||
```
|
||||
|
||||
- **Details**
|
||||
|
||||
The function can take either a `string` or an `Instance` as its first argument.
|
||||
|
||||
- If given a `string`, a new instance with the same class name will be created.
|
||||
- If given an `Instance`, a new instance that is a clone of the given instance
|
||||
will be created.
|
||||
|
||||
This returns another function that is used to apply any properties to the new
|
||||
instance.
|
||||
|
||||
- **Property setting rules**
|
||||
|
||||
- **index is string:**
|
||||
- **value is function:**
|
||||
- **property is event:** connect function as callback
|
||||
- **property is not event:** create effect to update property
|
||||
- **value is not function:** set property to value
|
||||
- **index is number:**
|
||||
- **value is action:** run action
|
||||
- **value is table:** recurse table
|
||||
- **value is function:** create effect to update children
|
||||
- **value is instance:** set instance as child
|
||||
|
||||
- **Example**
|
||||
|
||||
Basic element creation.
|
||||
|
||||
```luau
|
||||
local frame = create "TextButton" {
|
||||
Name = "Button",
|
||||
Size = UDim2.fromOffset(200, 160),
|
||||
|
||||
Activated = function()
|
||||
print "clicked"
|
||||
end,
|
||||
|
||||
create "UICorner" {}
|
||||
}
|
||||
```
|
||||
|
||||
## action()
|
||||
|
||||
Creates a special object that can be passed to `create()` to invoke custom
|
||||
actions on instances.
|
||||
|
||||
- **Type**
|
||||
|
||||
```luau
|
||||
function action((Instance) -> (), priority: number = 1): Action
|
||||
```
|
||||
|
||||
- **Details**
|
||||
|
||||
When passed to `create()`, the function is called with the instance being
|
||||
created as the only argument. Actions take precedence over property and
|
||||
child assignments.
|
||||
|
||||
A priority can be optionally specified to ensure certain actions run after
|
||||
other actions. Lower priority values are ran first.
|
||||
|
||||
- **Example**
|
||||
|
||||
An action to listen to changed properties:
|
||||
|
||||
```luau
|
||||
local function changed(property: string, fn: (new) -> ())
|
||||
return action(function(instance)
|
||||
local cn = instance:GetPropertyChangedSignal(property):Connect(function()
|
||||
fn(instance[property])
|
||||
end)
|
||||
|
||||
-- disconnect on scope destruction to allow gc of instance
|
||||
cleanup(function()
|
||||
cn:Disconnect()
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
local output = source ""
|
||||
|
||||
create "TextBox" {
|
||||
-- will update the output source anytime the text property is changed
|
||||
changed("Text", output)
|
||||
}
|
||||
```
|
||||
|
||||
## changed()
|
||||
|
||||
A wrapper for `action()` to listen for property changes.
|
||||
|
||||
- **Type**
|
||||
|
||||
```luau
|
||||
function changed(property: string, fn: (unknown) -> ()): Action
|
||||
```
|
||||
|
||||
- **Details**
|
||||
|
||||
Will run the given function immediately and whenever the property updates.
|
||||
|
||||
The function is called with the updated property value.
|
||||
|
||||
Runs with an action priority of 1.
|
||||
|
||||
## mount() <Badge type="info" text="STABLE"><a href="/vide/api/reactivity-core#Scopes">STABLE</a></Badge>
|
||||
|
||||
Runs a function in a new stable scope and optionally applies its result to a
|
||||
target instance.
|
||||
|
||||
- **Type**
|
||||
|
||||
```luau
|
||||
function mount<T>(component: () -> T, target: Instance?): () -> ()
|
||||
```
|
||||
|
||||
- **Details**
|
||||
|
||||
This is a utility for `root()` when parenting a component to an existing
|
||||
instance.
|
||||
|
||||
The result of the function is applied to a target in the same way
|
||||
properties are using `create()`.
|
||||
|
||||
Returns a function that when called will destroy the stable scope.
|
||||
|
||||
- **Example**
|
||||
|
||||
```luau
|
||||
local function App()
|
||||
return create "ScreenGui" {
|
||||
create "TextLabel" { Text = "Vide" }
|
||||
}
|
||||
end
|
||||
|
||||
local destroy = mount(App, game.StarterGui)
|
||||
```
|
||||
155
.cursor/rules/vide/api/reactivity-core.md
Normal file
155
.cursor/rules/vide/api/reactivity-core.md
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
# Reactivity: Core
|
||||
|
||||
## Scopes
|
||||
|
||||
Vide code can run in one of two scopes: <Badge type="info" text="STABLE"><a href="/vide/api/reactivity-core#Scopes">STABLE</a></Badge> or <Badge type="tip" text="STABLE"><a href="/vide/api/reactivity-core#Scopes">REACTIVE</a></Badge>.
|
||||
|
||||
- Reactive scopes rerun if a source read within updates.
|
||||
- Stable scopes never rerun.
|
||||
- Reactive scopes cannot be created directly within another reactive scope.
|
||||
- When a scope is destroyed, all scopes created within are also destroyed.
|
||||
|
||||
Different functions in Vide's API will run code in different scopes.
|
||||
|
||||
:::warning
|
||||
Yielding is not allowed in any stable or reactive scope. Strict mode will check
|
||||
for this.
|
||||
:::
|
||||
|
||||
## root() <Badge type="info" text="STABLE"><a href="/vide/api/reactivity-core#Scopes">STABLE</a></Badge>
|
||||
|
||||
Runs a function in a new stable scope.
|
||||
|
||||
- **Type**
|
||||
|
||||
```luau
|
||||
function root<T...>(fn: (Destructor) -> T...): (Destructor, T...)
|
||||
|
||||
type Destructor = () -> ()
|
||||
```
|
||||
|
||||
- **Details**
|
||||
|
||||
Returns a destructor and any values returned by the callback.
|
||||
|
||||
## source()
|
||||
|
||||
Creates a new source.
|
||||
|
||||
- **Type**
|
||||
|
||||
```luau
|
||||
function source<T>(value: T): Source<T>
|
||||
|
||||
type Source<T> =
|
||||
() -> T -- get
|
||||
& (T) -> () -- set
|
||||
```
|
||||
|
||||
- **Details**
|
||||
|
||||
Call the returned source with no argument to read its value.
|
||||
Call the returned source with an argument to set its value.
|
||||
|
||||
- **Example**
|
||||
|
||||
```luau
|
||||
local count = source(0)
|
||||
print(count())-- 0
|
||||
count(count() + 1)
|
||||
print(count()) -- 1
|
||||
```
|
||||
|
||||
## effect() <Badge type="tip" text="STABLE"><a href="/vide/api/reactivity-core#Scopes">REACTIVE</a></Badge>
|
||||
|
||||
Runs a function in a new reactive scope.
|
||||
|
||||
- **Type**
|
||||
|
||||
```luau
|
||||
function effect(fn: () -> ())
|
||||
```
|
||||
|
||||
- **Details**
|
||||
|
||||
The function is ran once immediately.
|
||||
|
||||
- **Example**
|
||||
|
||||
```luau
|
||||
local count = source(1)
|
||||
|
||||
effect(function()
|
||||
print(count())
|
||||
end)
|
||||
|
||||
-- prints 1
|
||||
|
||||
count(2)
|
||||
|
||||
-- prints 2
|
||||
```
|
||||
|
||||
## derive() <Badge type="tip" text="STABLE"><a href="/vide/api/reactivity-core#Scopes">REACTIVE</a></Badge>
|
||||
|
||||
Runs a function in a new reactive scope to compute a value for new source.
|
||||
|
||||
- **Type**
|
||||
|
||||
```luau
|
||||
function derive<T>(fn: () -> T): () -> T
|
||||
```
|
||||
|
||||
- **Details**
|
||||
|
||||
Anytime the reactive scope reruns, the output source value is set to what is
|
||||
returned.
|
||||
|
||||
The function is ran once immediately.
|
||||
|
||||
- **Example**
|
||||
|
||||
```luau
|
||||
local count = source(0)
|
||||
local text = derive(function() return `count: {count()}` end)
|
||||
|
||||
print(text()) -- "count: 0"
|
||||
|
||||
count(1)
|
||||
|
||||
print(text()) -- "count: 1"
|
||||
```
|
||||
|
||||
A `derive()` should be used instead of a pure function when you expect it to
|
||||
be read multiple times between updates, because `derive()` will cache the
|
||||
result to prevent recomputing it on every read.
|
||||
|
||||
::: code-group
|
||||
|
||||
```luau [Pure Function]
|
||||
local count = source(0)
|
||||
|
||||
local text = function()
|
||||
print "ran"
|
||||
return `count: {count()}`
|
||||
end
|
||||
|
||||
count(1)
|
||||
print(text()) -- prints "ran" followed by "count: 1"
|
||||
print(text()) -- prints "ran" followed by "count: 1"
|
||||
```
|
||||
|
||||
```luau [Derived Source]
|
||||
local count = source(0)
|
||||
|
||||
local text = derive(function() -- [!code highlight]
|
||||
print "ran"
|
||||
return `count: {count()}`
|
||||
end) -- [!code highlight]
|
||||
|
||||
count(1) -- prints "ran"
|
||||
print(text()) -- prints "count: 1"
|
||||
print(text()) -- prints "count: 1"
|
||||
```
|
||||
|
||||
:::
|
||||
229
.cursor/rules/vide/api/reactivity-dynamic.md
Normal file
229
.cursor/rules/vide/api/reactivity-dynamic.md
Normal file
|
|
@ -0,0 +1,229 @@
|
|||
# Reactivity: Dynamic Scopes
|
||||
|
||||
Dynamic scopes are scopes that are created or destroyed in response to
|
||||
source updates. Vide provides functions for some common use-cases for dynamic scopes.
|
||||
|
||||
## show() <Badge type="tip" text="STABLE"><a href="/vide/api/reactivity-core#Scopes">REACTIVE</a></Badge>
|
||||
|
||||
Shows a component if the source is truthy. Optionally shows a fallback component
|
||||
if the source is falsey.
|
||||
|
||||
- **Type**
|
||||
|
||||
```luau
|
||||
function show<T>(source: () -> unknown, component: Constructor<T>): () -> T?
|
||||
function show<T, U>(source: () -> unknown, component: Constructor<T>, fallback: () -> U): () -> T | U
|
||||
|
||||
type Constructor<T> = () -> (T, number?)
|
||||
```
|
||||
|
||||
- **Details**
|
||||
|
||||
Creates a reactive scope internally to detect source updates.
|
||||
|
||||
The component is run in a stable scope when truthy, otherwise the stable
|
||||
scope is destroyed.
|
||||
|
||||
Returns a source holding an instance of the currently shown component or
|
||||
`nil` if no component is currently shown.
|
||||
|
||||
Destruction of the scope can be delayed by returning the number of seconds
|
||||
to delay by, after the component.
|
||||
|
||||
## switch() <Badge type="tip" text="STABLE"><a href="/vide/api/reactivity-core#Scopes">REACTIVE</a></Badge>
|
||||
|
||||
Shows one of a set of components depending on a source and a mapping table.
|
||||
|
||||
- **Type**
|
||||
|
||||
```luau
|
||||
function switch<K, V>(source: () -> K): (map: Map<K, Constructor<V>>): () -> V?
|
||||
|
||||
type Constructor<T> = () -> (T, number?)
|
||||
```
|
||||
|
||||
- **Details**
|
||||
|
||||
Creates a reactive scope internally to detect source updates.
|
||||
|
||||
When the source updates, its value is inputted into a map to get a component
|
||||
constructor. This component is then run in a stable scope. The previous
|
||||
stable scope is destroyed.
|
||||
|
||||
Returns a source holding an instance of the currently shown component or
|
||||
`nil` if no component is currently shown.
|
||||
|
||||
Destruction of the scope can be delayed by returning the number of seconds
|
||||
to delay by, after the component.
|
||||
|
||||
- **Example**
|
||||
|
||||
```luau
|
||||
local logged = source(false)
|
||||
|
||||
local button = switch(logged) {
|
||||
[true] = function()
|
||||
return Button { Text = "Log out", Toggle = logged }
|
||||
end,
|
||||
|
||||
[false] = function()
|
||||
return Button { Text = "Log in", Toggle = logged }
|
||||
end
|
||||
}
|
||||
```
|
||||
|
||||
## indexes() <Badge type="tip" text="STABLE"><a href="/vide/api/reactivity-core#Scopes">REACTIVE</a></Badge>
|
||||
|
||||
Shows a component for each index in a table.
|
||||
|
||||
- **Type**
|
||||
|
||||
```luau
|
||||
function indexes<KI, VI, VO>(
|
||||
source: () -> Map<KI, VI>,
|
||||
constructor: (value: () -> VI, index: KI) -> (VO, number?)
|
||||
): Array<VO>
|
||||
```
|
||||
|
||||
- **Details**
|
||||
|
||||
Creates a reactive scope internally to detect source updates.
|
||||
|
||||
When the source table updates, a component is generated for each index in
|
||||
the table.
|
||||
|
||||
- For any added index, the `constructor` function is run in a new stable
|
||||
scope to produce an instance that is cached.
|
||||
- For any removed index, the stable scope for that index is destroyed.
|
||||
|
||||
The `constructor` function is called with:
|
||||
|
||||
1. A *source containing the index's value*.
|
||||
2. The *index itself*.
|
||||
|
||||
Anytime an existing index's value changes, the `constructor` function is not
|
||||
rerun, instead, that index's corresponding source is updated with the new
|
||||
value.
|
||||
|
||||
Returns a source holding an array of instances currently shown.
|
||||
|
||||
Destruction of the scope can be delayed by returning the number of seconds
|
||||
to delay by, after the component.
|
||||
|
||||
- **Example**
|
||||
|
||||
```luau
|
||||
type Item = {
|
||||
name: string,
|
||||
icon: number
|
||||
}
|
||||
|
||||
local items = source {} :: () -> Array<Item>
|
||||
|
||||
local displays = indexes(items, function(item, i)
|
||||
return ItemDisplay {
|
||||
Name = function()
|
||||
return i .. ": " .. item().name
|
||||
end,
|
||||
|
||||
Image = function()
|
||||
return "rbxassetid://" .. item().icon
|
||||
end,
|
||||
}
|
||||
end)
|
||||
```
|
||||
|
||||
## values() <Badge type="tip" text="STABLE"><a href="/vide/api/reactivity-core#Scopes">REACTIVE</a></Badge>
|
||||
|
||||
Shows a component for each value in a table.
|
||||
|
||||
- **Type**
|
||||
|
||||
```luau
|
||||
function values<KI, VI, VO>(
|
||||
source: () -> Map<KI, VI>,
|
||||
constructor: (value: VI, index: () -> KI) -> (VO, number?)
|
||||
): Array<VO>
|
||||
|
||||
- **Details**
|
||||
|
||||
Operates with the same idea as `indexes()`, but applied to values instead of
|
||||
indexes.
|
||||
|
||||
Creates a reactive scope internally to detect source updates.
|
||||
|
||||
When the source table updates, a component is generated for each value in
|
||||
the table.
|
||||
|
||||
- For any added value, the `constructor` function is run in a new stable scope
|
||||
to produce an instance that is cached.
|
||||
- For any removed value, the stable scope for that value is destroyed.
|
||||
|
||||
The `constructor` function is called with:
|
||||
|
||||
1. The *value itself*.
|
||||
2. A *source containing the value's index*.
|
||||
|
||||
Anytime an existing value's index changes, the `constructor` function is not
|
||||
rerun, instead, that value's corresponding source is updated with the new
|
||||
index.
|
||||
|
||||
Returns a source holding an array of instances currently shown.
|
||||
|
||||
Destruction of the scope can be delayed by returning the number of seconds
|
||||
to delay by, after the component.
|
||||
|
||||
::: warning
|
||||
Having the same values appear multiple times in the input source table can
|
||||
cause unexpected behavior. Strict mode has checks for this.
|
||||
:::
|
||||
|
||||
- **Example**
|
||||
|
||||
```luau
|
||||
type Item = {
|
||||
name: string,
|
||||
icon: number
|
||||
}
|
||||
|
||||
local items = source {} :: () -> Array<Item>
|
||||
|
||||
local displays = values(items, function(item, i)
|
||||
return ItemDisplay {
|
||||
Name = function()
|
||||
return i() .. ": " .. item.Name
|
||||
end
|
||||
|
||||
Image = "rbxassetid://" .. item.icon,
|
||||
}
|
||||
end)
|
||||
```
|
||||
|
||||
- **Extra**
|
||||
|
||||
When should you use `indexes()` and `values()`?
|
||||
|
||||
`values()` should be used when you have a fixed set of objects where the
|
||||
same objects can be re-arranged in the source table. It maps a value to a
|
||||
UI element.
|
||||
|
||||
e.g.
|
||||
- List of all players.
|
||||
- Inventory of items.
|
||||
- Chat message history.
|
||||
- Toast notifications.
|
||||
|
||||
`indexes()` should be used in other cases, especially when your source table
|
||||
has primitive values. It maps an index to a UI element.
|
||||
|
||||
e.g.
|
||||
- List of character or weapon stats.
|
||||
|
||||
In most cases, both functions will produce the same observed result.
|
||||
The main difference is performance, picking the right function to use can
|
||||
result in less property updates and less re-renders. One case to note is
|
||||
that `values()` works nicely when animating re-ordering of instances, since
|
||||
the source index can be used to animate a change in position for the UI
|
||||
element.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
158
.cursor/rules/vide/api/reactivity-utility.md
Normal file
158
.cursor/rules/vide/api/reactivity-utility.md
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
# Reactivity: Utility
|
||||
|
||||
## cleanup()
|
||||
|
||||
Queues a callback to run when a scope is reran or destroyed.
|
||||
|
||||
- **Type**
|
||||
|
||||
```luau
|
||||
function cleanup(v: Function | Disconnectable | Destroyable | thread)
|
||||
|
||||
type Function = () -> ()
|
||||
type Destroyable = { destroy: () -> () }
|
||||
type Disconnectable = { disconnect: () -> () }
|
||||
```
|
||||
|
||||
- **Example**
|
||||
|
||||
```luau
|
||||
local count = source(0)
|
||||
|
||||
local destroy = root(function()
|
||||
effect(function()
|
||||
count()
|
||||
|
||||
cleanup(function()
|
||||
print "cleaned"
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
-- nothing printed yet
|
||||
count(1) -- prints "cleaned"
|
||||
count(2) -- prints "cleaned"
|
||||
destroy() -- prints "cleaned"
|
||||
```
|
||||
|
||||
## untrack() <Badge type="info" text="STABLE"><a href="/vide/api/reactivity-core#Scopes">STABLE</a></Badge>
|
||||
|
||||
Runs a function in a new stable scope.
|
||||
|
||||
- **Type**
|
||||
|
||||
```luau
|
||||
function untrack<T>(source: () -> T): T
|
||||
```
|
||||
|
||||
- **Details**
|
||||
|
||||
Can be used inside a reactive scope to read from sources you do not want
|
||||
tracked by the reactive scope.
|
||||
|
||||
- **Example**
|
||||
|
||||
```luau
|
||||
local a = source(0)
|
||||
local b = source(0)
|
||||
|
||||
local sum = derive(function()
|
||||
return a() + untrack(b)
|
||||
end)
|
||||
|
||||
print(sum()) -- 0
|
||||
b(1) -- untracked so reactive scope created by derive() does not rerun
|
||||
print(sum()) -- 0
|
||||
a(1) -- reactive scope created by derive() reruns
|
||||
print(sum()) -- 2
|
||||
```
|
||||
|
||||
## read()
|
||||
|
||||
Utility used to read a value that is either a primitive or a source.
|
||||
|
||||
- **Type**
|
||||
|
||||
```luau
|
||||
function read<T>(value: T | () -> T): T
|
||||
```
|
||||
|
||||
## batch()
|
||||
|
||||
Runs a function where any source updates made within the function do not
|
||||
trigger effects until after the function ends.
|
||||
|
||||
- **Type**
|
||||
|
||||
```luau
|
||||
function batch(fn: () -> ())
|
||||
```
|
||||
|
||||
- **Details**
|
||||
|
||||
Improves performance when an effect depends on multiple sources, and those
|
||||
sources need to be updated.
|
||||
|
||||
- **Example**
|
||||
|
||||
```luau
|
||||
local a = source(0)
|
||||
local b = source(0)
|
||||
|
||||
effect(function()
|
||||
print(a() + b())
|
||||
end)
|
||||
|
||||
-- prints "0"
|
||||
|
||||
batch(function()
|
||||
a(1) -- no print
|
||||
b(2) -- no print
|
||||
end)
|
||||
|
||||
-- prints "3"
|
||||
```
|
||||
|
||||
## context() <Badge type="info" text="STABLE"><a href="/vide/api/reactivity-core#Scopes">STABLE</a></Badge>
|
||||
|
||||
Creates a new context.
|
||||
|
||||
- **Type**
|
||||
|
||||
```luau
|
||||
function context<T>(default: T): Context<T>
|
||||
|
||||
type Context<T> =
|
||||
() -> T -- get
|
||||
& <U>(T, () -> U) -> U -- set
|
||||
```
|
||||
|
||||
- **Details**
|
||||
|
||||
Calling `context()` returns a new context function.
|
||||
Call this function with no arguments to get the context value.
|
||||
Call this function with a value and a function to create a new context with
|
||||
the given value.
|
||||
|
||||
The new context is run under a stable scope.
|
||||
|
||||
- **Example**
|
||||
|
||||
```luau
|
||||
local theme = context()
|
||||
|
||||
local function Button()
|
||||
print(theme())
|
||||
end
|
||||
|
||||
root(function()
|
||||
theme("light", function()
|
||||
Button() -- prints "light"
|
||||
|
||||
theme("dark", function()
|
||||
Button() -- prints "dark"
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
```
|
||||
|
||||
37
.cursor/rules/vide/api/strict-mode.md
Normal file
37
.cursor/rules/vide/api/strict-mode.md
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
# Strict Mode
|
||||
|
||||
Strict mode is library-wide and can get set by doing:
|
||||
|
||||
```luau
|
||||
vide.strict = true
|
||||
```
|
||||
|
||||
It is automatically enabled when Vide is first required and not running in O2
|
||||
optimization level.
|
||||
|
||||
Strict mode is designed to help the development process by adding safety checks
|
||||
and identifying improper usage.
|
||||
|
||||
Currently, strict mode will:
|
||||
|
||||
1. Run reactive scopes twice when a source updates.
|
||||
2. Throw an error if yields occur where they are not allowed.
|
||||
3. Checks for `indexes()` and `values()` outputting primitive values.
|
||||
4. Checks for `values()` input having duplicate values.
|
||||
5. Checks for duplicate nested properties at same depth.
|
||||
6. Checks for destruction of an active scope.
|
||||
7. Better error reporting and stack traces.
|
||||
|
||||
By rerunning reactive scopes twice each time they update, it helps ensure that
|
||||
computations are pure, and that any cleanup is done correctly.
|
||||
|
||||
Accidental yielding within reactive scopes can break Vide's reactive graph,
|
||||
which strict mode will catch.
|
||||
|
||||
As well as additional safety checks, Vide will dedicate extra resources to
|
||||
recording and better emitting stack traces where errors occur, particularly
|
||||
when implicit effects are created for instance property updating.
|
||||
|
||||
It is recommended to develop UI with strict mode and to disable it when pushing to
|
||||
production. In Roblox, production code compiles at O2 by default, so you do not
|
||||
need to worry about disabling strict mode unless you have manually enabled it.
|
||||
Loading…
Add table
Add a link
Reference in a new issue