@rbxts/app-forge 0.7.1 → 0.7.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/out/react/hooks/usePx.d.ts +15 -0
- package/out/react/hooks/usePx.luau +117 -0
- package/out/vide/classes/renders.luau +2 -2
- package/out/vide/context.d.ts +1 -1
- package/out/vide/decorator.luau +2 -1
- package/out/vide/hooks/useAppContext.d.ts +1 -1
- package/out/vide/hooks/useEventListener.d.ts +22 -0
- package/out/vide/hooks/useEventListener.luau +67 -0
- package/out/vide/hooks/usePx.d.ts +19 -0
- package/out/vide/hooks/usePx.luau +120 -0
- package/out/vide/types.d.ts +1 -1
- package/package.json +9 -3
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scaled pixel unit helper.
|
|
3
|
+
*/
|
|
4
|
+
export declare const px: ((value: number) => number) & {
|
|
5
|
+
scale: (value: number) => number;
|
|
6
|
+
even: (value: number) => number;
|
|
7
|
+
floor: (value: number) => number;
|
|
8
|
+
ceil: (value: number) => number;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Initializes global px scaling.
|
|
12
|
+
*
|
|
13
|
+
* Should be called exactly once at app mount.
|
|
14
|
+
*/
|
|
15
|
+
export declare function usePx(target?: GuiObject | Camera, baseResolution?: Vector2, minScale?: number): void;
|
|
@@ -0,0 +1,117 @@
|
|
|
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
|
+
-- React
|
|
6
|
+
local useEffect = TS.import(script, TS.getModule(script, "@rbxts", "react")).useEffect
|
|
7
|
+
--* Default reference resolution for px calculations
|
|
8
|
+
local BASE_RESOLUTION = Vector2.new(1920, 1080)
|
|
9
|
+
--* Minimum allowed scale to prevent unreadable UI
|
|
10
|
+
local MIN_SCALE = 0.5
|
|
11
|
+
--[[
|
|
12
|
+
*
|
|
13
|
+
* Interpolates between width- and height-based scaling.
|
|
14
|
+
* 0 = width-driven, 1 = height-driven
|
|
15
|
+
|
|
16
|
+
]]
|
|
17
|
+
local DOMINANT_AXIS = 0.5
|
|
18
|
+
local TARGET = Workspace.CurrentCamera
|
|
19
|
+
local SCALE = 1
|
|
20
|
+
local GLOBAL_INITIALIZED = false
|
|
21
|
+
--[[
|
|
22
|
+
*
|
|
23
|
+
* Assigns a call signature to an object.
|
|
24
|
+
|
|
25
|
+
]]
|
|
26
|
+
local function callable(callback, object)
|
|
27
|
+
return setmetatable(object, {
|
|
28
|
+
__call = function(_, ...)
|
|
29
|
+
local args = { ... }
|
|
30
|
+
return callback(unpack(args))
|
|
31
|
+
end,
|
|
32
|
+
})
|
|
33
|
+
end
|
|
34
|
+
--[[
|
|
35
|
+
*
|
|
36
|
+
* Scaled pixel unit helper.
|
|
37
|
+
|
|
38
|
+
]]
|
|
39
|
+
local px = callable(function(value)
|
|
40
|
+
return math.round(value * SCALE)
|
|
41
|
+
end, {
|
|
42
|
+
scale = function(value)
|
|
43
|
+
return value * SCALE
|
|
44
|
+
end,
|
|
45
|
+
even = function(value)
|
|
46
|
+
return math.round(value * SCALE * 0.5) * 2
|
|
47
|
+
end,
|
|
48
|
+
floor = function(value)
|
|
49
|
+
return math.floor(value * SCALE)
|
|
50
|
+
end,
|
|
51
|
+
ceil = function(value)
|
|
52
|
+
return math.ceil(value * SCALE)
|
|
53
|
+
end,
|
|
54
|
+
})
|
|
55
|
+
--[[
|
|
56
|
+
*
|
|
57
|
+
* Recalculates the current scale factor.
|
|
58
|
+
|
|
59
|
+
]]
|
|
60
|
+
local function calculateScale()
|
|
61
|
+
local target = TARGET
|
|
62
|
+
if not target then
|
|
63
|
+
return nil
|
|
64
|
+
end
|
|
65
|
+
local size = if target:IsA("Camera") then target.ViewportSize elseif target:IsA("GuiObject") then target.AbsoluteSize else nil
|
|
66
|
+
if not size then
|
|
67
|
+
return nil
|
|
68
|
+
end
|
|
69
|
+
if BASE_RESOLUTION.X <= 0 or BASE_RESOLUTION.Y <= 0 then
|
|
70
|
+
return nil
|
|
71
|
+
end
|
|
72
|
+
local width = math.log(size.X / BASE_RESOLUTION.X, 2)
|
|
73
|
+
local height = math.log(size.Y / BASE_RESOLUTION.Y, 2)
|
|
74
|
+
local centered = width + (height - width) * DOMINANT_AXIS
|
|
75
|
+
local scale = 2 ^ centered
|
|
76
|
+
SCALE = math.max(scale, MIN_SCALE)
|
|
77
|
+
end
|
|
78
|
+
--[[
|
|
79
|
+
*
|
|
80
|
+
* Initializes global px scaling.
|
|
81
|
+
*
|
|
82
|
+
* Should be called exactly once at app mount.
|
|
83
|
+
|
|
84
|
+
]]
|
|
85
|
+
local function usePx(target, baseResolution, minScale)
|
|
86
|
+
useEffect(function()
|
|
87
|
+
if GLOBAL_INITIALIZED then
|
|
88
|
+
warn("usePx() may only be called once globally")
|
|
89
|
+
return nil
|
|
90
|
+
end
|
|
91
|
+
GLOBAL_INITIALIZED = true
|
|
92
|
+
if baseResolution then
|
|
93
|
+
BASE_RESOLUTION = baseResolution
|
|
94
|
+
end
|
|
95
|
+
if minScale ~= nil then
|
|
96
|
+
MIN_SCALE = minScale
|
|
97
|
+
end
|
|
98
|
+
if target then
|
|
99
|
+
TARGET = target
|
|
100
|
+
end
|
|
101
|
+
local resolvedTarget = TARGET
|
|
102
|
+
if not resolvedTarget then
|
|
103
|
+
warn("usePx(): no valid target to observe")
|
|
104
|
+
return nil
|
|
105
|
+
end
|
|
106
|
+
local signal = if resolvedTarget:IsA("Camera") then resolvedTarget:GetPropertyChangedSignal("ViewportSize") else resolvedTarget:GetPropertyChangedSignal("AbsoluteSize")
|
|
107
|
+
local connection = signal:Connect(calculateScale)
|
|
108
|
+
calculateScale()
|
|
109
|
+
return function()
|
|
110
|
+
connection:Disconnect()
|
|
111
|
+
end
|
|
112
|
+
end, {})
|
|
113
|
+
end
|
|
114
|
+
return {
|
|
115
|
+
usePx = usePx,
|
|
116
|
+
px = px,
|
|
117
|
+
}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
-- Compiled with roblox-ts v3.0.0
|
|
2
2
|
local TS = _G[script]
|
|
3
|
-
-- Services
|
|
4
3
|
-- Packages
|
|
5
|
-
local usePx = TS.import(script, TS.getModule(script, "@rbxts", "loners-pretty-vide-utils").out).usePx
|
|
6
4
|
local _vide = TS.import(script, TS.getModule(script, "@rbxts", "vide").src)
|
|
7
5
|
local apply = _vide.apply
|
|
8
6
|
local create = _vide.create
|
|
9
7
|
-- Types
|
|
10
8
|
-- Components
|
|
11
9
|
local AppRegistry = TS.import(script, script.Parent.Parent, "decorator").AppRegistry
|
|
10
|
+
-- Hooks
|
|
11
|
+
local usePx = TS.import(script, script.Parent.Parent, "hooks", "usePx").usePx
|
|
12
12
|
-- Classes
|
|
13
13
|
local Rules = TS.import(script, script.Parent, "rules").default
|
|
14
14
|
local Renders
|
package/out/vide/context.d.ts
CHANGED
package/out/vide/decorator.luau
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
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
|
|
6
7
|
local AppRegistry = {}
|
|
7
8
|
local function App(props)
|
|
8
9
|
return function(constructor)
|
|
@@ -0,0 +1,22 @@
|
|
|
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. The subscription is automatically
|
|
15
|
+
* disconnected when the scope cleans up.
|
|
16
|
+
*
|
|
17
|
+
* @param event The event-like object to subscribe to.
|
|
18
|
+
* @param listener The listener to subscribe with.
|
|
19
|
+
* @returns The connection object.
|
|
20
|
+
*/
|
|
21
|
+
export declare function useEventListener<T extends EventLike>(event: T, listener: T extends EventLike<infer U> ? U : never): ReturnType<T>;
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,67 @@
|
|
|
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
|
+
local connect = function(event, callback)
|
|
5
|
+
local _event = event
|
|
6
|
+
if typeof(_event) == "RBXScriptSignal" then
|
|
7
|
+
-- With deferred events, a "hard disconnect" is necessary to avoid causing
|
|
8
|
+
-- state updates after a component unmounts. Use 'Connected' to check if
|
|
9
|
+
-- the connection is still valid before invoking the callback.
|
|
10
|
+
-- https://devforum.roblox.com/t/deferred-engine-events/2276564/99
|
|
11
|
+
local connection
|
|
12
|
+
connection = event:Connect(function(...)
|
|
13
|
+
local args = { ... }
|
|
14
|
+
if connection.Connected then
|
|
15
|
+
return callback(unpack(args))
|
|
16
|
+
end
|
|
17
|
+
end)
|
|
18
|
+
return connection
|
|
19
|
+
elseif event.Connect ~= nil then
|
|
20
|
+
return event:Connect(callback)
|
|
21
|
+
elseif event.connect ~= nil then
|
|
22
|
+
return event:connect(callback)
|
|
23
|
+
elseif event.subscribe ~= nil then
|
|
24
|
+
return event:subscribe(callback)
|
|
25
|
+
else
|
|
26
|
+
error("Event-like object does not have a supported connect method.")
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
local disconnect = function(connection)
|
|
30
|
+
local _connection = connection
|
|
31
|
+
if type(_connection) == "function" then
|
|
32
|
+
connection()
|
|
33
|
+
else
|
|
34
|
+
local _connection_1 = connection
|
|
35
|
+
local _condition = typeof(_connection_1) == "RBXScriptConnection"
|
|
36
|
+
if not _condition then
|
|
37
|
+
_condition = connection.Disconnect ~= nil
|
|
38
|
+
end
|
|
39
|
+
if _condition then
|
|
40
|
+
connection:Disconnect()
|
|
41
|
+
elseif connection.disconnect ~= nil then
|
|
42
|
+
connection:disconnect()
|
|
43
|
+
else
|
|
44
|
+
error("Connection-like object does not have a supported disconnect method.")
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
--[[
|
|
49
|
+
*
|
|
50
|
+
* Subscribes to an event-like object. The subscription is automatically
|
|
51
|
+
* disconnected when the scope cleans up.
|
|
52
|
+
*
|
|
53
|
+
* @param event The event-like object to subscribe to.
|
|
54
|
+
* @param listener The listener to subscribe with.
|
|
55
|
+
* @returns The connection object.
|
|
56
|
+
|
|
57
|
+
]]
|
|
58
|
+
local function useEventListener(event, listener)
|
|
59
|
+
local connection = connect(event, listener)
|
|
60
|
+
cleanup(function()
|
|
61
|
+
return disconnect(connection)
|
|
62
|
+
end)
|
|
63
|
+
return connection
|
|
64
|
+
end
|
|
65
|
+
return {
|
|
66
|
+
useEventListener = useEventListener,
|
|
67
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scaled pixel unit helper.
|
|
3
|
+
*
|
|
4
|
+
* - `px(12)` → rounded scaled pixels
|
|
5
|
+
* - `px.scale(12)` → raw scaled value
|
|
6
|
+
* - `px.even(12)` → even pixel values (useful for strokes/borders)
|
|
7
|
+
*/
|
|
8
|
+
export declare const px: ((value: number) => number) & {
|
|
9
|
+
scale: (value: number) => number;
|
|
10
|
+
even: (value: number) => number;
|
|
11
|
+
floor: (value: number) => number;
|
|
12
|
+
ceil: (value: number) => number;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Initializes global px scaling.
|
|
16
|
+
*
|
|
17
|
+
* Should be called exactly once at app mount.
|
|
18
|
+
*/
|
|
19
|
+
export declare function usePx(target?: GuiObject | Camera, baseResolution?: Vector2, minScale?: number): void;
|
|
@@ -0,0 +1,120 @@
|
|
|
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
|
+
--* Default reference resolution for px calculations
|
|
10
|
+
local BASE_RESOLUTION = source(Vector2.new(1920, 1080))
|
|
11
|
+
--* Minimum allowed scale to prevent unreadable UI
|
|
12
|
+
local MIN_SCALE = source(0.5)
|
|
13
|
+
--[[
|
|
14
|
+
*
|
|
15
|
+
* Interpolates between width- and height-based scaling.
|
|
16
|
+
* 0 = width-driven, 1 = height-driven
|
|
17
|
+
|
|
18
|
+
]]
|
|
19
|
+
local DOMINANT_AXIS = 0.5
|
|
20
|
+
local TARGET = source(Workspace.CurrentCamera)
|
|
21
|
+
local SCALE = source(1)
|
|
22
|
+
local INITIALIZED = false
|
|
23
|
+
--[[
|
|
24
|
+
*
|
|
25
|
+
* Assigns a call signature to an object.
|
|
26
|
+
|
|
27
|
+
]]
|
|
28
|
+
local function callable(callback, object)
|
|
29
|
+
return setmetatable(object, {
|
|
30
|
+
__call = function(_, ...)
|
|
31
|
+
local args = { ... }
|
|
32
|
+
return callback(unpack(args))
|
|
33
|
+
end,
|
|
34
|
+
})
|
|
35
|
+
end
|
|
36
|
+
--[[
|
|
37
|
+
*
|
|
38
|
+
* Scaled pixel unit helper.
|
|
39
|
+
*
|
|
40
|
+
* - `px(12)` → rounded scaled pixels
|
|
41
|
+
* - `px.scale(12)` → raw scaled value
|
|
42
|
+
* - `px.even(12)` → even pixel values (useful for strokes/borders)
|
|
43
|
+
|
|
44
|
+
]]
|
|
45
|
+
local px = callable(function(value)
|
|
46
|
+
return math.round(value * SCALE())
|
|
47
|
+
end, {
|
|
48
|
+
scale = function(value)
|
|
49
|
+
return value * SCALE()
|
|
50
|
+
end,
|
|
51
|
+
even = function(value)
|
|
52
|
+
return math.round(value * SCALE() * 0.5) * 2
|
|
53
|
+
end,
|
|
54
|
+
floor = function(value)
|
|
55
|
+
return math.floor(value * SCALE())
|
|
56
|
+
end,
|
|
57
|
+
ceil = function(value)
|
|
58
|
+
return math.ceil(value * SCALE())
|
|
59
|
+
end,
|
|
60
|
+
})
|
|
61
|
+
--[[
|
|
62
|
+
*
|
|
63
|
+
* Recalculates the current scale factor based on the target size.
|
|
64
|
+
|
|
65
|
+
]]
|
|
66
|
+
local function calculateScale()
|
|
67
|
+
local target = TARGET()
|
|
68
|
+
if not target then
|
|
69
|
+
return nil
|
|
70
|
+
end
|
|
71
|
+
local size = if target:IsA("Camera") then target.ViewportSize elseif target:IsA("GuiObject") then target.AbsoluteSize else nil
|
|
72
|
+
if not size then
|
|
73
|
+
return nil
|
|
74
|
+
end
|
|
75
|
+
local res = BASE_RESOLUTION()
|
|
76
|
+
if res.X <= 0 or res.Y <= 0 then
|
|
77
|
+
return nil
|
|
78
|
+
end
|
|
79
|
+
local min = MIN_SCALE()
|
|
80
|
+
local width = math.log(size.X / res.X, 2)
|
|
81
|
+
local height = math.log(size.Y / res.Y, 2)
|
|
82
|
+
local centered = width + (height - width) * DOMINANT_AXIS
|
|
83
|
+
local scale = 2 ^ centered
|
|
84
|
+
SCALE(math.max(scale, min))
|
|
85
|
+
end
|
|
86
|
+
--[[
|
|
87
|
+
*
|
|
88
|
+
* Initializes global px scaling.
|
|
89
|
+
*
|
|
90
|
+
* Should be called exactly once at app mount.
|
|
91
|
+
|
|
92
|
+
]]
|
|
93
|
+
local function usePx(target, baseResolution, minScale)
|
|
94
|
+
if INITIALIZED then
|
|
95
|
+
warn("usePx() may only be called once")
|
|
96
|
+
return nil
|
|
97
|
+
end
|
|
98
|
+
INITIALIZED = true
|
|
99
|
+
if baseResolution then
|
|
100
|
+
BASE_RESOLUTION(baseResolution)
|
|
101
|
+
end
|
|
102
|
+
if minScale ~= nil then
|
|
103
|
+
MIN_SCALE(minScale)
|
|
104
|
+
end
|
|
105
|
+
if target then
|
|
106
|
+
TARGET(target)
|
|
107
|
+
end
|
|
108
|
+
local resolvedTarget = TARGET()
|
|
109
|
+
if not resolvedTarget then
|
|
110
|
+
warn("usePx(): no valid target to observe")
|
|
111
|
+
return nil
|
|
112
|
+
end
|
|
113
|
+
local signal = if resolvedTarget:IsA("Camera") then resolvedTarget:GetPropertyChangedSignal("ViewportSize") else resolvedTarget:GetPropertyChangedSignal("AbsoluteSize")
|
|
114
|
+
useEventListener(signal, calculateScale)
|
|
115
|
+
calculateScale()
|
|
116
|
+
end
|
|
117
|
+
return {
|
|
118
|
+
usePx = usePx,
|
|
119
|
+
px = px,
|
|
120
|
+
}
|
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",
|
|
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",
|