Skip to content

Commit

Permalink
feat: vide and iris support, feat: control ordering
Browse files Browse the repository at this point in the history
  • Loading branch information
PepeElToro41 committed Sep 22, 2024
1 parent 213ae6e commit a86ea4d
Show file tree
Hide file tree
Showing 31 changed files with 446 additions and 223 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@
*.tsbuildinfo
.DS_Store
sourcemap.json
/out

/build.rbxm
12 changes: 7 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -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": {
Expand All @@ -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",
Expand Down
15 changes: 15 additions & 0 deletions src/ControlTypings/ControlConversion.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { DatatypeControl, Datatypes, IsDatatype } from "./Datatypes";
import { IsPrimitive, PrimitiveControl, Primitives } from "./Primitives";
import { AllControls, ObjectControl } from "./Typing";

type ExtractWidenKeys<T, U> = { [K in keyof T]: U extends T[K] ? K : never }[keyof T];

type ConvertControl<T extends AllControls> = T extends IsPrimitive
? PrimitiveControl<ExtractWidenKeys<Primitives, T>>
: T extends IsDatatype
? DatatypeControl<ExtractWidenKeys<Datatypes, T>>
: T extends ObjectControl
? T
: never;

declare function ConvertControl<T extends AllControls>(control: T): ConvertControl<T>;
8 changes: 6 additions & 2 deletions src/ControlTypings/ControlUtils.d.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import { ControlsList } from "./Typing";
import { ConvertControl } from "./ControlConversion";
import { AllControls, ControlsList } from "./Typing";

interface ControlGroup<T extends ControlsList = ControlsList> {
EntryType: "ControlGroup";
Order?: number;
Controls: T;
}

declare function ControlGroup<T extends ControlsList>(controls: T): ControlGroup<T>;
declare function ControlGroup<T extends ControlsList>(controls: T, order?: number): ControlGroup<T>;

declare function Ordered<T extends AllControls>(control: T, order: number): ConvertControl<T>;
2 changes: 2 additions & 0 deletions src/ControlTypings/Datatypes.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { ExtractWidenKeys } from "./ControlConversion";
import { BaseControl } from "./Typing";

