Skip to content

Commit

Permalink
Better Types and docs.
Browse files Browse the repository at this point in the history
Improved luau types to make them more generic and changed documentation types to better describe the API.
  • Loading branch information
SirMallard committed Sep 2, 2024
1 parent 211d296 commit fd86d85
Show file tree
Hide file tree
Showing 9 changed files with 188 additions and 136 deletions.
108 changes: 54 additions & 54 deletions lib/API.lua

Large diffs are not rendered by default.

90 changes: 51 additions & 39 deletions lib/Internal.lua
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ return function(Iris: Types.Iris): Types.Internal
Internal._fullErrorTracebacks = game:GetService("RunService"):IsStudio()

--[=[
@prop _cycleCoroutine thread
@within Internal
@prop _cycleCoroutine thread
The thread which handles all connected functions. Each connection is within a pcall statement which prevents
Iris from crashing and instead stopping at the error.
Expand Down Expand Up @@ -116,14 +116,13 @@ return function(Iris: Types.Iris): Types.Internal
Never chain states together so that each state changes the value of another state in a cyclic nature. This will cause a continous callback.
:::
]=]

local StateClass = {}
StateClass.__index = StateClass

--[=[
@method get
@within State
@return any
@method get<T>
@return T
Returns the states current value.
]=]
Expand All @@ -132,8 +131,10 @@ return function(Iris: Types.Iris): Types.Internal
end

--[=[
@method set
@within State
@method set<T>
@param newValue T
@return T
Allows the caller to assign the state object a new value, and returns the new value.
]=]
Expand All @@ -146,17 +147,24 @@ return function(Iris: Types.Iris): Types.Internal
for _, thisWidget: Types.Widget in self.ConnectedWidgets do
Internal._widgets[thisWidget.type].UpdateState(thisWidget)
end

for _, callback in self.ConnectedFunctions do
callback(newValue)
end
return self.value
end

--[=[
@method onChange
@within State
@method onChange<T>
@param callback (newValue: T) -> ()
Allows the caller to connect a callback which is called when the states value is changed.
:::caution
Calling `:onChange()` every frame will add a new function every frame.
You must ensure you are only calling `:onChange()` once for each callback for the state's entire lifetime.
:::
]=]
function StateClass:onChange<T>(callback: (newValue: T) -> ()): () -> ()
local connectionIndex: number = #self.ConnectedFunctions + 1
Expand All @@ -175,8 +183,8 @@ return function(Iris: Types.Iris): Types.Internal
]]

--[=[
@function _cycle
@within Internal
@function _cycle
Called every frame to handle all of the widget management. Any previous frame data is ammended and everything updates.
]=]
Expand Down Expand Up @@ -276,9 +284,9 @@ return function(Iris: Types.Iris): Types.Internal
end

