diff --git a/docs/api/animation.md b/docs/api/animation.md
index 8370d14..fc64c68 100644
--- a/docs/api/animation.md
+++ b/docs/api/animation.md
@@ -1,56 +1,39 @@
# Animation API
-
-
## spring()
-Returns a new state with an animated value of the original.
+Returns a new state with a dynamically animated value of the source.
-### Type
+- ### Type
-```lua
-function spring(state: State, period: number, dampingRatio: number = 1): State
-```
+ ```lua
+ function spring(
+ source: () -> T & Animatable,
+ period: number = 1,
+ damping_ratio: number = 1
+ ): () -> T
-### Details
+ type Animatable = number | CFrame | Color3 | UDim | UDim2 | Vector2 | Vector3
+ ```
-The output state's value is updated every frame based on the current input state's value.
+- ### Details
-The change is physically simulated according to a [spring](https://en.wikipedia.org/wiki/Simple_harmonic_motion).
+ The output state value is updated every frame based on the source state
+ value.
-`period` is the amount of time in seconds it takes for the spring to complete one full cycle
+ The change is physically simulated according to a
+ [spring](https://en.wikipedia.org/wiki/Simple_harmonic_motion).
-`dampingRatio` is relared to the amount of resistant force applied to the spring.
+ `period` is the amount of time in seconds it takes for the spring to
+ complete one full oscillation.
-- \>1 = Overdamped (Not currently supported)
-- 1 = Critically damped
-- <1 = Underdamped
-- 0 = Undamped
+ `damping_ratio` is the amount of resistance applied to the spring.
-Velocity is conserved between input state updates for smooth animation.
+ - \>1 = Overdamped (not currently supported).
+ - 1 = Critically damped - reaches target without any overshoot.
+ - <1 = Underdamped - reaches target with some overshoot.
+ - 0 = Undamped - never stabilizes, oscillates forever.
-### Example
+ Velocity is conserved between source state updates for smooth animation.
-```lua
-local state = wrap(1)
-
-local springed = spring(state, 1, 1)
-```
-
-Example of an animated counter
-
-```lua
-local count = wrap(1000)
-
-local function Counter(props)
- local tweenedCount = spring(count, 0.5, 1)
-
- return create("TextLabel") {
- Text = "Count: " .. tweenedCount
- }
-end
-```
-
-
-
--------------------------------------------------------------------
+--------------------------------------------------------------------------------
diff --git a/docs/api/creation.md b/docs/api/creation.md
index 7ca416e..cfd7816 100644
--- a/docs/api/creation.md
+++ b/docs/api/creation.md
@@ -6,320 +6,76 @@
Creates a new UI element, applying any given properties.
-### Type
+- ### Type
-```lua
-function create(classNameOrInstance: string | Instance): (properties: Map) -> Instance
-```
+ ```lua
+ function create(class: string): (Properties) -> Instance
+ function create(instance: Instace): (Properties) -> Instance
-### Details
+ type Properties = Map
+ ```
-The function can take either a `string` or an `Instance` as its first argument.
+- ### Details
-- If given a `string`, a new instance with the string class name will be created with default properties already applied.
-- If given an `Instance`, a new instance that is a clone of the given instance will be created.
+ The function can take either a `string` or an `Instance` as its first argument.
-This returns another function that is used to apply any properties to the new instance.
+ - 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.
-### Example
+ This returns another function that is used to apply any properties to the new
+ instance.
-```lua
-local frame = create("Frame") {
- Name = "NewFrame",
- Position = UDim2.fromScale(1, 0)
-}
+- ### Property setting rules
--- creates a clone of `frame` with new properties applied.
-local frame2 = create(frame) {
- Size = UDim2.fromOffset(50, 100)
-}
-```
+ - If a table value is another table, that nested table is processed so that
+ any properties inside that table are also applied to the instance just
+ like the outer table.
+ - If a table index is a string:
+ - If its value is a function then it will either bind that property to
+ a state or connect it if the property type is a `RBXScriptSignal`.
+ - If the value is not a function then the property will be set to that
+ value.
+ - If a table index is a number:
+ - If its value is a function then it will parent any instances returned by
+ that function as children.
+ - If its value is an instance then it will be parented to the instance.
--------------------------------------------------------------------
+- ### Example
-
+ Basic element creation.
-## apply()
-
-Applies any given properties to a given instance.
-
-### Type
-
-```lua
-function apply(instance: Instance): (properties: Map) -> Instance
-```
-
-### Details
-
-Applies properties in the same manner as `create` for already existing existances.
-
-Can use symbols and bind state just like `create`.
-
-### Example
-
-```lua
-local frame = Instance.new("Frame")
-
-apply(frame) {
- Position = UDim2.fromScale(1, 0)
-}
-```
-
--------------------------------------------------------------------
-
-
-
-## Layout
-
-Symbol used to pass layout properties to elements.
-
-### Type
-
-```lua
-type Layout = Symbol
-
-type LayoutProps = {
- [Symbol] = {
- -- These are all properties considered to be "layout properties"
- AnchorPoint: Prop?;
- LayoutOrder: Prop?;
- Position: Prop?;
- Rotation: Prop?;
- Size: Prop?;
- SizeConstraint: Prop?;
- Visible: Prop?;
- ZIndex: Prop?;
+ ```lua
+ local frame = create "Frame" {
+ Name = "NewFrame",
+ Position = UDim2.fromScale(1, 0)
}
-}
+ ```
-type Prop = T | State
-```
+ A component using property nesting/grouping.
-### Details
-
-The primary purpose of this symbol is to enable easy passthrough of layout properties
-through user-defined component hierarchies.
-
-It is recommended to only set layout properties using the `Layout` symbol when using
-your own components.
-
-### Example
-
-```lua
-local function BlackFrame(props)
- return create("Frame") {
- BackgroundColor3 = Color3.new(0, 0, 0),
- [Layout] = props[Layout]
- }
-end
-
-BlackFrame {
- [Layout] = {
- AnchorPoint = Vector2.new(0.5, 0.5),
- Position = UDim2.fromScale(0.5, 0.5),
- Size = UDim2.fromOffset(100, 50)
- }
-}
-```
-
--------------------------------------------------------------------
-
-
-
-## Children
-
-Symbol used to pass child instances to elements.
-
-### Type
-
-```lua
-type Children = Symbol
-
-type ChildrenProps = {
- [Symbol] = ChildrenProp
-}
-
-type ChildrenProp = Prop | Array
-```
-
-### Details
-
-This symbol is flexible in the way that children can be passed in the form of nested arrays.
-
-Children can also be assigned using a state binding.
-
-### Example
-
-```lua
-create("Frame") {
- -- all of the below are valid methods of assigning children
- [Children] = create("TextLabel") {},
-
- [Children] = {
- create("TextLabel") {},
- create("TextLabel") {},
- },
-
- [Children] = {
- create("TextLabel") {},
- {
- create("TextLabel") {},
+ ```lua
+ type Layout = {
+ Layout = {
+ Position: UDim2?,
+ Size: UDim2?,
+ AnchorPoint: Vector2?
}
}
-}
-```
--------------------------------------------------------------------
+ type Children = {
+ Children = Array
+ }
-
-
-## Event
-
-Symbol used to connect callbacks to instance events.
-
-### Type
-
-```lua
-type Event = Map
-
-type EventProps = {
- [Symbol] = Prop<(...unknown) -> ()>
-}
-```
-
-### Details
-
-The `Event` symbol can be indexed to get symbols to connect to specific events.
-
-Event parameters are passed into the callback.
-
-When callbacks are connected by binding to a state,
-connections are automatically disconnected when the state changes.
-
-### Example
-
-```lua
-create("TextButton") {
- [Event.Activated] = function()
- print("Clicked")
+ function Background(props: Layout & Children & {
+ Color: Color3
+ })
+ return create "Frame" {
+ BackgroundColor3 = Color,
+ props.Layout,
+ props.Children
+ }
end
-}
-```
+ ```
--------------------------------------------------------------------
-
-
-
-## Changed
-
-Symbol used to connect callbacks to instance property changed events.
-
-### Type
-
-```lua
-type Changed = Map
-
-type ChangedProps = {
- [Symbol] = Prop<(...unknown) -> ()>
-}
-```
-
-### Details
-
-The `Changed` symbol can be indexed to get symbols to connect to specific events just like `Event`.
-
-Event parameters are passed into the callback.
-
-When callbacks are connected by binding to a state,
-connections are automatically disconnected when the state changes.
-
-### Example
-
-```lua
-create("TextBox") {
- [Changed.Text] = function()
- print("New text entered")
- end
-}
-```
-
--------------------------------------------------------------------
-
-
-
-## Bind
-
-Symbol used to bind states to instance properties.
-
-### Type
-
-```lua
-type Bind = Map
-
-type BindProps = {
- [Symbol] = State
-}
-```
-
-### Details
-
-The `Bind` symbol can be indexed to bind specific properties just like `Event`.
-
-Sets the given state value to the instance property value immediately after instance creation.
-
-When an instance property is changed, the value of the given state will automatically
-be set to the new property. Effectively a shorthand for connecting a property changed event
-to set state values.
-
-### Example
-
-```lua
-local text = wrap()
-
-local box = create("TextBox") {
- [Bind.Text] = text
-}
-
-box.Text = "New text"
-print(text.Value) -- "New text"
-```
-
--------------------------------------------------------------------
-
-
-
-## Created
-
-Symbol used to run a callback once immediately after instance creation.
-
-### Type
-
-```lua
-type Created = Symbol
-
-type CreatedProps = {
- [Symbol] = (Instance) -> ()
-}
-```
-
-### Details
-
-The instance being defined with the `Created` symbol is passed as the first
-argument to the callback.
-
-### Example
-
-```lua
-local frame
-
-create("Frame") {
- Name = "Background",
- [Created] = function(instance)
- frame = instance
- end
-}
-
-print(frame.Name) -- "Background"
-```
-
--------------------------------------------------------------------
+--------------------------------------------------------------------------------
diff --git a/docs/api/reactivity-core.md b/docs/api/reactivity-core.md
index 4f91693..e534cde 100644
--- a/docs/api/reactivity-core.md
+++ b/docs/api/reactivity-core.md
@@ -2,248 +2,167 @@
-## wrap()
+## source()
-Wraps and returns any given values with reactive state objects.
+Creates a new source state with the given value.
-### Type
+- ### Type
-```lua
-function wrap(value: T): State
-function wrap(value: ...unknown): ...State
+ ```lua
+ function source(value: T): (T?) -> T
+ ```
-type State = {
- Value: T,
- value: T
-}
-```
+- ### Details
-### Details
+ Calling the returned state with no arguments will return its stored value,
+ calling with arguments will set a new value.
-The state object has a single mutable field `.Value`.
+ Reading from the state from within any reactive scope will cause changes
+ to that state to be tracked and anything depending on it to update.
-Read operations to `.Value` are tracked and write operations can trigger
-dependency updates and watchers.
+- ### Example
-### Example
+ ```lua
+ local count = source(0)
-```lua
-local count = wrap(0)
+ count() -- 0
-print(count.Value) -- 0
+ count(count() + 1) -- 1
+ ```
-count.Value += 1
-
-print(count.Value) -- 1
-```
-
--------------------------------------------------------------------
-
-
+--------------------------------------------------------------------------------
## derive()
-Derives a new reactive state object from an existing state object.
+Derives a new state from existing states.
-### Type
+- ### Type
-```lua
-function derive(
- (from) -> T,
- cleanup: (value: T) -> ()?
-): State
+ ```lua
+ function derive(source: () -> T): () -> T
+ ```
-function from(T | State): T
-```
+- ### Details
-### Details
+ The derived state will have its value recalculated when any source state it
+ derives from is updated.
-The derived state will have its value recalculated when any state it derives from is updated.
+ Anytime its value is recalculated it is also cached, subsequent calls will
+ retun this cached value until it recalculates again.
-Takes a callback that is immediately run to determine what states are being referenced. Only states referenced in the immediate function scope can trigger updates.
+ Takes a callback that is immediately run to determine what states are being
+ referenced.
-The state object returned by this function is readonly.
+> ⚠️ Non-yielding.
-Has an optional cleanup parameter which takes a function that is called with the old value any
-time the derived state recalculates a value.
+- ### Example
-An optional utility function is passed as the first argument to the callback, if given a state, the value of the state will be returned (changes to this state still triggers updates unlike `unwrap`), if given a value the value is returned.
+ ```lua
+ local count = wrap(0)
+ local text = derive(function() return `count: {count()}` end)
-> ⚠️ The callback cannot yield.
+ text() -- "count: 0"
-### Example
+ count(1)
-```lua
-local count = wrap(0)
-local text = derive(function() return "Count: "..count.Value end)
+ text() -- "count: 1"
+ ```
-print(text.Value) -- "Count: 0"
+--------------------------------------------------------------------------------
-count.Value += 1
+## map()
-print(text.Value) -- "Count: 1"
-```
+Maps each value in a table state to a new table state.
-```lua
-local count = wrap(0)
-local text = derive(function(from)
- return "Count: "..from(count)
-end)
-```
+- ### Type
-A shorthand method for deriving states also exists, following example is equivalent to the above:
+ ```lua
+ function map(
+ source: () -> Map,
+ transform: (value: () -> VI, index: KI) -> VO
+ ): Map
-```lua
-local count = wrap(0)
-local text = "Count: "..count -- all binary operators are supported
-```
+- ### Details
--------------------------------------------------------------------
+ The transform function is called only ever *once* for each index in the
+ source table. The first argument is a state containing the index's value and
+ the second argument is just the index.
-
+ Anytime a new index is added, the transform function will be called again for
+ that new index.
-## foreach()
+ Anytime an existing index changes, the transform function is not rerun,
+ instead the passed state for that index will update, causing anything
+ depending on it to update too.
-Derives a new state object from an existing state object.
-Designed to work specifically with table states.
+ Returns a state containing the mapped key-value pairs.
-Also works with non state tables.
+ > ⚠️ Non-yielding.
-### Type
+- ### Example
-```lua
-function foreach( -- number as first arg
- i: number,
- transform: (key: number) -> (KO, VO),
- cleanup: (KO, VO) -> ()?
-): Map
+ ```lua
+ type Item = {
+ name: string,
+ icon: number
+ }
-function foreach( -- table as first arg
- table: Map,
- transform: (key: KI, value: VI) -> (KO, VO),
- cleanup: (KO, VO) -> ()?
-): Map
+ local items = source {} :: () -> Array-
-function foreach( -- state as first arg
- state: State