diff --git a/.moonwave/static/TutorialAssets/Chapter1/State/CoinsCountToTen.gif b/.moonwave/static/TutorialAssets/Chapter1/State/CoinsCountToTen.gif
new file mode 100644
index 00000000..c9880491
Binary files /dev/null and b/.moonwave/static/TutorialAssets/Chapter1/State/CoinsCountToTen.gif differ
diff --git a/.moonwave/static/TutorialAssets/Chapter1/State/CoinsPoundsFormat.gif b/.moonwave/static/TutorialAssets/Chapter1/State/CoinsPoundsFormat.gif
new file mode 100644
index 00000000..35f54ef5
Binary files /dev/null and b/.moonwave/static/TutorialAssets/Chapter1/State/CoinsPoundsFormat.gif differ
diff --git a/.moonwave/static/TutorialAssets/Chapter1/State/CoinsReactive.gif b/.moonwave/static/TutorialAssets/Chapter1/State/CoinsReactive.gif
new file mode 100644
index 00000000..18485b2c
Binary files /dev/null and b/.moonwave/static/TutorialAssets/Chapter1/State/CoinsReactive.gif differ
diff --git a/.moonwave/static/TutorialAssets/Chapter1/VirtualInstance/CoinCounterFull.jpg b/.moonwave/static/TutorialAssets/Chapter1/VirtualInstance/CoinCounterFull.jpg
new file mode 100644
index 00000000..6b595bea
Binary files /dev/null and b/.moonwave/static/TutorialAssets/Chapter1/VirtualInstance/CoinCounterFull.jpg differ
diff --git a/.moonwave/static/TutorialAssets/Chapter1/VirtualInstance/CoinCounterIntermediaryInstanceOut.jpg b/.moonwave/static/TutorialAssets/Chapter1/VirtualInstance/CoinCounterIntermediaryInstanceOut.jpg
deleted file mode 100644
index 14dce742..00000000
Binary files a/.moonwave/static/TutorialAssets/Chapter1/VirtualInstance/CoinCounterIntermediaryInstanceOut.jpg and /dev/null differ
diff --git a/.moonwave/static/TutorialAssets/Chapter1/VirtualInstance/CoinCounterSimple.jpg b/.moonwave/static/TutorialAssets/Chapter1/VirtualInstance/CoinCounterSimple.jpg
new file mode 100644
index 00000000..7c7c498b
Binary files /dev/null and b/.moonwave/static/TutorialAssets/Chapter1/VirtualInstance/CoinCounterSimple.jpg differ
diff --git a/.moonwave/static/TutorialAssets/Chapter1/VirtualInstance/PremadeCoinCounter.rbxmx b/.moonwave/static/TutorialAssets/Chapter1/VirtualInstance/PremadeCoinCounter.rbxmx
index 7a70f1d8..48a12be6 100644
--- a/.moonwave/static/TutorialAssets/Chapter1/VirtualInstance/PremadeCoinCounter.rbxmx
+++ b/.moonwave/static/TutorialAssets/Chapter1/VirtualInstance/PremadeCoinCounter.rbxmx
@@ -49,7 +49,7 @@
false
false
0
- CoinCointer
+ CoinCounter
[null]
[null]
[null]
diff --git a/.moonwave/static/TutorialAssets/Chapter1/VirtualInstance/PremadeCoinCounterScreenshot.jpg b/.moonwave/static/TutorialAssets/Chapter1/VirtualInstance/PremadeCoinCounterScreenshot.jpg
deleted file mode 100644
index ff47024d..00000000
Binary files a/.moonwave/static/TutorialAssets/Chapter1/VirtualInstance/PremadeCoinCounterScreenshot.jpg and /dev/null differ
diff --git a/docs/Chapter1/State.md b/docs/Chapter1/State.md
index 73f87454..f57e4733 100644
--- a/docs/Chapter1/State.md
+++ b/docs/Chapter1/State.md
@@ -4,89 +4,137 @@ sidebar_position: 5
# Creating & Mapping State
-:::warning
-Tutorials are still in progress, and will be released section-by-section
-:::
+At its heart, Dec is also a language for representing ***State***. State is any
+hidden variable that, when changed, will eventually lead to something updating
+in a User Interface. State can be things like coins, whether or not a player is
+hovering/pressing over a UI component, the price/display name/thumbnail of an
+item being sold to the user, and more. Creating reactive UI Components in Dec
+requires breaking down what simple variables are being displayed to the user
+on-screen.
+
+In the last section, we showed an example of a shop menu which appears when a
+player interacts with an NPC:
-## Using State in your Components
+![NPC Shop](/TutorialAssets/Chapter1/VirtualInstance/GecsSeafaringSupplies.jpg)
-At its heart, Dec is also a language for representing ***State***, and having
-instances reactively change their properties based on changes in state. States
-are any variables underlying what's being rendered. Writing effective Dec
-applications also requires down what *States* each component is rendering:
+We can break this UI down into *States* by thinking about what hidden variables
+are being conveyed to the user. Here's a breakdown of what variables some of
+these UI components are using:
-(image of state breakdown)
+### `ShopHeader`:
+```lua
+local title: string -- The display name of the NPC's shop
+```
-In the previous section, we created a CoinCounter UI using a premade template.
-In this example, the only state that CoinCounter needs to render is a number
-representing how many coins a player has. We can create this state using
-`Dec.State`, passing in an initial value for the coins as a first argument:
+### `CoinCounter`:
+```lua
+local coins: number -- How many coins the player currently has
+```
+
+### `ShopItem`:
+```lua
+local id: string -- What's the ID of the item we're showing?
+local thumbnail: string -- What's the ID of the image thumbnail we're showing?
+local displayName: string -- e.g. "Flintlock", "Sword"
+local price: number -- How many coins does this cost?
+```
+
+Let's focus in on the `CoinCounter` Component that was covered in the last
+section, and let's represent this "coins" variable as a state.
+
+## `CoinCounter` Component
+
+We can create a State that holds a number representing the player's coins by
+calling the function [Dec.State](/api/State):
```lua
local coins = Dec.State(0)
```
-Dec States can be updated using `Set()`, and their current value can be
-retreived using `Current()`:
+Then, we can use `:Set()` to update this state and `:Current()` to get its
+current value:
+
```lua
print(coins:Current()) -- 0
coins:Set(42)
print(coins:Current()) -- 42
```
-So far, we've seen VirtualInstances defining the static properties of an
-instance to be renderered — however, we can also have these properties change
-*reactively* to state
+Let's now utilize this state in our UI.
+
+So far, we've seen examples of using ***VirtualInstances*** to assign static
+properties of an instance:
+```lua
+local coinsLabel = Dec.Premade("TextLabel", {
+ Text = "42",
+})
+```
+
+Dec also supports passing in *States* to the property table of a virtual
+instance. Doing so will cause the UI to automatically update whenever this
+state changes!
+
```lua
local coinsLabel = Dec.Premade("TextLabel", {
Text = coins,
})
```
-(Image of coin counter showing 42 coins)
+![Reactive Coins UI](/TutorialAssets/Chapter1/State/CoinsReactive.gif)
+
+The way in which Dec Components generate visuals from State follows a software
+paradigm called [*Reactive Programming*](https://en.wikipedia.org/wiki/Reactive_programming).
+To gain a better understanding of how Reactive Programming works in Dec, let's
+quickly go over a core concept in Dec: ***Observables***
## Observables
-States are actually a type of ***Observable***. Observables are objects that,
-generally speaking, *hold some value* and can *listen to changes in this value*.
-`Dec.State` is a special type of Observable in that its value can be written
-to; however, many times, we only need to read the value of an Observable rather
-than writing to it.
+***State*** actually [*inherits*](https://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming))
+from a base class called ***Observable***. Observables are objects that *hold
+some value* and can *listen to changes in this value*.
-Observables can be passed as ***Props*** to a Component. Props is essentially
-a table of named parameters to a Dec component which affects the final
-output of the component:
+`Dec.State` is a special type of Observable in that its value can be *written
+to;* however, some observables are "read-only" and their value depends on other
+factors.
+
+Let's pass "coins" as a paramater to the CoinCounter component. "coins" is both
+a ***State*** object and an ***Observable*** object; however, since we only need
+to read from this state within the `CoinCounter` component, we can type this
+parameter as an ***Observable*** to make the component more re-usable.
```lua
-local function CoinCounter(props: {
- coins: Dec.Observable
-})
+local function CoinCounter(coins: Dec.Observable)
return Dec.Premade("Frame", {}, {
CoinsLabel = Dec.Premade("TextLabel", {
- Text = props.coins,
+ Text = coins,
})
})
end
```
-In this example, we can use the CoinCounter to modify a premade asset by
-updating the text label "CoinsLabel" to match the value of an observable state
-we pass in:
+If we now render this component in our application, we can write some code that
+1) Creates a Coins state; 2) Creates a CoinCounter that reactively renders this
+state; and 3) updates this state over time.
```lua
--- CoinCounter will start rendering "0"
+-- Create a state to hold coins
local coins = Dec.State(0)
-local CoinCounter = CoinCounter({
- coins = coins,
-})
-task.wait(3)
+-- Render a new CoinCounter component within a Dec.Root object (presumed to
+-- exist in this scope)
+root:Render(CoinCounter(coins))
-coins:Set(42) -- CoinCounter will now render with "42" after 3 seconds
+-- Increment the value of coins every second
+while task.wait(1) do
+ coins:Set(coins:Current() + 1)
+end
```
-(video of animation changing the coins display from 0 to 42 in realtime after 3
-seconds)
+![Reactive Coins UI](/TutorialAssets/Chapter1/State/CoinsCountToTen.gif)
+
+The `CoinCounter` is now a fully *reactive* Component, as it generates visuals
+based on the value of an ***Observable***, and updates these visuals whenever
+the Observable's value changes!
## Mapping Observables
@@ -96,9 +144,11 @@ and two decimal points, so that `42` shows up as `£42.00`. To do this, we will
need to transform the coins state somehow.
***Mapping*** Is the process of transforming one observable to another by using
-a mapping functions. Mapping is achieved in Dec by using `Dec.Map`, with the
-input observables as arguments. This function returns another function
-which should be called with the ***Mapping Function*** as a first argument:
+a transformation function. Mapping is achieved in Dec by calling
+[Dec.Map](/api/Dec#Map) with the state we want to map, then calling the returned
+value again with a transformation function.
+
+The ***Mapping*** syntax looks like this:
```lua
local coinsFormatted = Dec.Map(coins)(function(currentCoins)
@@ -106,16 +156,37 @@ local coinsFormatted = Dec.Map(coins)(function(currentCoins)
end)
```
-The `coinsFormatted` object is an Observable object which updates its value
-based on the current value of coins:
+Here we created a an ***Observable string***, whose value depends on the
+current value of coins (an observable number). Updating the `coins` state will
+also update the value of `coinsFormatted`:
```lua
coins:Set(123)
print(coinsFormatted:Current()) -- £123.00
```
-Mapping functions can take in multiple arguments. For example, if you wanted to
-also store the currency as a state, you could map it like so:
+Let's use a mapped value to format the `coins` observable in our `CoinCounter`
+component example:
+```lua
+local function CoinCounter(coins: Dec.Observable)
+ return Dec.Premade("Frame", {}, {
+ CoinsLabel = Dec.Premade("TextLabel", {
+ Text = Dec.Map(coins)(function(currentCoins)
+ return string.format("£%.2f", currentCoins)
+ end),
+ })
+ })
+end
+```
+
+![Mapping In Use](/TutorialAssets/Chapter1/State/CoinsPoundsFormat.gif)
+
+## Mapping Multiple Values
+
+***Observable Mapping*** can take in multiple inputs. For example, if you wanted
+to derive a value from `coins` and a `currency` type, you would simply call
+`Dec.Map` with two arguments:
+
```lua
local coins = Dec.State(0)
local currency = Dec.State("£")
@@ -125,40 +196,40 @@ local coinsFormatted = Dec.Map(currency, coins)(function(
)
return string.format("%s%.2f", currentCurrency, currentCoins)
end)
-
print(coinsFormatted:Current()) -- £0.00
+
coins:Set(42)
currency:Set("$")
print(coinsFormatted:Current()) -- $42.00
```
-We can also use `coins:Map()` as a shorthand—however, doing so will limit the
-mapping function to one argument, and will discard the type information of the
-returned observable. It's recommended to only call the `:Map()` in cases
-like VirtualInstances properties, the value returned by `:Map()` is only used
-in one place and never stored directly in a variable:
+:::info
+Dec provides a shorthand method for mapping an single input observable to a
+single output observable called [:Map()](/api/Observable#Map). Due to a current
+Luau language limitation, calling the `:Map()` method will discard the type
+information of the output observable, so you should prefer using `Dec.Map`
+over `Observable:Map()` in most cases for the sake of type safety.
+`:Map()` is still useful in situations where you do not need the type of the
+output observable, such as when storing it as a VirtualInstance property:
```lua
-local function CoinCounter(props: {
- coins: Dec.Observable
+return Dec.Premade("TextLabel", {
+ Text = coins:Map(function(currentCoins)
+ return string.format("£%.2f", currentCoins)
+ end),
})
- return Dec.Premade("Frame", {}, {
- CoinsLabel = Dec.Premade("TextLabel", {
- Text = props.coins:Map(function(currentCoins)
- return string.format("£%.2f", currentCoins)
- end),
- })
- })
-end
```
-
-(Image of formatted CoinCounter UI)
+:::
## Using Math Operations on Observables
-Dec provides operator overloads for observables of the same number or vector
+:::caution
+This feature has been disabled due to a regression in Luau's type system.
+:::
+
+~~Dec provides operator overloads for observables of the same number or vector
type! You can use operators like `+`, `-`, `*`, `/`, and `^` between two
-observable objects to get a mapped observable:
+observable objects to get a mapped observable:~~
```lua
local a = Dec.State(3)
@@ -169,25 +240,29 @@ a:Set(4)
print(sum:Current()) -- 8
```
-In the above example, `sum` is equivalent to mapping `a` and `b` with an
-summation mapping function:
+~~In the above example, `sum` is equivalent to mapping `a` and `b` with an
+summation mapping function:~~
```lua
local sum = Dec.Map(a, b)(function(currentA, currentB)
return currentA + currentB
end)
```
-## Subscribing to State
+~~You can also use math overloads on an Observable and its same value type. For
+example, you can add a UDim2 with an *Observable UDim2*:~~
-One nice thing about Observables in Dec is that they will always be garbage
-collected (freed from memory) whenever they go *unused*. Observables are only
-considered to be "used" if they are used by an active VirtualInstance, or if
-they are ***Subscribed***
+```lua
+local basePosition: Dec.Observable = Dec.State(UDim2.fromScale(0.5, 0.1))
+local PADDING = UDim2.fromScale(0.05, 0.05)
+local paddedPosition = basePosition + PADDING
+print(paddedPosition:Current()) -- ~ {0.55, 0}, {0.15, 0}
+```
-Subscribing to an observable lets you listen to changes in the value. For
-example, if you wanted to print every time a certain value changes, you could do
-so by calling `value:Subscribe()`, which in turn returns an `unsubscribe`
-function
+## Subscribing to State
+
+The primary feature of Observables is, of course, that they can be *observed*.
+This is done by calling the `:Subscribe()` method, which calls a listener
+whenever the observable's value changes, and can be unsubscribed.
```lua
local value = Dec.State(42)
@@ -195,33 +270,41 @@ local unsubscribe = value:Subscribe(function(currentValue)
print("The current value is ", currentValue)
end)
value:Set(128) -- The current value is 128
+value:Set(256) -- The current value is 256
```
-:::warning
+:::danger
If you directly Subscribe to Observables, **make sure to always handle the
returned unsubscribe function** when the observable is no longer needed. More
complex observables may stick around in memory until they are unsubscribed!
:::
+Observables have one caveat that they *might* stick around in memory as long as
+there is a listener subscribing to them. This is because, as we will cover in
+later sections, some observables like *Stopwatches*, *Springs*, etc. need to
+bind to Heartbeat to update their value every frame. Subscribing to an
+Observable for the first time may *set up* side effects that will only be taken
+down once the Observable is *unsubscribed* by all listeners.
+
### A Safer Alternative to `:Subscribe()`
A safe alternative to calling `Observable:Subscribe()` is the function
`Observable:SubscribeWhileMounted()`, which takes in a VirtualInstance as a
first parameter, and automatically unsubscribes to the observable's value once
-the VirtualInstance is `unmounted` (i.e. is no longer being rendered by dec).
+the VirtualInstance is ***Unmounted*** (i.e. is no longer being rendered by
+Dec).
-This is useful for components that have side effects on an input observable,
-such as printing:
+We can use this inside a component to safely handle side effects and debugging
+in a way that cleans itself up when the Component's Virtual Instances stop being
+rendered by Dec:
```lua
-local function ComponentWithSideEffects(props: {
- value: Dec.Observable
-})
+local function ComponentWithSideEffects(value: Dec.Observable)
local frame = Dec.Premade("Frame")
- -- This will keep printing until ComponentWithSideEffects is no longer
- -- rendered.
- props.value:SubscribeWhileMounted(frame, function(currentValue)
+ -- This will keep printing changes to the value until the frame is no longer
+ -- rendered
+ value:SubscribeWhileMounted(frame, function(currentValue)
print("The current value is", currentValue)
end)
diff --git a/docs/Chapter1/VirtualInstance.md b/docs/Chapter1/VirtualInstance.md
index 31ec18a9..f491f6ba 100644
--- a/docs/Chapter1/VirtualInstance.md
+++ b/docs/Chapter1/VirtualInstance.md
@@ -100,7 +100,7 @@ local coinCounter = Dec.New("Frame", {
So far, this translates to the following instance tree:
-![Instance Tree Visualization](/TutorialAssets/Chapter1/VirtualInstance/CoinCounterIntermediaryInstanceOut.jpg)
+![Instance Tree Visualization](/TutorialAssets/Chapter1/VirtualInstance/CoinCounterSimple.jpg)
In order to make this a proper ***Dec Component***, we should create a
function named `CoinCounter` which returns this virtual instance tree.
@@ -192,7 +192,7 @@ downloadable template:
This can be placed directly in StarterGui and used by Dec:
-![Premade Coin Counter UI in StarterGui](/TutorialAssets/Chapter1/VirtualInstance/PremadeCoinCounterScreenshot.jpg)
+![Premade Coin Counter UI in StarterGui](/TutorialAssets/Chapter1/VirtualInstance/CoinCounterFull.jpg)
Once the template is in place, the `CoinCounter` component's code can be greatly
simplified to only modify the text of the CoinsLabel object, since that is the
diff --git a/proposals/clock.md b/proposals/clock.md
new file mode 100644
index 00000000..6d6b8239
--- /dev/null
+++ b/proposals/clock.md
@@ -0,0 +1,41 @@
+# Proposal: Dec.Clock observable subclass
+
+This is a proposal to add an observable subclass, `Dec.Clock`, which tracks
+the current result of `os.time()` and updates every second exactly when
+`os.time()`'s return value updates
+
+# Status: Unimplemented
+
+## Use Cases:
+
+This has many use cases in live events, countdown timers, and other widgets
+which need to update their value exactly once per second.
+
+## Example:
+
+```lua
+local function CountdownTimer()
+ return Dec.Premade("TextLabel", {
+ Text = Dec.Clock():Map(function(currentTimeUTC)
+ local remaining = endTimeUTC - currentTimeUTC
+
+ if remaining <= 0 then
+ return "Event Has Ended!"
+ end
+
+ return string.format(
+ "%d Seconds Remaining . . .",
+ remaining
+ )
+ end)
+ })
+end
+```
+
+`Dec.Clock()` can just return a frozen singleton object, as subscribing to
+real-time clock updates only needs to happen once in a whole application, and
+clocks will always output the same value no matter what.
+
+Dec's update stream system also means that `Dec.Clock()` will only bind to
+render step / heartbeat exactly when and if it's necessary to do so in any
+visible UI.
\ No newline at end of file
diff --git a/proposals/readonlyDict.md b/proposals/readonlyDict.md
new file mode 100644
index 00000000..a7daabe3
--- /dev/null
+++ b/proposals/readonlyDict.md
@@ -0,0 +1,55 @@
+## Proposal: Readonly Dict/Record types
+
+This is a proposal to add type-casting overloads to the `Dec.Dict` and
+`Dec.Record` constructor functions, which can cast an existing observable state
+to a Record/Dict type, allowing indexing an arbitrary state, so long as its base
+type is a table.
+
+## Status: Unimplemented
+
+## Use Cases:
+
+`Record:Index` and `Dict:Index` are very powerful methods, as they reduce the
+time complexity of state updates that may happen in UI code from O(N) to O(1)
+for free.
+
+A very common use case for this would be something like an infinite-scroll shop
+component, which contains many different cards. Sometimes state is held
+monolithically, and needs to be distilled to a number of smaller states, but
+doing so is difficult if `Dict` and `Record` is unable to be directly used.
+
+This proposal adds an overload to `Dec.Dict()` and `Dec.Record` that wraps/
+essentially typecasts an existing Observable object to a Dict/Record, provided
+the root observable's type is a table.
+
+## Examples
+
+One way this can be used is indexing parts of a state passed in props.
+```lua
+function Component(props: {
+ info: Dec.Observable<{
+ id: string,
+ displayName: string,
+ description: string,
+ }>
+})
+ -- Cast as Dec.ReadOnlyRecord to allow indexing
+ local info = Dec.Record(valueFromProps)
+
+ return Dec.Premade("Frame", {}, {
+ Title = Dec.Premade("TextLabel", {
+ Text = info:Index("displayName"),
+ }),
+ Body = Dec.Premade("TextLabel", {
+ Text = info:Index("description"),
+ })
+ })
+end
+```
+
+Here, using `info:Index()`` simplifies a more complex 3-line expression:
+```lua
+Text = info:Map(function(currentInfo)
+ return info.displayName,
+end)
+```
\ No newline at end of file
diff --git a/proposals/sequence.md b/proposals/sequence.md
index 6b698c02..3136e718 100644
--- a/proposals/sequence.md
+++ b/proposals/sequence.md
@@ -1,10 +1,21 @@
-# API Propposal: Timed sequences
+# Proposal: Timed sequences
+
+This is a proposal to add a observable subclass, created via `Dec.Sequence`,
+which is an object that holds state about a timed sequence.
# Status: Unimplemented
-This is pretty important for a number of use cases. I figure, since Dec already
-contains a number of utility subclasses for observable, having one for sequences
-would be immeasurably useful, provided the API is easy to get a hang of.
+## Use Case:
+
+Sequences are pretty important for a number of use cases involving animations
+that have multiple steps.
+
+I figure, since Dec already contains a number of utility subclasses for
+observables involving animations/timing, having one for discretely-steped
+sequences would be immeasurably useful, provided the API is easy to get a hang
+of.
+
+## Example:
```lua
--!nocheck
diff --git a/src/Observables/Observable.luau b/src/Observables/Observable.luau
index 48748a29..72fc4421 100644
--- a/src/Observables/Observable.luau
+++ b/src/Observables/Observable.luau
@@ -487,35 +487,33 @@ local function createMappingMetamethod(
binop: (a: number, b: number) -> number
): (any, any) -> any
return function(a, b)
- if IsObservable(a) then
- if IsObservable(b) then
- -- Map from two constant observables
- return Observable.new(function()
- return applyBinopPolymorphic(
- a:Current(),
- b:Current(),
- binop
- )
- end, function(notifyUpdates)
- local unsubscribeA = a:Subscribe(notifyUpdates)
- local unsubscribeB = b:Subscribe(notifyUpdates)
- return function()
- unsubscribeA()
- unsubscribeB()
- end
- end)
- else
- -- lhs is observable, rhs is constant
- return a:Map(function(aCurrent)
- return applyBinopPolymorphic(aCurrent, b, binop)
- end)
- end
- else
+ if not IsObservable(a) then
-- rhs is observable, lhs is constant
return b:Map(function(bCurrent)
return applyBinopPolymorphic(a, bCurrent, binop)
end)
end
+ if not IsObservable(b) then
+ -- lhs is observable, rhs is constant
+ return a:Map(function(aCurrent)
+ return applyBinopPolymorphic(aCurrent, b, binop)
+ end)
+ end
+ -- Map from two constant observables
+ return Observable.new(function()
+ return applyBinopPolymorphic(
+ a:Current(),
+ b:Current(),
+ binop
+ )
+ end, function(notifyUpdates)
+ local unsubscribeA = a:Subscribe(notifyUpdates)
+ local unsubscribeB = b:Subscribe(notifyUpdates)
+ return function()
+ unsubscribeA()
+ unsubscribeB()
+ end
+ end)
end
end
Observable.__add = createMappingMetamethod(function(a, b)
diff --git a/testing_proof_checksum.txt b/testing_proof_checksum.txt
index 35111f04..c09b77ed 100644
--- a/testing_proof_checksum.txt
+++ b/testing_proof_checksum.txt
@@ -1 +1 @@
-30ca881_112_0_0_success
\ No newline at end of file
+2d31de06_112_0_0_success
\ No newline at end of file
diff --git a/wally.toml b/wally.toml
index 3810d457..c6c3d0db 100644
--- a/wally.toml
+++ b/wally.toml
@@ -1,7 +1,7 @@
[package]
name = "ambergracesoftware/dec"
description = "A libary for building Roblox user interfaces"
-version = "0.1.1"
+version = "0.1.2"
authors = [ "Amber Grace" ]
license = "MIT"
registry = "https://github.com/UpliftGames/wally-index"