export interface Datatypes {
Expand Down Expand Up @@ -29,6 +30,7 @@ interface DatatypeControlProps {
}

type DatatypeControl<T extends keyof Datatypes> = BaseControl<T, Datatypes[T]> & DatatypeControlProps[T];
type ConvertDatatype<T extends IsDatatype> = DatatypeControl<ExtractWidenKeys<Datatypes, T>>;

declare namespace Datatype {
function Color3(def: Color3): DatatypeControl<"Color3">;
Expand Down
2 changes: 2 additions & 0 deletions src/ControlTypings/Primitives.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { ExtractWidenKeys } from "./ControlConversion";
import { BaseControl } from "./Typing";

export interface Primitives {
Expand All @@ -22,6 +23,7 @@ interface PrimitiveControlProps {
}

type PrimitiveControl<T extends keyof Primitives> = BaseControl<T, Primitives[T]> & PrimitiveControlProps[T];
type ConvertPrimitive<T extends IsPrimitive> = PrimitiveControl<ExtractWidenKeys<Primitives, T>>;

type Filter = (input: string, oldInput: string) => string;

Expand Down
3 changes: 1 addition & 2 deletions src/ControlTypings/Typing.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@ interface BaseControl<T, C> {
EntryType: "Control";
Type: T;
ControlValue: C;
OnReset?: () => void;
Order?: number;
}

type IsPrimitiveControl = IsPrimitive | PrimitiveControl<keyof Primitives>;
type IsDatatypeControl = IsDatatype | PrimitiveControl<keyof Primitives>;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,8 @@ function Controls.EnumList<T>(list: RecordList<T>, def: string): Utils.Control<T

local control = CreateBaseControl("EnumList", list[def])
control.List = list
control.CurrentIndex = def
control.DefIndex = def

control.OnReset = function()
control.CurrentIndex = def
end

return control
end

Expand Down
36 changes: 36 additions & 0 deletions src/Controls/ControlConversion.luau
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
local Primitive = require(script.Parent.PrimitiveControls).Primitive
local Datatype = require(script.Parent.DatatypeControls)

local ControlConversion = {}

local function ConvertPrimitive(value: any, primitive: string)
local converter = Primitive[primitive]

assert(converter, `UI-Labs: Primitive ({primitive}) can't be converted to a control`)
return converter(value)
end

local function ConvertDatatype(value: any, datatype: string)
local converter = Datatype[datatype]

assert(converter, `UI-Labs: Datatype ({datatype}) can't be converted to a control`)
return converter(value)
end

function ControlConversion.ConvertControl(control: any)
local controlType = typeof(control)

if controlType == "table" then
return control
end

if Primitive[controlType] then
return ConvertPrimitive(control, controlType)
elseif Datatype[controlType] then
return ConvertDatatype(control, controlType)
else
error(`UI-Labs: Control ({control}) is not a valid control`)
end
end

return ControlConversion
11 changes: 0 additions & 11 deletions src/Controls/ControlUtils.lua

This file was deleted.

18 changes: 18 additions & 0 deletions src/Controls/ControlUtils.luau
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
local ControlConversion = require(script.Parent.ControlConversion)
local ControlUtils = {}

function ControlUtils.ControlGroup(controls: { [string]: any })
local group = {
EntryType = "ControlGroup",
Controls = controls,
}
return group
end

function ControlUtils.Ordered<T>(control: T, order: number): T
local converted = ControlConversion.ConvertControl(control)
converted.Order = order
return converted
end

return ControlUtils
File renamed without changes.
File renamed without changes.
3 changes: 1 addition & 2 deletions src/Controls/Utils.lua → src/Controls/Utils.luau
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@ export type Control<T> = {
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
Expand Down
16 changes: 15 additions & 1 deletion src/Environment.lua → src/Environment.luau
Original file line number Diff line number Diff line change
Expand Up @@ -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) :: () -> ()

Expand All @@ -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
Expand Down
86 changes: 29 additions & 57 deletions src/Libraries/Signal.d.ts
Original file line number Diff line number Diff line change
@@ -1,64 +1,36 @@
//Types Borrowed from @rbxts/signal
// types from @rbxts/lemon-signal

export interface Signal<ConnectedFunctionSignature extends (...args: any) => 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<ConnectedFunctionSignature>): void;
export declare type SignalParameters<T> = 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<O extends Array<unknown> = Parameters<ConnectedFunctionSignature>>(
callback: Generic extends true
? Parameters<ConnectedFunctionSignature> extends Array<unknown>
? (...args: O) => void
: ConnectedFunctionSignature
: ConnectedFunctionSignature,
): RBXScriptConnection;
export declare type SignalCallback<T> = (...args: SignalParameters<T>) => unknown;
export declare type SignalWait<T> = T extends unknown[] ? LuaTuple<T> : 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<O extends Array<unknown> = Parameters<ConnectedFunctionSignature>>(
callback: Generic extends true
? Parameters<ConnectedFunctionSignature> extends Array<unknown>
? (...args: O) => void
: ConnectedFunctionSignature
: ConnectedFunctionSignature,
): RBXScriptConnection;
export declare class Connection<T> {
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<O extends Array<unknown> = Parameters<ConnectedFunctionSignature>>(
callback: Generic extends true
? Parameters<ConnectedFunctionSignature> extends Array<unknown>
? (...args: O) => void
: ConnectedFunctionSignature
: ConnectedFunctionSignature,
): RBXScriptConnection;
public Destroy(): void;
public Disconnect(): void;
public Reconnect(): void;
}

export declare class Signal<T> {
public readonly RBXScriptConnection?: RBXScriptConnection;
public readonly TotalConnections?: number;
public readonly OnConnectionsChanged: Signal<number>;

/**
* Yields the current thread until the thread is fired.
*/
Wait(): LuaTuple<Parameters<ConnectedFunctionSignature>>;
public constructor(trackConnections?: boolean);
public static is: <O extends object>(object: O) => boolean;
public static wrap: <T extends Callback>(
signal: RBXScriptSignal<T>,
trackConnections?: boolean,
) => Signal<Parameters<T>>;

/**
* Destroys the Signal
*/
Destroy(): void;
public Connect(fn: SignalCallback<T>): Connection<T>;
public Once(fn: SignalCallback<T>): Connection<T>;
public Wait(): SignalWait<T>;
public Fire(...args: SignalParameters<T>): void;
public DisconnectAll(): void;
public Destroy(): void;
}
14 changes: 13 additions & 1 deletion src/StoryCreators.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<T extends StoryInfo>(
info: T & StoryBase & WithReact,
Expand All @@ -18,9 +20,19 @@ declare function CreateRoactStory<T extends StoryInfo>(

declare function CreateFusionStory<T extends StoryInfo>(
info: T & StoryBase & WithFusion,
render: StoryCreation<InferFusionProps<T["controls"]>, Instance>,
render: StoryCreation<InferFusionProps<T["controls"]>, Instance | StoryCleanup | undefined | void>,
): FusionStory<T>;

declare function CreateIrisStory<T extends StoryInfo>(
info: T & StoryBase & WithIris,
render: StoryCreation<InferIrisProps<T["controls"]>, StoryCleanup | void | undefined>,
): IrisStory<T>;

declare function CreateVideStory<T extends StoryInfo>(
info: T & StoryBase & WithVide,
render: StoryCreation<InferVideProps<T["controls"]>, Vide.Node | void | undefined>,
): VideStory<T>;

declare function CreateGenericStory<T extends StoryInfo>(
info: T & StoryBase,
render: StoryCreation<InferGenericProps<T["controls"]>, StoryCleanup>,
Expand Down
Loading

0 comments on commit a86ea4d

Please sign in to comment.