### Install Project Dependencies Source: https://github.com/pepeeltoro41/ui-labs/blob/main/CONTRIBUTING.md Install all necessary Node.js dependencies for the project using npm. ```bash npm install ``` -------------------------------- ### Fusion Story Example in Luau Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/stories/function.md Shows how to mount and destroy a Fusion component within a UI Labs story using Luau. ```lua local function story(target: Frame) local component = Fusion.New "Frame" { Parent = target, } return function() component:Destroy() end end return story ``` -------------------------------- ### CreateControlStates Luau Example Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/stories/advanced/generic.md Demonstrates how to use CreateControlStates in Luau to generate control states with a custom creator function. ```lua local UILabs = require(...) local CreateControlStates = UILabs.CreateControlStates -- We're gonna use an imaginary library called Lib for this example local controls = { ... } local story = { controls = controls, render = function(props) local states = CreateControlStates(props.converted, props.controls, function(value) -- // [!code focus:3] return Lib.State(value) -- This is how the library would create a state end) return function() -- Cleanup end end } return story ``` -------------------------------- ### Install Roblox-TS Globally Source: https://github.com/pepeeltoro41/ui-labs/blob/main/CONTRIBUTING.md If the 'npm run watch' command fails, try installing roblox-ts globally first. This ensures the compiler is available system-wide. ```bash npm install -G roblox-ts ``` -------------------------------- ### Iris Story with Demo Window Source: https://context7.com/pepeeltoro41/ui-labs/llms.txt Integrates with the Iris immediate-mode GUI library, providing automatic setup and cleanup for stories. ```lua -- Iris story with demo window local Iris = require(ReplicatedStorage.Iris) local controls = { WindowTitle = "Settings", IsUncollapsed = false, } local story = { iris = Iris, controls = controls, story = function(props) local controls = props.controls Iris:Connect(function() Iris.Window({ controls.WindowTitle:get() }, { isUncollapsed = controls.IsUncollapsed }) Iris.Text({ "Hello from Iris!" }) if Iris.Button({ "Click Me" }).clicked() then print("Button clicked!") end Iris.End() end) end } return story ``` -------------------------------- ### Luau UI Controls Example with EnumList Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/controls/advanced.md A Luau example showcasing the integration of various UI controls, including Choose and EnumList, within a configuration object. This snippet illustrates how to define options for themes, currencies, window sizes, and text colors. ```lua local UILabs = require(...) -- Path of your Utility Package local controls = { -- [[ Choose ]] -- Theme = UILabs.Choose({"Dark", "Light"}), Currency = UILabs.Choose({"Coins", "Gems"}), -- [[ EnumList ]] -- WindowSize = UILabs.EnumList({ Mobile = 500, Tablet = 1000, Desktop = 1500, }, "Mobile"), TextColor = UILabs.EnumList({ Red = Color3.new(1, 0, 0), Green = Color3.new(0, 1, 0), Blue = Color3.new(0, 0, 1), }, "Red"), Volume = UILabs.Slider(50, 0, 100, 1), -- it only has integer values FrameColor = UILabs.RGBA(Color3.new(1, 1, 1), 0) -- you will need to set BackgroundTransparency too } local story = { controls = controls, story = ... } return story ``` -------------------------------- ### Roact Story Example in Luau Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/stories/function.md Demonstrates mounting and unmounting a Roact component within a UI Labs story using Luau. ```lua local function story(target) local component = Roact.createElement("Frame", {}) local root = Roact.mount(component, target) return function() Roact.unmount(root) end end return story ``` -------------------------------- ### Open Documentation in VS Code Source: https://github.com/pepeeltoro41/ui-labs/blob/main/CONTRIBUTING.md Open the 'docs' folder in Visual Studio Code to start contributing to the project's documentation. This command assumes you are in the project's root directory. ```bash code . ``` -------------------------------- ### Roblox Instance Story Example in Luau Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/stories/function.md Demonstrates creating, parenting, and destroying a raw Roblox Instance within a UI Labs story using Luau. ```lua local function story(target: Frame) local component = Instance.new("Frame") component.Parent = target return function() component:Destroy() end end return story ``` -------------------------------- ### Fusion.js Story Example Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/stories/advanced/generic.md This snippet demonstrates how to define a story using Fusion.js, including control state management and component lifecycle. ```typescript type FusionValues = InferCreatedControls; const story = { controls: controls, render: (props: InferGenericProps) => { const states: FusionValues = CreateControlStates(props.converted, props.controls, (value) => { return Fusion.Value(value); }); const component = Fusion.New("Frame")({ Parent: props.target, Size: UDim2.fromOffset(200, 100), Visible: states.Visible, // This will be a Fusion.Value }); props.subscribe((values) => { // we need to cast "state" to the correct type UpdateControlStates(states, props.converted, values, (state: Fusion.Value, value) => { state.set(value); }); }); return () => { component.Destroy(); }; }, }; export = story; ``` -------------------------------- ### Luau Story Example Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/plugin/visualizing.md A basic Luau function that creates a TextLabel with "Hello UI Labs" and returns a cleanup function to destroy the element. ```lua local function story(target) local element = Instance.new("TextLabel") element.Text = "Hello UI Labs" element.Size = UDim2.fromOffset(250, 80) element.TextSize = 20 element.Parent = target return function() element:Destroy() end end return story ``` -------------------------------- ### Create a Basic Story Module Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/stories/create.md Story modules should return the story object to be rendered. This example shows the basic structure for both Luau and Roblox-TS. ```lua local story = ... return story ``` ```ts const story = ... export = story; ``` -------------------------------- ### Roblox Instance Story Example in Roblox-TS Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/stories/function.md Demonstrates creating, parenting, and destroying a raw Roblox Instance within a UI Labs story using Roblox-TS. ```typescript function story(target: Frame) { const component = new Instance("Frame"); component.Parent = target; return () => { component.Destroy(); }; } export = story; ``` -------------------------------- ### Fusion Story Example in Roblox-TS Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/stories/function.md Shows how to mount and destroy a Fusion component within a UI Labs story using Roblox-TS. ```typescript function story(target: Frame) { const component = Fusion.New("Frame")({ Parent: target, }); return () => { component: Destroy(); }; } export = story; ``` -------------------------------- ### Roact Story Example in Roblox-TS Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/stories/function.md Demonstrates mounting and unmounting a Roact component within a UI Labs story using Roblox-TS. ```typescript function story(target: Frame) { const component = ; Roact.mount(component, target); return () => { Roact.unmount(component); }; } export = story; ``` -------------------------------- ### CreateGenericStory Luau Example Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/stories/advanced/generic.md Example of using CreateGenericStory in Luau to define a UI component story. It sets up a basic Frame component and subscribes to control value changes. ```lua local UILabs = require(...) local CreateGenericStory = UILabs.CreateGenericStory local story = CreateGenericStory({ controls = {}, }, function(props) local component = Instance.new("Frame") component.Size = UDim2.fromOffset(200, 100) component.Parent = props.target props.subscribe(function(values) print("controls changed", values) end) return function() component:Destroy() end end) return story ``` -------------------------------- ### CreateControlStates Roblox-TS Example Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/stories/advanced/generic.md Shows how to use CreateControlStates in Roblox-TS, including type inference for control properties. ```typescript import { CreateControlStates, InferGenericProps } from "@rbxts/ui-labs" -- We're gonna use an imaginary library called Lib for this example const controls = { ... } const story = { controls: controls, render: (props: InferGenericProps) => { const states = CreateControlStates(props.converted, props.controls, (value) => { // [!code focus:3] return Lib.State(value) // This is how the library would create a state }) return () => { // Cleanup } } } export = story; ``` -------------------------------- ### Define Storybook with Story Roots Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/storybooks.md Configure a Storybook by specifying the `storyRoots` which are the folders containing your story files. This setup is used to organize and display stories in the UI Labs explorer. ```lua local storybook = { name = "Stories", storyRoots = { game.ServerScriptService.GameStories, game.ReplicatedStorage.OtherStories, }, } return storybook ``` ```typescript const storybook: Storybook = { name: "Stories", storyRoots: [ game.ServerScriptService.GameStories, game.ReplicatedStorage.OtherStories, ], }; export = storybook; ``` -------------------------------- ### Access UI Labs Environment Variables Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/es/docs/environment.md Use these variables to check the current environment and get unique identifiers. Ensure UI Labs is required before accessing. ```Luau local UILabs = require(ReplicatedStorage.UILabs) local Environment = UILabs.Environment print(Environment.IsStory()) print(Environment.EnvironmentUID) print(Environment.PreviewUID) print(Environment.OriginalG) print(Environment.PluginWidget) ``` -------------------------------- ### Create a Vide story using the Story Creator utility in Luau Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/stories/advanced/vide.md The `CreateVideStory` function from the UILabs utility package simplifies story creation and infers control types for Roblox-TS. This example shows its usage in Luau. ```Luau local Vide = require(...) local UILabs = require(...) local CreateVideStory = UILabs.CreateVideStory local controls = { ... } local story = CreateVideStory({ vide = Vide, controls = controls, }, function(props) return Vide.create "Frame" { Size = UDim2.fromOffset(200, 100), } end) ``` -------------------------------- ### Basic Advanced Story Structure in Luau Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/stories/advanced/index.md This Luau snippet demonstrates the fundamental structure of an advanced story, including its summary and the placeholder for the story rendering function. It's a starting point for creating stories that can be managed by UI Labs. ```lua local story = { summary = "This is a summary", controls = nil, -- We'll learn about controls later story = function() ... end } return story ``` -------------------------------- ### Commit Changes with Conventional Commits Source: https://github.com/pepeeltoro41/ui-labs/blob/main/CONTRIBUTING.md When committing changes, it is preferred to use conventional commit formats for clarity. Examples include 'feat:' for features, 'fix:' for bug fixes, and 'docs:' for documentation changes. ```bash git commit -m "feat: describe your feature, fix: describe your fix, docs: describe your documentation" ``` -------------------------------- ### Create a Vide story using the Story Creator utility in Roblox-TS Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/stories/advanced/vide.md The `CreateVideStory` function from the UILabs utility package simplifies story creation and infers control types for Roblox-TS. This example shows its usage in TypeScript. ```Roblox-TS import Vide from "@rbxts/vide" import { CreateVideStory } from "@rbxts/ui-labs" const controls = { ... } const story = CreateVideStory({ vide: Vide, controls: controls, }, (props: InferVideProps) => { return }) ``` -------------------------------- ### Preview Documentation Build Source: https://github.com/pepeeltoro41/ui-labs/blob/main/CONTRIBUTING.md Preview the built documentation site locally to check for any rendering issues. This command should be run from the 'docs' directory. ```bash npm run docs:preview ``` -------------------------------- ### Navigate to Project Directory Source: https://github.com/pepeeltoro41/ui-labs/blob/main/CONTRIBUTING.md Change your current directory to the cloned ui-labs project folder. ```bash cd ui-labs ``` -------------------------------- ### Build Documentation Source: https://github.com/pepeeltoro41/ui-labs/blob/main/CONTRIBUTING.md Build the documentation site to ensure it compiles correctly before making a pull request. This command should be run from the 'docs' directory. ```bash npm run docs:build ``` -------------------------------- ### CreateGenericStory Roblox-TS Example Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/stories/advanced/generic.md Example of using CreateGenericStory in Roblox-TS to define a UI component story. It sets up a basic Frame component and subscribes to control value changes. ```typescript import { CreateGenericStory } from "@rbxts/ui-labs"; const story = CreateGenericStory({ controls: {}, }, (props) => { const component = new Instance("Frame"); component.Size = UDim2.fromOffset(200, 100) component.Parent = props.target; props.subscribe((values) => { print("controls changed", values); }); return () => { component.Destroy(); }; }); export = story; ``` -------------------------------- ### Manual Creation of Primitive Controls Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/controls/primitive.md Explains how to manually create primitive controls using constructors provided in the UI Labs Utility Package, offering more customization options. ```APIDOC ## Manual Creation of Primitive Controls Primitive controls can also be created manually using constructors from the UI Labs Utility Package. ### String Control - **Method**: `String(def, filters?)` - **Parameters**: - `def` (string): Default control value. - `filters` (Array, Optional): An array of functions to filter input values. ### Number Control - **Method**: `Number(def, min?, max?, step?, dragger?, sens?) - **Parameters**: - `def` (number): Default control value. - `min` (number, Optional): Minimum accepted value. Defaults to -infinity. - `max` (number, Optional): Maximum accepted value. Defaults to infinity. - `step` (number, Optional): The increment/decrement step. Defaults to nil. - `dragger` (boolean, Optional): Whether to include a drag handle. Defaults to true. - `sens` (number, Optional): Sensitivity of the control. Defaults to `def`. ### Boolean Control - **Method**: `Boolean(def)` - **Parameters**: - `def` (boolean): The default value of the control. ``` -------------------------------- ### Handling User Input with InputListener Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/environment.md Shows how to connect to various input events provided by the Environment.InputListener, including InputBegan, InputEnded, InputChanged, and MouseMoved. This is essential for creating interactive UI elements within UI Labs. ```Luau local inputListener = Environment.InputListener inputListener.InputBegan:Connect(function(input, gameProcessed) print(input.UserInputType) end) inputListener.InputEnded:Connect(function(input, gameProcessed) print(input.UserInputType) end) inputListener.InputChanged:Connect(function(input, gameProcessed) print(input.UserInputType) end) inputListener.MouseMoved:Connect(function(mousePos) print(mousePos) end) ``` ```Roblox-TS const inputListener = Environment.InputListener; inputListener.InputBegan.Connect((input, gameProcessed) => { print(input.UserInputType); }); inputListener.InputEnded.Connect((input, gameProcessed) => { print(input.UserInputType); }); inputListener.InputChanged.Connect((input, gameProcessed) => { print(input.UserInputType); }); inputListener.MouseMoved.Connect((mousePos) => { print(mousePos); }); ``` -------------------------------- ### Serve Rojo Project Source: https://github.com/pepeeltoro41/ui-labs/blob/main/CONTRIBUTING.md Use Rojo to serve the project, syncing files with your Roblox place. This command should be run from the project's root directory. ```bash rojo serve ``` -------------------------------- ### Create Fusion Story in Luau Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/stories/advanced/fusion.md Use this Luau snippet to create a Fusion story with the UILabs.CreateFusionStory function. Ensure the Utility Package is installed. ```lua local Fusion = require(...) local UILabs = require(...) local CreateFusionStory = UILabs.CreateFusionStory local controls = { ... } local story = CreateFusionStory({ fusion = Fusion, controls = controls, }, function(props) local component = Fusion.New "Frame" { Parent = props.target, } return function() component:Destroy() end end) return story ``` -------------------------------- ### Clone UI Labs Repository Source: https://github.com/pepeeltoro41/ui-labs/blob/main/CONTRIBUTING.md Clone the UI Labs repository to your local machine to begin development. Ensure you replace YOUR_USERNAME with your GitHub username. ```bash git clone https://github.com/YOUR_USERNAME/ui-labs.git ``` -------------------------------- ### Compile Roblox-TS with Watch Mode Source: https://github.com/pepeeltoro41/ui-labs/blob/main/CONTRIBUTING.md Start the Roblox-TS compiler in watch mode to automatically recompile TypeScript files as they change. This is essential for development. ```bash npm run watch ``` -------------------------------- ### Accessing Environment Properties and Functions Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/environment.md Demonstrates how to access environment-specific properties like unique IDs and the original global environment, as well as how to use functions for reloading, unmounting, creating snapshots, and setting story holders. This is useful for interacting with the UI Labs environment in Luau. ```Luau local UILabs = require(ReplicatedStorage.UILabs) local Environment = UILabs.Environment print(Environment.IsStory()) ---- print(Environment.EnvironmentUID) print(Environment.PreviewUID) print(Environment.OriginalG) print(Environment.PluginWidget) ---- Environment.Reload() Environment.Unmount() Environment.CreateSnapshot("MySnapshot") Environment.SetStoryHolder(game.Workspace.Baseplate) ``` ```Roblox-TS import { Environment } from "@rbxts/ui-labs"; print(Environment.IsStory()); /* ------- print(Environment.EnvironmentUID); print(Environment.PreviewUID); print(Environment.OriginalG); print(Environment.PluginWidget); /* ------- * Environment.Reload(); Environment.Unmount(); Environment.CreateSnapshot("MySnapshot"); Environment.SetStoryHolder(game.Workspace.Baseplate); ``` -------------------------------- ### Environment.InputListener Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/environment.md Provides a user input listener for environments where UserInputService might not work directly. ```APIDOC ## Environment.InputListener ### Description Gives you a user input listener. This is useful as `UserInputService` will not work inside Plugin Widgets. ### Method Environment.InputListener ### Parameters None ### Response #### Success Response (InputSignals) - **InputBegan**: Signal for input beginning. - **InputChanged**: Signal for input changes. - **InputEnded**: Signal for input ending. - **MouseMoved**: Signal for mouse movement. ### Type Definition ```ts type InputSignals = { InputBegan: UserInputService.InputBegan; InputChanged: UserInputService.InputChanged; InputEnded: UserInputService.InputEnded; MouseMoved: Signal<(mousePos: Vector2)>; } ``` ### Notes Defaults to `nil` in non-story environments. ``` -------------------------------- ### Environment.UserInput Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/environment.md Provides access to UserInputService, with fallbacks for missing methods. ```APIDOC ## Environment.UserInput ### Description Same as `Environment.InputListener`. The difference is that this is typed as `UserInputService` and will default to it. This will also fallback to `UserInputService` for any missing methods. ### Method Environment.UserInput ### Parameters None ### Response #### Success Response (UserInputService) - **UserInputService**: The UserInputService object. ### Notes Defaults to `UserInputService` in non-story environments. ``` -------------------------------- ### UpdateControlStates Usage Example Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/stories/advanced/generic.md This snippet demonstrates how to use UpdateControlStates within a subscribe callback to update component states. It requires importing CreateControlStates and UpdateControlStates from the UI Labs library. ```Luau local UILabs = require(...)local CreateControlStates = UILabs.CreateControlStateslocal UpdateControlStates = UILabs.UpdateControlStates-- We will use an imaginary library called Lib for this examplelocal controls = { ... }local story = { controls = controls, render = function(props) local states = CreateControlStates(props.converted, props.controls, function(value) return Lib.State(value) -- This is how the library would create a state end) props.subscribe(function(values) -- // [!code focus:5] UpdateControlStates(states, props.converted, values, function(state, value) return state:set(value) -- This is how the library would update a state end) end) return function() -- Cleanup end end}return story ``` ```Roblox-TS import { CreateControlStates, UpdateControlStates, InferGenericProps } from "@rbxts/ui-labs"-- We will use an imaginary library called Lib for this exampleconst controls = { ... }const story = { controls: controls, render: (props: InferGenericProps) => { const states = CreateControlStates(props.converted, props.controls, (value) => { return Lib.State(value) // This is how the library would create a state }) props.subscribe((values) => { // [!code focus:6] -- "state" argument will be typed as any, you need to cast it to the correct type UpdateControlStates(states, props.converted, values, (state: Lib.State, value) => { return state.set(value) // This is how the library would update a state }) }) return () => { -- Cleanup } }}export = story; ``` -------------------------------- ### Render a basic Frame component with Vide Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/stories/advanced/vide.md Return a Vide.create instance to be rendered as children in the target frame. This is the standard way to render a story. ```Luau local story = { vide = Vide, story = function(props) return Vide.create "Frame" { Size = UDim2.fromOffset(200, 100), } end } ``` -------------------------------- ### Render Story with Controls (Luau) Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/stories/advanced/react.md Pass control values from the 'props.controls' table to your component's properties. This example demonstrates binding a 'Visible' control to a Frame's visibility. ```lua local controls = { Visible = true, } local story = { react = react, reactRoblox = reactRoblox, controls = controls, story = function(props) local component = React.createElement("Frame", { Visible = props.controls.Visible }) return component end } return story ``` -------------------------------- ### Using the Janitor for Resource Management Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/environment.md Illustrates how to use the janitor provided by the Environment module to manage resources, such as Instances and cleanup functions. This is crucial for preventing memory leaks in UI Labs environments. ```Luau local janitor = Environment.GetJanitor() janitor:Add(Instance.new("Part")) janitor:Add(function() print("Cleanup") end) ``` ```Roblox-TS const janitor = Environment.GetJanitor(); janitor.Add(new Instance("Part")); janitor.Add(() => { print("Cleanup"); }); ``` -------------------------------- ### Access UI Labs Environment Variables (Roblox-TS) Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/es/docs/environment.md Use these variables to check the current environment and get unique identifiers in TypeScript. Ensure UI Labs is imported before accessing. ```TypeScript import { Environment } from "@rbxts/ui-labs"; print(Environment.IsStory()); print(Environment.EnvironmentUID); print(Environment.PreviewUID); print(Environment.OriginalG); print(Environment.PluginWidget); ``` -------------------------------- ### Roblox-TS Story Example Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/plugin/visualizing.md A Roblox-TS function that creates a TextLabel with "Hello UI Labs" and returns a cleanup function to destroy the element. This is the TypeScript equivalent of the Luau story. ```typescript function story(target: Frame) { const element = new Instance("TextLabel"); element.Text = "Hello UI Labs"; element.Size = UDim2.fromOffset(250, 80); element.TextSize = 20; element.Parent = target; return () => { element.Destroy(); } } export = story; ``` -------------------------------- ### Connect Iris in Story Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/stories/advanced/iris.md Connect Iris and show the demo window within your story. This is called once when the story is initialized. ```lua local story = { iris = Iris, story = function(props) Iris:Connect(function() Iris.ShowDemoWindow() end) end, } ``` ```typescript const story = { iris: Iris, story: (props: InferIrisProps) => { Iris.Connect(() => { Iris.ShowDemoWindow() }) }, } ``` -------------------------------- ### Using ListenControl Utility (Luau) Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/stories/advanced/generic.md The `ListenControl` utility simplifies checking for control changes within a `subscribe` callback. It takes control info and a callback function that receives the new value if a change is detected. ```Luau local UILabs = require(...) local ListenControl = UILabs.ListenControl local controls = { Visible = true, } local story = { controls = controls, render = function(props) local component = Instance.new("Frame") component.Size = UDim2.fromOffset(200, 100) component.Visible = props.controls.Visible -- first update component.Parent = props.target props.subscribe(function(values, infos) ListenControl(infos.Visible, function(newValue) component.Visible = newValue end) end) return function() component:Destroy() end end } return story ``` -------------------------------- ### Cleanup Story Instance (Luau) Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/stories/advanced/fusion.md Shows how to return a cleanup function from a Fusion story in Luau to destroy a created component when the story is unmounted. ```lua local story = { fusion = Fusion, controls = controls, story = function(props) local component = Fusion.New "Frame" { Parent = props.target, } return function() component:Destroy() end end } return story ``` -------------------------------- ### Get Janitor for Cleanup Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/environment.md Retrieve a Janitor object via Environment.GetJanitor for managing cleanup tasks. The Janitor is destroyed when the story unmounts, simplifying resource management. Returns nil in non-story environments. ```typescript local janitor = Environment.GetJanitor() ``` -------------------------------- ### Create React Stories with UI Labs Source: https://context7.com/pepeeltoro41/ui-labs/llms.txt Use the `CreateReactStory` helper function to create stories with React components, providing type inference for controls and integrating with React and ReactRoblox. ```ts import React from "@rbxts/react"; import ReactRoblox from "@rbxts/react-roblox"; import { CreateReactStory, } from "@rbxts/ui-labs"; // React story creator const reactStory = CreateReactStory({ react: React, reactRoblox: ReactRoblox, controls: { Visible: true }, }, (props) => ); ``` -------------------------------- ### Type Inference Utilities for UI Labs (TypeScript) Source: https://context7.com/pepeeltoro41/ui-labs/llms.txt Leverage UI Labs' TypeScript utilities like `InferProps`, `InferFusionProps`, and `InferControls` to get type inference for control values and props across different story types. ```ts import { InferProps, InferFusionProps, InferVideProps, InferIrisProps, InferGenericProps, InferControls, InferCreatedControls, HKT, } from "@rbxts/ui-labs"; import Fusion from "@rbxts/fusion"; const controls = { Visible: true, Count: 10, Name: "Test", }; // Infer control values type type ControlValues = InferControls; // { Visible: boolean, Count: number, Name: string } // Infer props for different story types type ReactProps = InferProps; type FusionProps = InferFusionProps; type VideProps = InferVideProps; type GenericProps = InferGenericProps; // HKT for CreateControlStates typing interface FusionValueCreator extends HKT { new: (x: this["T"]) => Fusion.Value; } type FusionStates = InferCreatedControls; // { Visible: Fusion.Value, Count: Fusion.Value, ... } ``` -------------------------------- ### Provide React Library for Storybook Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/stories/advanced/react.md Configure your story table with 'react' and 'reactRoblox' keys to provide the necessary React libraries. The 'renderer' key is optional and can be set to 'deferred' (default) or 'legacy'. ```lua local story = { react = React, reactRoblox = ReactRoblox, controls = controls, story = function(props) local component = React.createElement("Frame", {}) return component end } return story ``` -------------------------------- ### TypeScript EnumList Type Widening Example Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/controls/advanced.md Demonstrates how the 'widen' parameter in Choose and EnumList affects TypeScript type inference. Set 'widen' to true to generalize the type (e.g., string, number) instead of using specific literals. ```typescript Choose(["One", "Two", "Three"], 0, false); // type: "One" | "Two" | "Three" Choose(["One", "Two", "Three"], 0, true); // type: string Choose([1, 2, 3], 0, false); // type: 1 | 2 | 3 Choose([1, 2, 3], 0, true); // type: number ``` -------------------------------- ### Create Snapshot in UI Labs Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/environment.md Environment.CreateSnapshot allows for automatic UI cloning, similar to the 'Create Snapshot' button. An optional name can be provided for the created ScreenGui. ```typescript Environment.CreateSnapshot("MySnapshotName") ``` ```typescript Environment.CreateSnapshot() ``` -------------------------------- ### Create Iris Story with Utility Package Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/stories/advanced/iris.md Use the `CreateIrisStory` function from the UI Labs Utility Package to simplify story creation and infer control types for Roblox-TS. ```lua local Iris = require(...) local UILabs = require(...) local CreateIrisStory = UILabs.CreateIrisStory local controls = { ... } local story = CreateIrisStory({ iris = Iris, controls = controls, }, function(props) Iris:Connect(function() Iris.ShowDemoWindow() end) end) ``` ```typescript import Iris from "@rbxts/iris" import { CreateIrisStory } from "@rbxts/ui-labs" const controls = { ... } const story = CreateIrisStory({ fusion: Fusion, controls: controls, }, (props: InferIrisProps) => { Iris.Connect(() => { Iris.ShowDemoWindow() }) }) ``` -------------------------------- ### CreateControlStates Implementation (Luau) Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/stories/advanced/generic.md Provides the internal implementation of the CreateControlStates utility function, useful for understanding its logic or for custom reimplementations. ```lua local function CreateControlStates(converted, controls, creator) local states = {} for key, control in pairs(converted) do local controlValue = controls[key] if control.EntryType == "ControlGroup" then -- control is a control group, we need to recurse states[key] = CreateControlStates(control.Controls, controlValue, creator) continue end states[key] = creator(controlValue) end return states end ``` -------------------------------- ### Create Vide Stories with UI Labs Source: https://context7.com/pepeeltoro41/ui-labs/llms.txt Utilize `CreateVideStory` to build stories featuring Vide components. This function provides type inference for controls and integrates with the Vide library. ```ts import Vide from "@rbxts/vide"; import { CreateVideStory, } from "@rbxts/ui-labs"; // Vide story creator const videStory = CreateVideStory({ vide: Vide, controls: { Text: "Hello" }, }, (props) => ); ``` -------------------------------- ### Environment.SetStoryHolder Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/environment.md Changes the target instance for the 'View On Explorer' button. ```APIDOC ## Environment.SetStoryHolder ### Description Changes what the [View On Explorer](/docs/plugin/extras.md#view-in-explorer) button selects when clicked. Useful when the story does not use the provided target frame (e.g using React Portals), or when the story is not a UI. Calling this function without a value will reset the story holder to the target frame. ### Method Environment.SetStoryHolder ### Parameters #### Path Parameters - **target** (Instance) - Optional - The new target instance for the 'View On Explorer' button. ### Request Example ```json { "target": "InstanceName" } ``` ### Response #### Success Response (void) This method does not return any value upon successful execution. ### Notes Defaults to an empty function in non-story environments. ``` -------------------------------- ### Handle User Input with UI Labs InputListener Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/es/docs/environment.md Connect to the InputListener events to detect and respond to various user inputs like InputBegan, InputEnded, InputChanged, and MouseMoved. This is crucial for interactive UI elements. ```Luau local inputListener = Environment.InputListener inputListener.InputBegan:Connect(function(input, gameProcessed) print(input.UserInputType) end) inputListener.InputEnded:Connect(function(input, gameProcessed) print(input.UserInputType) end) inputListener.InputChanged:Connect(function(input, gameProcessed) print(input.UserInputType) end) inputListener.MouseMoved:Connect(function(mousePos) print(mousePos) end) ``` -------------------------------- ### Choose Control Constructor Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/controls/advanced.md Use Choose to create a control that allows selection from a list of options, displayed as a dropdown. Options can be of various types. The index argument specifies the default option, and widen is a boolean for TypeScript. ```javascript Choose(options, index?, widen?) ``` -------------------------------- ### Control Stories with Environment API (Lua) Source: https://context7.com/pepeeltoro41/ui-labs/llms.txt Use the Environment API to check if running in UI Labs, control story lifecycle (unmount, reload, snapshot), access environment info, set custom story holders, manage cleanup with a janitor, and handle input events. ```lua local UILabs = require(ReplicatedStorage.UILabs) local Environment = UILabs.Environment -- Check if running in UI Labs if Environment.IsStory() then print("Running inside UI Labs") end -- Story lifecycle control Environment.Unmount() -- Unmount the story Environment.Reload() -- Force reload the story Environment.CreateSnapshot("MyUI") -- Clone UI to StarterGui -- Access environment info print(Environment.EnvironmentUID) -- Changes on reload print(Environment.PreviewUID) -- Persists between reloads -- Custom story holder for View In Explorer Environment.SetStoryHolder(myCustomFrame) -- Janitor for automatic cleanup local janitor = Environment.GetJanitor() janitor:Add(connection) janitor:Add(function() print("Cleaned up!") end) -- Input handling (works in plugin widgets) local inputListener = Environment.InputListener inputListener.InputBegan:Connect(function(input, gameProcessed) if input.UserInputType == Enum.UserInputType.MouseButton1 then print("Left click at", input.Position) end end) -- Alternative: UserInputService-like interface local userInput = Environment.UserInput userInput.InputBegan:Connect(function(input) print(input.KeyCode) end) -- Access plugin APIs local plugin = Environment.Plugin local widget = Environment.PluginWidget ``` -------------------------------- ### Generic Story with Subscribe Pattern (Lua) Source: https://context7.com/pepeeltoro41/ui-labs/llms.txt A generic story that works with any UI library using a manual control subscription pattern. Requires explicit subscription to listen for control changes. ```lua -- Generic story with subscribe pattern local UILabs = require(ReplicatedStorage.UILabs) local ListenControl = UILabs.ListenControl local controls = { Visible = true, Width = 200, } local story = { controls = controls, render = function(props) local component = Instance.new("Frame") component.Size = UDim2.fromOffset(props.controls.Width, 100) component.Visible = props.controls.Visible component.Parent = props.target props.subscribe(function(values, infos) ListenControl(infos.Visible, function(newValue) component.Visible = newValue end) ListenControl(infos.Width, function(newValue) component.Size = UDim2.fromOffset(newValue, 100) end) end) return function() component:Destroy() end end } return story ``` -------------------------------- ### Create React Story in Luau Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/stories/advanced/react.md Use this snippet to create a React story with the Story Creator in Luau. Ensure UILabs and React/ReactRoblox are required. ```lua local React = require(...) local ReactRoblox = require(...) local UILabs = require(...) local CreateReactStory = UILabs.CreateReactStory local story = CreateReactStory({ react = React, reactRoblox = ReactRoblox, controls = {}, }, function(props) local component = React.createElement("Frame", {}) return component end) return story ``` -------------------------------- ### Create Generic Stories with UI Labs Source: https://context7.com/pepeeltoro41/ui-labs/llms.txt Use `CreateGenericStory` for creating stories with custom logic or non-framework specific components. It allows for control inference and provides a target for mounting UI elements. ```ts import Iris from "@rbxts/iris"; import { CreateIrisStory, CreateGenericStory, } from "@rbxts/ui-labs"; // Generic story creator const genericStory = CreateGenericStory({ controls: { Value: 42 }, }, (props) => { const label = new Instance("TextLabel"); label.Text = tostring(props.controls.Value); label.Parent = props.target; return () => label.Destroy(); }); ``` -------------------------------- ### ListenControl Utility Implementation (Luau) Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/stories/advanced/generic.md This is a direct implementation of the `ListenControl` utility function, which checks if a control's new value differs from its old value before executing a callback. ```Luau local function ListenControl(info, callback) local oldValue = info.__old local newValue = info.__new if oldValue ~= newValue then callback(newValue) end end ``` -------------------------------- ### Provide Roact Library for Storybook Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/stories/advanced/react.md Configure your story table with the 'roact' key to provide the Roact library. This is essential for rendering Roact components within the Storybook. ```lua local story = { roact = Roact, controls = controls, story = function(props) local component = Roact.createElement("Frame", {}) return component end } return story ``` -------------------------------- ### Using Scopes for Cleanup (Luau) Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/stories/advanced/fusion.md Demonstrates using scopes in Fusion 0.3 (Luau) for managing cleanup. Objects created within the scope are automatically cleaned up when the story unmounts, making explicit cleanup functions often unnecessary. ```lua local Fusion = require(...) local controls = { ... } local story = { fusion = Fusion, controls = controls, story = function(props) local scope = props.scope local value = scope:Value("foo") local component = scope:New "Frame" { Parent = props.target, } -- cleanup function is not needed end, } return story ``` -------------------------------- ### Environment.CreateSnapshot Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/environment.md Creates a snapshot of the current story, similar to the 'Create Snapshot' button. ```APIDOC ## Environment.CreateSnapshot ### Description Does the same as [Create Snapshot](/docs/plugin/extras.md#creating-snapshots) button does. Useful for cloning the UI automatically. An additional `name` argument can be given for the created `ScreenGui`. ### Method Environment.CreateSnapshot ### Parameters #### Path Parameters - **name** (string) - Optional - The name for the created `ScreenGui`. ### Request Example ```json { "name": "MySnapshotName" } ``` ### Response #### Success Response (void) This method does not return any value upon successful execution. ### Notes Defaults an empty function in non-story environments. ``` -------------------------------- ### React Story with Luau Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/stories/advanced/generic.md Implement a React story using Luau. It's recommended to abstract library usage into your own utility functions to avoid repetitive boilerplate code. ```lua local React = require(...) local ReactRoblox = require(...) local controls = { Visible = true, } -- This would be the `story` function key local function RenderComponent(controls) return React.createElement("Frame", { Size = UDim2.fromOffset(200, 100), Visible = controls.Visible }) end local story = { controls = controls, render = function(props) local component = RenderComponent(props.controls) local root = ReactRoblox.createRoot(props.target) root:render(component) props.subscribe(function(values) local newComponent = RenderComponent(values) root:render(newComponent) end) return function() root:unmount() end end } return story ``` -------------------------------- ### Roact Story with Luau Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/stories/advanced/generic.md Implement a Roact story using Luau. Abstracting library usage into your own utility functions is recommended to avoid repetitive boilerplate code. ```lua local Roact = require(...) local controls = { Visible = true, } -- This would be the `story` function key function RenderComponent(controlList) return Roact.createElement("Frame", { Size = UDim2.fromOffset(200, 100), Visible = controlList.Visible }) end local story = { controls = controls, render = function(props) local component = RenderComponent(props.controls) local tree = Roact.mount(component, props.target) props.subscribe(function(values) local newComponent = RenderComponent(values) Roact.update(tree, newComponent) end) return function() React.unmount(tree) end end } return story ``` -------------------------------- ### Fusion Story with Luau Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/stories/advanced/generic.md Implement a Fusion story using Luau with `CreateControlStates` and `UpdateControlStates` utilities. Abstracting library usage into your own utility functions is recommended to avoid repetitive boilerplate code. ```lua local Fusion = require(...) local UILabs = require(...) local CreateControlStates = UILabs.CreateControlStates local UpdateControlStates = UILabs.UpdateControlStates local controls = { Visible = true, } local story = { controls = controls, render = function(props) local states = CreateControlStates(props.converted, props.controls, function(value) return Fusion.Value(value) end) local component = Fusion.New "Frame" { Parent = props.target, Size = UDim2.fromOffset(200, 100), Visible = states.Visible, -- This will be a Fusion.Value } props.subscribe(function(values) UpdateControlStates(states, props.converted, values, function(state, value) state:set(value) end) end) return function() component:Destroy() end end } return story ``` -------------------------------- ### Vide Story with Reactive Sources Source: https://context7.com/pepeeltoro41/ui-labs/llms.txt A Vide story that runs within a stable scope and uses Vide.Source controls for reactivity. Includes a cleanup function. ```lua -- Vide story with reactive sources local Vide = require(ReplicatedStorage.Vide) local controls = { Visible = true, LabelText = "Hello World", } local story = { vide = Vide, controls = controls, story = function(props) Vide.cleanup(function() print("Story unmounted") end) return Vide.create "TextLabel" { Size = UDim2.fromOffset(200, 50), Visible = props.controls.Visible, -- Vide.Source Text = props.controls.LabelText, -- Vide.Source TextColor3 = Color3.new(1, 1, 1), BackgroundTransparency = 1, } end } return story ``` -------------------------------- ### Create Primitive Controls with Literal Values Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/controls/primitive.md Define primitive controls (String, Number, Boolean, Color3) using literal values. UI Labs automatically detects these literals to create control values. ```lua local controls = { String = "Hello UI Labs!", Number = 10, Boolean = true, Color3 = Color3.fromRGB(255, 0, 0), } local story = { controls = controls, story = ... } return story ``` ```typescript const controls = { String: "Hello UI Labs!", Number: 10, Boolean: true, Color3: Color3.fromRGB(255, 0, 0), } const story = { controls: controls, story: ... } export = story; ``` -------------------------------- ### Choose Control Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/controls/advanced.md Enables selection from a list of predefined options, presented as a dropdown menu. ```APIDOC ## Choose Control ### Description Choose control allows you to select between a set of options, it gets displayed as a dropdown with the options as the entries. ### Method Constructor ### Endpoint N/A (Client-side control) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Constructor Signature `Choose(options: Array, index?: number, widen?: boolean)` ### Arguments - **options** (Array) - Required - Array of possible options. Possible values include Tables, Datatypes, Enums, Functions, Primitives. You can mix types, but this is not recommended. - **index** (number) - Optional - Index of the default option. Default: 1. - **widen** (boolean) - Optional - If true, the control type will be widened (TypeScript only). Default: false. ### Request Example ```json { "control": "Choose", "options": ["Option 1", "Option 2", "Option 3"], "default": 1 } ``` ### Response #### Success Response (200) N/A (Client-side control) #### Response Example N/A ``` -------------------------------- ### Push Changes to Origin Main Source: https://github.com/pepeeltoro41/ui-labs/blob/main/CONTRIBUTING.md After committing, push your changes to the 'main' branch on your remote repository. ```bash git push origin main ``` -------------------------------- ### Instantiate Primitive Controls in Luau Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/es/docs/controls/primitive.md Use this snippet to create instances of various primitive type controls like String, Number, Boolean, and Color3 in Luau. Ensure the UI Labs package is correctly required. ```lua local UILabs = require(...) -- Ubicación de tu Paquete de Utilidades local Datatype = UILabs.Datatype local controls = { String = UILabs.String("Hello UI Labs!"), Number = UILabs.Number(10), Boolean = UILabs.Boolean(true), -- Color3 está dentro de 'Datatype', esto es para evitar colisiones de nombres Color3 = Datatype.Color3(Color3.fromRGB(255, 0, 0)) } local story = { controls = controls, story = ... } return story ``` -------------------------------- ### Subscribe to Control Changes (Luau) Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/stories/advanced/generic.md Use the `subscribe` function to execute a callback whenever control values change. The returned function can be used to unsubscribe. ```Luau local controls = { Visible = true, } local story = { controls = controls, render = function(props) local component = Instance.new("Frame") component.Size = UDim2.fromOffset(200, 100) component.Visible = props.controls.Visible -- first update component.Parent = props.target local unsubscribe = props.subscribe(function(values, infos) local info = infos.Visible if (info.__new ~= info.__old) then component.Visible = info.__new end end) return function() component:Destroy() end end } return story ``` -------------------------------- ### Manually Create a String Control Source: https://github.com/pepeeltoro41/ui-labs/blob/main/docs/en/docs/controls/primitive.md Create a String control manually using the 'String' constructor. This allows for custom filtering of input values. ```lua String("Default value", filters?) ```