--[=[
@within Internal
@ignore
@function _NoOp
@within Internal
A dummy function which does nothing. Used as a placeholder for optional methods in a widget class.
Used in `Internal.WidgetConstructor`
Expand All @@ -288,8 +296,8 @@ return function(Iris: Types.Iris): Types.Internal
-- Widget

--[=[
@function WidgetConstructor
@within Internal
@function WidgetConstructor
@param type string -- name used to denote the widget class.
@param widgetClass Types.WidgetClass -- table of methods for the new widget.
Expand Down Expand Up @@ -396,12 +404,12 @@ return function(Iris: Types.Iris): Types.Internal
end

--[=[
@function _Insert
@within Internal
@function _Insert
@param widgetType: string -- name of widget class.
@param arguments Types.WidgetArguments? -- arguments of the widget.
@param states Types.States? -- states of the widget.
@return Types.Widget -- the widget.
@param arguments { [string]: number } -- arguments of the widget.
@param states { [string]: States<any> }? -- states of the widget.
@return Widget -- the widget.
Every widget is created through _Insert. An ID is generated based on the line of the calling code and is used to
find the previous frame widget if it exists. If no widget exists, a new one is created.
Expand Down Expand Up @@ -489,13 +497,13 @@ return function(Iris: Types.Iris): Types.Internal
end

--[=[
@function _GenNewWidget
@within Internal
@function _GenNewWidget
@param widgetType string
@param arguments Types.Arguments -- arguments of the widget.
@param states Types.States? -- states of the widget.
@param ID Types.ID -- id of the new widget. Determined in `Internal._Insert`
@return Types.Widget -- the newly created widget.
@param arguments { [string]: any } -- arguments of the widget.
@param states { [string]: State<any> }? -- states of the widget.
@param ID ID -- id of the new widget. Determined in `Internal._Insert`
@return Widget -- the newly created widget.
All widgets are created as tables with properties. The widget class contains the functions to create the UI instances and
update the widget or change state.
Expand Down Expand Up @@ -574,11 +582,11 @@ return function(Iris: Types.Iris): Types.Internal
end

--[=[
@function _ContinueWidget
@within Internal
@param ID Types.ID -- id of the widget.
@function _ContinueWidget
@param ID ID -- id of the widget.
@param widgetType string
@return Types.Widget -- the widget.
@return Widget -- the widget.
Since the widget has already been created this frame, we can just add it back to the stack. There is no checking of
arguments or states.
Expand All @@ -599,9 +607,9 @@ return function(Iris: Types.Iris): Types.Internal
end

--[=[
@function _DiscardWidget
@within Internal
@param widgetToDiscard Types.Widget
@function _DiscardWidget
@param widgetToDiscard Widget
Destroys the widget instance and updates any parent. This happens if the widget was not called in the
previous frame. There is no code which needs to update any widget tables since they are already reset
Expand All @@ -622,12 +630,12 @@ return function(Iris: Types.Iris): Types.Internal
end

--[=[
@function _widgetState
@within Internal
@param thisWidget Types.Widget -- widget the state belongs to.
@function _widgetState
@param thisWidget Widget -- widget the state belongs to.
@param stateName string
@param initialValue any
@return Types.State -- the state for the widget.
@return State<any> -- the state for the widget.
Connects the state to the widget. If no state exists then a new one is created. Called for every state in every
widget if the user does not provide a state.
Expand All @@ -649,9 +657,9 @@ return function(Iris: Types.Iris): Types.Internal
end

--[=[
@function _EventCall
@within Internal
@param thisWidget Types.Widget
@function _EventCall
@param thisWidget Widget
@param evetName string
@return boolean -- the value of the event.
Expand All @@ -671,9 +679,9 @@ return function(Iris: Types.Iris): Types.Internal
end

--[=[
@function _GetParentWidget
@within Internal
@return Types.Widget -- the parent widget
@function _GetParentWidget
@return Widget -- the parent widget
Returns the parent widget of the currently active widget, based on the stack depth.
]=]
Expand All @@ -685,8 +693,9 @@ return function(Iris: Types.Iris): Types.Internal

--[=[
@ignore
@function _generateEmptyVDOM
@within Internal
@function _generateEmptyVDOM
@return { [ID]: Widget }
Creates the VDOM at the start of each frame containing jsut the root instance.
]=]
Expand All @@ -698,8 +707,8 @@ return function(Iris: Types.Iris): Types.Internal

--[=[
@ignore
@function _generateRootInstance
@within Internal
@function _generateRootInstance
Creates the root instance.
]=]
Expand All @@ -712,8 +721,8 @@ return function(Iris: Types.Iris): Types.Internal

--[=[
@ignore
@function _generateSelctionImageObject
@within Internal
@function _generateSelctionImageObject
Creates the selection object for buttons.
]=]
Expand Down Expand Up @@ -749,9 +758,10 @@ return function(Iris: Types.Iris): Types.Internal
-- Utility

--[=[
@function _getID
@within Internal
@function _getID
@param levelsToIgnore number -- used to skip over internal calls to `_getID`.
@return ID
Generates a unique ID for each widget which is based on the line that the widget is
created from. This ensures that the function is heuristic and always returns the same
Expand Down Expand Up @@ -786,10 +796,11 @@ return function(Iris: Types.Iris): Types.Internal

--[=[
@ignore
@function _deepCompare
@within Internal
@param t1 table
@param t2 table
@function _deepCompare
@param t1 {}
@param t2 {}
@return boolean
Compares two tables to check if they are the same. It uses a recursive iteration through one table
to compare against the other. Used to determine if the arguments of a widget have changed since last
Expand Down Expand Up @@ -819,9 +830,10 @@ return function(Iris: Types.Iris): Types.Internal

--[=[
@ignore
@function _deepCopy
@within Internal
@param t table
@function _deepCopy
@param t {}
@return {}
Performs a deep copy of a table so that neither table contains a shared reference.
]=]
Expand Down
8 changes: 4 additions & 4 deletions lib/Types.lua
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ export type Internal = {
_rootWidget: ParentWidget,
_lastWidget: Widget,
SelectionImageObject: Frame,
parentInstance: BasePlayerGui,
parentInstance: Instance,
_utility: WidgetUtility,

-- Config
Expand Down Expand Up @@ -563,7 +563,7 @@ export type Iris = {

State: <T>(initialValue: T) -> State<T>,
WeakState: <T>(initialValue: T) -> T,
ComputedState: <T, U>(firstState: State<T>, onChangeCallback: (firstState: T) -> U) -> State<U>,
ComputedState: <T, U>(firstState: State<T>, onChangeCallback: (firstValue: T) -> U) -> State<U>,

--[[
-------------
Expand All @@ -581,9 +581,9 @@ export type Iris = {
SetFocusedWindow: (thisWidget: Window?) -> (),

-- ID API
PushId: (id: ID) -> (),
PushId: (ID: ID) -> (),
PopId: () -> (),
SetNextWidgetID: (id: ID) -> (),
SetNextWidgetID: (ID: ID) -> (),

-- Config API
UpdateGlobalConfig: (deltaStyle: { [string]: any }) -> (),
Expand Down
16 changes: 14 additions & 2 deletions lib/WidgetTypes.lua
Original file line number Diff line number Diff line change
@@ -1,15 +1,27 @@
--[=[
@within Iris
@type ID string
]=]
export type ID = string

--[=[
@within State
@type State<T> { value: T, get: (self) -> T, set: (self, newValue: T) -> T, onChange: (self, callback: (newValue: T) -> ()) -> (), ConnectedWidgets: { [ID]: Widget }, ConnectedFunctions: { (newValue: T) -> () } }
]=]
export type State<T> = {
value: T,
ConnectedWidgets: { [ID]: Widget },
ConnectedFunctions: { (T) -> () },
ConnectedFunctions: { (newValue: T) -> () },

get: (self: State<T>) -> T,
set: (self: State<T>, newValue: T) -> (),
onChange: (self: State<T>, funcToConnect: (T) -> ()) -> () -> (),
onChange: (self: State<T>, funcToConnect: (newValue: T) -> ()) -> () -> (),
}

--[=[
@within Iris
@type Widget { ID: ID, type: string, lastCycleTick: number, parentWidget: Widget, Instance: GuiObject, ZIndex: number, arguments: { [string]: any }}
]=]
export type Widget = {
ID: ID,
type: string,
Expand Down
Loading

0 comments on commit fd86d85

Please sign in to comment.