diff --git a/.gitignore b/.gitignore index 10ea8d2..185de78 100644 --- a/.gitignore +++ b/.gitignore @@ -6,5 +6,6 @@ *.tsbuildinfo .DS_Store sourcemap.json +/out /build.rbxm \ No newline at end of file diff --git a/package.json b/package.json index 3b9697f..7a757cc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@rbxts/ui-labs", - "version": "2.2.0-ts.1", + "version": "2.3.0-test1", "description": "Utilities for UI-Labs, a storybook-like plugin for roblox", "main": "src/init.lua", "scripts": { @@ -26,20 +26,22 @@ "files": [ "src", "!**/*.tsbuildinfo", - "!**/*.spec.lua" + "!**/*.spec.lua", + "!build.rbxm" ], "publishConfig": { "access": "public" }, "devDependencies": { + "@rbxts/compiler-types": "2.1.0-types.1", + "@rbxts/fusion": "^0.2.0", + "@rbxts/iris": "^2.3.1-ts.0", "@rbxts/react": "^0.3.6", "@rbxts/react-roblox": "^0.3.6", "@rbxts/roact": "^1.4.4-ts.0", - "@rbxts/fusion": "^0.2.0", - "@rbxts/iris": "^2.2.0-ts.0", - "@rbxts/compiler-types": "2.1.0-types.1", "@rbxts/services": "^1.5.1", "@rbxts/types": "^1.0.704", + "@rbxts/vide": "^0.4.5", "@typescript-eslint/eslint-plugin": "^5.61.0", "@typescript-eslint/parser": "^5.61.0", "eslint": "^8.44.0", diff --git a/src/ControlTypings/ControlConversion.d.ts b/src/ControlTypings/ControlConversion.d.ts new file mode 100644 index 0000000..a441795 --- /dev/null +++ b/src/ControlTypings/ControlConversion.d.ts @@ -0,0 +1,15 @@ +import { DatatypeControl, Datatypes, IsDatatype } from "./Datatypes"; +import { IsPrimitive, PrimitiveControl, Primitives } from "./Primitives"; +import { AllControls, ObjectControl } from "./Typing"; + +type ExtractWidenKeys = { [K in keyof T]: U extends T[K] ? K : never }[keyof T]; + +type ConvertControl = T extends IsPrimitive + ? PrimitiveControl> + : T extends IsDatatype + ? DatatypeControl> + : T extends ObjectControl + ? T + : never; + +declare function ConvertControl(control: T): ConvertControl; diff --git a/src/ControlTypings/ControlUtils.d.ts b/src/ControlTypings/ControlUtils.d.ts index 9a60dff..04ca949 100644 --- a/src/ControlTypings/ControlUtils.d.ts +++ b/src/ControlTypings/ControlUtils.d.ts @@ -1,8 +1,12 @@ -import { ControlsList } from "./Typing"; +import { ConvertControl } from "./ControlConversion"; +import { AllControls, ControlsList } from "./Typing"; interface ControlGroup { EntryType: "ControlGroup"; + Order?: number; Controls: T; } -declare function ControlGroup(controls: T): ControlGroup; +declare function ControlGroup(controls: T, order?: number): ControlGroup; + +declare function Ordered(control: T, order: number): ConvertControl; diff --git a/src/ControlTypings/Datatypes.d.ts b/src/ControlTypings/Datatypes.d.ts index 496f442..f33e4d1 100644 --- a/src/ControlTypings/Datatypes.d.ts +++ b/src/ControlTypings/Datatypes.d.ts @@ -1,3 +1,4 @@ +import { ExtractWidenKeys } from "./ControlConversion"; import { BaseControl } from "./Typing"; export interface Datatypes { @@ -29,6 +30,7 @@ interface DatatypeControlProps { } type DatatypeControl = BaseControl & DatatypeControlProps[T]; +type ConvertDatatype = DatatypeControl>; declare namespace Datatype { function Color3(def: Color3): DatatypeControl<"Color3">; diff --git a/src/ControlTypings/Primitives.d.ts b/src/ControlTypings/Primitives.d.ts index 20ee264..bbd2456 100644 --- a/src/ControlTypings/Primitives.d.ts +++ b/src/ControlTypings/Primitives.d.ts @@ -1,3 +1,4 @@ +import { ExtractWidenKeys } from "./ControlConversion"; import { BaseControl } from "./Typing"; export interface Primitives { @@ -22,6 +23,7 @@ interface PrimitiveControlProps { } type PrimitiveControl = BaseControl & PrimitiveControlProps[T]; +type ConvertPrimitive = PrimitiveControl>; type Filter = (input: string, oldInput: string) => string; diff --git a/src/ControlTypings/Typing.d.ts b/src/ControlTypings/Typing.d.ts index 0010f3c..52b1376 100644 --- a/src/ControlTypings/Typing.d.ts +++ b/src/ControlTypings/Typing.d.ts @@ -7,9 +7,8 @@ interface BaseControl { EntryType: "Control"; Type: T; ControlValue: C; - OnReset?: () => void; + Order?: number; } - type IsPrimitiveControl = IsPrimitive | PrimitiveControl; type IsDatatypeControl = IsDatatype | PrimitiveControl; diff --git a/src/Controls/AdvancedControls.lua b/src/Controls/AdvancedControls.luau similarity index 91% rename from src/Controls/AdvancedControls.lua rename to src/Controls/AdvancedControls.luau index 82f91a9..54e32cc 100644 --- a/src/Controls/AdvancedControls.lua +++ b/src/Controls/AdvancedControls.luau @@ -26,13 +26,8 @@ function Controls.EnumList(list: RecordList, def: string): Utils.Control(control: T, order: number): T + local converted = ControlConversion.ConvertControl(control) + converted.Order = order + return converted +end + +return ControlUtils diff --git a/src/Controls/DatatypeControls.lua b/src/Controls/DatatypeControls.luau similarity index 100% rename from src/Controls/DatatypeControls.lua rename to src/Controls/DatatypeControls.luau diff --git a/src/Controls/PrimitiveControls.lua b/src/Controls/PrimitiveControls.luau similarity index 100% rename from src/Controls/PrimitiveControls.lua rename to src/Controls/PrimitiveControls.luau diff --git a/src/Controls/Utils.lua b/src/Controls/Utils.luau similarity index 62% rename from src/Controls/Utils.lua rename to src/Controls/Utils.luau index 2e1873e..e1087ef 100644 --- a/src/Controls/Utils.lua +++ b/src/Controls/Utils.luau @@ -4,12 +4,11 @@ export type Control = { ControlValue: T, } -function Utils.CreateBaseControl(controlType: string, def, onReset: () -> any) +function Utils.CreateBaseControl(controlType: string, def) local control = { EntryType = "Control", Type = controlType, ControlValue = def, - OnReset = onReset, } return control end diff --git a/src/Environment.lua b/src/Environment.luau similarity index 78% rename from src/Environment.lua rename to src/Environment.luau index adcb71f..ed679be 100644 --- a/src/Environment.lua +++ b/src/Environment.luau @@ -19,6 +19,20 @@ function Environment.IsStory() return env ~= nil end +function UserInputFallback(userInput: any?) + if not userInput then + return + end + if userInput == UserInputService then + return + end + + local clone = table.clone(userInput) + + return setmetatable(clone, { + __index = UserInputService, + }) +end Environment.Unmount = SearchInEnv("Unmount", function() end) :: () -> () @@ -38,7 +52,7 @@ type InputSignals = { } Environment.InputListener = SearchInEnv("InputListener", nil) :: InputSignals -Environment.UserInput = SearchInEnv("InputListener", UserInputService) :: UserInputService +Environment.UserInput = UserInputFallback(SearchInEnv("InputListener", UserInputService)) :: UserInputService Environment.EnvironmentUID = SearchInEnv("EnvironmentUID", "") :: string Environment.PreviewUID = SearchInEnv("PreviewUID", "") :: string diff --git a/src/Libraries/Signal.d.ts b/src/Libraries/Signal.d.ts index 4305e37..92d7728 100644 --- a/src/Libraries/Signal.d.ts +++ b/src/Libraries/Signal.d.ts @@ -1,64 +1,36 @@ -//Types Borrowed from @rbxts/signal +// types from @rbxts/lemon-signal -export interface Signal any = () => void, Generic extends boolean = false> { - /** - * Fires the BindableEvent with any number of arguments - * @param args The arguments to pass into the connected functions - */ - Fire(...args: Parameters): void; +export declare type SignalParameters = Parameters< + T extends unknown[] ? (...args: T) => never : T extends unknown ? (arg: T) => never : () => never +>; - /** - * Establishes a function to be called when the event fires. - * Returns a `RBXScriptConnection` object associated with the connection. - * @param callback The function to connect to `BindableEvent.Event` - */ - Connect = Parameters>( - callback: Generic extends true - ? Parameters extends Array - ? (...args: O) => void - : ConnectedFunctionSignature - : ConnectedFunctionSignature, - ): RBXScriptConnection; +export declare type SignalCallback = (...args: SignalParameters) => unknown; +export declare type SignalWait = T extends unknown[] ? LuaTuple : T; - /** - * Establishes a function to be called when the event fires. - * Returns a `RBXScriptConnection` object associated with the connection. - * When the event fires, the signal callback is executed in a desynchronized state. - * Using `ConnectParallel` is similar to, but more efficient than, using `Connect` followed by a call to `task.desynchronize()` in the signal handler. - * Note: Scripts that connect in parallel must be rooted under an Actor. - * @param callback The function to connect to `BindableEvent.Event` - */ - ConnectParallel = Parameters>( - callback: Generic extends true - ? Parameters extends Array - ? (...args: O) => void - : ConnectedFunctionSignature - : ConnectedFunctionSignature, - ): RBXScriptConnection; +export declare class Connection { + public readonly Connected: boolean; - /** - * Establishes a function to be called when the event fires. - * Returns a `RBXScriptConnection` object associated with the connection. - * The behavior of `Once` is similar to `Connect`. - * However, instead of allowing multiple events to be received by the specified function, only the first event will be delivered. - * Using `Once` also ensures that the connection to the function will be automatically disconnected prior the function being called. - * @param callback The function to connect to `BindableEvent.Event` - */ - Once = Parameters>( - callback: Generic extends true - ? Parameters extends Array - ? (...args: O) => void - : ConnectedFunctionSignature - : ConnectedFunctionSignature, - ): RBXScriptConnection; + public Destroy(): void; + public Disconnect(): void; + public Reconnect(): void; +} + +export declare class Signal { + public readonly RBXScriptConnection?: RBXScriptConnection; + public readonly TotalConnections?: number; + public readonly OnConnectionsChanged: Signal; - /** - * Yields the current thread until the thread is fired. - */ - Wait(): LuaTuple>; + public constructor(trackConnections?: boolean); + public static is: (object: O) => boolean; + public static wrap: ( + signal: RBXScriptSignal, + trackConnections?: boolean, + ) => Signal>; - /** - * Destroys the Signal - */ - Destroy(): void; + public Connect(fn: SignalCallback): Connection; + public Once(fn: SignalCallback): Connection; + public Wait(): SignalWait; + public Fire(...args: SignalParameters): void; + public DisconnectAll(): void; + public Destroy(): void; } diff --git a/src/StoryCreators.d.ts b/src/StoryCreators.d.ts index 8abb810..5508a84 100644 --- a/src/StoryCreators.d.ts +++ b/src/StoryCreators.d.ts @@ -5,6 +5,8 @@ import Roact from "@rbxts/roact"; import { FusionStory, InferFusionProps, WithFusion } from "./Typing/Fusion"; import { RoactStory, WithRoact } from "./Typing/Roact"; import { GenericStory, InferGenericProps } from "./Typing/Generic"; +import { InferIrisProps, IrisStory, WithIris } from "./Typing/Iris"; +import { InferVideProps, VideStory, WithVide } from "./Typing/Vide"; declare function CreateReactStory( info: T & StoryBase & WithReact, @@ -18,9 +20,19 @@ declare function CreateRoactStory( declare function CreateFusionStory( info: T & StoryBase & WithFusion, - render: StoryCreation, Instance>, + render: StoryCreation, Instance | StoryCleanup | undefined | void>, ): FusionStory; +declare function CreateIrisStory( + info: T & StoryBase & WithIris, + render: StoryCreation, StoryCleanup | void | undefined>, +): IrisStory; + +declare function CreateVideStory( + info: T & StoryBase & WithVide, + render: StoryCreation, Vide.Node | void | undefined>, +): VideStory; + declare function CreateGenericStory( info: T & StoryBase, render: StoryCreation, StoryCleanup>, diff --git a/src/StoryCreators.lua b/src/StoryCreators.lua deleted file mode 100644 index 3087639..0000000 --- a/src/StoryCreators.lua +++ /dev/null @@ -1,105 +0,0 @@ -local Creators = {} -local Utils = require(script.Parent.Controls.Utils) - -type StoryInfo = { - name: string?, - summary: string?, - cleanup: (() -> ())?, - controls: { [string]: Utils.Control }?, -} -type WithReact = { - react: any?, - use: "React"?, - reactRoblox: any?, - renderer: ("deferred" | "legacy")?, -} -type WithRoact = { - roact: any?, - use: "Roact"?, -} -type WithFusion = { - fusion: any?, - use: "Fusion"?, -} -type WithGeneric = { - use: "Generic", -} - -type Props = { controls: { [string]: any }, inputListener: InputSignals } -type StoryRender = (props: Props) -> any - -type StoryRenderKey = { - story: StoryRender, -} - -type Listener = (values: { [string]: any }, info: { [string]: any }) -> any -type Updater = (listener: Listener) -> any -type GenericProps = { controls: { [string]: any }, updated: Updater } -type GenericStoryRender = (props: GenericProps) -> any -type StoryGenericRenderKey = { - render: StoryRender, -} - -type InputSignals = { - InputBegan: RBXScriptConnection, - InputEnded: RBXScriptConnection, - InputChanged: RBXScriptConnection, - MouseMoved: RBXScriptConnection, -} - -local function CombineTableInfo(table1, table2) - for key, val in pairs(table2) do - table1[key] = val - end - return table1 -end - -function Creators.CreateRoactStory( - info: StoryInfo & WithRoact, - render: StoryRender -): StoryInfo & WithRoact & StoryRenderKey - local returnStory = { - use = "Roact", - story = render, - } - - return CombineTableInfo(returnStory, info) -end - -function Creators.CreateReactStory( - info: StoryInfo & WithReact, - render: StoryRender -): StoryInfo & WithReact & StoryRenderKey - local returnStory = { - use = "React", - story = render, - } - - return CombineTableInfo(returnStory, info) -end - -function Creators.CreateFusionStory( - info: StoryInfo & WithFusion, - render: StoryRender -): StoryInfo & WithFusion & StoryRenderKey - local returnStory = { - use = "Fusion", - story = render, - } - - return CombineTableInfo(returnStory, info) -end - -function Creators.CreateGenericStory( - info: StoryInfo & WithGeneric, - render: StoryRender -): StoryInfo & WithGeneric & StoryGenericRenderKey - local returnStory = { - use = "Generic", - render = render, - } - - return CombineTableInfo(returnStory, info) -end - -return Creators diff --git a/src/StoryCreators.luau b/src/StoryCreators.luau new file mode 100644 index 0000000..bc4e232 --- /dev/null +++ b/src/StoryCreators.luau @@ -0,0 +1,80 @@ +local Creators = {} +local Types = require(script.Parent.Types) + +type InputSignals = { + InputBegan: RBXScriptConnection, + InputEnded: RBXScriptConnection, + InputChanged: RBXScriptConnection, + MouseMoved: RBXScriptConnection, +} + +local function CombineTableInfo(table1, table2) + for key, val in pairs(table2) do + table1[key] = val + end + return table1 +end + +function Creators.CreateRoactStory( + info: Types.StoryBase & Types.WithRoact, + render: Types.ReactStoryKey +): Types.RoactStory + local returnStory = { + use = "roact", + story = render, + } + + return CombineTableInfo(returnStory, info) +end + +function Creators.CreateReactStory( + info: Types.StoryBase & Types.WithReact, + render: Types.ReactStoryKey +): Types.ReactStory + local returnStory = { + use = "react", + story = render, + } + + return CombineTableInfo(returnStory, info) +end + +function Creators.CreateFusionStory( + info: Types.StoryBase & Types.WithFusion, + render: Types.FusionStoryKey +): Types.FusionStory + local returnStory = { + use = "fusion", + story = render, + } + + return CombineTableInfo(returnStory, info) +end + +function Creators.CreateIrisStory(info: Types.StoryBase & Types.WithIris, render: Types.IrisStoryKey): Types.IrisStory + local returnStory = { + use = "iris", + story = render, + } + + return CombineTableInfo(returnStory, info) +end + +function Creators.CreateVideStory(info: Types.StoryBase & Types.WithVide, render: Types.VideStoryKey): Types.VideStory + local returnStory = { + use = "Vide", + story = render, + } + + return CombineTableInfo(returnStory, info) +end + +function Creators.CreateGenericStory(info: Types.StoryBase, render: Types.GenericRenderKey): Types.GenericStory + local returnStory = { + render = render, + } + + return CombineTableInfo(returnStory, info) +end + +return Creators diff --git a/src/Test.ts b/src/Test.ts new file mode 100644 index 0000000..4fc925a --- /dev/null +++ b/src/Test.ts @@ -0,0 +1,5 @@ +import { EnumList } from "./ControlTypings/Advanced"; +import { Ordered } from "./ControlTypings/ControlUtils"; + +const list = EnumList({ Hello: 2, Test: 5 }, ""); +const control = Ordered("list, 1", 2); diff --git a/src/Types.luau b/src/Types.luau new file mode 100644 index 0000000..f04f11f --- /dev/null +++ b/src/Types.luau @@ -0,0 +1,110 @@ +export type Storybook = { + name: string?, + storyRoots: { Instance }, + groupRoots: boolean?, +} +type Cleanup = () -> () +export type FunctionStory = (frame: Frame) -> Cleanup + +export type StoryBase = { + name: string?, + summary: string?, + cleanup: Cleanup?, +} + +type StoryControls = { [string]: any } + +------------------------------- REACT/ROACT ------------------------------ + +export type ReactProps = { + controls: { [string]: any }, +} +export type WithReact = { + use: "react"?, + react: any, + reactRoblox: any, +} +export type ReactStoryKey = (props: ReactProps) -> any +export type ReactStory = StoryBase & WithReact & { + story: ReactStoryKey, +} + +export type WithRoact = { + use: "roact"?, + roact: any, +} +export type RoactStory = StoryBase & WithRoact & { + story: ReactStoryKey, +} + +--------------------------------- FUSION --------------------------------- + +export type FusionProps = { + controls: { [string]: any }, + scope: any, + target: GuiObject, +} + +export type WithFusion = { + use: "fusion", + fusion: any, +} + +export type FusionStoryKey = (props: FusionProps) -> Cleanup | nil | Instance +export type FusionStory = StoryBase & WithFusion & { + story: FusionStoryKey, +} + +---------------------------------- IRIS ---------------------------------- + +export type IrisProps = { + controls: { [string]: any }, + target: GuiObject, +} + +export type WithIris = { + use: "iris", + iris: any, +} + +export type IrisStoryKey = (props: IrisProps) -> Cleanup | nil +export type IrisStory = StoryBase & WithIris & { + story: IrisStoryKey, +} + +---------------------------------- VIDE ---------------------------------- + +export type VideProps = { + controls: { [string]: any }, + target: GuiObject, +} + +export type WithVide = { + use: "vide", + vide: any, +} + +export type VideStoryKey = (props: VideProps) -> Cleanup | nil +export type VideStory = StoryBase & WithVide & { + story: VideStoryKey, +} + +---------------------------------- GENERIC -------------------------------- +export type GenericInfo = { __old: T, __new: T } + +export type SubscribeListener = (values: { [string]: any }, info: { [string]: GenericInfo }) -> () + +export type GenericProps = { + controls: { [string]: any }, + target: GuiObject, + converted: { [string]: any }, + subscribe: (listener: SubscribeListener) -> Cleanup, +} + +export type GenericRenderKey = (props: GenericProps) -> Cleanup + +export type GenericStory = StoryBase & { + render: GenericRenderKey, +} + +return {} diff --git a/src/Typing/Fusion.d.ts b/src/Typing/Fusion.d.ts index 3ffb647..408a53d 100644 --- a/src/Typing/Fusion.d.ts +++ b/src/Typing/Fusion.d.ts @@ -5,7 +5,7 @@ import { GetStoryProps, InferControlType, StoryCleanup } from "./Typing"; import { StoryBase, StoryCreationKey, StoryInfo } from "./Typing"; interface WithFusion { - use?: "Fusion"; + use?: "fusion"; fusion: typeof Fusion; } @@ -32,4 +32,4 @@ type InferFusionProps = GetStoryProps>; type FusionStory = T & StoryBase & WithFusion & - StoryCreationKey, Instance | StoryCleanup>; + StoryCreationKey, Instance | StoryCleanup | undefined | void>; diff --git a/src/Typing/Iris.d.ts b/src/Typing/Iris.d.ts index 7f6cced..2b9bd66 100644 --- a/src/Typing/Iris.d.ts +++ b/src/Typing/Iris.d.ts @@ -1,31 +1,30 @@ -import { State } from "@rbxts/iris/out/IrisDeclaration"; import { AllControls, ControlsList, ReturnControls } from "../ControlTypings/Typing"; +import Iris from "@rbxts/iris"; import { GetStoryProps, InferControlType, - IntrinsicProps, StoryBase, StoryCleanup, StoryCreationKey, StoryInfo, } from "./Typing"; -import Iris from "@rbxts/iris"; + import { ControlGroup } from "../ControlTypings/ControlUtils"; interface WithIris { - use?: "Fusion"; - fusion: typeof Iris; + use?: "iris"; + iris: typeof Iris; } type InferIrisControlGroup = { - [K in keyof T]: State>; + [K in keyof T]: Iris.State>; }; type InferIrisControls = { [K in keyof T]: T[K] extends ControlGroup ? InferIrisControlGroup : T[K] extends AllControls - ? State> + ? Iris.State> : never; }; @@ -36,7 +35,7 @@ type IrisControlProps = { type InferIrisProps = GetStoryProps>; -type FusionStory = T & +type IrisStory = T & StoryBase & WithIris & StoryCreationKey, StoryCleanup | void | undefined>; diff --git a/src/Typing/React.d.ts b/src/Typing/React.d.ts index 618f007..49a94bc 100644 --- a/src/Typing/React.d.ts +++ b/src/Typing/React.d.ts @@ -4,7 +4,7 @@ import React from "@rbxts/react"; import ReactRoblox from "@rbxts/react-roblox"; interface WithReact { - use?: "React"; + use?: "react"; react: typeof React; reactRoblox: typeof ReactRoblox; renderer?: "deferred" | "legacy"; diff --git a/src/Typing/Roact.d.ts b/src/Typing/Roact.d.ts index 0e22e40..4b6bb94 100644 --- a/src/Typing/Roact.d.ts +++ b/src/Typing/Roact.d.ts @@ -2,7 +2,7 @@ import Roact from "@rbxts/roact"; import { StoryInfo, StoryBase, StoryCreationKey, InferProps } from "./Typing"; interface WithRoact { - use?: "Roact"; + use?: "roact"; roact: typeof Roact; } diff --git a/src/Typing/Typing.d.ts b/src/Typing/Typing.d.ts index caf35bf..2a8178e 100644 --- a/src/Typing/Typing.d.ts +++ b/src/Typing/Typing.d.ts @@ -19,10 +19,10 @@ interface Storybook { } interface InputSignals { - InputBegan: Signal<(input: InputObject, gameProcessed: boolean) => void>; - InputEnded: Signal<(input: InputObject, gameProcessed: boolean) => void>; - InputChanged: Signal<(input: InputObject, gameProcessed: boolean) => void>; - MouseMoved: Signal<(mousePos: Vector2) => void>; + InputBegan: Signal<[input: InputObject, gameProcessed: boolean]>; + InputEnded: Signal<[input: InputObject, gameProcessed: boolean]>; + InputChanged: Signal<[input: InputObject, gameProcessed: boolean]>; + MouseMoved: Signal<[mousePos: Vector2]>; } interface StoryBase { diff --git a/src/Typing/Vide.d.ts b/src/Typing/Vide.d.ts new file mode 100644 index 0000000..4bd8fd3 --- /dev/null +++ b/src/Typing/Vide.d.ts @@ -0,0 +1,34 @@ +import Vide from "@rbxts/vide"; +import { ControlGroup } from "../ControlTypings/ControlUtils"; +import { AllControls, ControlsList, ReturnControls } from "../ControlTypings/Typing"; +import { GetStoryProps, InferControlType } from "./Typing"; +import { StoryBase, StoryCreationKey, StoryInfo } from "./Typing"; + +interface WithVide { + use?: "vide"; + vide: typeof Vide; +} + +type InferVideControlGroup = { + [K in keyof T]: Vide.Source>; +}; + +type InferVideControls = { + [K in keyof T]: T[K] extends ControlGroup + ? InferVideControlGroup + : T[K] extends AllControls + ? Vide.Source> + : never; +}; + +type VideProps = { + controls: T extends ReturnControls ? InferVideControls : never; + target: Frame; +}; + +type InferVideProps = GetStoryProps>; + +type VideStory = T & + StoryBase & + WithVide & + StoryCreationKey, Vide.Node | void | undefined>; diff --git a/src/Utils/init.lua b/src/Utils/init.luau similarity index 63% rename from src/Utils/init.lua rename to src/Utils/init.luau index e66a7ad..35aa170 100644 --- a/src/Utils/init.lua +++ b/src/Utils/init.luau @@ -1,6 +1,7 @@ local Utils = {} +local Types = require(script.Parent.Types) -function Utils.ListenControl(info, callback) +function Utils.ListenControl(info: Types.GenericInfo, callback: (newVal: T) -> ()) local oldValue = info.__old local newValue = info.__new @@ -9,7 +10,11 @@ function Utils.ListenControl(info, callback) end end -function Utils.CreateControlStates(converted, controls, creator) +function Utils.CreateControlStates( + converted: { [string]: any }, + controls: { [string]: any }, + creator: (control: any) -> any +) local states = {} for key, control in pairs(converted) do @@ -25,7 +30,12 @@ function Utils.CreateControlStates(converted, controls, creator) return states end -function Utils.UpdateControlStates(states, converted, controls, updater) +function Utils.UpdateControlStates( + states: { [string]: any }, + converted: { [string]: any }, + controls: { [string]: any }, + updater: (state: any, value: any) -> () +) for key, control in pairs(converted) do local controlValue = controls[key] diff --git a/src/index.d.ts b/src/index.d.ts index 472615c..3e36b93 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -2,7 +2,14 @@ export { String, Number, Boolean, Primitive } from "./ControlTypings/Primitives" export { Choose, EnumList, RGBA, Slider, Object } from "./ControlTypings/Advanced"; -export { CreateReactStory, CreateRoactStory, CreateFusionStory, CreateGenericStory } from "./StoryCreators"; +export { + CreateReactStory, + CreateRoactStory, + CreateFusionStory, + CreateIrisStory, + CreateVideStory, + CreateGenericStory, +} from "./StoryCreators"; export { ListenControl, CreateControlStates, UpdateControlStates } from "./Utils"; export { InferControls, InferControlType, FunctionStory, Storybook, InputSignals } from "./Typing/Typing"; @@ -10,6 +17,8 @@ export { InferControls, InferControlType, FunctionStory, Storybook, InputSignals export { ReactStory } from "./Typing/React"; export { RoactStory } from "./Typing/Roact"; export { FusionStory, InferFusionControls, InferFusionProps, InferFusionControlGroup } from "./Typing/Fusion"; +export { IrisStory, InferIrisControls, InferIrisProps, InferIrisControlGroup } from "./Typing/Iris"; +export { VideStory, InferVideControls, InferVideProps, InferVideControlGroup } from "./Typing/Vide"; export { GenericStory, @@ -22,6 +31,7 @@ export { export { HKT } from "./HKT"; -export { ControlGroup } from "./ControlTypings/ControlUtils"; +export { ConvertControl } from "./ControlTypings/ControlConversion"; +export { ControlGroup, Ordered } from "./ControlTypings/ControlUtils"; export { Datatype } from "./ControlTypings/Datatypes"; export { Environment } from "./Environment"; diff --git a/src/init.lua b/src/init.luau similarity index 59% rename from src/init.lua rename to src/init.luau index 642c22f..88518d7 100644 --- a/src/init.lua +++ b/src/init.luau @@ -3,14 +3,17 @@ local DatatypeControls = require(script.Controls.DatatypeControls) local AdvancedControls = require(script.Controls.AdvancedControls) local StoryCreators = require(script.StoryCreators) local ControlUtils = require(script.Controls.ControlUtils) +local ControlConversion = require(script.Controls.ControlConversion) local Utils = require(script.Utils) local Environment = require(script.Environment) +local Types = require(script.Types) type PrimitiveControls = typeof(PrimitiveControls) type DatatypeControls = typeof(DatatypeControls) type AdvancedControls = typeof(AdvancedControls) -type StoryCreators = typeof(StoryCreators) type ControlUtils = typeof(ControlUtils) +type ControlConversion = typeof(ControlConversion) +type StoryCreators = typeof(StoryCreators) type Utils = typeof(Utils) type Environment = typeof(Environment) @@ -19,16 +22,27 @@ type UILabs = & AdvancedControls & StoryCreators & ControlUtils + & ControlConversion & Utils & { Datatype: DatatypeControls } & { Environment: Environment } -export type Storybook = { - name: string?, - storyRoots: { Instance }, - groupRoots: boolean?, -} -export type FunctionStory = (frame: Frame) -> () -> () +export type Storybook = Types.Storybook +export type FunctionStory = Types.FunctionStory +export type ReactStory = Types.ReactStory +export type RoactStory = Types.RoactStory +export type FusionStory = Types.FusionStory +export type IrisStory = Types.IrisStory +export type VideStory = Types.VideStory +export type GenericStory = Types.GenericStory + +export type ReactProps = Types.ReactProps +export type FusionProps = Types.FusionProps +export type IrisProps = Types.IrisProps +export type VideProps = Types.VideProps +export type GenericProps = Types.GenericProps +export type GenericInfo = Types.GenericInfo +export type SubscribeListener = Types.SubscribeListener function CombinedExport(...) local final = {} @@ -44,6 +58,7 @@ local UILabs = CombinedExport( PrimitiveControls, ControlUtils, Utils, + ControlConversion, AdvancedControls, StoryCreators, { Environment = Environment }, diff --git a/yarn.lock b/yarn.lock index 2cc2f27..074bec9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -89,10 +89,10 @@ resolved "https://registry.yarnpkg.com/@rbxts/fusion/-/fusion-0.2.0.tgz#082cbe02299abe36a0ff376535ce0eaac87ec190" integrity sha512-Hs+IXSPM+5KE4FMKh+zyifG2+1EI8B0K1DA3gN6TncwiQxdVzz6XchxRVI/BTqto7uLBtEAVMQzhrkUneaJNIQ== -"@rbxts/iris@^2.2.0-ts.0": - version "2.2.0-ts.0" - resolved "https://registry.yarnpkg.com/@rbxts/iris/-/iris-2.2.0-ts.0.tgz#39845d47d731702cdf2efb4ca1baaa3d5d1863cf" - integrity sha512-oOiURnUsnPMztNk/2GitbJ5A0dnh8PtgyqcODX9IL651y7wZOfIX7f+N+/WDyiDs5HGuybOCUyU+VBzjjAdekw== +"@rbxts/iris@^2.3.1-ts.0": + version "2.3.1-ts.0" + resolved "https://registry.yarnpkg.com/@rbxts/iris/-/iris-2.3.1-ts.0.tgz#0b6987102134259f151c3cf58b0d5f62624905e7" + integrity sha512-YMXNS45i5BOd2sRGm28I+EmFYNHFI5nqd72NodA7Nzsi/d/pf+l+s1+l4Feb0BqYvUa0Juhcd11NE2R3S3NKjg== "@rbxts/react-roblox@^0.3.6": version "0.3.6" @@ -129,6 +129,11 @@ resolved "https://registry.yarnpkg.com/@rbxts/types/-/types-1.0.731.tgz#a70eaa560a2f8ed22f80ad81682476cdf9c3cc30" integrity sha512-2iSGCO37voYcJ4q8wRuBF67zirC5kiP6pZAfX5v/Sg0szYj6VCiFBAh3sqW5+AcEs4u9gHtaa3NYituVGMlseQ== +"@rbxts/vide@^0.4.5": + version "0.4.5" + resolved "https://registry.yarnpkg.com/@rbxts/vide/-/vide-0.4.5.tgz#cadea286d9a4108445b610e97f9c63c2762bc548" + integrity sha512-eOqoAZyqRCrc7VeijWSe3csvVO3smvNFI5KJgmZ/6SwvgQ02oWH6IetAK1eXhM2HyxSM+CGh5sWHxkFkJ1aAVQ== + "@roblox-ts/luau-ast@^1.0.10": version "1.0.10" resolved "https://registry.yarnpkg.com/@roblox-ts/luau-ast/-/luau-ast-1.0.10.tgz#3c752a95b878c5f66c0af6d0f18f8857c34e7b13"