mirror of
https://github.com/centau/vide.git
synced 2026-08-20 14:41:37 +00:00
This commit is contained in:
parent
8e31946dda
commit
13965868ce
13 changed files with 421 additions and 448 deletions
54
README.md
54
README.md
|
|
@ -1,54 +1,14 @@
|
|||
# Notice
|
||||
|
||||
The library is currently in a very early development stage, with breaking changes being made often, out of date documentation and no versioning. Not recommended for use.
|
||||
|
||||
<br>
|
||||
The library is currently in a very early development stage, with breaking
|
||||
changes being made often, out of date documentation and no versioning. Not
|
||||
recommended for use.
|
||||
|
||||
# Vide
|
||||
|
||||
Vide is a declarative, reactive Luau library for building user interfaces on Roblox.
|
||||
Vide is a declarative, reactive Luau library for building user interfaces on
|
||||
Roblox.
|
||||
|
||||
## API Reference
|
||||
- ### [API Reference](docs/api/index.md)
|
||||
|
||||
### [Reactivity: Core](docs/api/reactivity-core)
|
||||
|
||||
- [wrap()](docs/api/reactivity-core#wrap)
|
||||
- [derive()](docs/api/reactivity-core#derive)
|
||||
- [foreach()](docs/api/reactivity-core#wrap)
|
||||
- [match()](docs/api/reactivity-core#match)
|
||||
- [watch()](docs/api/reactivity-core#watch)
|
||||
|
||||
### [Reactivity: Utility](docs/api/reactivity-utility)
|
||||
|
||||
- [isState()](docs/api/reactivity-utility#isState)
|
||||
- [unwrap()](docs/api/reactivity-utility#unwrap)
|
||||
- [readonly()](docs/api/reactivity-utility#readonly)
|
||||
- [mutate()](docs/api/reactivity-utility#mutate)
|
||||
|
||||
### [Element Creation](docs/api/creation)
|
||||
|
||||
- [create()](docs/api/creation#create)
|
||||
- [apply()](docs/api/creation#apply)
|
||||
- [Layout](docs/api/creation#Layout)
|
||||
- [Children](docs/api/creation#Children)
|
||||
- [Event](docs/api/creation#Event)
|
||||
- [Changed](docs/api/creation#Changed)
|
||||
- [Bind](docs/api/creation#Bind)
|
||||
- [Created](docs/api/creation#Created)
|
||||
|
||||
### [Animation](docs/api/animation)
|
||||
|
||||
- [spring()](docs/api/animation#spring)
|
||||
|
||||
### [Types](docs/api/types)
|
||||
|
||||
- [State<T>](docs/api/types#State)
|
||||
- [Prop<T>](docs/api/types#Prop)
|
||||
|
||||
<br/>
|
||||
|
||||
## Tutorials
|
||||
|
||||
### [Crash Course](docs/tutorials/crash-course)
|
||||
|
||||
### [Reactive Graph](docs/tutorials/reactive-graph)
|
||||
- ### [Crash Course](docs/tut/crash-course/1-introduction.md)
|
||||
|
|
|
|||
22
docs/api/index.md
Normal file
22
docs/api/index.md
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
# API Reference
|
||||
|
||||
### [Reactivity: Core](../api/reactivity-core.md)
|
||||
|
||||
- [source()](../api/reactivity-core.md#source)
|
||||
- [derive()](../api/reactivity-core.md#derive)
|
||||
- [map()](../api/reactivity-core.md#map)
|
||||
- [watch()](../api/reactivity-core.md#watch)
|
||||
|
||||
### [Reactivity: Utility](../api/reactivity-utility.md)
|
||||
|
||||
- [cleanup()](../api/reactivity-utility.md#cleanup)
|
||||
|
||||
### [Element Creation](../api/creation.md)
|
||||
|
||||
- [create()](../api/creation.md#create)
|
||||
|
||||
### [Animation](../api/animation.md)
|
||||
|
||||
- [spring()](../api/animation.md#spring)
|
||||
|
||||
### [Strict Mode](../api/strict.md)
|
||||
|
|
@ -1,351 +0,0 @@
|
|||
# Vide Crash Course
|
||||
|
||||
This is a brief tutorial designed to give you a quick run through the usage of
|
||||
Vide.
|
||||
|
||||
Vide is largely inspired by Solid and Fusion.
|
||||
|
||||
<br>
|
||||
|
||||
## Why Vide?
|
||||
|
||||
Creating UI is a slow and tedious process. The purpose of Vide is to make UI
|
||||
declarative and concise, making it faster to create and more importantly easier
|
||||
to maintain. Vide achieves this using a reactive style of programming which
|
||||
allows you to focus on the flow of data through your application without
|
||||
worrying about manually updating UI instances.
|
||||
|
||||
Some of the main focuses behind Vide's design choices:
|
||||
|
||||
- Concise syntax to reduce verbosity as much as possible.
|
||||
- Reducing the amount of imports needed for usage by using Luau's syntax and
|
||||
semantics.
|
||||
- Being completely typecheckable.
|
||||
- Flexibility, particularly with integrating other libraries.
|
||||
|
||||
## Creating UI Instances
|
||||
|
||||
Instances are created using [`create()`](../api/creation#create).
|
||||
|
||||
```lua
|
||||
local vide = require(vide)
|
||||
local create = vide.create
|
||||
```
|
||||
|
||||
```lua
|
||||
local frame = create "Frame" {
|
||||
Name = "Background",
|
||||
Position = UDim2.fromScale(0.5, 0.5)
|
||||
}
|
||||
```
|
||||
|
||||
`create()` returns a constructor for a given class which then takes a table of
|
||||
properties to assign when creating a new instance for that class.
|
||||
|
||||
String keys are assumed to be properties, integer keys are assumed to be
|
||||
children.
|
||||
|
||||
```lua
|
||||
create "ScreenGui" {
|
||||
Parent = game.StarterGui,
|
||||
|
||||
create("Frame") {
|
||||
AnchorPoint = Vector2.new(0.5, 0.5),
|
||||
Position = UDim2.fromScale(0.5, 0.5),
|
||||
Size = UDim2.fromScale(0.4, 0.7),
|
||||
|
||||
create("TextLabel") {
|
||||
Text = "hi"
|
||||
},
|
||||
|
||||
create("TextLabel") {
|
||||
Text = "bye"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
To connect to an event, just set the event property name to a function.
|
||||
|
||||
```lua
|
||||
create "TextButton" {
|
||||
Activated = function()
|
||||
print "clicked!"
|
||||
end
|
||||
}
|
||||
```
|
||||
|
||||
All event arguments are passed into the function.
|
||||
|
||||
<br>
|
||||
|
||||
## State
|
||||
|
||||
State in Vide are special objects that store data.
|
||||
|
||||
A state object in Vide can be created using
|
||||
[`source()`](../api/reactivity-core#source).
|
||||
|
||||
```lua
|
||||
local source = vide.source
|
||||
```
|
||||
|
||||
```lua
|
||||
local visible = source(false)
|
||||
|
||||
local image = create("ImageLabel") {
|
||||
Visible = visible -- bind property to state
|
||||
}
|
||||
|
||||
visible(false) -- image label is hidden
|
||||
|
||||
visible(true) -- image label is shown
|
||||
```
|
||||
|
||||
`source()` creates a new data source which can be set by calling it with the new
|
||||
value to set.
|
||||
|
||||
Any time the value is set, anything depending on it will automatically be
|
||||
updated using the new value.
|
||||
|
||||
Vide detects when you assign a state object as a property value. This is known
|
||||
as *binding* and doing so will cause the property to *automatically* update
|
||||
whenever that state object's value is changed.
|
||||
|
||||
You as the programmer do not have to worry about manually updating variables or
|
||||
UI instances, you can just focus on defining how the data maps to UI and
|
||||
everything will update when changes occur.
|
||||
|
||||
<br>
|
||||
|
||||
## Derived State
|
||||
|
||||
You can create new state from other states. This is known as *deriving state*.
|
||||
|
||||
```lua
|
||||
local count = source(0)
|
||||
|
||||
local function text()
|
||||
return "count: " .. count()
|
||||
end
|
||||
|
||||
create "TextLabel" {
|
||||
Text = text
|
||||
}
|
||||
```
|
||||
|
||||
To read from a state, you call without any arguments which returns its stored
|
||||
value.
|
||||
|
||||
Assigning a non-event property a function will bind that property to that
|
||||
function, anytime a state being read from inside that function is changed, the
|
||||
function will be re-ran and the property value updated.
|
||||
|
||||
Sometimes when using expensive computations to derive state, you only want to
|
||||
recalculate it when a source state has changed.
|
||||
|
||||
```lua
|
||||
local derive = vide.derive
|
||||
```
|
||||
|
||||
```lua
|
||||
local count = source(0)
|
||||
|
||||
local factorial = derive(function()
|
||||
local n = 1
|
||||
for i = 2, count() do
|
||||
n *= i
|
||||
end
|
||||
return n
|
||||
end)
|
||||
```
|
||||
|
||||
`derive()` will cache and return the same value until a source state has
|
||||
changed, where it will recompute and cache a new value.
|
||||
|
||||
```lua
|
||||
create "TextLabel" {
|
||||
Text = function()
|
||||
return "factorial: " .. factorial()
|
||||
end
|
||||
}
|
||||
|
||||
count(3) -- displays "factorial: 6"
|
||||
count(4) -- displays "factorial: 24"
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
## Components
|
||||
|
||||
Components are custom-made reusable pieces of UI made from other pieces of UI.
|
||||
|
||||
```lua
|
||||
local function Background(args)
|
||||
return create("Frame") {
|
||||
BackgroundColor3 = Color3.new(0, 0, 0),
|
||||
Position = args.Position,
|
||||
Size = args.Size
|
||||
}
|
||||
end
|
||||
|
||||
local background = Background {
|
||||
Position = UDim2.new(),
|
||||
Size = UDim2.new()
|
||||
}
|
||||
```
|
||||
|
||||
Above is a simple example of a frame component with its background color set to
|
||||
black.
|
||||
|
||||
A single parameter `args` is used to pass properties to the component.
|
||||
|
||||
Components allow you to *encapsulate* behavior. You can only modify the
|
||||
component in ways that you allow in the component.
|
||||
|
||||
This also promotes code reusability. Anytime you want a black frame all you do
|
||||
is call `Background {}` instead of creating a new frame and settings it color
|
||||
each time.
|
||||
|
||||
<br>
|
||||
|
||||
## Stateful components
|
||||
|
||||
Often, you need components that maintain their own internal state, such as a
|
||||
toggle-able button or a counter.
|
||||
|
||||
Below you can see how a simple counter component can be implemented.
|
||||
|
||||
```lua
|
||||
local function Counter()
|
||||
local count = source(0)
|
||||
|
||||
return create "TextButton" {
|
||||
Text = function()
|
||||
return "count: " .. count()
|
||||
end
|
||||
|
||||
Activated = function()
|
||||
count(count() + 1)
|
||||
end,
|
||||
}
|
||||
end
|
||||
```
|
||||
|
||||
Each time you call `Counter {}`, it will create a new counter component which
|
||||
each maintains their own count state.
|
||||
|
||||
Clicking on the UI element will automatically increment and display its count.
|
||||
|
||||
## Nested Properties and Typechecking
|
||||
|
||||
When a key is assigned a table, Vide does not attempt to assign it to a
|
||||
property, instead, the table is iterated and processed just like the nesting
|
||||
table.
|
||||
|
||||
Below is an example of how you can use this to pass groups of similar properties
|
||||
together such as position and size, while also using typechecking.
|
||||
|
||||
```lua
|
||||
type Layout = {
|
||||
Layout = {
|
||||
Position: UDim2?,
|
||||
Size: UDim2?,
|
||||
AnchorPoint: Vector2?
|
||||
}
|
||||
}
|
||||
|
||||
local function Button(args: Layout & {
|
||||
Text: string,
|
||||
Callback: () -> ()
|
||||
})
|
||||
local count = source(0)
|
||||
|
||||
return create "TextButton" {
|
||||
Text = args.Text
|
||||
Activated = args.Callback,
|
||||
Layout = args.Layout
|
||||
}
|
||||
end
|
||||
|
||||
Button {
|
||||
Text = "Click me!",
|
||||
|
||||
Callback = function()
|
||||
print "clicked me!"
|
||||
end,
|
||||
|
||||
Layout = {
|
||||
Position = UDim2.new(),
|
||||
Size = UDim2.new()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Here the button component is assigned a position and size as if you passed those
|
||||
properties directly.
|
||||
|
||||
The same can be done for properties such as children.
|
||||
|
||||
```lua
|
||||
type Children = {
|
||||
Children = Array<Instance>
|
||||
}
|
||||
|
||||
local function List(args: Children & Layout)
|
||||
return create "Frame" {
|
||||
Layout = args.Layout,
|
||||
Children = args.Children,
|
||||
|
||||
create "UIListLayout" {}
|
||||
}
|
||||
end
|
||||
|
||||
List {
|
||||
Layout = {
|
||||
Position = UDim2.new()
|
||||
},
|
||||
|
||||
Children = {
|
||||
create "TextLabel" { Text = "1" }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Tables of data
|
||||
|
||||
Vide has functions for dealing with table states.
|
||||
|
||||
Below is an example using the above `List` class.
|
||||
|
||||
```lua
|
||||
type Item = {
|
||||
Name: string,
|
||||
Icon: number
|
||||
}
|
||||
|
||||
local items = source({} :: Array<Item>)
|
||||
|
||||
List {
|
||||
Children = map(items, function(item, i)
|
||||
return create "ImageLabel" {
|
||||
Image = function()
|
||||
return "rbxassetid://" .. item().Icon
|
||||
end,
|
||||
|
||||
LayoutOrder = i
|
||||
}
|
||||
end)
|
||||
}
|
||||
```
|
||||
|
||||
Here we map each element in `items` to a value returned by a callback.
|
||||
|
||||
The callback is called only *once* per key. The first argument given to the
|
||||
callback is a state that has the value of the table key's value.
|
||||
|
||||
Anytime the value of the corresponding table key changes, the state value
|
||||
changes too. This saves us from having to recreate a UI element any time a
|
||||
table index changes.
|
||||
|
||||
## WIP
|
||||
27
docs/tut/crash-course/1-introduction.md
Normal file
27
docs/tut/crash-course/1-introduction.md
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
# [Introduction](./index.md)
|
||||
|
||||
This is a brief tutorial designed to give you a quick run through the usage of
|
||||
Vide.
|
||||
|
||||
Vide is largely inspired by other UI libraries such as Solid and Fusion.
|
||||
|
||||
## Why Vide?
|
||||
|
||||
Creating UI is a slow and tedious process. The purpose of Vide is to make UI
|
||||
declarative and concise, making it faster to create and more importantly easier
|
||||
to maintain. Vide achieves this using a reactive style of programming which
|
||||
allows you to focus on the flow of data through your application without
|
||||
worrying about manually updating UI instances.
|
||||
|
||||
Some of the main focuses behind Vide's design choices:
|
||||
|
||||
- Concise syntax to reduce verbosity as much as possible.
|
||||
- Reducing the amount of imports needed for usage by using Luau's syntax and
|
||||
semantics.
|
||||
- Being completely typecheckable.
|
||||
- Flexibility, particularly with integrating other libraries and allowing users
|
||||
to use their own patterns.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
### [Element Creation →](./2-creation.md)
|
||||
67
docs/tut/crash-course/2-creation.md
Normal file
67
docs/tut/crash-course/2-creation.md
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
# [Creating UI Elements](./index.md)
|
||||
|
||||
Instances are created using [`create()`](../../api/creation.md#create).
|
||||
|
||||
```lua
|
||||
local vide = require(path_to_vide)
|
||||
local create = vide.create
|
||||
```
|
||||
|
||||
`create()` returns a constructor for a given class which then takes a table of
|
||||
properties to assign when creating a new instance for that class.
|
||||
|
||||
```lua
|
||||
local frame = create "Frame" {
|
||||
Name = "Background",
|
||||
Position = UDim2.fromScale(0.5, 0.5)
|
||||
}
|
||||
```
|
||||
|
||||
String keys are assigned as properties and integer keys are assigned as child
|
||||
instances.
|
||||
|
||||
```lua
|
||||
create "ScreenGui" {
|
||||
Parent = game.StarterGui,
|
||||
|
||||
create "Frame" {
|
||||
AnchorPoint = Vector2.new(0.5, 0.5),
|
||||
Position = UDim2.fromScale(0.5, 0.5),
|
||||
Size = UDim2.fromScale(0.4, 0.7),
|
||||
|
||||
create "TextLabel" {
|
||||
Text = "hi"
|
||||
},
|
||||
|
||||
create"TextLabel" {
|
||||
Text = "bye"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
To connect to an event, just set the event property name to a function.
|
||||
|
||||
All event arguments are passed into the function.
|
||||
|
||||
|
||||
```lua
|
||||
create "TextButton" {
|
||||
Activated = function()
|
||||
print "clicked!"
|
||||
end
|
||||
}
|
||||
```
|
||||
|
||||
## Summary
|
||||
|
||||
In short:
|
||||
|
||||
- String keys = properties
|
||||
- Function values = events
|
||||
- Non-function values = property values
|
||||
- Numeric keys = children
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
### [← Introduction](./1-introduction.md) | [Components →](./3-components.md)
|
||||
52
docs/tut/crash-course/3-components.md
Normal file
52
docs/tut/crash-course/3-components.md
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
# [Components](./index.md)
|
||||
|
||||
Components are custom-made reusable pieces of UI made from other pieces of UI.
|
||||
|
||||
Using components you make your application more modular and better organized.
|
||||
|
||||
Components leverage functions to create self-contained UI that can even have
|
||||
its own state and behavior.
|
||||
|
||||
```lua
|
||||
local function Button(props: {
|
||||
Position: UDim2,
|
||||
Text: string,
|
||||
Callback: () -> ()
|
||||
})
|
||||
return create "TextButton" {
|
||||
BackgroundColor3 = Color3.fromRGB(50, 50, 50),
|
||||
Size = UDim2.fromOffset(400, 250),
|
||||
|
||||
Position = props.Position,
|
||||
Text = props.Text,
|
||||
Callback = props.Callback
|
||||
}
|
||||
end
|
||||
|
||||
local button = Button {
|
||||
Position = UDim2.new(),
|
||||
Text = "Click me!",
|
||||
|
||||
Callback = function()
|
||||
print "clicked"
|
||||
end
|
||||
}
|
||||
```
|
||||
|
||||
Above is a simple example of a button component with its background color set to
|
||||
a dark grey and with a fixed size.
|
||||
|
||||
A single parameter `props` is used to pass properties to the component.
|
||||
|
||||
Components allow you to *encapsulate* behavior. You can only modify the
|
||||
component in ways that you allow in the component.
|
||||
|
||||
This also promotes code reusability. Anytime you want a new button all you do
|
||||
is call `Button {}` instead of creating and setting every property each time.
|
||||
|
||||
This can be extended to much more complicated UI.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
### [← Element Creation](./2-creation.md) | [State →](./4-state.md)
|
||||
|
||||
57
docs/tut/crash-course/4-state.md
Normal file
57
docs/tut/crash-course/4-state.md
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
# [State](./index.md)
|
||||
|
||||
State in Vide are special objects that store data.
|
||||
|
||||
A state object in Vide can be created using
|
||||
[`source()`](../../api/reactivity-core.md#source).
|
||||
|
||||
```lua
|
||||
local source = vide.source
|
||||
```
|
||||
|
||||
```lua
|
||||
-- create a new source
|
||||
local count = source(0)
|
||||
|
||||
-- set source value
|
||||
count(10)
|
||||
|
||||
-- get source value
|
||||
print(count()) -- "10"
|
||||
```
|
||||
|
||||
Below is an example of a counter component that has state.
|
||||
|
||||
```lua
|
||||
local function Counter()
|
||||
local count = source(0)
|
||||
|
||||
return create "TextButton" {
|
||||
Text = count
|
||||
|
||||
Activated = function()
|
||||
count(count() + 1)
|
||||
end,
|
||||
}
|
||||
end
|
||||
```
|
||||
|
||||
Any time the source value is set, anything depending on it will automatically be
|
||||
updated using the new value.
|
||||
|
||||
Vide detects when you assign a function to a property. This is known
|
||||
as *binding* and doing so will cause the property to *automatically* update
|
||||
whenever a state in that function is updated, by rerunning the function and
|
||||
assigning its return value. You can only bind non-event
|
||||
properties, otherwise the function is connected as the event callback.
|
||||
|
||||
You as the programmer do not have to worry about manually updating variables or
|
||||
UI instances, you can just focus on defining how the data maps to UI and
|
||||
everything will update when changes occur.
|
||||
|
||||
Each call of `Counter {}` will create a new counter element, each with their own
|
||||
independent count state.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
### [← Components](./3-components.md) | [Derived State →](./5-derived-state.md)
|
||||
57
docs/tut/crash-course/5-derived-state.md
Normal file
57
docs/tut/crash-course/5-derived-state.md
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
# [Derived State](./index.md)
|
||||
|
||||
You can create new state from existing states. This is known as *deriving
|
||||
state*.
|
||||
|
||||
```lua
|
||||
local count = source(0)
|
||||
|
||||
local function text()
|
||||
return "count: " .. count()
|
||||
end
|
||||
|
||||
create "TextLabel" {
|
||||
Text = text
|
||||
}
|
||||
```
|
||||
|
||||
Assigning a non-event property a function will bind that property to that
|
||||
function, anytime a state being read from inside that function is changed, the
|
||||
function will be re-ran and the property value updated.
|
||||
|
||||
Sometimes when using expensive computations to derive state, you only want to
|
||||
recalculate it when a source state has changed.
|
||||
|
||||
```lua
|
||||
local derive = vide.derive
|
||||
```
|
||||
|
||||
```lua
|
||||
local count = source(0)
|
||||
|
||||
local factorial = derive(function()
|
||||
local n = 1
|
||||
for i = 2, count() do
|
||||
n *= i
|
||||
end
|
||||
return n
|
||||
end)
|
||||
```
|
||||
|
||||
`derive()` will cache and return the same value until a source state has
|
||||
changed, where it will recompute and cache a new value.
|
||||
|
||||
```lua
|
||||
create "TextLabel" {
|
||||
Text = function()
|
||||
return "factorial: " .. factorial()
|
||||
end
|
||||
}
|
||||
|
||||
count(3) -- displays "factorial: 6"
|
||||
count(4) -- displays "factorial: 24"
|
||||
```
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
### [← State](./4-State.md) | [Table State →](./6-table-state.md)
|
||||
39
docs/tut/crash-course/6-table-state.md
Normal file
39
docs/tut/crash-course/6-table-state.md
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
# [Table State](./index.md)
|
||||
|
||||
Vide has functions for dealing with table states.
|
||||
|
||||
Below is an example using the above `List` class.
|
||||
|
||||
```lua
|
||||
type Item = {
|
||||
Name: string,
|
||||
Icon: number
|
||||
}
|
||||
|
||||
local items = source({} :: Array<Item>)
|
||||
|
||||
List {
|
||||
Children = map(items, function(item, i)
|
||||
return create "ImageLabel" {
|
||||
Image = function()
|
||||
return "rbxassetid://" .. item().Icon
|
||||
end,
|
||||
|
||||
LayoutOrder = i
|
||||
}
|
||||
end)
|
||||
}
|
||||
```
|
||||
|
||||
Here we map each element in `items` to a value returned by a callback.
|
||||
|
||||
The callback is called only *once* per key. The first argument given to the
|
||||
callback is a state that has the value of the table key's value.
|
||||
|
||||
Anytime the value of the corresponding table key changes, the state value
|
||||
changes too. This saves us from having to recreate a UI element any time a
|
||||
table index changes.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
### [← Derived State](./5-derived-state.md) | [Property Groups →](./7-property-groups.md)
|
||||
78
docs/tut/crash-course/7-property-groups.md
Normal file
78
docs/tut/crash-course/7-property-groups.md
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
# [Property Groups](./index.md)
|
||||
|
||||
When a key is assigned a table, Vide does not attempt to assign it to a
|
||||
property, instead, the table is iterated and processed just like the nesting
|
||||
table.
|
||||
|
||||
Below is an example of how you can use this to pass groups of similar properties
|
||||
together such as position and size, while also using typechecking.
|
||||
|
||||
```lua
|
||||
type Layout = {
|
||||
Layout = {
|
||||
Position: UDim2?,
|
||||
Size: UDim2?,
|
||||
AnchorPoint: Vector2?
|
||||
}
|
||||
}
|
||||
|
||||
local function Button(args: Layout & {
|
||||
Text: string,
|
||||
Callback: () -> ()
|
||||
})
|
||||
local count = source(0)
|
||||
|
||||
return create "TextButton" {
|
||||
Text = args.Text
|
||||
Activated = args.Callback,
|
||||
Layout = args.Layout
|
||||
}
|
||||
end
|
||||
|
||||
Button {
|
||||
Text = "Click me!",
|
||||
|
||||
Callback = function()
|
||||
print "clicked me!"
|
||||
end,
|
||||
|
||||
Layout = {
|
||||
Position = UDim2.new(),
|
||||
Size = UDim2.new()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Here the button component is assigned a position and size as if you passed those
|
||||
properties directly.
|
||||
|
||||
The same can be done for properties such as children.
|
||||
|
||||
```lua
|
||||
type Children = {
|
||||
Children = Array<Instance>
|
||||
}
|
||||
|
||||
local function List(args: Children & Layout)
|
||||
return create "Frame" {
|
||||
Layout = args.Layout,
|
||||
Children = args.Children,
|
||||
|
||||
create "UIListLayout" {}
|
||||
}
|
||||
end
|
||||
|
||||
List {
|
||||
Layout = {
|
||||
Position = UDim2.new()
|
||||
},
|
||||
|
||||
Children = {
|
||||
create "TextLabel" { Text = "1" }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
### [← Table State](./6-table-state.md)
|
||||
15
docs/tut/crash-course/index.md
Normal file
15
docs/tut/crash-course/index.md
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
# Crash Course
|
||||
|
||||
1. ### [Introduction](./1-introduction.md)
|
||||
|
||||
2. ### [Element Creation](./2-creation.md)
|
||||
|
||||
3. ### [Components](./3-introduction.md)
|
||||
|
||||
4. ### [State](./4-introduction.md)
|
||||
|
||||
5. ### [Derived State](./5-introduction.md)
|
||||
|
||||
6. ### [Table State](./6-introduction.md)
|
||||
|
||||
7. ### [Property Groups](./7-introduction.md)
|
||||
|
|
@ -486,7 +486,6 @@ end)
|
|||
|
||||
TEST("cleanup()", function()
|
||||
local source = vide.source
|
||||
local derive = vide.derive
|
||||
local watch = vide.watch
|
||||
local cleanup = vide.cleanup
|
||||
|
||||
|
|
|
|||
49
todo.md
49
todo.md
|
|
@ -11,52 +11,3 @@
|
|||
- batch
|
||||
- async/loading/suspense
|
||||
- define order with nested properties
|
||||
|
||||
```lua
|
||||
type Action<T> = {
|
||||
type: T,
|
||||
priority: number,
|
||||
callback: (Instance) -> ()
|
||||
}
|
||||
|
||||
local function action(priority: number, fn: (Instance) -> ()): Action
|
||||
|
||||
end
|
||||
|
||||
local function changed(property: string, callback: () -> ())
|
||||
return action(1, function(instance)
|
||||
instance:GetPropertyChangedSignal(property):Connect(callback)
|
||||
end) :: Action<"Changed">
|
||||
end
|
||||
|
||||
create "TextBox" {
|
||||
Text = "test",
|
||||
|
||||
changed "Text" < function(self, data)
|
||||
|
||||
end
|
||||
}
|
||||
```
|
||||
|
||||
## version 1
|
||||
|
||||
```lua
|
||||
map(items, function(item, i)
|
||||
return Item {
|
||||
Item = item, -- primitive
|
||||
LayoutOrder = i
|
||||
}
|
||||
end)
|
||||
```
|
||||
|
||||
## version 2
|
||||
|
||||
```lua
|
||||
each(items, function(item, i)
|
||||
return Item {
|
||||
Item = item, -- state
|
||||
LayoutOrder = i
|
||||
}
|
||||
end)
|
||||
```
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue