Add delayed scope destruction to docs

This commit is contained in:
centauri 2026-01-17 20:15:05 +00:00
parent a0eca04903
commit 6da33722e9
5 changed files with 92 additions and 20 deletions

View file

@ -16,11 +16,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
effects to set children. effects to set children.
- `spring()` returns a second value, a setter to set position, velocity and - `spring()` returns a second value, a setter to set position, velocity and
impulse. impulse.
- Improved `spring()` updating and unscheduling.
- `show()` now receives a source to its callback returning the current value - `show()` now receives a source to its callback returning the current value
of the condition. of the condition.
- Ignore `false` passed as a child. - Ignore `false` passed as a child.
- Flag `vide.defaults` to disable the setting of default properties. - Flag `vide.defaults` to disable the setting of default properties.
- Delayed scope destruction for control flow functions: `show()` `switch()` `indexes()` `values()`. - Delayed scope destruction for control flow functions: `show()` `switch()` `indexes()` `values()`.
- Better `create()` types for the new type solver.
### Changed ### Changed

View file

@ -11,11 +11,11 @@ Returns a new source with a value always moving torwards the input source value.
source: () -> T & Animatable, source: () -> T & Animatable,
period: number = 1, period: number = 1,
damping_ratio: number = 1 damping_ratio: number = 1
): (() -> T, SpringConfig<T>) ): (() -> T, SpringControl<T>)
type Animatable = number | CFrame | Color3 | UDim | UDim2 | Vector2 | Vector3 | Rect type Animatable = number | CFrame | Color3 | UDim | UDim2 | Vector2 | Vector3 | Rect
type SpringConfig<T> = ({ type SpringControl<T> = ({
position: T?, position: T?,
velocity: T?, velocity: T?,
impulse: T? impulse: T?

View file

@ -1,7 +1,7 @@
# Reactivity: Dynamic Scoping # Reactivity: Dynamic Scopes
Dynamic scoping is the act of creating and destroying new scopes in response to Dynamic scopes are scopes that are created or destroyed in response to
source updates. Vide provides functions for some common use-cases to do this. 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> ## show() <Badge type="tip" text="STABLE"><a href="/vide/api/reactivity-core#Scopes">REACTIVE</a></Badge>
@ -11,8 +11,10 @@ if the source is falsey.
- **Type** - **Type**
```luau ```luau
function show<T>(source: () -> unknown, component: () -> T): () -> T? function show<T>(source: () -> unknown, component: Constructor<T>): () -> T?
function show<T, U>(source: () -> unknown, component: () -> T, fallback: () -> U): () -> T | U function show<T, U>(source: () -> unknown, component: Constructor<T>, fallback: () -> U): () -> T | U
type Constructor<T> = () -> (T, number?)
``` ```
- **Details** - **Details**
@ -25,6 +27,9 @@ if the source is falsey.
Returns a source holding an instance of the currently shown component or Returns a source holding an instance of the currently shown component or
`nil` if no component is currently shown. `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> ## 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. Shows one of a set of components depending on a source and a mapping table.
@ -32,7 +37,9 @@ Shows one of a set of components depending on a source and a mapping table.
- **Type** - **Type**
```luau ```luau
function switch<K, V>(source: () -> K): (map: Map<K, () -> V>): () -> V? function switch<K, V>(source: () -> K): (map: Map<K, Constructor<V>>): () -> V?
type Constructor<T> = () -> (T, number?)
``` ```
- **Details** - **Details**
@ -46,6 +53,9 @@ Shows one of a set of components depending on a source and a mapping table.
Returns a source holding an instance of the currently shown component or Returns a source holding an instance of the currently shown component or
`nil` if no component is currently shown. `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** - **Example**
```luau ```luau
@ -71,8 +81,9 @@ Shows a component for each index in a table.
```luau ```luau
function indexes<KI, VI, VO>( function indexes<KI, VI, VO>(
source: () -> Map<KI, VI>, source: () -> Map<KI, VI>,
transform: (value: () -> VI, index: KI) -> VO constructor: (value: () -> VI, index: KI) -> (VO, number?)
): Array<VO> ): Array<VO>
```
- **Details** - **Details**
@ -81,21 +92,24 @@ Shows a component for each index in a table.
When the source table updates, a component is generated for each index in When the source table updates, a component is generated for each index in
the table. the table.
- For any added index, the `transform` function is run in a new stable - For any added index, the `constructor` function is run in a new stable
scope to produce an instance that is cached. scope to produce an instance that is cached.
- For any removed index, the stable scope for that index is destroyed. - For any removed index, the stable scope for that index is destroyed.
The `transform` function is called with: The `constructor` function is called with:
1. A *source containing the index's value*. 1. A *source containing the index's value*.
2. The *index itself*. 2. The *index itself*.
Anytime an existing index's value changes, the `transform` function is not Anytime an existing index's value changes, the `constructor` function is not
rerun, instead, that index's corresponding source is updated with the new rerun, instead, that index's corresponding source is updated with the new
value. value.
Returns a source holding an array of instances currently shown. 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** - **Example**
```luau ```luau
@ -128,7 +142,7 @@ Shows a component for each value in a table.
```luau ```luau
function values<KI, VI, VO>( function values<KI, VI, VO>(
source: () -> Map<KI, VI>, source: () -> Map<KI, VI>,
transform: (value: VI, index: () -> KI) -> VO constructor: (value: VI, index: () -> KI) -> (VO, number?)
): Array<VO> ): Array<VO>
- **Details** - **Details**
@ -141,21 +155,24 @@ Shows a component for each value in a table.
When the source table updates, a component is generated for each value in When the source table updates, a component is generated for each value in
the table. the table.
- For any added value, the `transform` function is run in a new stable scope - For any added value, the `constructor` function is run in a new stable scope
to produce an instance that is cached. to produce an instance that is cached.
- For any removed value, the stable scope for that value is destroyed. - For any removed value, the stable scope for that value is destroyed.
The `transform` function is called with: The `constructor` function is called with:
1. The *value itself*. 1. The *value itself*.
2. A *source containing the value's index*. 2. A *source containing the value's index*.
Anytime an existing value's index changes, the `transform` function is not Anytime an existing value's index changes, the `constructor` function is not
rerun, instead, that value's corresponding source is updated with the new rerun, instead, that value's corresponding source is updated with the new
index. index.
Returns a source holding an array of instances currently shown. 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 ::: warning
Having the same values appear multiple times in the input source table can Having the same values appear multiple times in the input source table can
cause unexpected behavior. Strict mode has checks for this. cause unexpected behavior. Strict mode has checks for this.

View file

@ -1,6 +1,6 @@
# Dynamic Scoping # Dynamic Scopes
Dynamic scoping is the act of creating and destroying new scopes in response to Dynamic scopes are scopes that are created and destroyed in response to
source updates. This is needed for conditionally rendering parts of your UI, source updates. This is needed for conditionally rendering parts of your UI,
such as opening and closing menus. such as opening and closing menus.

View file

@ -4,7 +4,7 @@ Eventually you may need a way to dynamically create and destroy UI elements
resulting from source updates. Vide provides functions to help you do this, resulting from source updates. Vide provides functions to help you do this,
known as *dynamic scope* functions. known as *dynamic scope* functions.
These functions create and destroy components for you in response to source These functions create and destroy scopes for you in response to source
updates. They return a source containing the created component. This source can updates. They return a source containing the created component. This source can
be parented as a child which will update the shown children whenever the source be parented as a child which will update the shown children whenever the source
updates. updates.
@ -156,3 +156,56 @@ local data = src()
table.insert(data, 3) -- no effects will run table.insert(data, 3) -- no effects will run
src(data) -- effects will run src(data) -- effects will run
``` ```
--------------------------------------------------------------------------------
All dynamic scope functions also support delaying the destruction of the scope.
This is useful for playing any sort of animation or effect before the UI
instance is removed.
If you have the following code, for example:
```lua
local function Menu()
return create "Frame" {}
end
local toggled = source(true)
create "ScreenGui" {
show(toggled, function()
return Menu {}
end)
}
toggled(false) -- menu will disappear immediately
```
```lua
local function Menu(props: { Visible: () -> boolean })
local transparency = spring(function()
return if p.Visible then 0 else 1
end
return create "Frame" {
BackgroundTransparency = transparency
}
end
local toggled = source(true)
create "ScreenGui" {
show(toggled, function(_, present)
return Menu { p.Visible = present }, 3 -- give a generous 3 seconds for the spring to complete before destroying
end)
}
toggled(false)
-- `present` will go `false` immediately
-- transparency will begin being sprung
-- after 3 seconds the scope is destroyed, giving the spring enough time to complete
```
If `toggled` goes from truthy to falsey, beginning the timer, but then back
to truthy before the timer finishes, the timer is cancelled and the scope is
not destroyed.