@wvdsh/sdk-js 1.3.18 → 1.3.20

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 CHANGED
@@ -665,16 +665,18 @@ declare class LobbyManager extends WavedashManager {
665
665
  * Owns the iframe ↔ parent interactions for the Wavedash overlay UI:
666
666
  * - Shift+Tab inside the iframe toggles the overlay on the host page
667
667
  * (the host owns the overlay, so we postMessage up).
668
- * - When the parent closes the overlay it sends TAKE_FOCUS so keyboard
669
- * input goes back to the game; we walk the DOM for a focusable target.
670
- * - `takeFocus()` is also called after load completes so the game starts
671
- * with keyboard focus without the player clicking first.
668
+ * - When the parent closes the overlay it sends TAKE_FOCUS, which hands
669
+ * keyboard focus back to the game (see `takeFocus`).
670
+ * - While the overlay is open we suspend pointer lock (the host broadcasts
671
+ * OVERLAY_CHANGED) so a game can't hold/re-grab the cursor behind it.
672
672
  */
673
673
  declare class OverlayManager extends WavedashManager {
674
+ private restorePointerLock;
674
675
  constructor(sdk: WavedashSDK);
676
+ private setOpen;
675
677
  toggleOverlay(): void;
676
- takeFocus(): void;
677
678
  private handleKeyDown;
679
+ destroy(): void;
678
680
  }
679
681
 
680
682
  /**
@@ -795,9 +797,13 @@ declare class P2PManager extends WavedashManager {
795
797
  }
796
798
 
797
799
  declare class PaidContentManager extends WavedashManager {
800
+ private paywallOpen;
801
+ private restorePointerLock;
798
802
  isEntitled(contentId: string): Promise<boolean>;
799
803
  getEntitlements(): Promise<string[]>;
800
804
  triggerPaywall(contentIdentifier: string): Promise<boolean>;
805
+ isPaywallOpen(): boolean;
806
+ destroy(): void;
801
807
  }
802
808
 
803
809
  declare class StatsManager extends WavedashManager {
package/dist/index.js CHANGED
@@ -1849,6 +1849,44 @@ var LobbyManager = _LobbyManager;
1849
1849
 
1850
1850
  // src/services/overlay.ts
1851
1851
  import { IFRAME_MESSAGE_TYPE as IFRAME_MESSAGE_TYPE5 } from "@wvdsh/api";
1852
+
1853
+ // src/utils/focus.ts
1854
+ function takeFocus() {
1855
+ if (typeof document === "undefined") return;
1856
+ const gameFocusTargets = document.getElementsByClassName("game-focus-target");
1857
+ if (gameFocusTargets.length > 0) {
1858
+ gameFocusTargets[0].focus();
1859
+ return;
1860
+ }
1861
+ const focusableElement = document.querySelector(
1862
+ "canvas, input, button, [tabindex]:not([tabindex='-1'])"
1863
+ );
1864
+ focusableElement?.focus();
1865
+ }
1866
+
1867
+ // src/utils/pointerLock.ts
1868
+ var hasDom = typeof Element !== "undefined" && typeof document !== "undefined";
1869
+ var nativeRequestPointerLock = hasDom ? Element.prototype.requestPointerLock : void 0;
1870
+ var depth = 0;
1871
+ function suspendPointerLock() {
1872
+ if (!hasDom || !nativeRequestPointerLock) return () => {
1873
+ };
1874
+ if (++depth === 1) {
1875
+ Element.prototype.requestPointerLock = function() {
1876
+ return Promise.resolve();
1877
+ };
1878
+ }
1879
+ document.exitPointerLock();
1880
+ let disposed = false;
1881
+ return () => {
1882
+ if (disposed) return;
1883
+ disposed = true;
1884
+ if (--depth === 0)
1885
+ Element.prototype.requestPointerLock = nativeRequestPointerLock;
1886
+ };
1887
+ }
1888
+
1889
+ // src/services/overlay.ts
1852
1890
  var OverlayManager = class extends WavedashManager {
1853
1891
  constructor(sdk) {
1854
1892
  super(sdk);
@@ -1860,29 +1898,36 @@ var OverlayManager = class extends WavedashManager {
1860
1898
  };
1861
1899
  this.sdk.iframeMessenger.addEventListener(
1862
1900
  IFRAME_MESSAGE_TYPE5.TAKE_FOCUS,
1863
- () => this.takeFocus()
1901
+ takeFocus
1902
+ );
1903
+ this.sdk.iframeMessenger.addEventListener(
1904
+ IFRAME_MESSAGE_TYPE5.OVERLAY_CHANGED,
1905
+ ({ isOpen }) => this.setOpen(isOpen)
1864
1906
  );
1865
1907
  if (typeof window !== "undefined") {
1866
1908
  window.addEventListener("keydown", this.handleKeyDown);
1867
1909
  }
1868
1910
  }
1911
+ setOpen(open) {
1912
+ if (open) {
1913
+ this.restorePointerLock ?? (this.restorePointerLock = suspendPointerLock());
1914
+ } else {
1915
+ this.restorePointerLock?.();
1916
+ this.restorePointerLock = void 0;
1917
+ }
1918
+ }
1869
1919
  toggleOverlay() {
1870
1920
  this.sdk.iframeMessenger.postToParent(
1871
1921
  IFRAME_MESSAGE_TYPE5.TOGGLE_OVERLAY,
1872
1922
  {}
1873
1923
  );
1874
1924
  }
1875
- takeFocus() {
1876
- if (typeof document === "undefined") return;
1877
- const gameFocusTargets = document.getElementsByClassName("game-focus-target");
1878
- if (gameFocusTargets.length > 0) {
1879
- gameFocusTargets[0].focus();
1880
- return;
1925
+ destroy() {
1926
+ this.restorePointerLock?.();
1927
+ this.restorePointerLock = void 0;
1928
+ if (typeof window !== "undefined") {
1929
+ window.removeEventListener("keydown", this.handleKeyDown);
1881
1930
  }
1882
- const focusableElement = document.querySelector(
1883
- "canvas, input, button, [tabindex]:not([tabindex='-1'])"
1884
- );
1885
- focusableElement?.focus();
1886
1931
  }
1887
1932
  };
1888
1933
 
@@ -3204,6 +3249,10 @@ function readEntitlementsFromJwt(jwt) {
3204
3249
  return ents.filter((e) => typeof e === "string");
3205
3250
  }
3206
3251
  var PaidContentManager = class extends WavedashManager {
3252
+ constructor() {
3253
+ super(...arguments);
3254
+ this.paywallOpen = false;
3255
+ }
3207
3256
  async isEntitled(contentId) {
3208
3257
  const jwt = await this.sdk.ensureGameplayJwt();
3209
3258
  return readEntitlementsFromJwt(jwt).includes(contentId);
@@ -3214,15 +3263,34 @@ var PaidContentManager = class extends WavedashManager {
3214
3263
  }
3215
3264
  async triggerPaywall(contentIdentifier) {
3216
3265
  if (await this.isEntitled(contentIdentifier)) return true;
3217
- const response = await this.sdk.iframeMessenger.requestFromParent(
3218
- IFRAME_MESSAGE_TYPE6.TRIGGER_PAYWALL,
3219
- { contentIdentifier },
3220
- PAYWALL_TIMEOUT_MS
3221
- );
3266
+ if (this.paywallOpen) {
3267
+ throw new Error("Paywall already in progress");
3268
+ }
3269
+ this.paywallOpen = true;
3270
+ this.restorePointerLock = suspendPointerLock();
3271
+ let response;
3272
+ try {
3273
+ response = await this.sdk.iframeMessenger.requestFromParent(
3274
+ IFRAME_MESSAGE_TYPE6.TRIGGER_PAYWALL,
3275
+ { contentIdentifier },
3276
+ PAYWALL_TIMEOUT_MS
3277
+ );
3278
+ } finally {
3279
+ this.restorePointerLock?.();
3280
+ this.restorePointerLock = void 0;
3281
+ this.paywallOpen = false;
3282
+ }
3222
3283
  if (!response.purchased) return false;
3223
3284
  await this.sdk.ensureGameplayJwt(true);
3224
3285
  return true;
3225
3286
  }
3287
+ isPaywallOpen() {
3288
+ return this.paywallOpen;
3289
+ }
3290
+ destroy() {
3291
+ this.restorePointerLock?.();
3292
+ this.restorePointerLock = void 0;
3293
+ }
3226
3294
  };
3227
3295
 
3228
3296
  // src/services/stats.ts
@@ -3683,6 +3751,7 @@ var SwMessenger = class {
3683
3751
  import {
3684
3752
  IFRAME_MESSAGE_TYPE as IFRAME_MESSAGE_TYPE7,
3685
3753
  UrlParams,
3754
+ PlayRouteCaller,
3686
3755
  SERVICE_WORKER_MESSAGE_TYPE
3687
3756
  } from "@wvdsh/api";
3688
3757
 
@@ -4032,7 +4101,6 @@ var WavedashSDK = class extends EventTarget {
4032
4101
  this.gameFinishedLoading = true;
4033
4102
  this.heartbeatManager.start();
4034
4103
  iframeMessenger.postToParent(IFRAME_MESSAGE_TYPE7.LOADING_COMPLETE, {});
4035
- this.overlayManager.takeFocus();
4036
4104
  }
4037
4105
  get gameLoaded() {
4038
4106
  return this.gameFinishedLoading;
@@ -4961,7 +5029,11 @@ var WavedashSDK = class extends EventTarget {
4961
5029
  await previous.catch(() => {
4962
5030
  });
4963
5031
  }
4964
- const response = await fetch("/auth/refresh", {
5032
+ const refreshQuery = new URLSearchParams({
5033
+ [UrlParams.Caller]: PlayRouteCaller.Wavedash
5034
+ });
5035
+ const refreshPath = `/auth/refresh?${refreshQuery.toString()}`;
5036
+ const response = await fetch(refreshPath, {
4965
5037
  method: "POST",
4966
5038
  credentials: "same-origin"
4967
5039
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wvdsh/sdk-js",
3
- "version": "1.3.18",
3
+ "version": "1.3.20",
4
4
  "type": "module",
5
5
  "description": "Wavedash JavaScript SDK",
6
6
  "main": "./dist/client.js",
@@ -49,7 +49,7 @@
49
49
  "typescript-eslint": "^8.52.0"
50
50
  },
51
51
  "dependencies": {
52
- "@wvdsh/api": "^0.1.34",
52
+ "@wvdsh/api": "^0.1.36",
53
53
  "convex": "^1.39.1",
54
54
  "lodash.throttle": "^4.1.1"
55
55
  }