@rbxts/app-forge 0.7.1 → 0.7.2-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -13
- package/out/react/hooks/usePx.d.ts +15 -0
- package/out/react/hooks/usePx.luau +117 -0
- package/out/vide/classes/renders.d.ts +4 -0
- package/out/vide/classes/renders.luau +50 -45
- package/out/vide/classes/rules/exclusiveGroup.luau +22 -15
- package/out/vide/classes/rules/init.luau +17 -13
- package/out/vide/classes/rules/parent.luau +8 -4
- package/out/vide/context.d.ts +1 -1
- package/out/vide/debug/debugger.d.ts +18 -0
- package/out/vide/debug/debugger.luau +89 -0
- package/out/vide/debug/index.d.ts +3 -0
- package/out/vide/debug/init.luau +8 -0
- package/out/vide/debug/logger.d.ts +5 -0
- package/out/vide/debug/logger.luau +37 -0
- package/out/vide/decorator.d.ts +8 -0
- package/out/vide/decorator.luau +41 -4
- package/out/vide/hooks/useAppContext.d.ts +1 -1
- package/out/vide/hooks/useAppContext.luau +5 -1
- package/out/vide/hooks/useEventListener.d.ts +17 -0
- package/out/vide/hooks/useEventListener.luau +61 -0
- package/out/vide/hooks/usePx.d.ts +11 -0
- package/out/vide/hooks/usePx.luau +103 -0
- package/out/vide/index.d.ts +5 -2
- package/out/vide/init.luau +85 -24
- package/out/vide/types.d.ts +1 -1
- package/package.json +9 -3
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
local TS = _G[script]
|
|
3
|
+
-- debug/logger.ts
|
|
4
|
+
local RunService = TS.import(script, TS.getModule(script, "@rbxts", "services")).RunService
|
|
5
|
+
local Logger
|
|
6
|
+
do
|
|
7
|
+
Logger = setmetatable({}, {
|
|
8
|
+
__tostring = function()
|
|
9
|
+
return "Logger"
|
|
10
|
+
end,
|
|
11
|
+
})
|
|
12
|
+
Logger.__index = Logger
|
|
13
|
+
function Logger.new(...)
|
|
14
|
+
local self = setmetatable({}, Logger)
|
|
15
|
+
return self:constructor(...) or self
|
|
16
|
+
end
|
|
17
|
+
function Logger:constructor(scope)
|
|
18
|
+
self.scope = scope
|
|
19
|
+
end
|
|
20
|
+
function Logger:log(level, message, data, traceback)
|
|
21
|
+
if not RunService:IsStudio() then
|
|
22
|
+
return nil
|
|
23
|
+
end
|
|
24
|
+
local prefix = `[{self.scope}][{level}]`
|
|
25
|
+
if data ~= nil then
|
|
26
|
+
print(prefix, message, data)
|
|
27
|
+
else
|
|
28
|
+
print(prefix, message)
|
|
29
|
+
end
|
|
30
|
+
if traceback ~= "" and traceback then
|
|
31
|
+
print(traceback)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
return {
|
|
36
|
+
default = Logger,
|
|
37
|
+
}
|
package/out/vide/decorator.d.ts
CHANGED
|
@@ -2,7 +2,15 @@ import Vide from "@rbxts/vide";
|
|
|
2
2
|
import type Types from "./types";
|
|
3
3
|
import type AppForge from ".";
|
|
4
4
|
export declare const AppRegistry: Map<string, Types.AppRegistry.Static>;
|
|
5
|
+
/**
|
|
6
|
+
* Registers a Vide App with AppForge.
|
|
7
|
+
*
|
|
8
|
+
* This runs at definition time and validates static configuration.
|
|
9
|
+
*/
|
|
5
10
|
export declare function App<N extends AppNames>(props: Types.AppRegistry.Props<N>): <T extends new (props: Types.Props.Main, name: AppNames) => Args>(constructor: T) => T;
|
|
11
|
+
/**
|
|
12
|
+
* Base class for all AppForge Apps.
|
|
13
|
+
*/
|
|
6
14
|
export declare abstract class Args {
|
|
7
15
|
readonly forge: AppForge;
|
|
8
16
|
readonly props: Types.Props.Class;
|
package/out/vide/decorator.luau
CHANGED
|
@@ -1,15 +1,40 @@
|
|
|
1
1
|
-- Compiled with roblox-ts v3.0.0
|
|
2
2
|
local TS = _G[script]
|
|
3
3
|
-- Packages
|
|
4
|
-
local px = TS.import(script, TS.getModule(script, "@rbxts", "loners-pretty-vide-utils").out).px
|
|
5
4
|
-- Types
|
|
5
|
+
-- Hooks
|
|
6
|
+
local px = TS.import(script, script.Parent, "hooks", "usePx").px
|
|
7
|
+
-- Debug
|
|
8
|
+
local Logger = TS.import(script, script.Parent, "debug", "logger").default
|
|
9
|
+
local logger = Logger.new("AppRegistry")
|
|
6
10
|
local AppRegistry = {}
|
|
11
|
+
--[[
|
|
12
|
+
*
|
|
13
|
+
* Registers a Vide App with AppForge.
|
|
14
|
+
*
|
|
15
|
+
* This runs at definition time and validates static configuration.
|
|
16
|
+
|
|
17
|
+
]]
|
|
7
18
|
local function App(props)
|
|
8
19
|
return function(constructor)
|
|
9
20
|
local _name = props.name
|
|
10
21
|
if AppRegistry[_name] ~= nil then
|
|
11
|
-
|
|
22
|
+
logger:log("ERROR", "Duplicate App name detected", {
|
|
23
|
+
name = props.name,
|
|
24
|
+
})
|
|
25
|
+
error(`Duplicate registered App name "{props.name}". ` .. `App names must be globally unique.`, 2)
|
|
12
26
|
end
|
|
27
|
+
local _value = props.name
|
|
28
|
+
if not (_value ~= "" and _value) then
|
|
29
|
+
logger:log("ERROR", "Attempted to register App without a name", props)
|
|
30
|
+
error("App registration failed: missing app name", 2)
|
|
31
|
+
end
|
|
32
|
+
logger:log("DEBUG", "Registering App", {
|
|
33
|
+
name = props.name,
|
|
34
|
+
renderGroup = props.renderGroup,
|
|
35
|
+
visible = props.visible,
|
|
36
|
+
rules = props.rules,
|
|
37
|
+
})
|
|
13
38
|
local _name_1 = props.name
|
|
14
39
|
local _arg1 = {
|
|
15
40
|
constructor = constructor,
|
|
@@ -21,6 +46,11 @@ local function App(props)
|
|
|
21
46
|
return constructor
|
|
22
47
|
end
|
|
23
48
|
end
|
|
49
|
+
--[[
|
|
50
|
+
*
|
|
51
|
+
* Base class for all AppForge Apps.
|
|
52
|
+
|
|
53
|
+
]]
|
|
24
54
|
local Args
|
|
25
55
|
do
|
|
26
56
|
Args = {}
|
|
@@ -28,13 +58,20 @@ do
|
|
|
28
58
|
local _binding = props
|
|
29
59
|
local forge = _binding.forge
|
|
30
60
|
self.forge = forge
|
|
61
|
+
self.name = name
|
|
31
62
|
local _object = table.clone(props.props)
|
|
32
63
|
setmetatable(_object, nil)
|
|
33
64
|
_object.px = px
|
|
34
65
|
_object.forge = forge
|
|
35
66
|
self.props = _object
|
|
36
|
-
|
|
37
|
-
|
|
67
|
+
local src = forge:getSource(name)
|
|
68
|
+
if not src then
|
|
69
|
+
logger:log("ERROR", "Missing visibility source for App", {
|
|
70
|
+
name = name,
|
|
71
|
+
})
|
|
72
|
+
error(`Failed to retrieve visibility source for app "{name}"`, 2)
|
|
73
|
+
end
|
|
74
|
+
self.source = src
|
|
38
75
|
end
|
|
39
76
|
end
|
|
40
77
|
return {
|
|
@@ -2,10 +2,14 @@
|
|
|
2
2
|
local TS = _G[script]
|
|
3
3
|
-- Components
|
|
4
4
|
local Contexts = TS.import(script, script.Parent.Parent, "context").default
|
|
5
|
+
-- Debug
|
|
6
|
+
local Logger = TS.import(script, script.Parent.Parent, "debug", "logger").default
|
|
7
|
+
local logger = Logger.new("useAppContext")
|
|
5
8
|
local default = function()
|
|
6
9
|
local context = Contexts.App()
|
|
7
10
|
if not context then
|
|
8
|
-
|
|
11
|
+
logger:log("ERROR", "Failed to retrieve App context")
|
|
12
|
+
error(`Failed to retrieve App Props for Vide\n{debug.traceback()}`, 2)
|
|
9
13
|
end
|
|
10
14
|
return context
|
|
11
15
|
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
type EventLike<T extends Callback = Callback> = {
|
|
2
|
+
Connect(callback: T): ConnectionLike;
|
|
3
|
+
} | {
|
|
4
|
+
connect(callback: T): ConnectionLike;
|
|
5
|
+
} | {
|
|
6
|
+
subscribe(callback: T): ConnectionLike;
|
|
7
|
+
};
|
|
8
|
+
type ConnectionLike = {
|
|
9
|
+
Disconnect(): void;
|
|
10
|
+
} | {
|
|
11
|
+
disconnect(): void;
|
|
12
|
+
} | (() => void);
|
|
13
|
+
/**
|
|
14
|
+
* Subscribes to an event-like object and auto-cleans up.
|
|
15
|
+
*/
|
|
16
|
+
export declare function useEventListener<T extends EventLike>(event: T, listener: T extends EventLike<infer U> ? U : never): ReturnType<T>;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
local TS = _G[script]
|
|
3
|
+
local cleanup = TS.import(script, TS.getModule(script, "@rbxts", "vide").src).cleanup
|
|
4
|
+
-- Debug
|
|
5
|
+
local Logger = TS.import(script, script.Parent.Parent, "debug", "logger").default
|
|
6
|
+
local logger = Logger.new("useEventListener")
|
|
7
|
+
local connect = function(event, callback)
|
|
8
|
+
local _event = event
|
|
9
|
+
if typeof(_event) == "RBXScriptSignal" then
|
|
10
|
+
local connection
|
|
11
|
+
connection = event:Connect(function(...)
|
|
12
|
+
local args = { ... }
|
|
13
|
+
if connection.Connected then
|
|
14
|
+
return callback(unpack(args))
|
|
15
|
+
end
|
|
16
|
+
end)
|
|
17
|
+
return connection
|
|
18
|
+
elseif event.Connect ~= nil then
|
|
19
|
+
return event:Connect(callback)
|
|
20
|
+
elseif event.connect ~= nil then
|
|
21
|
+
return event:connect(callback)
|
|
22
|
+
elseif event.subscribe ~= nil then
|
|
23
|
+
return event:subscribe(callback)
|
|
24
|
+
end
|
|
25
|
+
logger:log("ERROR", "Unsupported event-like object", event)
|
|
26
|
+
error("Event-like object does not have a supported connect method.", 2)
|
|
27
|
+
end
|
|
28
|
+
local disconnect = function(connection)
|
|
29
|
+
local _connection = connection
|
|
30
|
+
if type(_connection) == "function" then
|
|
31
|
+
connection()
|
|
32
|
+
else
|
|
33
|
+
local _connection_1 = connection
|
|
34
|
+
local _condition = typeof(_connection_1) == "RBXScriptConnection"
|
|
35
|
+
if not _condition then
|
|
36
|
+
_condition = connection.Disconnect ~= nil
|
|
37
|
+
end
|
|
38
|
+
if _condition then
|
|
39
|
+
connection:Disconnect()
|
|
40
|
+
elseif connection.disconnect ~= nil then
|
|
41
|
+
connection:disconnect()
|
|
42
|
+
else
|
|
43
|
+
logger:log("WARN", "Unsupported connection-like object during cleanup", connection)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
--[[
|
|
48
|
+
*
|
|
49
|
+
* Subscribes to an event-like object and auto-cleans up.
|
|
50
|
+
|
|
51
|
+
]]
|
|
52
|
+
local function useEventListener(event, listener)
|
|
53
|
+
local connection = connect(event, listener)
|
|
54
|
+
cleanup(function()
|
|
55
|
+
return disconnect(connection)
|
|
56
|
+
end)
|
|
57
|
+
return connection
|
|
58
|
+
end
|
|
59
|
+
return {
|
|
60
|
+
useEventListener = useEventListener,
|
|
61
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare const px: ((value: number) => number) & {
|
|
2
|
+
scale: (value: number) => number;
|
|
3
|
+
even: (value: number) => number;
|
|
4
|
+
floor: (value: number) => number;
|
|
5
|
+
ceil: (value: number) => number;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Initializes global px scaling.
|
|
9
|
+
* Must be called exactly once.
|
|
10
|
+
*/
|
|
11
|
+
export declare function usePx(target?: GuiObject | Camera, baseResolution?: Vector2, minScale?: number): void;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
local TS = _G[script]
|
|
3
|
+
-- Services
|
|
4
|
+
local Workspace = TS.import(script, TS.getModule(script, "@rbxts", "services")).Workspace
|
|
5
|
+
-- Packages
|
|
6
|
+
local source = TS.import(script, TS.getModule(script, "@rbxts", "vide").src).source
|
|
7
|
+
-- Helpers
|
|
8
|
+
local useEventListener = TS.import(script, script.Parent, "useEventListener").useEventListener
|
|
9
|
+
-- Debug
|
|
10
|
+
local Logger = TS.import(script, script.Parent.Parent, "debug", "logger").default
|
|
11
|
+
local logger = Logger.new("usePx")
|
|
12
|
+
--* Default reference resolution for px calculations
|
|
13
|
+
local BASE_RESOLUTION = source(Vector2.new(1920, 1080))
|
|
14
|
+
--* Minimum allowed scale to prevent unreadable UI
|
|
15
|
+
local MIN_SCALE = source(0.5)
|
|
16
|
+
--* 0 = width-based, 1 = height-based
|
|
17
|
+
local DOMINANT_AXIS = 0.5
|
|
18
|
+
local TARGET = source(Workspace.CurrentCamera)
|
|
19
|
+
local SCALE = source(1)
|
|
20
|
+
local INITIALIZED = false
|
|
21
|
+
local function callable(callback, object)
|
|
22
|
+
return setmetatable(object, {
|
|
23
|
+
__call = function(_, ...)
|
|
24
|
+
local args = { ... }
|
|
25
|
+
return callback(unpack(args))
|
|
26
|
+
end,
|
|
27
|
+
})
|
|
28
|
+
end
|
|
29
|
+
local px = callable(function(value)
|
|
30
|
+
return math.round(value * SCALE())
|
|
31
|
+
end, {
|
|
32
|
+
scale = function(value)
|
|
33
|
+
return value * SCALE()
|
|
34
|
+
end,
|
|
35
|
+
even = function(value)
|
|
36
|
+
return math.round(value * SCALE() * 0.5) * 2
|
|
37
|
+
end,
|
|
38
|
+
floor = function(value)
|
|
39
|
+
return math.floor(value * SCALE())
|
|
40
|
+
end,
|
|
41
|
+
ceil = function(value)
|
|
42
|
+
return math.ceil(value * SCALE())
|
|
43
|
+
end,
|
|
44
|
+
})
|
|
45
|
+
local function calculateScale()
|
|
46
|
+
local target = TARGET()
|
|
47
|
+
if not target then
|
|
48
|
+
return nil
|
|
49
|
+
end
|
|
50
|
+
local size = if target:IsA("Camera") then target.ViewportSize elseif target:IsA("GuiObject") then target.AbsoluteSize else nil
|
|
51
|
+
if not size then
|
|
52
|
+
return nil
|
|
53
|
+
end
|
|
54
|
+
local res = BASE_RESOLUTION()
|
|
55
|
+
if res.X <= 0 or res.Y <= 0 then
|
|
56
|
+
return nil
|
|
57
|
+
end
|
|
58
|
+
local min = MIN_SCALE()
|
|
59
|
+
local width = math.log(size.X / res.X, 2)
|
|
60
|
+
local height = math.log(size.Y / res.Y, 2)
|
|
61
|
+
local centered = width + (height - width) * DOMINANT_AXIS
|
|
62
|
+
local scale = 2 ^ centered
|
|
63
|
+
SCALE(math.max(scale, min))
|
|
64
|
+
end
|
|
65
|
+
--[[
|
|
66
|
+
*
|
|
67
|
+
* Initializes global px scaling.
|
|
68
|
+
* Must be called exactly once.
|
|
69
|
+
|
|
70
|
+
]]
|
|
71
|
+
local function usePx(target, baseResolution, minScale)
|
|
72
|
+
if INITIALIZED then
|
|
73
|
+
logger:log("WARN", "usePx() called more than once")
|
|
74
|
+
return nil
|
|
75
|
+
end
|
|
76
|
+
INITIALIZED = true
|
|
77
|
+
logger:log("DEBUG", "Initializing px scaling", {
|
|
78
|
+
target = target,
|
|
79
|
+
baseResolution = baseResolution,
|
|
80
|
+
minScale = minScale,
|
|
81
|
+
})
|
|
82
|
+
if baseResolution then
|
|
83
|
+
BASE_RESOLUTION(baseResolution)
|
|
84
|
+
end
|
|
85
|
+
if minScale ~= nil then
|
|
86
|
+
MIN_SCALE(minScale)
|
|
87
|
+
end
|
|
88
|
+
if target then
|
|
89
|
+
TARGET(target)
|
|
90
|
+
end
|
|
91
|
+
local resolvedTarget = TARGET()
|
|
92
|
+
if not resolvedTarget then
|
|
93
|
+
logger:log("WARN", "usePx(): no valid target to observe")
|
|
94
|
+
return nil
|
|
95
|
+
end
|
|
96
|
+
local signal = if resolvedTarget:IsA("Camera") then resolvedTarget:GetPropertyChangedSignal("ViewportSize") else resolvedTarget:GetPropertyChangedSignal("AbsoluteSize")
|
|
97
|
+
useEventListener(signal, calculateScale)
|
|
98
|
+
calculateScale()
|
|
99
|
+
end
|
|
100
|
+
return {
|
|
101
|
+
usePx = usePx,
|
|
102
|
+
px = px,
|
|
103
|
+
}
|
package/out/vide/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import Vide from "@rbxts/vide";
|
|
2
2
|
import Renders from "./classes/renders";
|
|
3
3
|
import Types from "./types";
|
|
4
|
+
import { Logger, Debugger } from "./debug";
|
|
4
5
|
type Destructor = () => void;
|
|
5
6
|
type Loaded = {
|
|
6
7
|
container: Vide.Node;
|
|
@@ -8,17 +9,19 @@ type Loaded = {
|
|
|
8
9
|
anchor?: Vide.Node;
|
|
9
10
|
};
|
|
10
11
|
export default class AppForge extends Renders {
|
|
12
|
+
readonly logger: Logger;
|
|
13
|
+
readonly debug: Debugger;
|
|
11
14
|
protected sources: Map<string, Vide.Source<boolean>>;
|
|
12
15
|
protected loaded: Map<string, Loaded>;
|
|
13
16
|
protected innerMount?: Destructor;
|
|
14
17
|
protected __px: boolean;
|
|
15
18
|
constructor();
|
|
16
|
-
protected createSource(name: AppNames):
|
|
19
|
+
protected createSource(name: AppNames): void;
|
|
20
|
+
getSource(name: AppNames): Vide.Source<boolean>;
|
|
17
21
|
isLoaded(name: AppNames): boolean;
|
|
18
22
|
bind(name: AppNames, value: Vide.Source<boolean>): void;
|
|
19
23
|
anchor(name: AppNames, anchorName: AppNames, props: Types.Props.Main): void;
|
|
20
24
|
index(name: AppNames, index: number): void;
|
|
21
|
-
getSource(name: AppNames): Vide.Source<boolean>;
|
|
22
25
|
set(name: AppNames, value: boolean, rules?: boolean): void;
|
|
23
26
|
open(name: AppNames, rules?: boolean): void;
|
|
24
27
|
close(name: AppNames, rules?: boolean): void;
|
package/out/vide/init.luau
CHANGED
|
@@ -14,6 +14,10 @@ local untrack = _vide.untrack
|
|
|
14
14
|
local Renders = TS.import(script, script, "classes", "renders").default
|
|
15
15
|
-- Helpers
|
|
16
16
|
local AppRegistry = TS.import(script, script, "decorator").AppRegistry
|
|
17
|
+
-- Debug
|
|
18
|
+
local _debug = TS.import(script, script, "debug")
|
|
19
|
+
local Logger = _debug.Logger
|
|
20
|
+
local Debugger = _debug.Debugger
|
|
17
21
|
local AppForge
|
|
18
22
|
do
|
|
19
23
|
local super = Renders
|
|
@@ -30,6 +34,10 @@ do
|
|
|
30
34
|
end
|
|
31
35
|
function AppForge:constructor()
|
|
32
36
|
super.constructor(self)
|
|
37
|
+
self.logger = Logger.new("AppForge")
|
|
38
|
+
self.debug = Debugger.new(function(level, msg, data, trace)
|
|
39
|
+
return self.logger:log(level, msg, data, trace)
|
|
40
|
+
end)
|
|
33
41
|
self.sources = {}
|
|
34
42
|
self.loaded = {}
|
|
35
43
|
self.__px = false
|
|
@@ -46,22 +54,48 @@ do
|
|
|
46
54
|
local _name = name
|
|
47
55
|
local app = AppRegistry[_name]
|
|
48
56
|
if not app then
|
|
49
|
-
|
|
57
|
+
self.logger:log("ERROR", "App not registered while creating source", {
|
|
58
|
+
name = name,
|
|
59
|
+
})
|
|
60
|
+
return nil
|
|
50
61
|
end
|
|
51
62
|
local _sources = self.sources
|
|
52
63
|
local _name_1 = name
|
|
53
64
|
if _sources[_name_1] ~= nil then
|
|
54
65
|
return nil
|
|
55
66
|
end
|
|
56
|
-
local
|
|
67
|
+
local _debug_1 = self.debug
|
|
57
68
|
local _exp = name
|
|
69
|
+
local _object = {}
|
|
70
|
+
local _left = "default"
|
|
58
71
|
local _condition = app.visible
|
|
59
72
|
if _condition == nil then
|
|
60
73
|
_condition = false
|
|
61
74
|
end
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
75
|
+
_object[_left] = _condition
|
|
76
|
+
_debug_1:logTag("state", _exp, "Creating visibility source", _object)
|
|
77
|
+
local _sources_1 = self.sources
|
|
78
|
+
local _exp_1 = name
|
|
79
|
+
local _condition_1 = app.visible
|
|
80
|
+
if _condition_1 == nil then
|
|
81
|
+
_condition_1 = false
|
|
82
|
+
end
|
|
83
|
+
local _arg1 = source(_condition_1)
|
|
84
|
+
_sources_1[_exp_1] = _arg1
|
|
85
|
+
end
|
|
86
|
+
function AppForge:getSource(name)
|
|
87
|
+
local _sources = self.sources
|
|
88
|
+
local _name = name
|
|
89
|
+
if not (_sources[_name] ~= nil) then
|
|
90
|
+
self:createSource(name)
|
|
91
|
+
end
|
|
92
|
+
local _sources_1 = self.sources
|
|
93
|
+
local _name_1 = name
|
|
94
|
+
local src = _sources_1[_name_1]
|
|
95
|
+
if not src then
|
|
96
|
+
error(`AppForge invariant broken: missing visibility source for {name}`, 2)
|
|
97
|
+
end
|
|
98
|
+
return src
|
|
65
99
|
end
|
|
66
100
|
function AppForge:isLoaded(name)
|
|
67
101
|
local _loaded = self.loaded
|
|
@@ -70,6 +104,7 @@ do
|
|
|
70
104
|
end
|
|
71
105
|
function AppForge:bind(name, value)
|
|
72
106
|
if not RunService:IsRunning() then
|
|
107
|
+
self.debug:logTag("state", name, "Binding external visibility source")
|
|
73
108
|
local _sources = self.sources
|
|
74
109
|
local _name = name
|
|
75
110
|
local _value = value
|
|
@@ -81,17 +116,26 @@ do
|
|
|
81
116
|
end)
|
|
82
117
|
end)
|
|
83
118
|
else
|
|
84
|
-
|
|
119
|
+
self.logger:log("WARN", "forge.bind called while game is running", {
|
|
120
|
+
name = name,
|
|
121
|
+
})
|
|
85
122
|
end
|
|
86
123
|
end
|
|
87
124
|
function AppForge:anchor(name, anchorName, props)
|
|
88
125
|
if name == anchorName then
|
|
89
|
-
|
|
126
|
+
self.logger:log("ERROR", "Attempted to anchor app to itself", {
|
|
127
|
+
name = name,
|
|
128
|
+
})
|
|
129
|
+
return nil
|
|
90
130
|
end
|
|
91
131
|
local _anchorName = anchorName
|
|
92
132
|
local anchorApp = AppRegistry[_anchorName]
|
|
93
133
|
if not anchorApp then
|
|
94
|
-
|
|
134
|
+
self.logger:log("ERROR", "Anchor parent not registered", {
|
|
135
|
+
child = name,
|
|
136
|
+
parent = anchorName,
|
|
137
|
+
})
|
|
138
|
+
return nil
|
|
95
139
|
end
|
|
96
140
|
local _loaded = self.loaded
|
|
97
141
|
local _name = name
|
|
@@ -101,11 +145,17 @@ do
|
|
|
101
145
|
end
|
|
102
146
|
local render = _render
|
|
103
147
|
if not render then
|
|
104
|
-
|
|
148
|
+
self.debug:logTag("rules", name, "Anchor skipped (child not rendered yet)", {
|
|
149
|
+
parent = anchorName,
|
|
150
|
+
})
|
|
151
|
+
return nil
|
|
105
152
|
end
|
|
153
|
+
self.debug:logTag("rules", name, "Anchoring to parent", {
|
|
154
|
+
parent = anchorName,
|
|
155
|
+
})
|
|
106
156
|
local anchor = anchorApp.constructor.new(props, anchorName):render()
|
|
107
|
-
for _,
|
|
108
|
-
|
|
157
|
+
for _, child in anchor:GetDescendants() do
|
|
158
|
+
child:Destroy()
|
|
109
159
|
end
|
|
110
160
|
apply(anchor)({
|
|
111
161
|
Name = "Anchor",
|
|
@@ -116,7 +166,7 @@ do
|
|
|
116
166
|
local _name_1 = name
|
|
117
167
|
local prev = _loaded_1[_name_1]
|
|
118
168
|
if not prev then
|
|
119
|
-
error(`
|
|
169
|
+
error(`AppForge invariant broken: missing loaded app for {name}`, 2)
|
|
120
170
|
end
|
|
121
171
|
apply(prev.container)({
|
|
122
172
|
[0] = anchor,
|
|
@@ -133,22 +183,19 @@ do
|
|
|
133
183
|
local _name = name
|
|
134
184
|
local loaded = _loaded[_name]
|
|
135
185
|
if not loaded then
|
|
136
|
-
|
|
186
|
+
self.logger:log("WARN", "ZIndex skipped (app not loaded)", {
|
|
187
|
+
name = name,
|
|
188
|
+
index = index,
|
|
189
|
+
})
|
|
190
|
+
return nil
|
|
137
191
|
end
|
|
192
|
+
self.debug:logTag("rules", name, "Applying ZIndex", {
|
|
193
|
+
index = index,
|
|
194
|
+
})
|
|
138
195
|
apply(loaded.container)({
|
|
139
196
|
ZIndex = index,
|
|
140
197
|
})
|
|
141
198
|
end
|
|
142
|
-
function AppForge:getSource(name)
|
|
143
|
-
local _sources = self.sources
|
|
144
|
-
local _name = name
|
|
145
|
-
if not (_sources[_name] ~= nil) then
|
|
146
|
-
self:createSource(name)
|
|
147
|
-
end
|
|
148
|
-
local _sources_1 = self.sources
|
|
149
|
-
local _name_1 = name
|
|
150
|
-
return _sources_1[_name_1]
|
|
151
|
-
end
|
|
152
199
|
function AppForge:set(name, value, rules)
|
|
153
200
|
if rules == nil then
|
|
154
201
|
rules = true
|
|
@@ -162,10 +209,21 @@ do
|
|
|
162
209
|
local _name_1 = name
|
|
163
210
|
src = _sources_1[_name_1]
|
|
164
211
|
end
|
|
165
|
-
if src
|
|
212
|
+
if not src then
|
|
213
|
+
self.logger:log("ERROR", "Failed to set visibility (missing source)", {
|
|
214
|
+
name = name,
|
|
215
|
+
})
|
|
216
|
+
return nil
|
|
217
|
+
end
|
|
218
|
+
local prev = src()
|
|
219
|
+
if prev == value then
|
|
166
220
|
return nil
|
|
167
221
|
end
|
|
168
222
|
src(value)
|
|
223
|
+
self.debug:logTag("state", name, "Visibility changed", {
|
|
224
|
+
from = prev,
|
|
225
|
+
to = value,
|
|
226
|
+
})
|
|
169
227
|
if rules then
|
|
170
228
|
self:checkRules(name)
|
|
171
229
|
end
|
|
@@ -189,6 +247,7 @@ do
|
|
|
189
247
|
self:set(name, not self:getSource(name)(), rules)
|
|
190
248
|
end
|
|
191
249
|
function AppForge:story(props)
|
|
250
|
+
self.debug:logTag("lifecycle", "story", "Creating story mount")
|
|
192
251
|
local Container = create("Frame")({
|
|
193
252
|
Name = "Story Container",
|
|
194
253
|
BackgroundTransparency = 1,
|
|
@@ -202,6 +261,7 @@ do
|
|
|
202
261
|
return Container
|
|
203
262
|
end
|
|
204
263
|
function AppForge:mount(callback, props, target)
|
|
264
|
+
self.debug:logTag("lifecycle", "mount", "Mounting AppForge")
|
|
205
265
|
local Container = callback()
|
|
206
266
|
self.innerMount = mount(function()
|
|
207
267
|
apply(Container)({
|
|
@@ -212,6 +272,7 @@ do
|
|
|
212
272
|
return self.innerMount
|
|
213
273
|
end
|
|
214
274
|
function AppForge:unMount()
|
|
275
|
+
self.debug:logTag("lifecycle", "unmount", "Unmounting AppForge")
|
|
215
276
|
local _result = self.innerMount
|
|
216
277
|
if _result ~= nil then
|
|
217
278
|
_result()
|
package/out/vide/types.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rbxts/app-forge",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.2-alpha.2",
|
|
4
4
|
"description": "An App Manager for Vide",
|
|
5
5
|
"main": "out/init.lua",
|
|
6
6
|
"types": "out/index.d.ts",
|
|
@@ -38,11 +38,17 @@
|
|
|
38
38
|
"@rbxts/set-timeout": "^1.1.2"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
41
|
-
"@rbxts/loners-pretty-react-hooks": "^0.2.9",
|
|
42
|
-
"@rbxts/loners-pretty-vide-utils": "^0.1.7",
|
|
43
41
|
"@rbxts/react": "^17.3.7-ts.1",
|
|
44
42
|
"@rbxts/vide": "^0.5.7"
|
|
45
43
|
},
|
|
44
|
+
"peerDependenciesMeta": {
|
|
45
|
+
"@rbxts/react": {
|
|
46
|
+
"optional": true
|
|
47
|
+
},
|
|
48
|
+
"@rbxts/vide": {
|
|
49
|
+
"optional": true
|
|
50
|
+
}
|
|
51
|
+
},
|
|
46
52
|
"devDependencies": {
|
|
47
53
|
"@biomejs/biome": "^2.3.7",
|
|
48
54
|
"@rbxts/compiler-types": "3.0.0-types.0",
|