-
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
17 changed files
with
633 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
local Package = script.Parent | ||
local Packages = Package.Parent | ||
|
||
local React = require(Packages.React) | ||
local Signal = require(Packages.Signal) | ||
|
||
export type Component = React.ComponentType<unknown> | ||
export type Components = { [string]: Component } | ||
|
||
local components: Components = {} | ||
local componentsChanged = Signal.new() | ||
|
||
local function updateComponents(components: Components) | ||
components = components | ||
componentsChanged:Fire(components) | ||
end | ||
|
||
local function insertComponent(key: string, component: Component) | ||
components[key] = component | ||
updateComponents(components) | ||
end | ||
|
||
local function removeComponent(key: string) | ||
components[key] = nil | ||
updateComponents(components) | ||
end | ||
|
||
return { | ||
Components = components, | ||
ComponentsChanged = componentsChanged.Event, | ||
|
||
insertComponent = insertComponent, | ||
removeComponent = removeComponent, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
local Package = script.Parent.Parent | ||
local Packages = Package.Parent | ||
|
||
local React = require(Packages.React) | ||
local RegisteredComponents = require(Package.RegisteredComponents) | ||
|
||
local e = React.createElement | ||
local Fragment = React.Fragment | ||
local useEffect = React.useEffect | ||
local useMemo = React.useMemo | ||
local useState = React.useState | ||
|
||
export type RenderProps<P> = { | ||
child: React.ComponentType<P>, | ||
props: P, | ||
} | ||
|
||
export type Props<P> = { | ||
render: React.ComponentType<RenderProps<P>>?, | ||
props: P, | ||
} | ||
|
||
type Components = RegisteredComponents.Components | ||
type RenderedComponents = { [string]: React.ReactNode } | ||
|
||
local function DefaultRender<P>(props: RenderProps<P>): React.ReactNode | ||
return e(props.child, props.props) | ||
end | ||
|
||
local function RenderSystems<P>(props: Props<P>): React.ReactNode | ||
local render = props.render or DefaultRender | ||
local children: Components, updateChildren = useState({}) | ||
|
||
useEffect(function() | ||
updateChildren(RegisteredComponents.Components) | ||
|
||
local connection = RegisteredComponents.ComponentsChanged:Connect( | ||
function(components: Components) | ||
updateChildren(components) | ||
end | ||
) | ||
|
||
return function() | ||
connection.disconnect() | ||
end | ||
end, {}) | ||
|
||
local renderedChildren = useMemo(function(): RenderedComponents | ||
local renderedChildren = {} | ||
|
||
for key, component in children do | ||
renderedChildren[key] = e(render, { | ||
child = component, | ||
props = props.props, | ||
}) | ||
end | ||
|
||
return renderedChildren | ||
end, { children, render, props.props }) | ||
|
||
return e(Fragment, {}, renderedChildren) | ||
end | ||
|
||
return RenderSystems |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
local Package = script.Parent.Parent | ||
local Packages = Package.Parent | ||
local Contexts = Package.contexts | ||
|
||
local Params = require(Contexts.Params) | ||
local React = require(Packages.React) | ||
local Return = require(Contexts.Return) | ||
local Signal = require(Packages.Signal) | ||
|
||
local e = React.createElement | ||
local useEffect = React.useEffect | ||
local useState = React.useState | ||
|
||
export type Complete<T> = Return.Complete<T> | ||
export type PreviouslyComplete<T> = Return.PreviouslyComplete<T> | ||
export type Incomplete = Return.Incomplete | ||
export type Ready<T> = Return.Ready<T> | ||
|
||
export type Passed<Params, Return> = { | ||
params: Params, | ||
ready: Ready<Return>, | ||
} | ||
|
||
local function SystemComponent<Props, Params, Return>( | ||
component: React.ComponentType<Props>, | ||
passed: Passed<Params, Return>, | ||
signal: typeof(Signal.new()) | ||
): React.ComponentType<Props> | ||
return function(props: Props): React.ReactNode | ||
local passed, updatePassed = useState(passed) | ||
|
||
local function updateReturn(value: Return | (value: Return?) -> Return) | ||
if type(value) == "function" then | ||
updatePassed(function(oldPassed: Passed<Params, Return>): Passed<Params, Return> | ||
local newPassed = { | ||
params = oldPassed.params, | ||
ready = { | ||
completed = true, | ||
value = value( | ||
if oldPassed.ready.completed then oldPassed.ready.value else nil | ||
), | ||
}, | ||
} | ||
|
||
signal:Fire(newPassed) | ||
return newPassed | ||
end) | ||
else | ||
local newPassed = { | ||
params = passed.params, | ||
ready = { | ||
completed = true, | ||
value = value, | ||
}, | ||
} | ||
|
||
signal:Fire(newPassed) | ||
end | ||
end | ||
|
||
useEffect(function() | ||
local connection = signal:Connect(function(value: Passed<Params, Return>) | ||
updatePassed(value) | ||
end) | ||
|
||
return function() | ||
connection.disconnect() | ||
end | ||
end, {}) | ||
|
||
return e(Params.Provider, { | ||
value = { | ||
params = passed.params, | ||
}, | ||
}, { | ||
e(Return.Provider, { | ||
value = { | ||
updateReturn = updateReturn, | ||
}, | ||
}, { | ||
SystemComponent = e(component, props), | ||
}), | ||
}) | ||
end | ||
end | ||
|
||
return SystemComponent |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
local Package = script.Parent.Parent | ||
local Packages = Package.Parent | ||
|
||
local React = require(Packages.React) | ||
|
||
export type ParamType<T> = T & {} | ||
|
||
export type Params<T> = { | ||
params: ParamType<T>?, | ||
} | ||
|
||
local defaultParams: Params<unknown> = {} | ||
|
||
local Params = React.createContext(defaultParams) | ||
|
||
return Params |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
local Package = script.Parent.Parent | ||
local Packages = Package.Parent | ||
|
||
local React = require(Packages.React) | ||
|
||
export type Complete<T> = { | ||
completed: true, | ||
value: T, | ||
} | ||
|
||
export type PreviouslyComplete<T> = { | ||
completed: false, | ||
value: T, | ||
} | ||
|
||
export type Incomplete = { | ||
completed: false, | ||
} | ||
|
||
export type Ready<T> = Complete<T> | PreviouslyComplete<T> | Incomplete | ||
|
||
export type UpdateReturn<T> = (value: T | (value: T?) -> T) -> () | ||
|
||
export type Return<T> = { | ||
updateReturn: UpdateReturn<T>?, | ||
} | ||
|
||
local defaultReturn: Return<unknown> = {} | ||
|
||
local Return = React.createContext(defaultReturn) | ||
|
||
return Return |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
local function diffTables(left: { [unknown]: unknown }?, right: { [unknown]: unknown }?): boolean | ||
if left and right then | ||
if left == right then | ||
return false | ||
end | ||
|
||
local size = 0 | ||
|
||
for key, value in left do | ||
if value ~= right[key] then | ||
return true | ||
end | ||
size += 1 | ||
end | ||
|
||
for _ in right do | ||
size -= 1 | ||
end | ||
|
||
if size ~= 0 then | ||
return true | ||
end | ||
|
||
return false | ||
end | ||
|
||
return true | ||
end | ||
|
||
return diffTables |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
local diffTables = require(script.Parent.diffTables) | ||
|
||
return function() | ||
describe("function", function() | ||
it("should be true when both parameters are nil", function() | ||
expect(diffTables()).to.equal(true) | ||
end) | ||
|
||
it("should be true when the first parameter is nil", function() | ||
expect(diffTables(nil, {})).to.equal(true) | ||
end) | ||
|
||
it("should be true when the second parameter is nil", function() | ||
expect(diffTables({})).to.equal(true) | ||
end) | ||
|
||
it("should be false with two different empty tables", function() | ||
local left = {} | ||
local right = {} | ||
expect(diffTables(left, right)).to.equal(false) | ||
end) | ||
|
||
it("should be true with tables with different elements", function() | ||
local left = { | ||
1, | ||
2, | ||
3, | ||
} | ||
local right = { | ||
"a", | ||
"b", | ||
"c", | ||
} | ||
expect(diffTables(left, right)).to.equal(true) | ||
end) | ||
|
||
it("should be true with tables with nearly the same elements", function() | ||
local left = { | ||
1, | ||
2, | ||
3, | ||
} | ||
local right = { | ||
1, | ||
2, | ||
3, | ||
4, | ||
} | ||
expect(diffTables(left, right)).to.equal(true) | ||
end) | ||
|
||
it("should be false with different identical tables", function() | ||
local left = { | ||
1, | ||
2, | ||
3, | ||
} | ||
local right = { | ||
1, | ||
2, | ||
3, | ||
} | ||
expect(diffTables(left, right)).to.equal(false) | ||
end) | ||
|
||
it("should be false with the same table", function() | ||
local left = { | ||
1, | ||
2, | ||
3, | ||
} | ||
expect(diffTables(left, left)).to.equal(false) | ||
end) | ||
end) | ||
end |
Oops, something went wrong.