@oasiz/sdk 1.5.6 → 1.6.0

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 CHANGED
@@ -1,65 +1,47 @@
1
- # Oasiz game SDKs
1
+ # @oasiz/sdk
2
2
 
3
- Games on Oasiz can integrate using either of these official SDKs:
3
+ Typed SDK for integrating games with the Oasiz platform. Handles score submission, haptic feedback, cross-session state persistence, multiplayer room codes, navigation hooks, and app lifecycle events for local development.
4
4
 
5
- | Platform | Package | Use for |
6
- | --- | --- | --- |
7
- | **HTML5 / TypeScript** | [`@oasiz/sdk`](#html5--typescript-oasizsdk) (npm) | Canvas, Phaser, custom JS/TS, any browser game |
8
- | **Unity WebGL** | [Unity runtime](#unity-webgl-sdk) in this repo (`packages/OasizSDK/`) | Unity projects targeting WebGL |
9
-
10
- Both talk to the same host bridges (`window.submitScore`, `__oasizLeaveGame`, layout APIs, custom DOM events such as `oasiz:pause`, etc.). Unsupported hosts no-op safely; local dev usually logs warnings instead of crashing.
11
-
12
- ---
13
-
14
- ## HTML5 / TypeScript (`@oasiz/sdk`)
15
-
16
- Typed SDK for integrating browser games with the Oasiz platform: score, haptics, cross-session state, multiplayer hooks, layout (safe area, leaderboard visibility), navigation (back / leave), and lifecycle events.
17
-
18
- ### Install
5
+ ## Install
19
6
 
20
7
  ```bash
21
- npm install @oasiz/sdk
8
+ npm install @oasiz/sdk@^0.1.0
22
9
  ```
23
10
 
24
- The published package includes ESM, CommonJS, and TypeScript declarations.
25
-
26
11
  ## Quick start
27
12
 
28
13
  ```ts
29
14
  import { oasiz } from "@oasiz/sdk";
30
15
 
31
- // 1. Load persisted state at the start of each session
16
+ // 1. Emit score normalization config once on init
17
+ oasiz.emitScoreConfig({
18
+ anchors: [
19
+ { raw: 30, normalized: 100 },
20
+ { raw: 60, normalized: 300 },
21
+ { raw: 120, normalized: 600 },
22
+ { raw: 300, normalized: 950 },
23
+ ],
24
+ });
25
+
26
+ // 2. Load persisted state at the start of each session
32
27
  const state = oasiz.loadGameState();
33
28
  let level = typeof state.level === "number" ? state.level : 1;
34
29
 
35
- // 2. Save state at checkpoints
30
+ // 3. Save state at checkpoints
36
31
  oasiz.saveGameState({ level, coins: 42 });
37
32
 
38
- // 3. Trigger haptics on key events
33
+ // 4. Trigger haptics on key events
39
34
  oasiz.triggerHaptic("medium");
40
35
 
41
- // 4. Respect the host's top safe area (percent of viewport height → CSS vh)
42
- document.documentElement.style.setProperty(
43
- "--safe-top",
44
- `${oasiz.safeAreaTop}vh`,
45
- );
46
-
47
36
  // 5. Submit score when the game ends
48
37
  oasiz.submitScore(score);
49
-
50
- // 6. Optionally hide the leaderboard while a custom overlay is open
51
- oasiz.setLeaderboardVisible(false);
52
-
53
- // 7. Optionally surface console logs in-game while debugging
54
- oasiz.enableLogOverlay({
55
- enabled: new URLSearchParams(window.location.search).has("oasizLogs"),
56
- collapsed: true,
57
- });
58
38
  ```
59
39
 
60
- ### Score
40
+ ---
41
+
42
+ ## Score
61
43
 
62
- #### `oasiz.submitScore(score: number)`
44
+ ### `oasiz.submitScore(score: number)`
63
45
 
64
46
  Submit the player's final score at game over. Call this exactly once per session, when the game ends. The platform handles leaderboard persistence — do not track high scores locally.
65
47
 
@@ -72,9 +54,39 @@ private onGameOver(): void {
72
54
  - `score` must be a non-negative integer. Floats are floored automatically.
73
55
  - Do not call on intermediate scores or level completions, only on final game over.
74
56
 
75
- ### Haptics
57
+ ---
58
+
59
+ ### `oasiz.emitScoreConfig(config)`
76
60
 
77
- #### `oasiz.triggerHaptic(type: HapticType)`
61
+ Maps raw score values to the platform's normalized 0–1000 scale. Call once during initialization, not every frame.
62
+
63
+ ```ts
64
+ oasiz.emitScoreConfig({
65
+ anchors: [
66
+ { raw: 10, normalized: 100 }, // beginner
67
+ { raw: 30, normalized: 300 }, // good
68
+ { raw: 75, normalized: 600 }, // great
69
+ { raw: 200, normalized: 950 }, // godlike
70
+ ],
71
+ });
72
+ ```
73
+
74
+ **Anchor rules:**
75
+ - Exactly 4 anchors required.
76
+ - `raw` values must be strictly increasing.
77
+ - `normalized` values must end at exactly `950`.
78
+ - Choose thresholds based on realistic player skill bands.
79
+
80
+ **Practical guidance by game type:**
81
+ - Survival / time games → use seconds survived as `raw`
82
+ - Score accumulation games → use points as `raw`
83
+ - Puzzle games → use level reached or stars earned as `raw`
84
+
85
+ ---
86
+
87
+ ## Haptics
88
+
89
+ ### `oasiz.triggerHaptic(type: HapticType)`
78
90
 
79
91
  Trigger native haptic feedback. Always guard with the user's haptics setting.
80
92
 
@@ -83,7 +95,7 @@ type HapticType = "light" | "medium" | "heavy" | "success" | "error";
83
95
  ```
84
96
 
85
97
  | Type | When to use |
86
- | --- | --- |
98
+ |---|---|
87
99
  | `"light"` | UI button taps, menu navigation, D-pad press |
88
100
  | `"medium"` | Collecting items, standard collisions, scoring |
89
101
  | `"heavy"` | Explosions, major impacts, screen shake |
@@ -114,45 +126,20 @@ private onGameOver(): void {
114
126
 
115
127
  Haptics are throttled internally (50ms cooldown) to prevent spam.
116
128
 
117
- ### Debugging
118
-
119
- #### `oasiz.enableLogOverlay(options?: LogOverlayOptions)`
120
-
121
- Mount an opt-in in-game console viewer for local debugging, QA sessions, or creator support. It mirrors `console.log`, `console.info`, `console.warn`, `console.error`, and `console.debug` into a floating overlay inside the game iframe. The overlay can be collapsed, repositioned by dragging the top bar, and resized from the bottom-right corner while the action buttons remain clickable.
122
-
123
- ```ts
124
- const logOverlay = oasiz.enableLogOverlay({
125
- enabled: new URLSearchParams(window.location.search).has("oasizLogs"),
126
- collapsed: true,
127
- });
128
-
129
- console.log("[Boot] Scene ready");
130
-
131
- // Optional cleanup if your game tears down and remounts
132
- logOverlay.destroy();
133
- ```
134
-
135
- Options:
136
-
137
- - `enabled`: defaults to `true`. Pass your own flag or query-param check here.
138
- - `collapsed`: start with only the toggle pill visible.
139
- - `maxEntries`: cap retained log lines. Defaults to `200`.
140
- - `title`: optional label shown at the top of the panel. Defaults to `SDK Logs`.
141
-
142
- The returned handle supports `show()`, `hide()`, `clear()`, `isVisible()`, and `destroy()`.
129
+ ---
143
130
 
144
- ### Game state persistence
131
+ ## Game state persistence
145
132
 
146
133
  Persist cross-session data such as unlocked levels, inventory, or lifetime stats. State is stored per-user per-game in the Oasiz backend — available across devices and app reinstalls.
147
134
 
148
- #### `oasiz.loadGameState(): Record<string, unknown>`
135
+ ### `oasiz.loadGameState(): Record<string, unknown>`
149
136
 
150
137
  Returns the player's saved state synchronously. Returns `{}` if no state has been saved yet. Call once at the start of the game.
151
138
 
152
139
  ```ts
153
140
  private initFromSavedState(): void {
154
141
  const state = oasiz.loadGameState();
155
- this.level = typeof state.level === "number" ? state.level : 1;
142
+ this.level = typeof state.level === "number" ? state.level : 1;
156
143
  this.lifetimeHits = typeof state.lifetimeHits === "number" ? state.lifetimeHits : 0;
157
144
  this.unlockedSkins = Array.isArray(state.unlockedSkins) ? state.unlockedSkins : [];
158
145
  }
@@ -160,7 +147,7 @@ private initFromSavedState(): void {
160
147
 
161
148
  Always validate the shape of loaded data — it may be `{}` on first play.
162
149
 
163
- #### `oasiz.saveGameState(state: Record<string, unknown>)`
150
+ ### `oasiz.saveGameState(state: Record<string, unknown>)`
164
151
 
165
152
  Queues a debounced save. Saves are batched automatically — call freely at checkpoints without worrying about request spam.
166
153
 
@@ -177,12 +164,11 @@ private onLevelComplete(): void {
177
164
  ```
178
165
 
179
166
  **Rules:**
180
-
181
167
  - State must be a plain JSON object (not an array or primitive).
182
168
  - Do not use `localStorage` for cross-session progress — use `saveGameState` so data syncs across platforms.
183
169
  - Do not store scores here — scores are submitted via `submitScore`.
184
170
 
185
- #### `oasiz.flushGameState()`
171
+ ### `oasiz.flushGameState()`
186
172
 
187
173
  Forces an immediate write, bypassing the debounce. Use at important checkpoints like game over or before the page unloads.
188
174
 
@@ -194,88 +180,19 @@ private onGameOver(): void {
194
180
  }
195
181
  ```
196
182
 
197
- ### Layout
198
-
199
- Use runtime viewport insets instead of direct CSS `env(safe-area-inset-*)` reads or hardcoded offsets. The SDK resolves host-provided Oasiz values first, then browser CSS `env(safe-area-inset-*)`, then legacy `constant(safe-area-inset-*)`, and finally `0`.
200
-
201
- The top inset preserves the existing Oasiz game-safe top behavior: host chrome, invite UI, and leaderboard clearance can contribute to it. Left, right, and bottom are device safe-area insets today and may include future host UI obstructions.
202
-
203
- #### `oasiz.getViewportInsets(): ViewportInsets`
204
-
205
- Returns effective viewport insets in both CSS pixels and normalized percentages:
206
-
207
- ```ts
208
- const insets = oasiz.getViewportInsets();
209
- hud.style.paddingTop = `${insets.pixels.top}px`;
210
- hud.style.paddingRight = `${insets.pixels.right}px`;
211
- hud.style.paddingBottom = `${insets.pixels.bottom}px`;
212
- hud.style.paddingLeft = `${insets.pixels.left}px`;
213
- ```
214
-
215
- Percentages use the matching active viewport axis:
216
-
217
- - `top` / `bottom` are percentages of viewport height
218
- - `left` / `right` are percentages of viewport width
219
-
220
- Hosts may expose pixels via `window.getViewportInsets()` or `window.__OASIZ_VIEWPORT_INSETS__`, for example `{ top, right, bottom, left }` or `{ pixels: { top, right, bottom, left } }`. Hosts may expose percentages via `window.getViewportInsetsPercent()`, `window.__OASIZ_VIEWPORT_INSETS_PERCENT__`, or a `percent` object. Per-side globals such as `window.__OASIZ_SAFE_AREA_BOTTOM__` are also supported.
221
-
222
- #### `oasiz.getSafeAreaTop(): number`
223
-
224
- Legacy alias for `oasiz.getViewportInsets().percent.top`. Returns the top inset as a percentage of viewport height (0–100). To get pixels in JavaScript, prefer `oasiz.getViewportInsets().pixels.top`. In CSS, the percent value matches **`vh`** units (for example `12.5vh` for 12.5% of the viewport height). Unsupported hosts return `0`.
225
-
226
- ```ts
227
- const safeTopPct = oasiz.getSafeAreaTop();
228
- document.documentElement.style.setProperty("--safe-top", `${safeTopPct}vh`);
229
- ```
230
-
231
- #### `oasiz.safeAreaTop`
232
-
233
- Getter alias for `getSafeAreaTop()`.
234
-
235
- #### `oasiz.viewportInsets`
236
-
237
- Getter alias for `getViewportInsets()`.
238
-
239
- Recommended CSS pattern:
240
-
241
- ```css
242
- :root {
243
- --safe-top: 0px;
244
- }
245
-
246
- #top-bar {
247
- padding-top: var(--safe-top);
248
- }
249
- ```
250
-
251
- #### `oasiz.setLeaderboardVisible(visible: boolean): void`
252
-
253
- Show or hide the host leaderboard UI from inside the game. This only affects the leaderboard; back and social controls remain visible. Calls `window.__oasizSetLeaderboardVisible` when present.
254
-
255
- ```ts
256
- function openCustomOverlay(): void {
257
- oasiz.setLeaderboardVisible(false);
258
- }
259
-
260
- function closeCustomOverlay(): void {
261
- oasiz.setLeaderboardVisible(true);
262
- }
263
- ```
264
-
265
- Unsupported hosts safely no-op.
183
+ ---
266
184
 
267
- ### Lifecycle
185
+ ## Lifecycle
268
186
 
269
187
  The platform dispatches lifecycle events when the app goes to the background or returns to the foreground. Subscribe to pause game loops and audio accordingly.
270
188
 
271
- #### `oasiz.onPause(callback: () => void): Unsubscribe`
272
-
273
- #### `oasiz.onResume(callback: () => void): Unsubscribe`
189
+ ### `oasiz.onPause(callback: () => void): Unsubscribe`
190
+ ### `oasiz.onResume(callback: () => void): Unsubscribe`
274
191
 
275
192
  Both return an unsubscribe function.
276
193
 
277
194
  ```ts
278
- const offPause = oasiz.onPause(() => {
195
+ const offPause = oasiz.onPause(() => {
279
196
  this.gameLoop.stop();
280
197
  this.bgMusic.pause();
281
198
  });
@@ -290,17 +207,19 @@ offPause();
290
207
  offResume();
291
208
  ```
292
209
 
293
- ### Navigation
210
+ ---
211
+
212
+ ## Navigation
294
213
 
295
214
  Use navigation hooks when your game needs to control back behavior (Android back / web Escape) or participate in host-driven close events.
296
215
 
297
- #### `oasiz.onBackButton(callback: () => void): Unsubscribe`
216
+ ### `oasiz.onBackButton(callback: () => void): Unsubscribe`
298
217
 
299
218
  Registers a callback for platform back actions. While at least one back listener is subscribed, back actions are routed to your game instead of immediately closing it.
300
219
 
301
220
  Use this for pause menus, in-game overlays, or custom back-stack behavior.
302
221
 
303
- **If your callback throws**, the SDK calls `leaveGame()` (host close) and **rethrows** the error so you still see it in devtools or error reporting. Non-`Error` throws are normalized to an `Error` (strings become the message; otherwise `"Back button callback failed."`).
222
+ If your callback throws, Oasiz falls back to closing the game and returning the player to Oasiz home before rethrowing the error for debugging/reporting.
304
223
 
305
224
  ```ts
306
225
  const offBack = oasiz.onBackButton(() => {
@@ -315,7 +234,7 @@ const offBack = oasiz.onBackButton(() => {
315
234
  offBack();
316
235
  ```
317
236
 
318
- #### `oasiz.leaveGame(): void`
237
+ ### `oasiz.leaveGame(): void`
319
238
 
320
239
  Programmatically request the host to close the current game (for example, from a Quit button inside your game UI).
321
240
 
@@ -350,14 +269,14 @@ const offLeave = oasiz.onLeaveGame(() => {
350
269
  offLeave();
351
270
  ```
352
271
 
353
- ### Multiplayer
272
+ ---
273
+
274
+ ## Multiplayer
354
275
 
355
- #### `oasiz.shareRoomCode(code: string | null, options?: { inviteOverride?: boolean })`
276
+ ### `oasiz.shareRoomCode(code: string | null)`
356
277
 
357
278
  Notify the platform of the active multiplayer room so friends can join via the invite system. Pass `null` when leaving a room.
358
279
 
359
- Set `inviteOverride: true` when your game wants to hide the platform invite pill and render its own invite button/UI. The platform still tracks the room code, but your game owns the invite entry point.
360
-
361
280
  ```ts
362
281
  import { insertCoin, getRoomCode } from "playroomkit";
363
282
  import { oasiz } from "@oasiz/sdk";
@@ -369,26 +288,7 @@ oasiz.shareRoomCode(getRoomCode());
369
288
  oasiz.shareRoomCode(null);
370
289
  ```
371
290
 
372
- ```ts
373
- // Game-owned invite UI: hide the platform pill, keep room tracking
374
- oasiz.shareRoomCode(getRoomCode(), { inviteOverride: true });
375
- ```
376
-
377
- #### `oasiz.openInviteModal(): void`
378
-
379
- Opens the platform invite-friends UI when the bridge is available. Typically used together with `shareRoomCode` (for example, your own invite button calls this).
380
-
381
- ```ts
382
- import { openInviteModal, shareRoomCode } from "@oasiz/sdk";
383
-
384
- shareRoomCode("ABCD", { inviteOverride: true });
385
-
386
- inviteButton.addEventListener("click", () => {
387
- openInviteModal();
388
- });
389
- ```
390
-
391
- #### Read-only injected values
291
+ ### Read-only injected values
392
292
 
393
293
  These are populated by the platform before the game loads. Always check for `undefined` before using.
394
294
 
@@ -402,28 +302,25 @@ if (oasiz.roomCode) {
402
302
  }
403
303
 
404
304
  // Player identity for multiplayer games
405
- const name = oasiz.playerName;
305
+ const name = oasiz.playerName;
406
306
  const avatar = oasiz.playerAvatar;
407
307
  ```
408
308
 
409
- ### Named exports
309
+ ---
310
+
311
+ ## Named exports
410
312
 
411
313
  All methods are also available as named exports if you prefer not to use the `oasiz` namespace object:
412
314
 
413
315
  ```ts
414
316
  import {
415
317
  submitScore,
416
- share,
318
+ emitScoreConfig,
417
319
  triggerHaptic,
418
320
  loadGameState,
419
321
  saveGameState,
420
322
  flushGameState,
421
323
  shareRoomCode,
422
- openInviteModal,
423
- enableLogOverlay,
424
- getSafeAreaTop,
425
- getViewportInsets,
426
- setLeaderboardVisible,
427
324
  onPause,
428
325
  onResume,
429
326
  onBackButton,
@@ -436,200 +333,18 @@ import {
436
333
  } from "@oasiz/sdk";
437
334
  ```
438
335
 
439
- ### TypeScript types
440
-
441
- ```ts
442
- import type {
443
- GameState,
444
- HapticType,
445
- LogOverlayEntry,
446
- LogOverlayHandle,
447
- LogOverlayLevel,
448
- LogOverlayOptions,
449
- ShareRequest,
450
- ShareRoomCodeOptions,
451
- Unsubscribe,
452
- } from "@oasiz/sdk";
453
- ```
454
-
455
336
  ---
456
337
 
457
- ## Unity WebGL SDK
458
-
459
- C# API and **WebGL-only** `OasizBridge.jslib` live in this repository at **`packages/OasizSDK/`**. Copy the **`OasizSDK`** folder into your Unity project under **`Assets/`** (for example `Assets/OasizSDK`).
460
-
461
- ### Setup
462
-
463
- 1. Copy `packages/OasizSDK` from this repo into `Assets/OasizSDK`.
464
- 2. Ensure the **WebGL** platform is selected for release builds; the `.jslib` under `Runtime/Plugins/WebGL/` is included automatically for WebGL.
465
- 3. Add an **`OasizSDK`** component to a persistent GameObject early (for example a bootstrap scene), **or** rely on `OasizSDK.Instance` which creates a `DontDestroyOnLoad` object. The component registers listeners for `oasiz:pause`, `oasiz:resume`, `oasiz:back`, and `oasiz:leave` via `SendMessage`.
466
-
467
- ### Quick start
468
-
469
- ```csharp
470
- using Oasiz;
471
- using UnityEngine;
472
-
473
- public class GameManager : MonoBehaviour
474
- {
475
- void Start()
476
- {
477
- // Ensure the singleton is initialized early
478
- _ = OasizSDK.Instance;
479
-
480
- // Subscribe to lifecycle events
481
- OasizSDK.OnPause += OnPause;
482
- OasizSDK.OnResume += OnResume;
483
-
484
- // Offset UI for the host's top safe area (0–100 percent of Screen.height)
485
- float safeTopPct = OasizSDK.SafeAreaTop;
486
- float safeTopPx = safeTopPct / 100f * Screen.height;
487
- Debug.Log($"Safe area top: {safeTopPx}px ({safeTopPct}% of height)");
488
-
489
- // Emit score normalization anchors
490
- OasizSDK.EmitScoreConfig(new ScoreConfig(
491
- new ScoreAnchor(10, 100),
492
- new ScoreAnchor(30, 300),
493
- new ScoreAnchor(75, 600),
494
- new ScoreAnchor(200, 950)
495
- ));
496
- }
497
-
498
- void OnGameOver(int finalScore)
499
- {
500
- OasizSDK.SubmitScore(finalScore);
501
- OasizSDK.FlushGameState();
502
- OasizSDK.SetLeaderboardVisible(true);
503
- }
504
-
505
- void OnGameplayStart()
506
- {
507
- OasizSDK.SetLeaderboardVisible(false);
508
- }
509
-
510
- void OnPause() => Time.timeScale = 0f;
511
- void OnResume() => Time.timeScale = 1f;
512
-
513
- void OnDestroy()
514
- {
515
- OasizSDK.OnPause -= OnPause;
516
- OasizSDK.OnResume -= OnResume;
517
- }
518
- }
519
- ```
520
-
521
- ### API parity (TypeScript → C#)
522
-
523
- | HTML5 (`@oasiz/sdk`) | Unity (`Oasiz` namespace) |
524
- | --- | --- |
525
- | `oasiz.submitScore(n)` | `OasizSDK.SubmitScore(int)` |
526
- | `oasiz.triggerHaptic(type)` | `OasizSDK.TriggerHaptic(HapticType)` |
527
- | `oasiz.loadGameState()` | `OasizSDK.LoadGameState()` → `Dictionary<string, object>` |
528
- | `oasiz.saveGameState(obj)` | `OasizSDK.SaveGameState(Dictionary<string, object>)` |
529
- | `oasiz.flushGameState()` | `OasizSDK.FlushGameState()` |
530
- | `oasiz.getViewportInsets()` / `viewportInsets` | `OasizSDK.GetViewportInsets()` (`ViewportInsets`, each side 0–100, % of matching viewport axis) |
531
- | `oasiz.getSafeAreaTop()` / `safeAreaTop` | `OasizSDK.GetSafeAreaTop()` / `OasizSDK.SafeAreaTop` (`float`, 0–100, % of viewport height; legacy alias for top viewport inset) |
532
- | `oasiz.setLeaderboardVisible(v)` | `OasizSDK.SetLeaderboardVisible(bool)` |
533
- | `oasiz.onPause` / `onResume` | `OasizSDK.OnPause` / `OnResume` static events |
534
- | `oasiz.onBackButton` | `OasizSDK.OnBackButton` or `SubscribeBackButton(Action)` (reference-counts `__oasizSetBackOverride`) |
535
- | `oasiz.onLeaveGame` | `OasizSDK.OnLeaveGame` |
536
- | `oasiz.leaveGame()` | `OasizSDK.LeaveGame()` |
537
- | `oasiz.share(request)` | `OasizSDK.Share(ShareRequest)` |
538
- | `oasiz.shareRoomCode` | `OasizSDK.ShareRoomCode(string, ShareRoomCodeOptions)` |
539
- | `oasiz.openInviteModal()` | `OasizSDK.OpenInviteModal()` |
540
- | `oasiz.gameId` / `roomCode` / ... | `OasizSDK.GameId` / `RoomCode` / `PlayerName` / `PlayerAvatar` |
541
- | -- | `OasizSDK.EmitScoreConfig(ScoreConfig)` → `window.emitScoreConfig` (Unity-only helper for normalized score UI) |
542
- | `oasiz.enableLogOverlay` | `OasizSDK.EnableLogOverlay(LogOverlayOptions)` (see note below) |
543
- | -- | `OasizSDK.AppendLogOverlay(level, message, stackTrace)` (see note below) |
544
-
545
- ### Share (Unity)
546
-
547
- HTML5 **`oasiz.share`** returns a **Promise** you can `await`. Unity **`OasizSDK.Share(ShareRequest)`** returns **`void`**: C# validation throws **`ArgumentException`** with the same rules as TypeScript (at least one of text, score, or image; non-negative integer score; `http(s)` or `data:image/...;base64,...` image). The call forwards JSON to **`window.__oasizShareRequest`**. If the host promise rejects, the **WebGL `.jslib` logs the error** to the browser console.
548
-
549
- ```csharp
550
- OasizSDK.Share(new ShareRequest
551
- {
552
- Text = "Beat this run!",
553
- Score = 1200,
554
- Image = "https://example.com/card.png",
555
- });
556
- ```
557
-
558
- ### Types
559
-
560
- ```csharp
561
- // Haptic feedback intensity
562
- public enum HapticType { Light, Medium, Heavy, Success, Error }
563
-
564
- // Score normalization (exactly 4 anchors required)
565
- public struct ScoreAnchor { public int raw; public int normalized; }
566
- public struct ScoreConfig { public ScoreAnchor[] anchors; }
567
-
568
- // Host share sheet (text / score / image URL or data URL)
569
- public class ShareRequest
570
- {
571
- public string Text { get; set; }
572
- public int? Score { get; set; }
573
- public string Image { get; set; }
574
- }
575
-
576
- // Multiplayer invite options
577
- public class ShareRoomCodeOptions { public bool InviteOverride { get; set; } }
578
-
579
- // Log overlay configuration
580
- public class LogOverlayOptions
581
- {
582
- public bool Enabled { get; set; } = true;
583
- public bool Collapsed { get; set; } = false;
584
- public int MaxEntries { get; set; } = 200;
585
- public string Title { get; set; } = "SDK Logs";
586
- }
587
-
588
- // Log overlay lifecycle handle
589
- public class LogOverlayHandle
590
- {
591
- public void Clear();
592
- public void Hide();
593
- public void Show();
594
- public bool IsVisible();
595
- public void Destroy();
596
- }
597
- ```
598
-
599
- ### Back button and errors
600
-
601
- Matching the HTML5 SDK: if any **`OnBackButton`** handler throws, **`OasizSDK.LeaveGame()`** is invoked and the **original exception is rethrown** (`throw;` preserves the stack trace). Use **`SubscribeBackButton`** when you want an unsubscribe delegate; you can also use `OnBackButton +=` / `-=` directly.
338
+ ## TypeScript types
602
339
 
603
- ```csharp
604
- // Subscribe with automatic unsubscribe support
605
- var offBack = OasizSDK.SubscribeBackButton(() =>
606
- {
607
- if (isPaused)
608
- Resume();
609
- else
610
- Pause();
611
- });
612
-
613
- // Unsubscribe when no longer needed
614
- offBack();
340
+ ```ts
341
+ import type { HapticType, ScoreConfig, ScoreAnchor, GameState } from "@oasiz/sdk";
615
342
  ```
616
343
 
617
- ### Editor vs WebGL builds
618
-
619
- In the **Unity Editor**, bridge calls are mostly **logged** and return safe defaults (for example safe area `0`, `null` platform IDs). Real host integration applies to **WebGL player** builds running inside Oasiz.
620
-
621
- ### Log overlay (Unity)
622
-
623
- The C# API for the log overlay exists for API compatibility, but the **default `OasizBridge.jslib` in this repo does not inject DOM UI** — `EnableLogOverlay` / `AppendLogOverlay` are no-ops at the JavaScript layer. Use Unity's console and device logs for debugging unless you replace or extend the `.jslib` on your side.
624
-
625
- `AppendLogOverlay(level, message, stackTrace)` lets you pipe `Debug.Log` output into the overlay manually, since many embedded WebViews do not route Unity player logs through `console.log`. Valid levels: `"debug"`, `"log"`, `"info"`, `"warn"`, `"error"`.
626
-
627
344
  ---
628
345
 
629
346
  ## Local development
630
347
 
631
- ### HTML5 / TypeScript
632
-
633
348
  All methods safely no-op when the platform bridges are not injected. In development mode a console warning is logged so you know the call was made:
634
349
 
635
350
  ```
@@ -637,7 +352,3 @@ All methods safely no-op when the platform bridges are not injected. In developm
637
352
  ```
638
353
 
639
354
  No crashes, no special setup required for local dev.
640
-
641
- ### Unity WebGL
642
-
643
- The `.jslib` logs warnings when `window.*` bridges are missing (for example `submitScore`, `__oasizLeaveGame`). The Editor path avoids calling native plugins and prints `Debug.Log` for most operations instead.