chemical_docs/pages/api/ComposePage.tsx
2025-06-13 18:13:43 +02:00

222 lines
9 KiB
TypeScript

import React from 'react';
import { ContentPage } from '../../components/ContentPage';
import { ApiSection } from '../../types';
const composeApi: ApiSection[] = [
{
title: 'Chemical.Compose',
description: 'The `Compose` API is used for declaratively creating and managing Roblox UI Instances. It allows you to bind UI properties to reactive state (Values or Computeds) and handle UI events.',
entries: [
{
signature: 'Chemical.Compose(target: string | Instance): (properties: GuiProperties) => Instance & CompositionHandle',
description: 'Starts a UI composition. It takes a target, which can be a string (ClassName of the Instance to create, e.g., "TextLabel") or an existing Instance to adopt and manage.',
parameters: [
{ name: 'target', type: 'string | Instance', description: 'The ClassName of the UI element to create, or an existing Instance to manage.' },
],
returns: { type: '(properties: GuiProperties) => Instance & CompositionHandle', description: 'A function that takes a properties table and returns the created/managed Instance. The instance is augmented with a `.Destroy()` method specific to the composition.' },
example: `
local Chemical = require(game.ReplicatedStorage.Chemical)
local Compose = Chemical.Compose
-- Assuming playerGui is defined, e.g., local playerGui = game.Players.LocalPlayer:WaitForChild("PlayerGui")
local MyScreen = Compose("ScreenGui")({ Parent = playerGui })
-- Create a new TextLabel
local MyLabelFactory = Compose("TextLabel")
local labelInstance = MyLabelFactory({
Name = "ScoreLabel",
Text = "Score: 0",
Parent = MyScreen -- Parent to the ScreenGui
})
-- Adopt an existing Frame
local existingFrame = Instance.new("Frame")
existingFrame.Parent = MyScreen -- Parent to the ScreenGui
local MyFrameManager = Compose(existingFrame)
MyFrameManager({
BackgroundColor3 = Color3.new(1, 0, 0)
})
`,
},
],
},
{
title: 'Properties Table (GuiProperties)',
description: 'The properties table passed to the composer function defines the attributes and event handlers for the UI Instance.',
entries: [
{
signature: 'Standard Properties (e.g., Name, Size, Position, Text, BackgroundColor3)',
description: 'You can set any standard Roblox Instance property. If the value provided is a Chemical `Value` or `Computed`, the Instance property will reactively update whenever the stateful object changes.',
example: `
local Chemical = require(game.ReplicatedStorage.Chemical)
local Value = Chemical.Value
local Compose = Chemical.Compose
local Children = Chemical.Symbols.Children -- Alias for Children key
-- Assuming playerGui is defined
local labelText = Value("Loading...")
local labelColor = Value(Color3.new(1,1,1))
local MyScreen = Compose("ScreenGui")({
Parent = playerGui,
[Children] = {
Compose("TextLabel")({
Text = labelText, -- Reactive binding
TextColor3 = labelColor, -- Reactive binding
Size = UDim2.new(0, 200, 0, 50)
})
}
})
labelText:set("Ready!") -- The TextLabel's Text property updates
labelColor:set(Color3.new(0,1,0)) -- The TextLabel's TextColor3 updates
`,
},
{
signature: 'Parent: Instance',
description: 'Sets the `Parent` of the created/managed Instance.',
example: `
local Chemical = require(game.ReplicatedStorage.Chemical)
local Compose = Chemical.Compose
local Children = Chemical.Symbols.Children -- Alias for Children key
-- Assuming playerGui is defined
local MyScreen = Compose("ScreenGui")({ Parent = playerGui })
local MyFrame = Compose("Frame")({ Parent = MyScreen })
Compose("TextLabel")({
Parent = MyFrame, -- Sets the parent to MyFrame
[Children] = {} -- Empty children if none, but key must be present if Children symbol is used.
})
`,
},
{
signature: '[Chemical.Symbols.Children]: { Instance | CompositionHandle }',
description: 'An array of child Instances or other Compositions to parent under this element. The key for this property MUST be the `Chemical.Symbols.Children` symbol (often aliased to a local variable `Children` and used as `[Children]`).',
example: `
local Chemical = require(game.ReplicatedStorage.Chemical)
local Compose = Chemical.Compose
local Children = Chemical.Symbols.Children -- Alias the symbol
-- Assuming playerGui exists
Compose("ScreenGui")({
Parent = playerGui,
[Children] = { -- Use the aliased Children symbol
Compose("Frame")({
Name = "Container",
Size = UDim2.fromScale(0.8, 0.8),
Position = UDim2.fromScale(0.1, 0.1),
[Children] = { -- Use the aliased Children symbol
Compose("TextButton")({ Name = "Button1", Text = "B1", Size = UDim2.fromScale(0.2, 0.1) }),
Compose("ImageLabel")({ Name = "Icon", Size = UDim2.fromScale(0.2,0.2), Position = UDim2.fromOffset(100,0) })
}
})
}
})
`,
},
{
signature: '[Chemical.OnEvent(eventName: string)]: (Instance, ...args) -> ()',
description: 'Attaches an event handler to a Roblox Instance event (e.g., "Activated", "MouseButton1Click", "MouseEnter"). The `eventName` should match the Roblox event name.',
example: `
local Chemical = require(game.ReplicatedStorage.Chemical)
local Compose = Chemical.Compose
local OnEvent = Chemical.OnEvent
local Children = Chemical.Symbols.Children -- Alias for Children key
-- Assuming playerGui is defined
local MyScreen = Compose("ScreenGui")({
Parent = playerGui,
[Children] = {
Compose("TextButton")({
Text = "Click Me",
[OnEvent("Activated")] = function(buttonInstance)
print(buttonInstance.Name .. " was activated!")
end,
[OnEvent("MouseEnter")] = function(buttonInstance)
buttonInstance.BackgroundColor3 = Color3.new(0.5, 0.5, 0.5)
end,
[OnEvent("MouseLeave")] = function(buttonInstance)
buttonInstance.BackgroundColor3 = Color3.new(0.2, 0.2, 0.2)
end
})
}
})
`,
},
{
signature: '[Chemical.OnChange(propertyName: string)]: ((newValue: any) -> ()) | Value<any>',
description: 'Listens for changes to a specific property of the Instance (using `Instance:GetPropertyChangedSignal(propertyName)`). The provided callback function will be executed, or if a Chemical `Value` is provided, its `:set()` method will be called with the new property value.',
example: `
local Chemical = require(game.ReplicatedStorage.Chemical)
local Value = Chemical.Value
local Compose = Chemical.Compose
local OnChange = Chemical.OnChange
local Children = Chemical.Symbols.Children -- Alias for Children key
local Effect = Chemical.Effect
-- Assuming playerGui is defined
local currentText = Value("")
local MyScreen = Compose("ScreenGui")({
Parent = playerGui,
[Children] = {
Compose("TextBox")({
Name = "MyInput",
PlaceholderText = "Enter text here...",
[OnChange("Text")] = function(newText) -- Callback function
print("TextBox text changed to:", newText)
end,
-- OR bind to a Value:
-- [OnChange("Text")] = currentText
})
}
})
-- If bound to currentText:
-- Effect(function() print("currentText Value is:", currentText:get()) end)
`,
},
],
},
{
title: 'Composition Handle',
description: 'The function returned by `Chemical.Compose(target)` returns the Instance itself, but this instance is also augmented with a specific `Destroy` method related to the composition.',
entries: [
{
signature: 'compositionHandle:Destroy()',
description: 'Destroys the UI composition created by `Chemical.Compose`. This includes: destroying the root Instance, disconnecting all event listeners and property change signals established by the composition, and destroying any Effects that were created to bind reactive properties. If the composition managed child compositions, their `Destroy` methods are also called.',
example: `
local Chemical = require(game.ReplicatedStorage.Chemical)
local Compose = Chemical.Compose
local Children = Chemical.Symbols.Children -- Alias for Children key
-- Assuming playerGui is defined
local MyScreen = Compose("ScreenGui")({
Parent = playerGui,
[Children] = {
Compose("TextLabel")({
Text = "Hello"
})
}
})
local labelComposition = MyScreen.Children[1] -- Accessing the composed TextLabel
-- ... later
-- To destroy the label specifically (if it were assigned to a variable directly from Compose)
-- labelComposition:Destroy()
-- To destroy the entire screen and all its composed children:
MyScreen:Destroy() -- The ScreenGui instance and its TextLabel are destroyed, and all Chemical bindings are cleaned up.
`,
notes: "This is different from `instance:Destroy()`. While `instance:Destroy()` destroys the Roblox Instance, `compositionHandle:Destroy()` also cleans up Chemical-specific resources like effects and event connections associated with that composition."
}
]
}
];
export const ComposePage: React.FC = () => {
return <ContentPage title="Chemical.Compose" sections={composeApi} />;
};