@rbxts/app-forge 0.7.2-alpha.12 β 0.7.2-alpha.13
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 +35 -192
- package/out/vide/classes/renders.d.ts +8 -6
- package/out/vide/classes/renders.luau +1 -1
- package/out/vide/init.luau +10 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -26,6 +26,7 @@ If youβve ever ended up with tangled UI state, duplicated visibility logic, or
|
|
|
26
26
|
* **px scaling** built-in via `loners-pretty-vide-utils`
|
|
27
27
|
* **Vide context integration**
|
|
28
28
|
* **Story / sandbox rendering**
|
|
29
|
+
* **Built-in debug logger & performance tracing**
|
|
29
30
|
* Fully typed with **roblox-ts**
|
|
30
31
|
|
|
31
32
|
---
|
|
@@ -86,6 +87,7 @@ Apps are registered using a decorator and rendered through `AppForge`.
|
|
|
86
87
|
* mounts and unmounts UI
|
|
87
88
|
* enforces rules
|
|
88
89
|
* exposes imperative helpers (`open`, `close`, `toggle`)
|
|
90
|
+
* owns the **debugger & logger** instance
|
|
89
91
|
|
|
90
92
|
You usually create **one Forge per UI root**.
|
|
91
93
|
|
|
@@ -134,8 +136,6 @@ const forge = new CreateVideForge();
|
|
|
134
136
|
|
|
135
137
|
### Mounting (Game Runtime)
|
|
136
138
|
|
|
137
|
-
AppForge is mounted once from application bootstrap code (commonly a Flamework controller).
|
|
138
|
-
|
|
139
139
|
```ts
|
|
140
140
|
const forge = new CreateVideForge();
|
|
141
141
|
|
|
@@ -152,52 +152,6 @@ forge.mount(
|
|
|
152
152
|
);
|
|
153
153
|
```
|
|
154
154
|
|
|
155
|
-
Notes:
|
|
156
|
-
|
|
157
|
-
* `forge` is **implicitly available** to Apps
|
|
158
|
-
* `props` are user-defined and become `this.props` inside Apps
|
|
159
|
-
* visibility & rules are controlled entirely by the Forge
|
|
160
|
-
|
|
161
|
-
---
|
|
162
|
-
|
|
163
|
-
### Mounting (Game Runtime)
|
|
164
|
-
|
|
165
|
-
AppForge is typically mounted from a **controller** (e.g. Flamework) and targets `PlayerGui`.
|
|
166
|
-
|
|
167
|
-
```ts
|
|
168
|
-
const forge = new CreateVideForge();
|
|
169
|
-
|
|
170
|
-
forge.mount(
|
|
171
|
-
() => (
|
|
172
|
-
<screengui
|
|
173
|
-
Name="App"
|
|
174
|
-
ZIndexBehavior="Sibling"
|
|
175
|
-
ResetOnSpawn={false}
|
|
176
|
-
/>
|
|
177
|
-
),
|
|
178
|
-
props,
|
|
179
|
-
Players.LocalPlayer.WaitForChild("PlayerGui"),
|
|
180
|
-
);
|
|
181
|
-
```
|
|
182
|
-
|
|
183
|
-
This:
|
|
184
|
-
|
|
185
|
-
* creates a single root `ScreenGui`
|
|
186
|
-
* mounts all rendered apps under it
|
|
187
|
-
* keeps AppForge in control of visibility & rules
|
|
188
|
-
|
|
189
|
-
---
|
|
190
|
-
|
|
191
|
-
### Mounting
|
|
192
|
-
|
|
193
|
-
```ts
|
|
194
|
-
forge.mount(
|
|
195
|
-
() => <screengui ResetOnSpawn={false} />,
|
|
196
|
-
props,
|
|
197
|
-
playerGui,
|
|
198
|
-
);
|
|
199
|
-
```
|
|
200
|
-
|
|
201
155
|
---
|
|
202
156
|
|
|
203
157
|
### Opening & Closing Apps
|
|
@@ -208,20 +162,11 @@ forge.close("Inventory");
|
|
|
208
162
|
forge.toggle("Inventory");
|
|
209
163
|
```
|
|
210
164
|
|
|
211
|
-
You can also access the reactive source directly:
|
|
212
|
-
|
|
213
|
-
```ts
|
|
214
|
-
const visible = forge.getSource("Inventory");
|
|
215
|
-
```
|
|
216
|
-
|
|
217
165
|
---
|
|
218
166
|
|
|
219
167
|
## π§± Defining an App
|
|
220
168
|
|
|
221
169
|
```ts
|
|
222
|
-
import { VideApp, VideArgs } from "@rbxts/app-forge";
|
|
223
|
-
import Vide from "@rbxts/vide";
|
|
224
|
-
|
|
225
170
|
@VideApp({
|
|
226
171
|
name: "Inventory",
|
|
227
172
|
renderGroup: "Lobby",
|
|
@@ -246,165 +191,71 @@ export class Inventory extends VideArgs {
|
|
|
246
191
|
|
|
247
192
|
---
|
|
248
193
|
|
|
249
|
-
##
|
|
250
|
-
|
|
251
|
-
```ts
|
|
252
|
-
@VideApp({
|
|
253
|
-
name: "InventoryInfo",
|
|
254
|
-
renderGroup: "Lobby",
|
|
255
|
-
rules: {
|
|
256
|
-
parent: "Inventory",
|
|
257
|
-
},
|
|
258
|
-
})
|
|
259
|
-
export class InventoryInfo extends VideArgs {
|
|
260
|
-
render() {
|
|
261
|
-
return <frame />;
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
```
|
|
265
|
-
|
|
266
|
-
Behavior:
|
|
267
|
-
|
|
268
|
-
* When `Inventory` closes β `InventoryInfo` closes
|
|
269
|
-
* Child is **anchored** to parent unless `detach: true`
|
|
270
|
-
|
|
271
|
-
```ts
|
|
272
|
-
rules: {
|
|
273
|
-
parent: "Inventory",
|
|
274
|
-
detach: true,
|
|
275
|
-
}
|
|
276
|
-
```
|
|
277
|
-
|
|
278
|
-
---
|
|
279
|
-
|
|
280
|
-
## π¦ Exclusive Groups
|
|
281
|
-
|
|
282
|
-
```ts
|
|
283
|
-
@VideApp({
|
|
284
|
-
name: "Settings",
|
|
285
|
-
rules: {
|
|
286
|
-
exclusiveGroup: "Menus",
|
|
287
|
-
},
|
|
288
|
-
})
|
|
289
|
-
```
|
|
194
|
+
## π Debugging & Logging
|
|
290
195
|
|
|
291
|
-
|
|
196
|
+
AppForge includes a **built-in debugger** designed for Studio-only diagnostics.
|
|
292
197
|
|
|
293
|
-
|
|
198
|
+
### Debug Tags
|
|
294
199
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
AppForge supports **multiple render selection modes**. You can render by:
|
|
298
|
-
|
|
299
|
-
* a single app name
|
|
300
|
-
* multiple app names
|
|
301
|
-
* one or more render groups
|
|
302
|
-
* combinations of `group + name(s)`
|
|
303
|
-
|
|
304
|
-
All render options are passed via `VideRenderProps`.
|
|
305
|
-
|
|
306
|
-
---
|
|
307
|
-
|
|
308
|
-
### Render a single app
|
|
200
|
+
Debug output is grouped by **typed tags**:
|
|
309
201
|
|
|
310
202
|
```ts
|
|
311
|
-
|
|
203
|
+
type DebugTag =
|
|
204
|
+
| "render"
|
|
205
|
+
| "rules"
|
|
206
|
+
| "state"
|
|
207
|
+
| "px"
|
|
208
|
+
| "lifecycle";
|
|
312
209
|
```
|
|
313
210
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
### Render multiple apps
|
|
317
|
-
|
|
318
|
-
```ts
|
|
319
|
-
render: { names: ["Inventory", "InventoryInfo"] }
|
|
320
|
-
```
|
|
211
|
+
Each subsystem logs under its respective tag.
|
|
321
212
|
|
|
322
213
|
---
|
|
323
214
|
|
|
324
|
-
###
|
|
215
|
+
### Enabling Debug Tags
|
|
325
216
|
|
|
326
217
|
```ts
|
|
327
|
-
render
|
|
218
|
+
forge.debug.enable("render");
|
|
219
|
+
forge.debug.enable("rules");
|
|
328
220
|
```
|
|
329
221
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
### Render by group + name
|
|
222
|
+
Enable everything at once:
|
|
333
223
|
|
|
334
224
|
```ts
|
|
335
|
-
|
|
336
|
-
group: "Lobby",
|
|
337
|
-
name: "Inventory",
|
|
338
|
-
}
|
|
225
|
+
forge.debug.enableAll();
|
|
339
226
|
```
|
|
340
227
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
---
|
|
344
|
-
|
|
345
|
-
### Render by group + names
|
|
228
|
+
Disable:
|
|
346
229
|
|
|
347
230
|
```ts
|
|
348
|
-
render
|
|
349
|
-
group: "Lobby",
|
|
350
|
-
names: ["Inventory", "Settings"],
|
|
351
|
-
}
|
|
231
|
+
forge.debug.disable("render");
|
|
352
232
|
```
|
|
353
233
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
* are in the specified group(s)
|
|
357
|
-
* and whose names match the provided list
|
|
234
|
+
Debug logging only runs in **Roblox Studio**.
|
|
358
235
|
|
|
359
236
|
---
|
|
360
237
|
|
|
361
|
-
|
|
238
|
+
### Performance Tracing
|
|
362
239
|
|
|
363
|
-
|
|
240
|
+
Certain systems emit **timing logs** when enabled:
|
|
364
241
|
|
|
365
242
|
```ts
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
return forge.story({
|
|
369
|
-
props,
|
|
370
|
-
config: {
|
|
371
|
-
px: {
|
|
372
|
-
target: storyProps.target,
|
|
373
|
-
},
|
|
374
|
-
},
|
|
375
|
-
render: { group: "Lobby" },
|
|
376
|
-
});
|
|
243
|
+
forge.debug.enable("render");
|
|
377
244
|
```
|
|
378
245
|
|
|
379
|
-
|
|
246
|
+
Output example:
|
|
380
247
|
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
248
|
+
```
|
|
249
|
+
[PERF][render][Inventory] 1.243ms
|
|
250
|
+
```
|
|
384
251
|
|
|
385
252
|
---
|
|
386
253
|
|
|
387
|
-
|
|
254
|
+
### Static Registration Logs
|
|
388
255
|
|
|
389
|
-
App
|
|
256
|
+
App registration (decorators) run **before a Forge exists**.
|
|
390
257
|
|
|
391
|
-
|
|
392
|
-
import { Provider } from "@rbxts/vide";
|
|
393
|
-
import { VideContexts } from "@rbxts/app-forge";
|
|
394
|
-
|
|
395
|
-
<Provider context={VideContexts.App} value={this.props}>
|
|
396
|
-
{() => <Child />}
|
|
397
|
-
</Provider>
|
|
398
|
-
```
|
|
399
|
-
|
|
400
|
-
Or via hook:
|
|
401
|
-
|
|
402
|
-
````ts
|
|
403
|
-
```ts
|
|
404
|
-
import { useVideAppContext } from "@rbxts/app-forge";
|
|
405
|
-
|
|
406
|
-
const app = useVideAppContext();
|
|
407
|
-
````
|
|
258
|
+
These use an internal **static logger** and will still emit warnings and errors during Studio load (e.g. duplicate app names).
|
|
408
259
|
|
|
409
260
|
---
|
|
410
261
|
|
|
@@ -418,6 +269,7 @@ AppForge
|
|
|
418
269
|
ββ Rule Engine
|
|
419
270
|
β ββ Parent Rule
|
|
420
271
|
β ββ Exclusive Group Rule
|
|
272
|
+
ββ Debugger / Logger
|
|
421
273
|
ββ Vide Mount
|
|
422
274
|
```
|
|
423
275
|
|
|
@@ -428,6 +280,7 @@ AppForge
|
|
|
428
280
|
* Apps are **singletons per Forge**
|
|
429
281
|
* Rendering twice will warn if px is reβinitialized
|
|
430
282
|
* Rules are enforced **reactively**
|
|
283
|
+
* Debug logging is **Studio-only**
|
|
431
284
|
* This package is currently **alpha** β APIs may change
|
|
432
285
|
|
|
433
286
|
---
|
|
@@ -443,27 +296,17 @@ AppForge
|
|
|
443
296
|
|
|
444
297
|
## βοΈ React Support (Planned)
|
|
445
298
|
|
|
446
|
-
AppForge is designed as a **renderer-agnostic App Manager**.
|
|
299
|
+
AppForge is designed as a **renderer-agnostic App Manager**.
|
|
447
300
|
|
|
448
301
|
Currently:
|
|
449
302
|
|
|
450
303
|
* β
**Vide renderer** is production-ready
|
|
451
304
|
* π§ **React renderer** exists but is **very early / experimental**
|
|
452
305
|
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
Public surface (subject to change):
|
|
456
|
-
|
|
457
|
-
```ts
|
|
458
|
-
import { ReactApp, ReactArgs, CreateReactForge } from "@rbxts/app-forge";
|
|
459
|
-
```
|
|
460
|
-
|
|
461
|
-
**Vide is the recommended and supported path today.**
|
|
306
|
+
Vide is the recommended and supported path today.
|
|
462
307
|
|
|
463
308
|
---
|
|
464
309
|
|
|
465
310
|
## π License
|
|
466
311
|
|
|
467
312
|
MIT
|
|
468
|
-
|
|
469
|
-
---
|
|
@@ -12,14 +12,16 @@ export default class Renders extends Rules {
|
|
|
12
12
|
* Entry point for mounting renders.
|
|
13
13
|
* Decides render strategy based on props.
|
|
14
14
|
*/
|
|
15
|
-
protected renderMount(this: AppForge, props: Types.Props.Main): Vide.Node
|
|
15
|
+
protected renderMount(this: AppForge, props: Types.Props.Main): void | Instance | Vide.InstanceAttributes<Instance> | Vide.VideAction<any> | ReadonlyMap<number, Vide.Node> | {
|
|
16
|
+
readonly [key: number]: Vide.Node;
|
|
17
|
+
} | Vide.FunctionNode;
|
|
16
18
|
private renderNames;
|
|
17
19
|
private collectByGroup;
|
|
18
20
|
private normalizeGroups;
|
|
19
21
|
protected renderApp(this: AppForge, props: Types.Props.Main): Vide.Node;
|
|
20
|
-
protected renderApps(this: AppForge, props: Types.Props.Main): Vide.Node[];
|
|
21
|
-
protected renderGroup(this: AppForge, props: Types.Props.Main): Vide.Node[];
|
|
22
|
-
protected renderGroupByName(this: AppForge, props: Types.Props.Main): Vide.Node[];
|
|
23
|
-
protected renderGroupByNames(this: AppForge, props: Types.Props.Main): Vide.Node[];
|
|
24
|
-
protected renderAll(this: AppForge, props: Types.Props.Main): Vide.Node[];
|
|
22
|
+
protected renderApps(this: AppForge, props: Types.Props.Main): void | Vide.Node[];
|
|
23
|
+
protected renderGroup(this: AppForge, props: Types.Props.Main): void | Vide.Node[];
|
|
24
|
+
protected renderGroupByName(this: AppForge, props: Types.Props.Main): void | Vide.Node[];
|
|
25
|
+
protected renderGroupByNames(this: AppForge, props: Types.Props.Main): void | Vide.Node[];
|
|
26
|
+
protected renderAll(this: AppForge, props: Types.Props.Main): void | Vide.Node[];
|
|
25
27
|
}
|
|
@@ -92,7 +92,7 @@ do
|
|
|
92
92
|
end
|
|
93
93
|
function Renders:renderNames(props, names, forge)
|
|
94
94
|
if #names == 0 then
|
|
95
|
-
|
|
95
|
+
return warn("No app names provided to render | Make sure you have the paths where decorators are used!")
|
|
96
96
|
end
|
|
97
97
|
-- βΌ ReadonlyArray.map βΌ
|
|
98
98
|
local _newValue = table.create(#names)
|
package/out/vide/init.luau
CHANGED
|
@@ -265,26 +265,28 @@ do
|
|
|
265
265
|
end
|
|
266
266
|
function AppForge:story(props)
|
|
267
267
|
self.debug:logTag("lifecycle", "story", "Creating story mount")
|
|
268
|
-
local
|
|
268
|
+
local container = create("Frame")({
|
|
269
269
|
Name = "Story Container",
|
|
270
270
|
BackgroundTransparency = 1,
|
|
271
271
|
AnchorPoint = Vector2.new(0.5, 0.5),
|
|
272
272
|
Position = UDim2.fromScale(0.5, 0.5),
|
|
273
273
|
Size = UDim2.fromScale(1, 1),
|
|
274
274
|
})
|
|
275
|
-
|
|
276
|
-
|
|
275
|
+
local render = self:renderMount(props)
|
|
276
|
+
apply(container)({
|
|
277
|
+
[0] = if render then render else nil,
|
|
277
278
|
})
|
|
278
|
-
return
|
|
279
|
+
return container
|
|
279
280
|
end
|
|
280
281
|
function AppForge:mount(callback, props, target)
|
|
281
282
|
self.debug:logTag("lifecycle", "mount", "Mounting AppForge")
|
|
282
|
-
local
|
|
283
|
+
local container = callback()
|
|
284
|
+
local render = self:renderMount(props)
|
|
283
285
|
self.innerMount = mount(function()
|
|
284
|
-
apply(
|
|
285
|
-
[0] =
|
|
286
|
+
apply(container)({
|
|
287
|
+
[0] = if render then render else nil,
|
|
286
288
|
})
|
|
287
|
-
return
|
|
289
|
+
return container
|
|
288
290
|
end, target)
|
|
289
291
|
return self.innerMount
|
|
290
292
|
end
|