@mission_sciences/provider-sdk 0.3.0-dev.31ea3d4 → 0.3.0-dev.6e896da

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.
@@ -22,6 +22,7 @@ export declare function useMarketplaceSession(options?: UseMarketplaceSessionOpt
22
22
  getFormattedTime: () => string;
23
23
  getFormattedTimeWithHours: () => string;
24
24
  isTimerRunning: () => boolean;
25
+ requestPurchase: (itemId: string) => void;
25
26
  getPurchaseStateManager: () => import('../../core/PurchaseStateManager').PurchaseStateManager;
26
27
  destroy: () => void;
27
28
  } | null, MarketplaceSDK | {
@@ -38,6 +39,7 @@ export declare function useMarketplaceSession(options?: UseMarketplaceSessionOpt
38
39
  getFormattedTime: () => string;
39
40
  getFormattedTimeWithHours: () => string;
40
41
  isTimerRunning: () => boolean;
42
+ requestPurchase: (itemId: string) => void;
41
43
  getPurchaseStateManager: () => import('../../core/PurchaseStateManager').PurchaseStateManager;
42
44
  destroy: () => void;
43
45
  } | null>;
@@ -1 +1 @@
1
- {"version":3,"file":"useMarketplaceSession.d.ts","sourceRoot":"","sources":["../../../src/adapters/vue/useMarketplaceSession.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAElG,MAAM,WAAW,4BAA6B,SAAQ,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5E,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxE,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,iBAAiB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,KAAK,CAAC,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC;CAC5B;AAED,wBAAgB,qBAAqB,CAAC,OAAO,GAAE,4BAAiE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4F/G"}
1
+ {"version":3,"file":"useMarketplaceSession.d.ts","sourceRoot":"","sources":["../../../src/adapters/vue/useMarketplaceSession.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAElG,MAAM,WAAW,4BAA6B,SAAQ,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5E,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxE,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,iBAAiB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,KAAK,CAAC,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC;CAC5B;AAED,wBAAgB,qBAAqB,CAAC,OAAO,GAAE,4BAAiE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4F/G"}
@@ -22,6 +22,7 @@ export declare class MarketplaceSDK {
22
22
  private jwtToken;
23
23
  private endReason;
24
24
  private purchaseStateManager;
25
+ private purchaseModal;
25
26
  constructor(config: SDKConfig);
26
27
  /**
27
28
  * Register event handlers
@@ -99,6 +100,11 @@ export declare class MarketplaceSDK {
99
100
  * Check if timer is running
100
101
  */
101
102
  isTimerRunning(): boolean;
103
+ /**
104
+ * Request purchase of an item — opens PurchaseModal directly
105
+ * Bypasses the add-ons panel; works for any active item (visible or hidden)
106
+ */
107
+ requestPurchase(itemId: string): void;
102
108
  /**
103
109
  * Get purchase state manager for item purchase state checking
104
110
  */
@@ -1 +1 @@
1
- {"version":3,"file":"MarketplaceSDK.d.ts","sourceRoot":"","sources":["../../src/core/MarketplaceSDK.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAI9D,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAiG,MAAM,UAAU,CAAC;AAE5J;;;;;;;GAOG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,SAAS,CAAgB;IACjC,OAAO,CAAC,KAAK,CAA6B;IAC1C,OAAO,CAAC,SAAS,CAAiC;IAClD,OAAO,CAAC,OAAO,CAA+B;IAC9C,OAAO,CAAC,KAAK,CAA6B;IAC1C,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,WAAW,CAA4B;IAC/C,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,CAAC,SAAS,CAA4C;IAC7D,OAAO,CAAC,oBAAoB,CAAuB;gBAEvC,MAAM,EAAE,SAAS;IAwC7B;;OAEG;IACH,EAAE,CAAC,CAAC,SAAS,MAAM,SAAS,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,IAAI;IAKpE;;OAEG;YACW,WAAW;IAuCzB;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAO/B;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,WAAW,CAAC;IA+LxC;;OAEG;YACW,mBAAmB;IAkCjC;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAqB5B;;OAEG;IACH,OAAO,CAAC,4BAA4B;IAapC;;OAEG;IACH,UAAU,IAAI,IAAI;IAYlB;;OAEG;IACH,UAAU,IAAI,IAAI;IAMlB;;OAEG;IACH,WAAW,IAAI,IAAI;IAMnB;;OAEG;IACG,aAAa,CAAC,iBAAiB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAoE7D;;OAEG;IACG,eAAe,CAAC,kBAAkB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgDjE;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IA2DjC;;OAEG;IACH,OAAO,CAAC,gBAAgB;IA0CxB;;OAEG;IACH,cAAc,IAAI,WAAW,GAAG,IAAI;IAIpC;;OAEG;IACH,gBAAgB,IAAI,MAAM;IAI1B;;OAEG;IACH,gBAAgB,IAAI,MAAM;IAI1B;;OAEG;IACH,yBAAyB,IAAI,MAAM;IAInC;;OAEG;IACH,cAAc,IAAI,OAAO;IAIzB;;OAEG;IACH,uBAAuB,IAAI,oBAAoB;IAI/C;;OAEG;IACH,OAAO,IAAI,IAAI;CAgBhB"}
1
+ {"version":3,"file":"MarketplaceSDK.d.ts","sourceRoot":"","sources":["../../src/core/MarketplaceSDK.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAI9D,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAgI,MAAM,UAAU,CAAC;AAG3L;;;;;;;GAOG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,SAAS,CAAgB;IACjC,OAAO,CAAC,KAAK,CAA6B;IAC1C,OAAO,CAAC,SAAS,CAAiC;IAClD,OAAO,CAAC,OAAO,CAA+B;IAC9C,OAAO,CAAC,KAAK,CAA6B;IAC1C,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,WAAW,CAA4B;IAC/C,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,CAAC,SAAS,CAA4C;IAC7D,OAAO,CAAC,oBAAoB,CAAuB;IACnD,OAAO,CAAC,aAAa,CAA8B;gBAEvC,MAAM,EAAE,SAAS;IAwC7B;;OAEG;IACH,EAAE,CAAC,CAAC,SAAS,MAAM,SAAS,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,IAAI;IAKpE;;OAEG;YACW,WAAW;IAuCzB;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAO/B;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,WAAW,CAAC;IA+LxC;;OAEG;YACW,mBAAmB;IAkCjC;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAqB5B;;OAEG;IACH,OAAO,CAAC,4BAA4B;IAapC;;OAEG;IACH,UAAU,IAAI,IAAI;IAYlB;;OAEG;IACH,UAAU,IAAI,IAAI;IAMlB;;OAEG;IACH,WAAW,IAAI,IAAI;IAMnB;;OAEG;IACG,aAAa,CAAC,iBAAiB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAoE7D;;OAEG;IACG,eAAe,CAAC,kBAAkB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgDjE;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IA2DjC;;OAEG;IACH,OAAO,CAAC,gBAAgB;IA0CxB;;OAEG;IACH,cAAc,IAAI,WAAW,GAAG,IAAI;IAIpC;;OAEG;IACH,gBAAgB,IAAI,MAAM;IAI1B;;OAEG;IACH,gBAAgB,IAAI,MAAM;IAI1B;;OAEG;IACH,yBAAyB,IAAI,MAAM;IAInC;;OAEG;IACH,cAAc,IAAI,OAAO;IAIzB;;;OAGG;IACH,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IA4ErC;;OAEG;IACH,uBAAuB,IAAI,oBAAoB;IAI/C;;OAEG;IACH,OAAO,IAAI,IAAI;CAiBhB"}
package/dist/index.d.ts CHANGED
@@ -11,10 +11,12 @@ export { TabSyncManager } from './core/TabSyncManager';
11
11
  export type { TabSyncMessage } from './core/TabSyncManager';
12
12
  export { WarningModal } from './ui/WarningModal';
13
13
  export { SessionHeader } from './ui/SessionHeader';
14
+ export { PurchaseModal } from './ui/PurchaseModal';
14
15
  export { lightTheme, darkTheme, getTheme, generateCSSVariables } from './styles/theme';
15
16
  export type { Theme, ThemeColors, ThemeTypography, ThemeSpacing } from './styles/theme';
16
17
  export type { SDKConfig, SessionData, SDKEvents, ModalStyles, ThemeMode, JWTHeader, JWTClaims, JWKSKey, JWKSResponse, SessionLifecycleHooks, SessionStartContext, SessionEndContext, SessionExtendContext, SessionWarningContext, } from './types';
17
- export { SDKError } from './types';
18
+ export { SDKError, PurchaseError } from './types';
19
+ export type { PurchaseResult } from './types';
18
20
  export { extractTokenFromURL, isBrowser } from './utils/url';
19
21
  export { Logger } from './utils/logger';
20
22
  export { MarketplaceSDK as default } from './core/MarketplaceSDK';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAGvD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,YAAY,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAG5D,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGnD,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACvF,YAAY,EAAE,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAGxF,YAAY,EACV,SAAS,EACT,WAAW,EACX,SAAS,EACT,WAAW,EACX,SAAS,EACT,SAAS,EACT,SAAS,EACT,OAAO,EACP,YAAY,EACZ,qBAAqB,EACrB,mBAAmB,EACnB,iBAAiB,EACjB,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,SAAS,CAAC;AAEjB,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAGnC,OAAO,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAGxC,OAAO,EAAE,cAAc,IAAI,OAAO,EAAE,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAGvD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,YAAY,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAG5D,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGnD,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACvF,YAAY,EAAE,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAGxF,YAAY,EACV,SAAS,EACT,WAAW,EACX,SAAS,EACT,WAAW,EACX,SAAS,EACT,SAAS,EACT,SAAS,EACT,OAAO,EACP,YAAY,EACZ,qBAAqB,EACrB,mBAAmB,EACnB,iBAAiB,EACjB,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,SAAS,CAAC;AAEjB,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAClD,YAAY,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAG9C,OAAO,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAGxC,OAAO,EAAE,cAAc,IAAI,OAAO,EAAE,MAAM,uBAAuB,CAAC"}
@@ -20,6 +20,13 @@ class SDKError extends Error {
20
20
  }
21
21
  }
22
22
  }
23
+ class PurchaseError extends SDKError {
24
+ constructor(message2, code, itemId, statusCode) {
25
+ super(message2, code, statusCode);
26
+ this.itemId = itemId;
27
+ this.name = "PurchaseError";
28
+ }
29
+ }
23
30
  var PurchaseState = /* @__PURE__ */ ((PurchaseState2) => {
24
31
  PurchaseState2["AVAILABLE"] = "AVAILABLE";
25
32
  PurchaseState2["PRIVY_REQUIRED"] = "PRIVY_REQUIRED";
@@ -2558,6 +2565,166 @@ function extractTokenFromURL(paramName = "gwSession", url) {
2558
2565
  function isBrowser() {
2559
2566
  return typeof window !== "undefined" && typeof window.document !== "undefined";
2560
2567
  }
2568
+ class PurchaseModal {
2569
+ constructor(themeMode = "light", customStyles) {
2570
+ this.modal = null;
2571
+ this.legacyStyles = null;
2572
+ const prefersDark = themeMode === "dark" || themeMode === "auto" && this.detectDarkMode();
2573
+ this.theme = getTheme(prefersDark);
2574
+ if (customStyles) {
2575
+ this.legacyStyles = {
2576
+ backgroundColor: customStyles.backgroundColor || "#ffffff",
2577
+ textColor: customStyles.textColor || "#333333",
2578
+ primaryColor: customStyles.primaryColor || "#007bff",
2579
+ borderRadius: customStyles.borderRadius || "8px",
2580
+ fontFamily: customStyles.fontFamily || '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif'
2581
+ };
2582
+ }
2583
+ }
2584
+ detectDarkMode() {
2585
+ if (typeof window !== "undefined" && window.matchMedia) {
2586
+ return window.matchMedia("(prefers-color-scheme: dark)").matches;
2587
+ }
2588
+ return false;
2589
+ }
2590
+ escapeHtml(text) {
2591
+ return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
2592
+ }
2593
+ /**
2594
+ * Show purchase confirmation modal
2595
+ */
2596
+ show(options) {
2597
+ this.hide();
2598
+ this.modal = document.createElement("div");
2599
+ this.modal.id = "gw-purchase-modal";
2600
+ this.modal.style.cssText = `
2601
+ position: fixed;
2602
+ top: 0;
2603
+ left: 0;
2604
+ width: 100%;
2605
+ height: 100%;
2606
+ background-color: rgba(0, 0, 0, 0.5);
2607
+ display: flex;
2608
+ align-items: center;
2609
+ justify-content: center;
2610
+ z-index: 99999;
2611
+ font-family: ${this.legacyStyles?.fontFamily || this.theme.typography.fontFamily};
2612
+ `;
2613
+ const content = document.createElement("div");
2614
+ const bgColor = this.legacyStyles?.backgroundColor || this.theme.colors.card;
2615
+ const textColor = this.legacyStyles?.textColor || this.theme.colors.cardForeground;
2616
+ const borderRadius = this.legacyStyles?.borderRadius || this.theme.spacing.borderRadius.lg;
2617
+ content.style.cssText = `
2618
+ background-color: ${bgColor};
2619
+ color: ${textColor};
2620
+ border-radius: ${borderRadius};
2621
+ padding: ${this.theme.spacing.padding.lg};
2622
+ max-width: 400px;
2623
+ width: 90%;
2624
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
2625
+ border: 1px solid ${this.theme.colors.border};
2626
+ `;
2627
+ content.innerHTML = `
2628
+ <h2 style="margin: 0 0 ${this.theme.spacing.padding.md} 0; font-size: ${this.theme.typography.fontSize.xl}; font-weight: ${this.theme.typography.fontWeight.semibold}; color: ${textColor};">
2629
+ 🛒 Confirm Purchase
2630
+ </h2>
2631
+ <p style="margin: 0 0 ${this.theme.spacing.padding.lg} 0; font-size: ${this.theme.typography.fontSize.base}; line-height: ${this.theme.typography.lineHeight.normal}; color: ${this.theme.colors.mutedForeground};">
2632
+ Are you sure you want to purchase item <strong style="color: ${textColor};">${this.escapeHtml(options.itemId)}</strong>?
2633
+ </p>
2634
+ <div style="display: flex; gap: ${this.theme.spacing.gap.md}; justify-content: flex-end;">
2635
+ <button id="gw-cancel-btn" style="
2636
+ padding: 10px 20px;
2637
+ background-color: ${this.theme.colors.secondary};
2638
+ color: ${this.theme.colors.secondaryForeground};
2639
+ border: 1px solid ${this.theme.colors.border};
2640
+ border-radius: ${this.theme.spacing.borderRadius.sm};
2641
+ font-size: ${this.theme.typography.fontSize.sm};
2642
+ font-weight: ${this.theme.typography.fontWeight.medium};
2643
+ cursor: pointer;
2644
+ transition: all 0.2s;
2645
+ font-family: ${this.theme.typography.fontFamily};
2646
+ ">
2647
+ Cancel
2648
+ </button>
2649
+ <button id="gw-confirm-btn" style="
2650
+ padding: 10px 20px;
2651
+ background-color: ${this.theme.colors.primary};
2652
+ color: ${this.theme.colors.primaryForeground};
2653
+ border: none;
2654
+ border-radius: ${this.theme.spacing.borderRadius.sm};
2655
+ font-size: ${this.theme.typography.fontSize.sm};
2656
+ font-weight: ${this.theme.typography.fontWeight.medium};
2657
+ cursor: pointer;
2658
+ transition: all 0.2s;
2659
+ font-family: ${this.theme.typography.fontFamily};
2660
+ ">
2661
+ Confirm Purchase
2662
+ </button>
2663
+ </div>
2664
+ `;
2665
+ this.modal.appendChild(content);
2666
+ document.body.appendChild(this.modal);
2667
+ const confirmBtn = document.getElementById("gw-confirm-btn");
2668
+ if (confirmBtn && options.onConfirm) {
2669
+ confirmBtn.addEventListener("click", () => {
2670
+ options.onConfirm?.();
2671
+ this.hide();
2672
+ });
2673
+ }
2674
+ const cancelBtn = document.getElementById("gw-cancel-btn");
2675
+ if (cancelBtn) {
2676
+ cancelBtn.addEventListener("click", () => {
2677
+ options.onCancel?.();
2678
+ this.hide();
2679
+ });
2680
+ }
2681
+ const buttons = content.querySelectorAll("button");
2682
+ buttons.forEach((button) => {
2683
+ button.addEventListener("mouseenter", () => {
2684
+ button.style.opacity = "0.9";
2685
+ });
2686
+ button.addEventListener("mouseleave", () => {
2687
+ button.style.opacity = "1";
2688
+ });
2689
+ button.addEventListener("focus", () => {
2690
+ button.style.outline = `2px solid ${this.theme.colors.ring}`;
2691
+ button.style.outlineOffset = "2px";
2692
+ });
2693
+ button.addEventListener("blur", () => {
2694
+ button.style.outline = "none";
2695
+ });
2696
+ });
2697
+ const handleKeyDown = (e) => {
2698
+ if (e.key === "Escape") {
2699
+ options.onCancel?.();
2700
+ this.hide();
2701
+ document.removeEventListener("keydown", handleKeyDown);
2702
+ }
2703
+ };
2704
+ document.addEventListener("keydown", handleKeyDown);
2705
+ this.modal.addEventListener("click", (e) => {
2706
+ if (e.target === this.modal) {
2707
+ options.onCancel?.();
2708
+ this.hide();
2709
+ }
2710
+ });
2711
+ }
2712
+ /**
2713
+ * Hide and remove modal
2714
+ */
2715
+ hide() {
2716
+ if (this.modal && this.modal.parentNode) {
2717
+ this.modal.parentNode.removeChild(this.modal);
2718
+ this.modal = null;
2719
+ }
2720
+ }
2721
+ /**
2722
+ * Check if modal is currently shown
2723
+ */
2724
+ isShown() {
2725
+ return this.modal !== null;
2726
+ }
2727
+ }
2561
2728
  class MarketplaceSDK {
2562
2729
  constructor(config) {
2563
2730
  this.timer = null;
@@ -2568,6 +2735,7 @@ class MarketplaceSDK {
2568
2735
  this.sessionData = null;
2569
2736
  this.jwtToken = null;
2570
2737
  this.endReason = "manual";
2738
+ this.purchaseModal = null;
2571
2739
  this.config = {
2572
2740
  jwksUri: config.jwksUri || "https://api.platform.generalwisdom.com/.well-known/jwks.json",
2573
2741
  jwtParamName: config.jwtParamName || "gwSession",
@@ -3104,6 +3272,73 @@ class MarketplaceSDK {
3104
3272
  isTimerRunning() {
3105
3273
  return this.timer?.isRunning() ?? false;
3106
3274
  }
3275
+ /**
3276
+ * Request purchase of an item — opens PurchaseModal directly
3277
+ * Bypasses the add-ons panel; works for any active item (visible or hidden)
3278
+ */
3279
+ requestPurchase(itemId) {
3280
+ if (!this.sessionData || !this.jwtToken) {
3281
+ throw new SDKError("No active session", "NO_SESSION");
3282
+ }
3283
+ this.logger.info("Requesting purchase for item:", itemId);
3284
+ this.events.onPurchaseStart?.({ itemId, quantity: 1 });
3285
+ if (!this.purchaseModal) {
3286
+ this.purchaseModal = new PurchaseModal(
3287
+ this.config.themeMode || "light",
3288
+ this.config.customStyles
3289
+ );
3290
+ }
3291
+ this.purchaseModal.show({
3292
+ itemId,
3293
+ onConfirm: async () => {
3294
+ try {
3295
+ const response = await fetch(
3296
+ `${this.config.apiEndpoint}/items/${itemId}/purchase`,
3297
+ {
3298
+ method: "POST",
3299
+ headers: {
3300
+ "Authorization": `Bearer ${this.jwtToken}`,
3301
+ "Content-Type": "application/json"
3302
+ },
3303
+ body: JSON.stringify({ item_id: itemId, quantity: 1 })
3304
+ }
3305
+ );
3306
+ if (!response.ok) {
3307
+ throw new PurchaseError(
3308
+ "Purchase failed",
3309
+ "PURCHASE_FAILED",
3310
+ itemId,
3311
+ response.status
3312
+ );
3313
+ }
3314
+ const data = await response.json();
3315
+ const result = {
3316
+ itemId,
3317
+ transactionId: data.transactionId,
3318
+ amount: data.amount
3319
+ };
3320
+ this.events.onPurchaseSuccess?.(result);
3321
+ this.events.onPurchaseComplete?.(itemId);
3322
+ if (data.newBalance !== void 0) {
3323
+ this.events.onBalanceUpdate?.(data.newBalance);
3324
+ }
3325
+ this.logger.info("Purchase successful:", result);
3326
+ } catch (error) {
3327
+ const purchaseError = error instanceof PurchaseError ? error : new PurchaseError(
3328
+ error instanceof Error ? error.message : "Purchase failed",
3329
+ "PURCHASE_ERROR",
3330
+ itemId
3331
+ );
3332
+ this.events.onPurchaseError?.(purchaseError);
3333
+ this.logger.error("Purchase failed:", purchaseError);
3334
+ }
3335
+ },
3336
+ onCancel: () => {
3337
+ this.events.onPurchaseCancelled?.(itemId);
3338
+ this.logger.info("Purchase cancelled for item:", itemId);
3339
+ }
3340
+ });
3341
+ }
3107
3342
  /**
3108
3343
  * Get purchase state manager for item purchase state checking
3109
3344
  */
@@ -3119,6 +3354,7 @@ class MarketplaceSDK {
3119
3354
  this.heartbeat?.stop();
3120
3355
  this.tabSync?.destroy();
3121
3356
  this.modal?.hide();
3357
+ this.purchaseModal?.hide();
3122
3358
  if (typeof sessionStorage !== "undefined") {
3123
3359
  sessionStorage.removeItem("gw_marketplace_jwt");
3124
3360
  this.logger.log("JWT token cleared from storage");
@@ -3329,6 +3565,8 @@ export {
3329
3565
  JWTParser,
3330
3566
  Logger,
3331
3567
  MarketplaceSDK,
3568
+ PurchaseError,
3569
+ PurchaseModal,
3332
3570
  SDKError,
3333
3571
  SessionHeader,
3334
3572
  TabSyncManager,