Skip to content

Commit

Permalink
Added WithChild SpecialKey
Browse files Browse the repository at this point in the history
I got this idea from this issue, dphfox/Fusion#124

This does make working with templates a lot nicer and simple, but I'm still not entirely sure about this design. I've proposed a different method in Instance/Keys/Children.luau.
  • Loading branch information
HappySunChild committed Feb 17, 2025
1 parent 62948a5 commit 7da8267
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 6 deletions.
19 changes: 19 additions & 0 deletions demos/Template/templateTest.client.luau
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
local Players = game:GetService 'Players'
local ReplicatedStorage = game:GetService 'ReplicatedStorage'

local Fusion = require(ReplicatedStorage.Libraries.ConFusion)
local scoped, WithChild = Fusion.scoped, Fusion.WithChild

local template = ReplicatedStorage:WaitForChild 'Template'

local scope = scoped(Fusion)

scope:New(template) {
Parent = Players.LocalPlayer.PlayerGui,

[WithChild 'Frame'] = {
BackgroundColor3 = Fusion.Clock:map(function(t)
return Color3.fromHSV(t % 1, 1, 1)
end),
},
}
61 changes: 55 additions & 6 deletions src/Instance/Keys/Children.luau
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
local package = script.Parent.Parent.Parent

local External = require(package.External)
local Types = require(package.Types)

local castToState = require(package.State.castToState)
Expand All @@ -11,11 +12,7 @@ local Children: Types.SpecialKey = table.freeze {
kind = 'key',
type = 'children',

apply = function(
scope: Types.Scope,
applyTo: Instance,
children: Types.Child
)
apply = function(scope: Types.Scope, applyTo: Instance, children: Types.Child?)
local newChildren, oldChildren = {}, {}
local newScopes, oldScopes = {}, {}

Expand All @@ -38,6 +35,52 @@ local Children: Types.SpecialKey = table.freeze {
if name then
child.Name = name
end
--[[
This is something I'm still considering.
I thought about how you could technically have "unresolved children" by using a function that passes the parent and returns the child/children.
Maybe this could be used during Hydrate to apply properties to existing children?
(got the idea from this issue: https://github.com/dphfox/Fusion/issues/206)
An example of what this could possibly look like in use:
```
local function ExistingChild(scope, childName)
return function(props)
-- this function gets called when updating the children.
return function(parent)
local child = parent:FindFirstChild(childName)
applyProperties(scope, child, props)
return child
end
end
end
```
This function could then be used like this:
```
scope:Hydrate(screenGui) {
[Children] = {
-- this returns a function which sort of functions as a "unresolved" child.
-- you could write variations of this function to work with `:WaitForChild`, `:FindFirstAncestor`, `:FindFirstChildOfClass`, etc.
scope:ExistingChild "Label" {
BackgroundColor3 = Color3.fromRGB(184, 85, 85),
Text = "Hello world!"
...etc
}
}
}
```
I haven't thoroughly tested this, but just from this brief example I think it'd work pretty well.
I could be wrong though!
]]
elseif childType == 'function' then
local childInstance = child(applyTo)

if childInstance then
processChild(childInstance)
end
elseif castToState(child) then
local value = peek(child)

Expand All @@ -49,6 +92,7 @@ local Children: Types.SpecialKey = table.freeze {

if not childScope then
childScope = {}

observe(child, updateChildren)
else
oldScopes[child] = nil
Expand All @@ -60,7 +104,11 @@ local Children: Types.SpecialKey = table.freeze {
processChild(subChild, key)
end
else
error(`Unknown child type, '{childType}'`, 2)
External.logErrorNonFatal(
'invalidChildType',
debug.traceback(nil, 2),
childType
)
end
end

Expand All @@ -83,6 +131,7 @@ local Children: Types.SpecialKey = table.freeze {

table.insert(scope, function()
children = nil

updateChildren()
end)

Expand Down
46 changes: 46 additions & 0 deletions src/Instance/Keys/WithChild.luau
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
local package = script.Parent.Parent.Parent

local External = require(package.External)
local Types = require(package.Types)

local applyProperties = require(package.Instance.applyProperties)

local keyCache = {}

local function WithChild(childName: string): Types.SpecialKey
local key = keyCache[childName]

if not key then
key = table.freeze {
type = 'children',
kind = 'key',

apply = function(
scope: Types.Scope,
applyTo: Instance,
properties: Types.Properties
)
local child = applyTo:FindFirstChild(childName)

if not child then
return External.logErrorNonFatal(
'missingChild',
nil,
childName,
applyTo.Name
)
end

applyProperties(scope, child, properties)

return
end,
}

keyCache[childName] = key
end

return key
end

return WithChild
1 change: 1 addition & 0 deletions src/init.luau
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ local ReFusion = table.freeze {
Out = require(Keys.Out),
OnEvent = require(Keys.OnEvent),
OnChange = require(Keys.OnChange),
WithChild = require(Keys.WithChild),
}

if game ~= nil then
Expand Down

0 comments on commit 7da8267

Please sign in to comment.