@threenative/ui 0.3.5 → 0.3.8
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/dist/index.d.ts +17 -1
- package/dist/index.js +27 -4
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -31,9 +31,25 @@ declare function UiLayer({ children }: {
|
|
|
31
31
|
* The UI holds a mirror, never the game object: on every native target the game is in another
|
|
32
32
|
* realm, and a HUD written against a live store would work on web and read nothing on a phone.
|
|
33
33
|
* The mirror is fed at the store's published cadence, which is not the game loop.
|
|
34
|
+
*
|
|
35
|
+
* **Reads `undefined` while the loading cover is up**, so a HUD cannot draw over the loading bar
|
|
36
|
+
* and no game writes a `loaded` field to prevent it. A UI that draws its own loading screen reads
|
|
37
|
+
* through `useUiStateDuringStartup`.
|
|
34
38
|
*/
|
|
35
39
|
declare function useUiState<TState extends object>(): TState | undefined;
|
|
36
40
|
declare function useUiState<TState extends object, TSelected>(selector: (state: TState) => TSelected): TSelected | undefined;
|
|
41
|
+
/**
|
|
42
|
+
* The named override of `useUiState`'s loading-cover gate, for a UI that draws the loading screen
|
|
43
|
+
* itself (a staged overlay reading the startup progress the game publishes). It reads state while
|
|
44
|
+
* the cover is up. `reason` is required and reported once as `TN_UI_STARTUP_OVERRIDE <reason>`,
|
|
45
|
+
* so a HUD that merely skipped the gate shows up in the log.
|
|
46
|
+
*/
|
|
47
|
+
declare function useUiStateDuringStartup<TState extends object>(options: {
|
|
48
|
+
readonly reason: string;
|
|
49
|
+
}): TState | undefined;
|
|
50
|
+
declare function useUiStateDuringStartup<TState extends object, TSelected>(options: {
|
|
51
|
+
readonly reason: string;
|
|
52
|
+
}, selector: (state: TState) => TSelected): TSelected | undefined;
|
|
37
53
|
/**
|
|
38
54
|
* Send an intent to the game — `restart`, `pause`, whatever the game named.
|
|
39
55
|
*
|
|
@@ -43,4 +59,4 @@ declare function useUiState<TState extends object, TSelected>(selector: (state:
|
|
|
43
59
|
*/
|
|
44
60
|
declare function useUiIntent(): (intent: string, payload?: unknown) => void;
|
|
45
61
|
|
|
46
|
-
export { DebugOverlay, GameCanvas, UiLayer, useGameState, useUiIntent, useUiState };
|
|
62
|
+
export { DebugOverlay, GameCanvas, UiLayer, useGameState, useUiIntent, useUiState, useUiStateDuringStartup };
|
package/dist/index.js
CHANGED
|
@@ -109,13 +109,18 @@ function DebugOverlayView() {
|
|
|
109
109
|
const clearOutline = () => setSelected(void 0);
|
|
110
110
|
hostWindow.addEventListener("keydown", toggle);
|
|
111
111
|
hostWindow.addEventListener("resize", clearOutline);
|
|
112
|
-
const timer = hostWindow.setInterval(() => setSnapshot(readSnapshot()), 100);
|
|
113
112
|
return () => {
|
|
114
113
|
hostWindow.removeEventListener("keydown", toggle);
|
|
115
114
|
hostWindow.removeEventListener("resize", clearOutline);
|
|
116
|
-
hostWindow.clearInterval(timer);
|
|
117
115
|
};
|
|
118
116
|
}, []);
|
|
117
|
+
useEffect(() => {
|
|
118
|
+
if (!open || typeof window === "undefined") return void 0;
|
|
119
|
+
const hostWindow = window;
|
|
120
|
+
setSnapshot(readSnapshot());
|
|
121
|
+
const timer = hostWindow.setInterval(() => setSnapshot(readSnapshot()), 100);
|
|
122
|
+
return () => hostWindow.clearInterval(timer);
|
|
123
|
+
}, [open]);
|
|
119
124
|
const capture = useCallback(() => {
|
|
120
125
|
const geometry = devTools()?.geometry;
|
|
121
126
|
if (typeof geometry !== "function" || capturing) return;
|
|
@@ -520,12 +525,30 @@ function UiLayer({ children }) {
|
|
|
520
525
|
] });
|
|
521
526
|
}
|
|
522
527
|
function useUiState(selector) {
|
|
523
|
-
|
|
528
|
+
return useMirrorState("useUiState", true, selector);
|
|
529
|
+
}
|
|
530
|
+
var reportedOverrides = /* @__PURE__ */ new Set();
|
|
531
|
+
function useUiStateDuringStartup(options, selector) {
|
|
532
|
+
const reason = options.reason;
|
|
533
|
+
if (typeof reason !== "string" || reason.trim().length === 0) {
|
|
534
|
+
throw new Error(
|
|
535
|
+
"TN_UI_STARTUP_OVERRIDE_REASON: useUiStateDuringStartup needs a non-empty reason."
|
|
536
|
+
);
|
|
537
|
+
}
|
|
538
|
+
if (!reportedOverrides.has(reason)) {
|
|
539
|
+
reportedOverrides.add(reason);
|
|
540
|
+
console.info(`TN_UI_STARTUP_OVERRIDE ${reason}`);
|
|
541
|
+
}
|
|
542
|
+
return useMirrorState("useUiStateDuringStartup", false, selector);
|
|
543
|
+
}
|
|
544
|
+
function useMirrorState(name, hideWhileCovered, selector) {
|
|
545
|
+
const { mirror } = useUiLayer(name);
|
|
524
546
|
const selectorRef = useRef(selector);
|
|
525
547
|
selectorRef.current = selector;
|
|
526
548
|
return useSyncExternalStore(
|
|
527
549
|
(onChange) => mirror.subscribe(onChange),
|
|
528
550
|
() => {
|
|
551
|
+
if (hideWhileCovered && mirror.covered()) return void 0;
|
|
529
552
|
const state = mirror.get();
|
|
530
553
|
if (state === void 0) return void 0;
|
|
531
554
|
return selectorRef.current === void 0 ? state : selectorRef.current(state);
|
|
@@ -541,4 +564,4 @@ function useUiIntent() {
|
|
|
541
564
|
);
|
|
542
565
|
}
|
|
543
566
|
|
|
544
|
-
export { DebugOverlay, GameCanvas, UiLayer, useGameState, useUiIntent, useUiState };
|
|
567
|
+
export { DebugOverlay, GameCanvas, UiLayer, useGameState, useUiIntent, useUiState, useUiStateDuringStartup };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@threenative/ui",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.8",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "React bindings for mounting a ThreeNative game and reading throttled state.",
|
|
6
6
|
"keywords": [
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
},
|
|
42
42
|
"sideEffects": false,
|
|
43
43
|
"peerDependencies": {
|
|
44
|
-
"@threenative/core": ">=0.3.
|
|
44
|
+
"@threenative/core": ">=0.3.8 <0.4.0",
|
|
45
45
|
"react": ">=19.2.0 <20",
|
|
46
46
|
"react-dom": ">=19.2.0 <20"
|
|
47
47
|
},
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"tsup": "8.5.1",
|
|
57
57
|
"typescript": "npm:@typescript/typescript6@6.0.2",
|
|
58
58
|
"@typescript/native": "npm:typescript@7.0.2",
|
|
59
|
-
"@threenative/core": "0.3.
|
|
59
|
+
"@threenative/core": "0.3.8"
|
|
60
60
|
},
|
|
61
61
|
"scripts": {
|
|
62
62
|
"build": "tsup --config tsup.config.ts && publint",
|