@cshah18/sdk 4.14.0 → 4.16.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/dist/cobuy-sdk.esm.js +1136 -60
- package/dist/cobuy-sdk.esm.js.map +1 -1
- package/dist/cobuy-sdk.umd.js +1136 -60
- package/dist/cobuy-sdk.umd.js.map +1 -1
- package/dist/types/core/api-client.d.ts +23 -1
- package/dist/types/core/endpoints.d.ts +3 -0
- package/dist/types/core/socket.d.ts +3 -2
- package/dist/types/core/types.d.ts +39 -0
- package/dist/types/ui/lobby/lobby-modal.d.ts +54 -2
- package/dist/types/ui/widget/widget-root.d.ts +6 -0
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ApiRequestOptions, ApiResponse, ApiClientConfig, ProductRewardData, ProductContextData, ProductPrimaryGroupData, GroupJoinResponseData, GroupInviteResponseData, InviteResolveResponseData, AuthStrategy, ShareChannel, Contact, CheckoutValidationData, CheckoutConfirmData } from "./types";
|
|
1
|
+
import { ApiRequestOptions, ApiResponse, ApiClientConfig, ProductRewardData, ProductContextData, ProductPrimaryGroupData, GroupJoinResponseData, GroupInviteResponseData, InviteResolveResponseData, AuthStrategy, ShareChannel, Contact, OfflineRedemption, LeaveGroupResponseData, RecoverOrJoinGroupResponseData, CheckoutValidationData, CheckoutConfirmData } from "./types";
|
|
2
2
|
/**
|
|
3
3
|
* HTTP client for communicating with CoBuy API
|
|
4
4
|
*
|
|
@@ -446,6 +446,28 @@ export declare class ApiClient {
|
|
|
446
446
|
* ```
|
|
447
447
|
*/
|
|
448
448
|
setContact(contact: Contact): Promise<ApiResponse<void>>;
|
|
449
|
+
/**
|
|
450
|
+
* Leave an active group for the current SDK session.
|
|
451
|
+
*/
|
|
452
|
+
leaveGroup(groupId: string, params?: {
|
|
453
|
+
leave_source?: "close_icon" | "browser_close" | "unknown";
|
|
454
|
+
leave_reason?: "voluntary_with_contact" | "voluntary_no_contact" | "unknown";
|
|
455
|
+
}): Promise<ApiResponse<LeaveGroupResponseData>>;
|
|
456
|
+
/**
|
|
457
|
+
* Fetch current session member's offline redemption codes for a group.
|
|
458
|
+
*/
|
|
459
|
+
getGroupOfflineRedemption(groupId: string): Promise<ApiResponse<{
|
|
460
|
+
offline_redemption?: OfflineRedemption;
|
|
461
|
+
}>>;
|
|
462
|
+
recoverOrJoinGroup(productId: string, contact?: Contact): Promise<ApiResponse<RecoverOrJoinGroupResponseData>>;
|
|
463
|
+
/**
|
|
464
|
+
* Best-effort leave signal for unload/pagehide scenarios.
|
|
465
|
+
* Uses fetch keepalive so it can run while page is closing.
|
|
466
|
+
*/
|
|
467
|
+
leaveGroupBestEffort(groupId: string, params?: {
|
|
468
|
+
leave_source?: "close_icon" | "browser_close" | "unknown";
|
|
469
|
+
leave_reason?: "voluntary_with_contact" | "voluntary_no_contact" | "unknown";
|
|
470
|
+
}): void;
|
|
449
471
|
/**
|
|
450
472
|
* Prepare checkout for a group
|
|
451
473
|
*
|
|
@@ -5,10 +5,13 @@ export declare const API_ENDPOINTS: {
|
|
|
5
5
|
readonly PRODUCT_CONTEXT: "/v1/sdk/products/:productId/context";
|
|
6
6
|
readonly PRODUCT_REWARD: "/v1/sdk/products/:productId/reward";
|
|
7
7
|
readonly PRODUCT_PRIMARY_GROUP: "/v1/sdk/products/:productId/group/primary";
|
|
8
|
+
readonly PRODUCT_RECOVER_OR_JOIN_GROUP: "/v1/sdk/products/:productId/group/recover-or-join";
|
|
8
9
|
readonly GROUP_JOIN: "/v1/sdk/groups/:groupId/join";
|
|
10
|
+
readonly GROUP_LEAVE: "/v1/sdk/groups/:groupId/leave";
|
|
9
11
|
readonly GROUP_CREATE_AND_JOIN: "/v1/sdk/groups/new/join";
|
|
10
12
|
readonly PRODUCT_ACTIVE_GROUPS: "/v1/sdk/products/:productId/groups/active";
|
|
11
13
|
readonly GROUP_INVITE: "/v1/sdk/groups/:groupId/invite";
|
|
14
|
+
readonly GROUP_OFFLINE_REDEMPTION: "/v1/sdk/groups/:groupId/offline-redemption";
|
|
12
15
|
readonly GROUP_CHECKOUT_PREPARE: "/v1/sdk/groups/:groupId/checkout/prepare";
|
|
13
16
|
readonly GROUP_CHECKOUT_VALIDATE: "/v1/sdk/groups/:groupId/checkout/validate";
|
|
14
17
|
readonly GROUP_CHECKOUT_CONFIRM: "/v1/sdk/groups/:groupId/checkout/confirm";
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { InternalConfig, GroupFulfilledEvent, GroupCreatedEvent, GroupMemberJoinedEvent } from "./types";
|
|
2
|
-
export type SocketEventName = "group:member:joined" | "group:created" | "group:fulfilled";
|
|
1
|
+
import { InternalConfig, GroupFulfilledEvent, GroupCreatedEvent, GroupMemberJoinedEvent, GroupMemberLeftEvent } from "./types";
|
|
2
|
+
export type SocketEventName = "group:member:joined" | "group:member:left" | "group:created" | "group:fulfilled";
|
|
3
3
|
export interface SocketHandlers {
|
|
4
4
|
onGroupMemberJoined?: (payload: GroupMemberJoinedEvent) => void;
|
|
5
|
+
onGroupMemberLeft?: (payload: GroupMemberLeftEvent) => void;
|
|
5
6
|
onGroupCreated?: (payload: GroupCreatedEvent) => void;
|
|
6
7
|
onGroupFulfilled?: (payload: GroupFulfilledEvent) => void;
|
|
7
8
|
}
|
|
@@ -305,6 +305,7 @@ export interface FulfilledGroup {
|
|
|
305
305
|
campaign_id: string;
|
|
306
306
|
campaign_name: string;
|
|
307
307
|
campaign_status: string;
|
|
308
|
+
campaign_redemption_method?: "online" | "offline" | "both";
|
|
308
309
|
participants_count: number;
|
|
309
310
|
max_participants: number;
|
|
310
311
|
status: string;
|
|
@@ -486,6 +487,10 @@ export interface ModalOptions {
|
|
|
486
487
|
* Offline redemption data for fulfilled groups
|
|
487
488
|
*/
|
|
488
489
|
offlineRedemption?: OfflineRedemption;
|
|
490
|
+
/**
|
|
491
|
+
* Campaign redemption method - controls which checkout options are shown
|
|
492
|
+
*/
|
|
493
|
+
redemptionMethod?: "online" | "offline" | "both";
|
|
489
494
|
/**
|
|
490
495
|
* Optional callback when modal opens
|
|
491
496
|
*/
|
|
@@ -582,6 +587,7 @@ export interface ProductContextCampaignData {
|
|
|
582
587
|
reward_value?: string | number | null;
|
|
583
588
|
start_date?: string | null;
|
|
584
589
|
end_date?: string | null;
|
|
590
|
+
redemption_method?: "online" | "offline" | "both" | null;
|
|
585
591
|
}
|
|
586
592
|
export interface ProductContextData {
|
|
587
593
|
product_id: string;
|
|
@@ -613,6 +619,7 @@ export interface ProductPrimaryGroupData {
|
|
|
613
619
|
campaign_id: string | null;
|
|
614
620
|
campaign_name: string | null;
|
|
615
621
|
campaign_status: string | null;
|
|
622
|
+
campaign_redemption_method?: "online" | "offline" | "both";
|
|
616
623
|
participants_count: number;
|
|
617
624
|
max_participants: number;
|
|
618
625
|
status: string;
|
|
@@ -632,6 +639,7 @@ export interface GroupJoinResponseData {
|
|
|
632
639
|
status: string;
|
|
633
640
|
expiry_at: string;
|
|
634
641
|
timeLeftSeconds: number;
|
|
642
|
+
campaign_redemption_method?: "online" | "offline" | "both";
|
|
635
643
|
};
|
|
636
644
|
membership: {
|
|
637
645
|
id: string;
|
|
@@ -642,6 +650,37 @@ export interface GroupJoinResponseData {
|
|
|
642
650
|
product_id: string;
|
|
643
651
|
offline_redemption?: OfflineRedemption;
|
|
644
652
|
}
|
|
653
|
+
export interface LeaveGroupResponseData {
|
|
654
|
+
left: boolean;
|
|
655
|
+
session_id: string;
|
|
656
|
+
group: {
|
|
657
|
+
id: string;
|
|
658
|
+
group_name: string;
|
|
659
|
+
description: string | null;
|
|
660
|
+
campaign_creative_id: string | null;
|
|
661
|
+
campaign_creative_name: string | null;
|
|
662
|
+
campaign_id: string | null;
|
|
663
|
+
campaign_name: string | null;
|
|
664
|
+
campaign_status: string | null;
|
|
665
|
+
campaign_redemption_method?: "online" | "offline" | "both";
|
|
666
|
+
participants_count: number;
|
|
667
|
+
max_participants: number;
|
|
668
|
+
status: string;
|
|
669
|
+
expiry_at: string;
|
|
670
|
+
timeLeftSeconds: number;
|
|
671
|
+
};
|
|
672
|
+
product_id?: string;
|
|
673
|
+
}
|
|
674
|
+
export interface RecoverOrJoinGroupResponseData extends GroupJoinResponseData {
|
|
675
|
+
recovery: {
|
|
676
|
+
recovered: boolean;
|
|
677
|
+
matched_by: "session" | "contact" | "none";
|
|
678
|
+
outcome: "existing_active_membership" | "rejoined_previous_group" | "joined_next_available_group" | "created_new_group";
|
|
679
|
+
previous_group_id?: string;
|
|
680
|
+
joined_group_id: string;
|
|
681
|
+
};
|
|
682
|
+
}
|
|
683
|
+
export type GroupMemberLeftEvent = LeaveGroupResponseData;
|
|
645
684
|
export type ShareChannel = "whatsapp" | "facebook" | "email" | "sms" | "copy_link" | "tiktok" | "x" | "other";
|
|
646
685
|
export interface GroupInviteResponseData {
|
|
647
686
|
invite_url?: string;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ApiClient } from "../../core/api-client";
|
|
2
|
+
import { AnalyticsClient } from "../../core/analytics";
|
|
2
3
|
import { OfflineRedemption } from "../../core/types";
|
|
3
4
|
import { SocketManager } from "../../core/socket";
|
|
4
5
|
import "./styles/styles.css";
|
|
@@ -17,6 +18,7 @@ export interface LobbyModalData {
|
|
|
17
18
|
activities?: ActivityItem[];
|
|
18
19
|
isLocked?: boolean;
|
|
19
20
|
offlineRedemption?: OfflineRedemption;
|
|
21
|
+
redemptionMethod?: "online" | "offline" | "both";
|
|
20
22
|
}
|
|
21
23
|
export interface ActivityItem {
|
|
22
24
|
emoji: string;
|
|
@@ -31,6 +33,9 @@ export interface LobbyModalCallbacks {
|
|
|
31
33
|
onCopyLink?: (link: string) => void;
|
|
32
34
|
onShare?: () => void;
|
|
33
35
|
}
|
|
36
|
+
interface CloseOptions {
|
|
37
|
+
skipLeaveFlow?: boolean;
|
|
38
|
+
}
|
|
34
39
|
/**
|
|
35
40
|
* LobbyModal - Renders and manages the group buying lobby modal
|
|
36
41
|
*/
|
|
@@ -38,6 +43,7 @@ export declare class LobbyModal {
|
|
|
38
43
|
private readonly logger;
|
|
39
44
|
private readonly socketManager;
|
|
40
45
|
private readonly apiClient;
|
|
46
|
+
private readonly analyticsClient;
|
|
41
47
|
private modalElement;
|
|
42
48
|
private data;
|
|
43
49
|
private readonly callbacks;
|
|
@@ -48,7 +54,36 @@ export declare class LobbyModal {
|
|
|
48
54
|
private currentGroupId;
|
|
49
55
|
private shareOverlay;
|
|
50
56
|
private keyboardHandler;
|
|
51
|
-
|
|
57
|
+
private leaveFlowInProgress;
|
|
58
|
+
private leaveSignalSent;
|
|
59
|
+
private hasContactProtection;
|
|
60
|
+
private initialContactPromptTimer;
|
|
61
|
+
private contactPromptOverlay;
|
|
62
|
+
private leaveLoaderOverlay;
|
|
63
|
+
private beforeUnloadHandler;
|
|
64
|
+
private pageHideHandler;
|
|
65
|
+
private visibilityChangeHandler;
|
|
66
|
+
private readonly CONTACT_PROTECTION_PREFIX;
|
|
67
|
+
private readonly LAST_LEFT_GROUP_PREFIX;
|
|
68
|
+
constructor(data: LobbyModalData, callbacks: LobbyModalCallbacks, apiClient: ApiClient | null, socketManager?: SocketManager | null, analyticsClient?: AnalyticsClient | null, debug?: boolean);
|
|
69
|
+
private getSessionId;
|
|
70
|
+
private getContactProtectionStorageKey;
|
|
71
|
+
private getLastLeftGroupStorageKey;
|
|
72
|
+
private readContactProtectionState;
|
|
73
|
+
private persistContactProtectionState;
|
|
74
|
+
private persistLastLeftGroup;
|
|
75
|
+
private clearInitialContactPromptTimer;
|
|
76
|
+
private clearContactPromptOverlay;
|
|
77
|
+
private showBlockingLoader;
|
|
78
|
+
private hideBlockingLoader;
|
|
79
|
+
private updateContactProtectionUI;
|
|
80
|
+
private showToastMessage;
|
|
81
|
+
private trackAnalyticsEvent;
|
|
82
|
+
private saveContactValue;
|
|
83
|
+
private openContactProtectionPrompt;
|
|
84
|
+
private openUnprotectedLeaveWarning;
|
|
85
|
+
private scheduleInitialContactPrompt;
|
|
86
|
+
private leaveGroupExplicitly;
|
|
52
87
|
/**
|
|
53
88
|
* Derive lock state from data so UI reflects completion
|
|
54
89
|
*/
|
|
@@ -103,6 +138,10 @@ export declare class LobbyModal {
|
|
|
103
138
|
* Create link section (just the link box and share button, no wrapper)
|
|
104
139
|
*/
|
|
105
140
|
private createLinkSection;
|
|
141
|
+
/**
|
|
142
|
+
* Create a standalone "Checkout Online" button for the link/share section
|
|
143
|
+
*/
|
|
144
|
+
private createOnlineCheckoutButton;
|
|
106
145
|
/**
|
|
107
146
|
* Create offline redemption section
|
|
108
147
|
*/
|
|
@@ -251,10 +290,16 @@ export declare class LobbyModal {
|
|
|
251
290
|
* Clean up keyboard event listeners
|
|
252
291
|
*/
|
|
253
292
|
private removeKeyboardAccessibility;
|
|
293
|
+
private registerLifecycleLeaveHandlers;
|
|
294
|
+
private unregisterLifecycleLeaveHandlers;
|
|
295
|
+
private triggerBestEffortLeave;
|
|
296
|
+
private shouldRunLeaveFlow;
|
|
297
|
+
private inferContactType;
|
|
298
|
+
private runLeaveFlowAndClose;
|
|
254
299
|
/**
|
|
255
300
|
* Close the modal
|
|
256
301
|
*/
|
|
257
|
-
close(): void;
|
|
302
|
+
close(options?: CloseOptions): void;
|
|
258
303
|
/**
|
|
259
304
|
* Check if modal is open
|
|
260
305
|
*/
|
|
@@ -291,10 +336,16 @@ export declare class LobbyModal {
|
|
|
291
336
|
* Subscribe to socket events
|
|
292
337
|
*/
|
|
293
338
|
private subscribeToSocketEvents;
|
|
339
|
+
private unsubscribeFromSocketEvents;
|
|
294
340
|
/**
|
|
295
341
|
* Handle socket group update events
|
|
296
342
|
*/
|
|
297
343
|
private readonly handleSocketGroupUpdate;
|
|
344
|
+
/**
|
|
345
|
+
* Fetch current user's offline redemption codes when group becomes fulfilled
|
|
346
|
+
* This ensures we show the current user's codes, not someone else's
|
|
347
|
+
*/
|
|
348
|
+
private fetchCurrentUserOfflineCodesIfNeeded;
|
|
298
349
|
/**
|
|
299
350
|
* Create activity item from socket event data
|
|
300
351
|
*/
|
|
@@ -308,3 +359,4 @@ export declare class LobbyModal {
|
|
|
308
359
|
*/
|
|
309
360
|
private updateTeamCard;
|
|
310
361
|
}
|
|
362
|
+
export {};
|
|
@@ -30,6 +30,7 @@ export declare class WidgetRoot {
|
|
|
30
30
|
private groupExpiryRefreshTriggered;
|
|
31
31
|
private offlineRedemption;
|
|
32
32
|
private offlineRedemptionModal;
|
|
33
|
+
private campaignRedemptionMethod;
|
|
33
34
|
private isRendering;
|
|
34
35
|
private renderPromise;
|
|
35
36
|
private liveRegionAnnouncer;
|
|
@@ -38,11 +39,16 @@ export declare class WidgetRoot {
|
|
|
38
39
|
private renderDebounceTimer;
|
|
39
40
|
private pendingRenderOptions;
|
|
40
41
|
private readonly RENDER_DEBOUNCE_MS;
|
|
42
|
+
private readonly LAST_LEFT_GROUP_PREFIX;
|
|
41
43
|
/**
|
|
42
44
|
* Get max retries from config (configurable via performance options)
|
|
43
45
|
*/
|
|
44
46
|
private get MAX_RETRIES();
|
|
45
47
|
constructor(config: InternalConfig, apiClient: ApiClient | null, analyticsClient?: AnalyticsClient | null);
|
|
48
|
+
private getRecoveryStorageKey;
|
|
49
|
+
private getStoredRecoveryGroupId;
|
|
50
|
+
private clearStoredRecoveryGroupId;
|
|
51
|
+
private showRecoveryToast;
|
|
46
52
|
/** Subscribe once to backend socket events routed through the host page */
|
|
47
53
|
private subscribeToSocketEvents;
|
|
48
54
|
/** Handle backend fulfillment notifications */
|