@growth-rail/react-native 0.0.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/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ # @growth-rail/react-native
2
+
3
+ ## 0.0.0
4
+
5
+ - Initial release of the React Native SDK.
package/README.md ADDED
@@ -0,0 +1,15 @@
1
+ # @growth-rail/react-native
2
+
3
+ Growth Rail SDK for React Native.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @growth-rail/react-native
9
+ # or
10
+ yarn add @growth-rail/react-native
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ Please refer to the documentation for usage instructions.
@@ -0,0 +1,171 @@
1
+ import React from 'react';
2
+
3
+ type GrowthRailOptions = {
4
+ apiKey: string;
5
+ cookieDomain?: string;
6
+ autoPageTrack?: boolean;
7
+ };
8
+ type AppUserType = {
9
+ attributes: Record<string, unknown>;
10
+ firstSeenAt: string;
11
+ lastSeenAt: string | null;
12
+ uniqueId: string;
13
+ referralCode: string;
14
+ referralLink: string;
15
+ referrerExperience: ReferrerExperience;
16
+ };
17
+ type AppUserTypeWithId = AppUserType & {
18
+ id: string;
19
+ };
20
+ type ReferralLink = {
21
+ referralCode: string;
22
+ referralLink: string;
23
+ };
24
+ type EventPayload = {
25
+ event: string;
26
+ userId?: string;
27
+ properties?: Record<string, any>;
28
+ timestamp: string;
29
+ };
30
+ type TrackReferralResponse = {
31
+ referralTrackingId: string;
32
+ promotionalText: string;
33
+ };
34
+ type TriggerButtonPosition = 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
35
+ type ReferrerTriggerButton = {
36
+ show: boolean;
37
+ position: TriggerButtonPosition;
38
+ displayMode: 'floating' | 'edge';
39
+ };
40
+ type ReferrerModalOptions = {
41
+ title: string;
42
+ description: string;
43
+ componentType: 'modal' | 'drawer';
44
+ theme: {
45
+ primaryColor: string;
46
+ tintColor: string;
47
+ tintAlpha: number;
48
+ backgroundColor: string;
49
+ };
50
+ };
51
+ interface ReferrerExperience {
52
+ trigger: ReferrerTriggerButton;
53
+ modal: ReferrerModalOptions;
54
+ }
55
+ interface NewUserExperience {
56
+ banner: {
57
+ show: boolean;
58
+ position: 'center-top' | 'center-bottom' | 'left-top' | 'left-bottom' | 'right-top' | 'right-bottom';
59
+ text: string;
60
+ themeColor: string;
61
+ };
62
+ }
63
+ interface DeviceFingerprint {
64
+ os: string;
65
+ osVersion: string;
66
+ deviceModel?: string;
67
+ deviceBrand?: string;
68
+ screenWidth?: number;
69
+ screenHeight?: number;
70
+ timezoneOffsetInMinutes: string;
71
+ locale?: string;
72
+ language?: string;
73
+ platform?: string;
74
+ pixelRatio?: number;
75
+ }
76
+
77
+ declare class GrowthRail {
78
+ private static api;
79
+ private static options;
80
+ private static currentUser;
81
+ private static referralObject;
82
+ private static initialized;
83
+ private static userReadyPromise;
84
+ private static userReadyResolver;
85
+ private constructor();
86
+ static init(options: GrowthRailOptions): Promise<void>;
87
+ private static handleInitialUrl;
88
+ private static setupLinkListeners;
89
+ private static checkDeferredReferral;
90
+ private static checkInstallReferrer;
91
+ static getDeviceFingerprint(): DeviceFingerprint;
92
+ private static checkDeferredDeepLinkFingerprint;
93
+ private static handleDeepLink;
94
+ private static ensureInitialized;
95
+ static initAppUser(clientProvidedId: string): Promise<AppUserType>;
96
+ static trackReferral(referralCode: string, rewardEventName?: string): Promise<TrackReferralResponse>;
97
+ static trackRewardEvent(eventName?: string): Promise<void>;
98
+ static createReferralLink(rewardEventName?: string): Promise<ReferralLink>;
99
+ static isInitialized(): boolean;
100
+ static getReferralLink(): string;
101
+ static getReferralCode(): string | undefined;
102
+ static getUserId(): string | undefined;
103
+ static isUserReady(): boolean;
104
+ static getReferrerExperience(): ReferrerExperience | undefined;
105
+ static ensureUserReady(): Promise<AppUserTypeWithId>;
106
+ static getNewUserExperience(): Promise<NewUserExperience>;
107
+ }
108
+
109
+ declare class StorageManager {
110
+ static setTrackedReferral(id: string): Promise<void>;
111
+ static getTrackedReferral(): Promise<string | null>;
112
+ static isFirstLaunch(): Promise<boolean>;
113
+ }
114
+
115
+ declare class APIClient {
116
+ private baseUrl;
117
+ private apiKey;
118
+ constructor(options: GrowthRailOptions);
119
+ private request;
120
+ getNewUserExperience(): Promise<NewUserExperience>;
121
+ initAppUser(clientProvidedId: string): Promise<AppUserType>;
122
+ createReferralLink(referrerId: string, rewardEventName?: string): Promise<{
123
+ referralCode: string;
124
+ referralLink: string;
125
+ }>;
126
+ trackReferral(referralCode: string, rewardEventName?: string): Promise<TrackReferralResponse>;
127
+ trackRewardEvent(refereeId: string, referralTrackingId: string, eventName?: string): Promise<any>;
128
+ checkDeferredDeepLink(fingerprint: DeviceFingerprint): Promise<TrackReferralResponse>;
129
+ }
130
+
131
+ interface GrowthRailContextType {
132
+ isInitialized: boolean;
133
+ isUserReady: boolean;
134
+ showDashboard: (options?: Partial<ReferrerModalOptions>) => void;
135
+ hideDashboard: () => void;
136
+ showFloatingButton: (options?: Partial<ReferrerTriggerButton>) => void;
137
+ hideFloatingButton: () => void;
138
+ }
139
+ interface GrowthRailProviderProps extends GrowthRailOptions {
140
+ userId?: string;
141
+ children: React.ReactNode;
142
+ }
143
+ declare const GrowthRailProvider: React.FC<GrowthRailProviderProps>;
144
+ declare const useGrowthRailContext: () => GrowthRailContextType;
145
+
146
+ interface ReferralDashboardProps {
147
+ visible: boolean;
148
+ options?: Partial<ReferrerModalOptions>;
149
+ onClose: () => void;
150
+ }
151
+ declare const ReferralDashboard: React.FC<ReferralDashboardProps>;
152
+
153
+ interface TriggerButtonProps {
154
+ onPress: () => void;
155
+ options?: Partial<ReferrerExperience>;
156
+ }
157
+ declare const TriggerButton: React.FC<TriggerButtonProps>;
158
+
159
+ interface UseGrowthRailReturn {
160
+ initUser: (userId: string) => Promise<AppUserType>;
161
+ trackReward: (eventName?: string) => Promise<void>;
162
+ showReferralDashboard: (options?: Partial<ReferrerModalOptions>) => void;
163
+ showFloatingButton: (options: Partial<ReferrerTriggerButton>) => void;
164
+ hideFloatingButton: () => void;
165
+ isLoading: boolean;
166
+ isInitialized: boolean;
167
+ error: Error | null;
168
+ }
169
+ declare const useGrowthRail: () => UseGrowthRailReturn;
170
+
171
+ export { APIClient, type AppUserType, type AppUserTypeWithId, type DeviceFingerprint, type EventPayload, GrowthRail, type GrowthRailOptions, GrowthRailProvider, type NewUserExperience, ReferralDashboard, type ReferralLink, type ReferrerExperience, type ReferrerModalOptions, type ReferrerTriggerButton, StorageManager, type TrackReferralResponse, TriggerButton, type TriggerButtonPosition, type UseGrowthRailReturn, useGrowthRail, useGrowthRailContext };
@@ -0,0 +1,171 @@
1
+ import React from 'react';
2
+
3
+ type GrowthRailOptions = {
4
+ apiKey: string;
5
+ cookieDomain?: string;
6
+ autoPageTrack?: boolean;
7
+ };
8
+ type AppUserType = {
9
+ attributes: Record<string, unknown>;
10
+ firstSeenAt: string;
11
+ lastSeenAt: string | null;
12
+ uniqueId: string;
13
+ referralCode: string;
14
+ referralLink: string;
15
+ referrerExperience: ReferrerExperience;
16
+ };
17
+ type AppUserTypeWithId = AppUserType & {
18
+ id: string;
19
+ };
20
+ type ReferralLink = {
21
+ referralCode: string;
22
+ referralLink: string;
23
+ };
24
+ type EventPayload = {
25
+ event: string;
26
+ userId?: string;
27
+ properties?: Record<string, any>;
28
+ timestamp: string;
29
+ };
30
+ type TrackReferralResponse = {
31
+ referralTrackingId: string;
32
+ promotionalText: string;
33
+ };
34
+ type TriggerButtonPosition = 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
35
+ type ReferrerTriggerButton = {
36
+ show: boolean;
37
+ position: TriggerButtonPosition;
38
+ displayMode: 'floating' | 'edge';
39
+ };
40
+ type ReferrerModalOptions = {
41
+ title: string;
42
+ description: string;
43
+ componentType: 'modal' | 'drawer';
44
+ theme: {
45
+ primaryColor: string;
46
+ tintColor: string;
47
+ tintAlpha: number;
48
+ backgroundColor: string;
49
+ };
50
+ };
51
+ interface ReferrerExperience {
52
+ trigger: ReferrerTriggerButton;
53
+ modal: ReferrerModalOptions;
54
+ }
55
+ interface NewUserExperience {
56
+ banner: {
57
+ show: boolean;
58
+ position: 'center-top' | 'center-bottom' | 'left-top' | 'left-bottom' | 'right-top' | 'right-bottom';
59
+ text: string;
60
+ themeColor: string;
61
+ };
62
+ }
63
+ interface DeviceFingerprint {
64
+ os: string;
65
+ osVersion: string;
66
+ deviceModel?: string;
67
+ deviceBrand?: string;
68
+ screenWidth?: number;
69
+ screenHeight?: number;
70
+ timezoneOffsetInMinutes: string;
71
+ locale?: string;
72
+ language?: string;
73
+ platform?: string;
74
+ pixelRatio?: number;
75
+ }
76
+
77
+ declare class GrowthRail {
78
+ private static api;
79
+ private static options;
80
+ private static currentUser;
81
+ private static referralObject;
82
+ private static initialized;
83
+ private static userReadyPromise;
84
+ private static userReadyResolver;
85
+ private constructor();
86
+ static init(options: GrowthRailOptions): Promise<void>;
87
+ private static handleInitialUrl;
88
+ private static setupLinkListeners;
89
+ private static checkDeferredReferral;
90
+ private static checkInstallReferrer;
91
+ static getDeviceFingerprint(): DeviceFingerprint;
92
+ private static checkDeferredDeepLinkFingerprint;
93
+ private static handleDeepLink;
94
+ private static ensureInitialized;
95
+ static initAppUser(clientProvidedId: string): Promise<AppUserType>;
96
+ static trackReferral(referralCode: string, rewardEventName?: string): Promise<TrackReferralResponse>;
97
+ static trackRewardEvent(eventName?: string): Promise<void>;
98
+ static createReferralLink(rewardEventName?: string): Promise<ReferralLink>;
99
+ static isInitialized(): boolean;
100
+ static getReferralLink(): string;
101
+ static getReferralCode(): string | undefined;
102
+ static getUserId(): string | undefined;
103
+ static isUserReady(): boolean;
104
+ static getReferrerExperience(): ReferrerExperience | undefined;
105
+ static ensureUserReady(): Promise<AppUserTypeWithId>;
106
+ static getNewUserExperience(): Promise<NewUserExperience>;
107
+ }
108
+
109
+ declare class StorageManager {
110
+ static setTrackedReferral(id: string): Promise<void>;
111
+ static getTrackedReferral(): Promise<string | null>;
112
+ static isFirstLaunch(): Promise<boolean>;
113
+ }
114
+
115
+ declare class APIClient {
116
+ private baseUrl;
117
+ private apiKey;
118
+ constructor(options: GrowthRailOptions);
119
+ private request;
120
+ getNewUserExperience(): Promise<NewUserExperience>;
121
+ initAppUser(clientProvidedId: string): Promise<AppUserType>;
122
+ createReferralLink(referrerId: string, rewardEventName?: string): Promise<{
123
+ referralCode: string;
124
+ referralLink: string;
125
+ }>;
126
+ trackReferral(referralCode: string, rewardEventName?: string): Promise<TrackReferralResponse>;
127
+ trackRewardEvent(refereeId: string, referralTrackingId: string, eventName?: string): Promise<any>;
128
+ checkDeferredDeepLink(fingerprint: DeviceFingerprint): Promise<TrackReferralResponse>;
129
+ }
130
+
131
+ interface GrowthRailContextType {
132
+ isInitialized: boolean;
133
+ isUserReady: boolean;
134
+ showDashboard: (options?: Partial<ReferrerModalOptions>) => void;
135
+ hideDashboard: () => void;
136
+ showFloatingButton: (options?: Partial<ReferrerTriggerButton>) => void;
137
+ hideFloatingButton: () => void;
138
+ }
139
+ interface GrowthRailProviderProps extends GrowthRailOptions {
140
+ userId?: string;
141
+ children: React.ReactNode;
142
+ }
143
+ declare const GrowthRailProvider: React.FC<GrowthRailProviderProps>;
144
+ declare const useGrowthRailContext: () => GrowthRailContextType;
145
+
146
+ interface ReferralDashboardProps {
147
+ visible: boolean;
148
+ options?: Partial<ReferrerModalOptions>;
149
+ onClose: () => void;
150
+ }
151
+ declare const ReferralDashboard: React.FC<ReferralDashboardProps>;
152
+
153
+ interface TriggerButtonProps {
154
+ onPress: () => void;
155
+ options?: Partial<ReferrerExperience>;
156
+ }
157
+ declare const TriggerButton: React.FC<TriggerButtonProps>;
158
+
159
+ interface UseGrowthRailReturn {
160
+ initUser: (userId: string) => Promise<AppUserType>;
161
+ trackReward: (eventName?: string) => Promise<void>;
162
+ showReferralDashboard: (options?: Partial<ReferrerModalOptions>) => void;
163
+ showFloatingButton: (options: Partial<ReferrerTriggerButton>) => void;
164
+ hideFloatingButton: () => void;
165
+ isLoading: boolean;
166
+ isInitialized: boolean;
167
+ error: Error | null;
168
+ }
169
+ declare const useGrowthRail: () => UseGrowthRailReturn;
170
+
171
+ export { APIClient, type AppUserType, type AppUserTypeWithId, type DeviceFingerprint, type EventPayload, GrowthRail, type GrowthRailOptions, GrowthRailProvider, type NewUserExperience, ReferralDashboard, type ReferralLink, type ReferrerExperience, type ReferrerModalOptions, type ReferrerTriggerButton, StorageManager, type TrackReferralResponse, TriggerButton, type TriggerButtonPosition, type UseGrowthRailReturn, useGrowthRail, useGrowthRailContext };
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ "use strict";var pe=Object.create;var $=Object.defineProperty;var ue=Object.getOwnPropertyDescriptor;var ge=Object.getOwnPropertyNames;var he=Object.getPrototypeOf,me=Object.prototype.hasOwnProperty;var we=(a,e,r)=>e in a?$(a,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):a[e]=r;var ye=(a,e)=>{for(var r in e)$(a,r,{get:e[r],enumerable:!0})},ne=(a,e,r,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let l of ge(e))!me.call(a,l)&&l!==r&&$(a,l,{get:()=>e[l],enumerable:!(o=ue(e,l))||o.enumerable});return a};var N=(a,e,r)=>(r=a!=null?pe(he(a)):{},ne(e||!a||!a.__esModule?$(r,"default",{value:a,enumerable:!0}):r,a)),be=a=>ne($({},"__esModule",{value:!0}),a);var P=(a,e,r)=>we(a,typeof e!="symbol"?e+"":e,r);var xe={};ye(xe,{APIClient:()=>j,GrowthRail:()=>g,GrowthRailProvider:()=>ke,ReferralDashboard:()=>re,StorageManager:()=>B,TriggerButton:()=>ie,useGrowthRail:()=>ve,useGrowthRailContext:()=>oe});module.exports=be(xe);var b=require("react-native"),ae=N(require("react-native-play-install-referrer"));var j=class{constructor(e){P(this,"baseUrl");P(this,"apiKey");let r=typeof process<"u"&&process.env?.ENV_BASE_URL;this.baseUrl=r||"https://api.growthrail.dev",this.apiKey=e.apiKey}async request(e,r,o){let l={"Content-Type":"application/json","X-GrowthRail-ProjectSecret":this.apiKey,Origin:this.baseUrl};try{let c=await fetch(`${this.baseUrl}${e}`,{method:r,headers:l,body:o?JSON.stringify(o):void 0});if(!c.ok){let p="";try{p=await c.text()}catch{}throw new Error(`GrowthRail API Error ${c.status} (${this.baseUrl}${e}): ${c.statusText} - ${p}`)}return c.json()}catch(c){throw console.error("GrowthRail SDK Error:",c),c}}async getNewUserExperience(){return this.request("/api/v1/sdk/new-user-experience","POST")}async initAppUser(e){return this.request("/api/v1/sdk/init-app-user","POST",{clientProvidedId:e})}async createReferralLink(e,r){return this.request("/api/v1/sdk/create-referral-link","POST",{referrerId:e,rewardEventName:r})}async trackReferral(e,r){return this.request("/api/v1/sdk/track-referral","POST",{referralCode:e,rewardEventName:r})}async trackRewardEvent(e,r,o){return this.request("/api/v1/sdk/track-reward-event","POST",{refereeId:e,referralTrackingId:r,eventName:o})}async checkDeferredDeepLink(e){return this.request("/api/v1/sdk/match-link","POST",{fingerprint:e})}};var H=N(require("@react-native-async-storage/async-storage")),Y={TRACKED_REFERRAL:"growth-rail-tracked-referral",IS_FIRST_LAUNCH:"growth-rail-is-first-launch"},B=class{static async setTrackedReferral(e){await H.default.setItem(Y.TRACKED_REFERRAL,e)}static async getTrackedReferral(){return await H.default.getItem(Y.TRACKED_REFERRAL)}static async isFirstLaunch(){return await H.default.getItem(Y.IS_FIRST_LAUNCH)===null?(await H.default.setItem(Y.IS_FIRST_LAUNCH,"false"),!0):!1}};var i=class i{constructor(){}static async init(e){i.initialized||(i.options=e,i.api=new j(e),i.initialized=!0,await i.handleInitialUrl(),await i.setupLinkListeners(),await i.checkDeferredReferral())}static async handleInitialUrl(){try{let e=await b.Linking.getInitialURL();e&&await i.handleDeepLink(e)}catch(e){console.error("GrowthRail: Error getting initial URL",e)}}static setupLinkListeners(){b.Linking.addEventListener("url",({url:e})=>{i.handleDeepLink(e)})}static async checkDeferredReferral(){await B.isFirstLaunch()&&(b.Platform.OS==="android"?await i.checkInstallReferrer():await i.checkDeferredDeepLinkFingerprint())}static checkInstallReferrer(){return new Promise(e=>{ae.default.getInstallReferrerInfo(async(r,o)=>{if(!o&&r&&r.installReferrer)try{let c=decodeURIComponent(r.installReferrer).match(/[?&]referralCode=([^&]+)/);if(c){let{referralTrackingId:p}=await i.trackReferral(c[1]);await B.setTrackedReferral(p),console.log("GrowthRail: Tracked referral via Install Referrer")}}catch(l){console.warn("GrowthRail: Failed to process install referrer",l)}else await i.checkDeferredDeepLinkFingerprint();e()})})}static getDeviceFingerprint(){let{width:e,height:r}=b.Dimensions.get("window"),o=Intl.DateTimeFormat().resolvedOptions().locale,l=b.PixelRatio.get(),c,p;if(b.Platform.OS==="android"){let m=b.Platform.constants;c=m.Model,p=m.Brand||m.Manufacturer}return{os:b.Platform.OS,platform:b.Platform.OS,osVersion:String(b.Platform.Version),screenWidth:e,screenHeight:r,timezoneOffsetInMinutes:String(new Date().getTimezoneOffset()),locale:o,language:o,deviceModel:c,deviceBrand:p,pixelRatio:l}}static async checkDeferredDeepLinkFingerprint(){try{let e=i.getDeviceFingerprint();console.log("GrowthRail executing deferred fingerprint check to API...");let{referralTrackingId:r}=await i.api.checkDeferredDeepLink(e);r&&(console.log("GrowthRail: Found deferred referral via fingerprinting",r),await B.setTrackedReferral(r))}catch(e){console.warn("GrowthRail: Fingerprint check failed",e)}}static async handleDeepLink(e){try{let r=new URL(e),o=r.searchParams.get("referralCode"),l=r.searchParams.get("rewardEventName");o&&(console.log("GrowthRail: Tracking referral from deep link",o),await i.trackReferral(o,l||void 0))}catch{let o=e.match(/[?&]referralCode=([^&]+)/);o&&await i.trackReferral(o[1])}}static ensureInitialized(){if(!i.initialized)throw new Error("GrowthRail.init() must be called before using the SDK")}static async initAppUser(e){i.ensureInitialized();let r=await i.api.initAppUser(e);return i.currentUser={...r,id:e},i.userReadyResolver&&i.userReadyResolver(i.currentUser),r}static async trackReferral(e,r){i.ensureInitialized();let o=await i.api.trackReferral(e,r);return await B.setTrackedReferral(o.referralTrackingId),o}static async trackRewardEvent(e){i.ensureInitialized();let r=i.currentUser?.id;if(!r)throw new Error("GrowthRail: User must be initialized before tracking a reward event.");let o=await B.getTrackedReferral();if(!o){console.warn("GrowthRail: No referral tracking ID found. Reward event not attributed.");return}return i.api.trackRewardEvent(r,o,e)}static async createReferralLink(e){i.ensureInitialized();let r=i.currentUser?.id;if(!r)throw new Error("GrowthRail: User must be initialized before creating a referral link.");if(i.referralObject)return i.referralObject;let o=await i.api.createReferralLink(r,e);return i.referralObject=o,o}static isInitialized(){return i.initialized}static getReferralLink(){if(!i.referralObject?.referralLink)throw new Error("GrowthRail: Referral Link not loaded or user not initialized");return i.referralObject.referralLink}static getReferralCode(){return i.referralObject?.referralCode||i.currentUser?.referralCode}static getUserId(){return i.currentUser?.id}static isUserReady(){return i.currentUser!==null}static getReferrerExperience(){return i.currentUser?.referrerExperience}static ensureUserReady(){return i.currentUser?Promise.resolve(i.currentUser):(i.userReadyPromise||(i.userReadyPromise=new Promise(e=>{i.userReadyResolver=e})),i.userReadyPromise)}static async getNewUserExperience(){return i.ensureInitialized(),i.api.getNewUserExperience()}};P(i,"api"),P(i,"options"),P(i,"currentUser",null),P(i,"referralObject",null),P(i,"initialized",!1),P(i,"userReadyPromise",null),P(i,"userReadyResolver",null);var g=i;var f=N(require("react"));var n=N(require("react")),t=require("react-native");var{width:se,height:te}=t.Dimensions.get("window"),re=({visible:a,options:e,onClose:r})=>{let[o,l]=(0,n.useState)(null),[c,p]=(0,n.useState)(!1),[m,T]=(0,n.useState)(!1),u=(0,n.useRef)(new t.Animated.Value(0)).current,d=(0,n.useRef)(new t.Animated.Value(0)).current,y=e?.title||"Invite Friends & Earn",R=e?.theme?.primaryColor||"#2563eb",G=e?.theme?.backgroundColor||"#ffffff",D=e?.theme?.tintColor||"#000000",X=e?.theme?.tintAlpha??.5,C=(e?.componentType||"modal")==="drawer",S=e?.position||"bottom-right",Q="#111827",M="#6b7280";(0,n.useEffect)(()=>{a?(o||Z(),t.Animated.parallel([t.Animated.timing(d,{toValue:1,duration:300,useNativeDriver:!0}),t.Animated.spring(u,{toValue:1,useNativeDriver:!0,tension:50,friction:8})]).start()):(u.setValue(0),d.setValue(0))},[a]);let L=()=>{t.Animated.parallel([t.Animated.timing(d,{toValue:0,duration:250,useNativeDriver:!0}),t.Animated.timing(u,{toValue:0,duration:250,useNativeDriver:!0})]).start(()=>{r()})},Z=async()=>{p(!0);try{if(g.isUserReady()){let A=await g.createReferralLink();l(A.referralLink)}}catch(A){console.error("GrowthRail: Failed to load referral link",A)}finally{p(!1)}},_=()=>{o&&(t.Clipboard.setString(o),T(!0),setTimeout(()=>T(!1),2e3))},I=A=>{if(!o)return;let O="",F=encodeURIComponent(o),ee=encodeURIComponent("Check this out!");switch(A){case"twitter":O=`https://twitter.com/intent/tweet?url=${F}&text=${ee}`;break;case"facebook":O=`https://www.facebook.com/sharer/sharer.php?u=${F}`;break;case"linkedin":O=`https://www.linkedin.com/sharing/share-offsite/?url=${F}`;break;case"whatsapp":O=`whatsapp://send?text=${ee}%20${F}`;break;case"email":O=`mailto:?subject=Check this out&body=${ee}%20${F}`;break}O&&t.Linking.openURL(O).catch(()=>{})},k=()=>{if(D.startsWith("#")){let A=parseInt(D.slice(1,3),16),O=parseInt(D.slice(3,5),16),F=parseInt(D.slice(5,7),16);return`rgba(${A}, ${O}, ${F}, ${X})`}return`rgba(0, 0, 0, ${X})`},W=[];C?S.includes("right")?W=[{translateX:u.interpolate({inputRange:[0,1],outputRange:[se,0]})}]:S.includes("left")?W=[{translateX:u.interpolate({inputRange:[0,1],outputRange:[-se,0]})}]:W=[{translateY:u.interpolate({inputRange:[0,1],outputRange:[te,0]})}]:W=[{scale:u.interpolate({inputRange:[0,1],outputRange:[.9,1]})},{translateY:u.interpolate({inputRange:[0,1],outputRange:[20,0]})}];let de=S.includes("top"),V=S.includes("right"),z=S.includes("left"),fe=C?{position:"absolute",...de?{top:100}:{bottom:100},...V?{right:0}:z?{left:0}:{left:0,right:0},width:V||z?"85%":"100%",maxHeight:V||z?te-200:"80%"}:{};return n.default.createElement(t.Modal,{visible:a,transparent:!0,animationType:"none",onRequestClose:L},n.default.createElement(t.View,{style:s.fullScreen},n.default.createElement(t.Animated.View,{style:[s.overlay,{backgroundColor:k(),opacity:d}]},n.default.createElement(t.TouchableOpacity,{style:s.fullScreen,activeOpacity:1,onPress:L})),n.default.createElement(t.Animated.View,{style:[C?fe:s.centeredModalContainer,{backgroundColor:G,transform:W},C&&V&&{borderTopLeftRadius:24,borderBottomLeftRadius:24},C&&z&&{borderTopRightRadius:24,borderBottomRightRadius:24},C&&!V&&!z&&S.includes("bottom")&&{borderTopLeftRadius:24,borderTopRightRadius:24},C&&!V&&!z&&S.includes("top")&&{borderBottomLeftRadius:24,borderBottomRightRadius:24},!C&&{borderRadius:24,opacity:u}]},n.default.createElement(t.View,{style:s.contentWrapper},C&&!V&&!z&&S.includes("bottom")&&n.default.createElement(t.View,{style:s.drawerHandle}),n.default.createElement(t.TouchableOpacity,{style:s.closeBtn,onPress:L},n.default.createElement(t.Text,{style:s.closeIcon},"\u2715")),n.default.createElement(t.ScrollView,{contentContainerStyle:s.scrollContent,showsVerticalScrollIndicator:!1},n.default.createElement(t.View,{style:s.header},n.default.createElement(t.Text,{style:s.iconLg},"\u{1F381}"),n.default.createElement(t.Text,{style:[s.title,{color:Q}]},y),n.default.createElement(t.Text,{style:[s.subtitle,{color:M}]},e?.description||"Share your unique link and earn rewards for every friend who signs up.")),g.isUserReady()?c?n.default.createElement(t.ActivityIndicator,{size:"large",color:R,style:s.loader}):n.default.createElement(t.View,{style:s.mainContent},n.default.createElement(t.Text,{style:s.label},"YOUR UNIQUE LINK"),n.default.createElement(t.View,{style:s.inputGroup},n.default.createElement(t.Text,{numberOfLines:1,style:s.input},o||"Initializing..."),n.default.createElement(t.TouchableOpacity,{style:[s.copyBtn,{backgroundColor:m?"#10b981":R}],onPress:_},n.default.createElement(t.Text,{style:s.copyBtnText},m?"Copied!":"Copy"))),n.default.createElement(t.View,{style:s.shareLabelContainer},n.default.createElement(t.View,{style:s.divider}),n.default.createElement(t.Text,{style:s.shareLabel},"Share via"),n.default.createElement(t.View,{style:s.divider})),n.default.createElement(t.View,{style:s.socialContainer},n.default.createElement(K,{platform:"twitter",color:"#000000",onPress:()=>I("twitter"),icon:"\u{1D54F}"}),n.default.createElement(K,{platform:"facebook",color:"#1877F2",onPress:()=>I("facebook"),icon:"f"}),n.default.createElement(K,{platform:"linkedin",color:"#0A66C2",onPress:()=>I("linkedin"),icon:"in"}),n.default.createElement(K,{platform:"whatsapp",color:"#25D366",onPress:()=>I("whatsapp"),icon:"W"}),n.default.createElement(K,{platform:"email",color:"#888888",onPress:()=>I("email"),icon:"\u2709"}))):n.default.createElement(t.View,{style:s.loadingBox},n.default.createElement(t.Text,{style:{color:M,textAlign:"center"}},"Please log in to view your referral dashboard.")),n.default.createElement(t.View,{style:s.footer},n.default.createElement(t.Text,{style:s.poweredBy},"Powered by ",n.default.createElement(t.Text,{style:s.brand,onPress:()=>t.Linking.openURL("https://growthrail.com")},"Growth Rail"))))))))},K=({color:a,onPress:e,icon:r})=>n.default.createElement(t.TouchableOpacity,{style:[s.socialBtn,{borderColor:"#e5e7eb"}],onPress:e},n.default.createElement(t.Text,{style:[s.socialIcon,{color:a}]},r)),s=t.StyleSheet.create({fullScreen:{flex:1},overlay:{...t.StyleSheet.absoluteFillObject},centeredModalContainer:{width:"90%",maxWidth:400,alignSelf:"center",marginTop:te*.15,overflow:"hidden",shadowColor:"#000",shadowOffset:{width:0,height:20},shadowOpacity:.25,shadowRadius:30,elevation:20},contentWrapper:{paddingTop:t.Platform.OS==="ios"?20:0},drawerHandle:{width:40,height:4,backgroundColor:"#e5e7eb",borderRadius:2,alignSelf:"center",marginTop:12},scrollContent:{padding:32,alignItems:"center"},closeBtn:{position:"absolute",top:20,right:20,zIndex:10,width:32,height:32,borderRadius:16,backgroundColor:"#f3f4f6",justifyContent:"center",alignItems:"center"},closeIcon:{fontSize:14,color:"#9ca3af"},header:{alignItems:"center",marginBottom:28},iconLg:{fontSize:32,marginBottom:12},title:{fontSize:22,fontWeight:"700",letterSpacing:-.5,marginBottom:8,textAlign:"center"},subtitle:{fontSize:14,lineHeight:20,textAlign:"center",paddingHorizontal:10},loadingBox:{padding:16,backgroundColor:"#f9fafb",borderRadius:12,width:"100%",alignItems:"center"},loader:{marginVertical:20},mainContent:{width:"100%"},label:{fontSize:12,fontWeight:"600",color:"#6b7280",marginBottom:8,letterSpacing:.5},inputGroup:{flexDirection:"row",alignItems:"center",backgroundColor:"#f9fafb",borderWidth:1,borderColor:"#e5e7eb",borderRadius:12,padding:6,marginBottom:24},input:{flex:1,paddingHorizontal:12,fontSize:14,color:"#111827",fontFamily:t.Platform.OS==="ios"?"Menlo":"monospace"},copyBtn:{paddingVertical:8,paddingHorizontal:16,borderRadius:8},copyBtnText:{color:"#fff",fontSize:13,fontWeight:"600"},shareLabelContainer:{flexDirection:"row",alignItems:"center",marginBottom:16},divider:{flex:1,height:1,backgroundColor:"#e5e7eb"},shareLabel:{marginHorizontal:12,fontSize:13,fontWeight:"500",color:"#6b7280"},socialContainer:{flexDirection:"row",justifyContent:"center",gap:12},socialBtn:{width:44,height:44,borderRadius:22,backgroundColor:"#fff",borderWidth:1,justifyContent:"center",alignItems:"center"},socialIcon:{fontSize:18,fontWeight:"bold"},footer:{marginTop:32,alignItems:"center"},poweredBy:{fontSize:11,color:"#9ca3af"},brand:{fontWeight:"600",textDecorationLine:"underline"}});var v=N(require("react")),w=require("react-native"),ie=({onPress:a,options:e})=>{let r=e?.modal?.theme?.primaryColor||"#2563eb",o=e?.trigger?.position||"bottom-right",c=(e?.trigger?.displayMode||"floating")==="edge",p=o.includes("right"),m=o.includes("top"),T=(0,v.useRef)(new w.Animated.Value(-1)).current;(0,v.useEffect)(()=>{let R=()=>{T.setValue(-1),w.Animated.timing(T,{toValue:2,duration:3e3,easing:w.Easing.linear,useNativeDriver:!0}).start(()=>{setTimeout(R,1e3)})};R()},[]);let u=T.interpolate({inputRange:[-1,2],outputRange:c?[-50,100]:[-60,120]}),d={"bottom-right":{bottom:100,right:0},"bottom-left":{bottom:100,left:0},"top-right":{top:100,right:0},"top-left":{top:100,left:0}};c||(d["bottom-right"]={bottom:30,right:20},d["bottom-left"]={bottom:30,left:20},d["top-right"]={top:60,right:20},d["top-left"]={top:60,left:20});let y=()=>v.default.createElement(w.View,{style:U.iconContainer},v.default.createElement(w.View,{style:U.giftBody},v.default.createElement(w.View,{style:U.giftLid}),v.default.createElement(w.View,{style:U.giftRibbonV}),v.default.createElement(w.View,{style:U.giftRibbonH})));return v.default.createElement(w.TouchableOpacity,{style:[c?U.edgeButton:U.floatingButton,{backgroundColor:r},d[o],c&&(p?U.edgeRight:U.edgeLeft)],onPress:a,activeOpacity:.9},v.default.createElement(w.View,{style:U.content},y()),v.default.createElement(w.Animated.View,{style:[U.shimmer,{transform:[{translateX:u},{skewX:"-15deg"}]}]}))},U=w.StyleSheet.create({floatingButton:{position:"absolute",width:60,height:60,borderRadius:30,justifyContent:"center",alignItems:"center",overflow:"hidden",shadowColor:"#000",shadowOffset:{width:0,height:8},shadowOpacity:.2,shadowRadius:12,elevation:8,zIndex:2147483646},edgeButton:{position:"absolute",width:50,height:50,justifyContent:"center",alignItems:"center",overflow:"hidden",shadowColor:"#000",shadowOffset:{width:0,height:4},shadowOpacity:.1,shadowRadius:8,elevation:4,zIndex:2147483646},edgeRight:{borderTopLeftRadius:8,borderBottomLeftRadius:8,paddingLeft:4},edgeLeft:{borderTopRightRadius:8,borderBottomRightRadius:8,paddingRight:4},content:{justifyContent:"center",alignItems:"center"},iconContainer:{width:24,height:24,justifyContent:"center",alignItems:"center"},giftBody:{width:16,height:14,backgroundColor:"rgba(255, 255, 255, 0.9)",borderRadius:1.5,marginTop:3,position:"relative"},giftLid:{position:"absolute",top:-3,left:-1.5,width:19,height:3,backgroundColor:"#fff",borderRadius:.5},giftRibbonV:{position:"absolute",top:-3,left:7,width:2.5,height:17,backgroundColor:"rgba(0, 0, 0, 0.1)"},giftRibbonH:{position:"absolute",top:5,left:0,width:16,height:2,backgroundColor:"rgba(0, 0, 0, 0.05)"},shimmer:{position:"absolute",top:0,left:0,width:50,height:"100%",backgroundColor:"rgba(255, 255, 255, 0.25)"}});var x=N(require("react")),h=require("react-native"),{width:Re}=h.Dimensions.get("window"),le=({visible:a,options:e,onClose:r})=>{let o=(0,x.useRef)(new h.Animated.Value(0)).current,[l,c]=(0,x.useState)(a),p=e.position.includes("bottom")?"bottom":"top",m=e.position.includes("left")?"left":e.position.includes("right")?"right":"center";if((0,x.useEffect)(()=>{a?(c(!0),h.Animated.spring(o,{toValue:1,useNativeDriver:!0,tension:50,friction:8}).start()):h.Animated.timing(o,{toValue:0,duration:250,useNativeDriver:!0}).start(()=>{c(!1)})},[a]),!l)return null;let T=o.interpolate({inputRange:[0,1],outputRange:[p==="top"?-100:100,0]}),u=o.interpolate({inputRange:[0,1],outputRange:[0,1]}),d={position:"absolute",[p]:h.Platform.OS==="ios"?60:40,zIndex:9999};return m==="center"?(d.left=20,d.right=20,d.alignItems="center"):d[m]=20,x.default.createElement(h.Animated.View,{style:[d,{transform:[{translateY:T}],opacity:u}]},x.default.createElement(h.View,{style:[q.banner,{backgroundColor:e.themeColor||"#2563eb"}]},x.default.createElement(h.Text,{style:q.icon},"\u{1F381}"),x.default.createElement(h.Text,{style:q.text},e.text),x.default.createElement(h.TouchableOpacity,{onPress:r,style:q.closeBtn},x.default.createElement(h.Text,{style:q.closeIcon},"\u2715"))))},q=h.StyleSheet.create({banner:{flexDirection:"row",alignItems:"center",padding:12,paddingHorizontal:16,borderRadius:12,shadowColor:"#000",shadowOffset:{width:0,height:4},shadowOpacity:.15,shadowRadius:10,elevation:5,maxWidth:Re-40},icon:{fontSize:18,marginRight:10},text:{color:"#fff",fontSize:14,fontWeight:"600",flex:1},closeBtn:{marginLeft:10,padding:4},closeIcon:{color:"rgba(255, 255, 255, 0.8)",fontSize:14,fontWeight:"bold"}});var ce=(0,f.createContext)(void 0),ke=({children:a,userId:e,...r})=>{let[o,l]=(0,f.useState)(g.isInitialized()),[c,p]=(0,f.useState)(g.isUserReady()),m=(0,f.useRef)(!1),[T,u]=(0,f.useState)(!1),[d,y]=(0,f.useState)(),[R,G]=(0,f.useState)(!1),[D,X]=(0,f.useState)(),[J,C]=(0,f.useState)(!1),[S,Q]=(0,f.useState)();(0,f.useEffect)(()=>{if(m.current)return;m.current=!0,(async()=>{if(await g.init(r),e)try{let k=await g.initAppUser(e);p(!0),k.referrerExperience?.trigger?.show&&G(!0)}catch(k){console.error("GrowthRail: User init failed",k)}try{let k=await g.getNewUserExperience();k.banner?.show&&(Q(k.banner),C(!0))}catch{}l(!0)})()},[]),(0,f.useEffect)(()=>{(async()=>{if(m.current&&e&&g.getUserId()!==e)try{let k=await g.initAppUser(e);p(!0),k.referrerExperience?.trigger?.show&&G(!0)}catch(k){console.error("GrowthRail: User init failed",k)}})()},[e]);let M={isInitialized:o,isUserReady:c,showDashboard:I=>{y(I),u(!0)},hideDashboard:()=>u(!1),showFloatingButton:I=>{X({trigger:I}),G(!0)},hideFloatingButton:()=>G(!1)};if(!o)return null;let L=g.getReferrerExperience(),Z={...L?.modal,...d,position:L?.trigger?.position||d?.position||"bottom-right",theme:{...L?.modal?.theme||{},...d?.theme||{}}},_={...L,...D,trigger:{...L?.trigger||{},...D?.trigger||{}}};return f.default.createElement(ce.Provider,{value:M},a,f.default.createElement(re,{visible:T,options:Z,onClose:()=>u(!1)}),R&&f.default.createElement(ie,{options:_,onPress:()=>M.showDashboard()}),J&&f.default.createElement(le,{visible:J,options:S,onClose:()=>C(!1)}))},oe=()=>{let a=(0,f.useContext)(ce);if(!a)throw new Error("useGrowthRail must be used within a GrowthRailProvider");return a};var E=require("react");var ve=()=>{let[a,e]=(0,E.useState)(!1),[r,o]=(0,E.useState)(null),l=oe(),c=(0,E.useCallback)(async d=>{e(!0),o(null);try{return await g.initAppUser(d)}catch(y){let R=y instanceof Error?y:new Error(String(y));throw o(R),R}finally{e(!1)}},[]),p=(0,E.useCallback)(async d=>{e(!0),o(null);try{await g.trackRewardEvent(d)}catch(y){let R=y instanceof Error?y:new Error(String(y));throw o(R),R}finally{e(!1)}},[]),m=(0,E.useCallback)(d=>{l.showDashboard(d)},[l]),T=(0,E.useCallback)(d=>{l.showFloatingButton(d)},[l]),u=(0,E.useCallback)(()=>{l.hideFloatingButton()},[l]);return{initUser:c,trackReward:p,showReferralDashboard:m,showFloatingButton:T,hideFloatingButton:u,isLoading:a,isInitialized:l.isInitialized,error:r}};0&&(module.exports={APIClient,GrowthRail,GrowthRailProvider,ReferralDashboard,StorageManager,TriggerButton,useGrowthRail,useGrowthRailContext});
package/dist/index.mjs ADDED
@@ -0,0 +1 @@
1
+ var ve=Object.defineProperty;var xe=(l,e,r)=>e in l?ve(l,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):l[e]=r;var v=(l,e,r)=>xe(l,typeof e!="symbol"?e+"":e,r);import{Linking as se,Platform as A,Dimensions as Te,PixelRatio as Ce}from"react-native";import Ie from"react-native-play-install-referrer";var K=class{constructor(e){v(this,"baseUrl");v(this,"apiKey");let r=typeof process<"u"&&process.env?.ENV_BASE_URL;this.baseUrl=r||"https://api.growthrail.dev",this.apiKey=e.apiKey}async request(e,r,i){let c={"Content-Type":"application/json","X-GrowthRail-ProjectSecret":this.apiKey,Origin:this.baseUrl};try{let a=await fetch(`${this.baseUrl}${e}`,{method:r,headers:c,body:i?JSON.stringify(i):void 0});if(!a.ok){let d="";try{d=await a.text()}catch{}throw new Error(`GrowthRail API Error ${a.status} (${this.baseUrl}${e}): ${a.statusText} - ${d}`)}return a.json()}catch(a){throw console.error("GrowthRail SDK Error:",a),a}}async getNewUserExperience(){return this.request("/api/v1/sdk/new-user-experience","POST")}async initAppUser(e){return this.request("/api/v1/sdk/init-app-user","POST",{clientProvidedId:e})}async createReferralLink(e,r){return this.request("/api/v1/sdk/create-referral-link","POST",{referrerId:e,rewardEventName:r})}async trackReferral(e,r){return this.request("/api/v1/sdk/track-referral","POST",{referralCode:e,rewardEventName:r})}async trackRewardEvent(e,r,i){return this.request("/api/v1/sdk/track-reward-event","POST",{refereeId:e,referralTrackingId:r,eventName:i})}async checkDeferredDeepLink(e){return this.request("/api/v1/sdk/match-link","POST",{fingerprint:e})}};import q from"@react-native-async-storage/async-storage";var X={TRACKED_REFERRAL:"growth-rail-tracked-referral",IS_FIRST_LAUNCH:"growth-rail-is-first-launch"},U=class{static async setTrackedReferral(e){await q.setItem(X.TRACKED_REFERRAL,e)}static async getTrackedReferral(){return await q.getItem(X.TRACKED_REFERRAL)}static async isFirstLaunch(){return await q.getItem(X.IS_FIRST_LAUNCH)===null?(await q.setItem(X.IS_FIRST_LAUNCH,"false"),!0):!1}};var t=class t{constructor(){}static async init(e){t.initialized||(t.options=e,t.api=new K(e),t.initialized=!0,await t.handleInitialUrl(),await t.setupLinkListeners(),await t.checkDeferredReferral())}static async handleInitialUrl(){try{let e=await se.getInitialURL();e&&await t.handleDeepLink(e)}catch(e){console.error("GrowthRail: Error getting initial URL",e)}}static setupLinkListeners(){se.addEventListener("url",({url:e})=>{t.handleDeepLink(e)})}static async checkDeferredReferral(){await U.isFirstLaunch()&&(A.OS==="android"?await t.checkInstallReferrer():await t.checkDeferredDeepLinkFingerprint())}static checkInstallReferrer(){return new Promise(e=>{Ie.getInstallReferrerInfo(async(r,i)=>{if(!i&&r&&r.installReferrer)try{let a=decodeURIComponent(r.installReferrer).match(/[?&]referralCode=([^&]+)/);if(a){let{referralTrackingId:d}=await t.trackReferral(a[1]);await U.setTrackedReferral(d),console.log("GrowthRail: Tracked referral via Install Referrer")}}catch(c){console.warn("GrowthRail: Failed to process install referrer",c)}else await t.checkDeferredDeepLinkFingerprint();e()})})}static getDeviceFingerprint(){let{width:e,height:r}=Te.get("window"),i=Intl.DateTimeFormat().resolvedOptions().locale,c=Ce.get(),a,d;if(A.OS==="android"){let u=A.constants;a=u.Model,d=u.Brand||u.Manufacturer}return{os:A.OS,platform:A.OS,osVersion:String(A.Version),screenWidth:e,screenHeight:r,timezoneOffsetInMinutes:String(new Date().getTimezoneOffset()),locale:i,language:i,deviceModel:a,deviceBrand:d,pixelRatio:c}}static async checkDeferredDeepLinkFingerprint(){try{let e=t.getDeviceFingerprint();console.log("GrowthRail executing deferred fingerprint check to API...");let{referralTrackingId:r}=await t.api.checkDeferredDeepLink(e);r&&(console.log("GrowthRail: Found deferred referral via fingerprinting",r),await U.setTrackedReferral(r))}catch(e){console.warn("GrowthRail: Fingerprint check failed",e)}}static async handleDeepLink(e){try{let r=new URL(e),i=r.searchParams.get("referralCode"),c=r.searchParams.get("rewardEventName");i&&(console.log("GrowthRail: Tracking referral from deep link",i),await t.trackReferral(i,c||void 0))}catch{let i=e.match(/[?&]referralCode=([^&]+)/);i&&await t.trackReferral(i[1])}}static ensureInitialized(){if(!t.initialized)throw new Error("GrowthRail.init() must be called before using the SDK")}static async initAppUser(e){t.ensureInitialized();let r=await t.api.initAppUser(e);return t.currentUser={...r,id:e},t.userReadyResolver&&t.userReadyResolver(t.currentUser),r}static async trackReferral(e,r){t.ensureInitialized();let i=await t.api.trackReferral(e,r);return await U.setTrackedReferral(i.referralTrackingId),i}static async trackRewardEvent(e){t.ensureInitialized();let r=t.currentUser?.id;if(!r)throw new Error("GrowthRail: User must be initialized before tracking a reward event.");let i=await U.getTrackedReferral();if(!i){console.warn("GrowthRail: No referral tracking ID found. Reward event not attributed.");return}return t.api.trackRewardEvent(r,i,e)}static async createReferralLink(e){t.ensureInitialized();let r=t.currentUser?.id;if(!r)throw new Error("GrowthRail: User must be initialized before creating a referral link.");if(t.referralObject)return t.referralObject;let i=await t.api.createReferralLink(r,e);return t.referralObject=i,i}static isInitialized(){return t.initialized}static getReferralLink(){if(!t.referralObject?.referralLink)throw new Error("GrowthRail: Referral Link not loaded or user not initialized");return t.referralObject.referralLink}static getReferralCode(){return t.referralObject?.referralCode||t.currentUser?.referralCode}static getUserId(){return t.currentUser?.id}static isUserReady(){return t.currentUser!==null}static getReferrerExperience(){return t.currentUser?.referrerExperience}static ensureUserReady(){return t.currentUser?Promise.resolve(t.currentUser):(t.userReadyPromise||(t.userReadyPromise=new Promise(e=>{t.userReadyResolver=e})),t.userReadyPromise)}static async getNewUserExperience(){return t.ensureInitialized(),t.api.getNewUserExperience()}};v(t,"api"),v(t,"options"),v(t,"currentUser",null),v(t,"referralObject",null),v(t,"initialized",!1),v(t,"userReadyPromise",null),v(t,"userReadyResolver",null);var p=t;import Q,{createContext as qe,useContext as Xe,useEffect as me,useState as L,useRef as Ye}from"react";import o,{useEffect as Pe,useState as ie,useRef as le}from"react";import{Modal as Ue,View as b,Text as R,StyleSheet as ce,TouchableOpacity as Y,Clipboard as Se,ActivityIndicator as Le,Linking as de,ScrollView as Oe,Platform as fe,Animated as C,Dimensions as Be}from"react-native";var{width:pe,height:oe}=Be.get("window"),ue=({visible:l,options:e,onClose:r})=>{let[i,c]=ie(null),[a,d]=ie(!1),[u,w]=ie(!1),f=le(new C.Value(0)).current,s=le(new C.Value(0)).current,g=e?.title||"Invite Friends & Earn",h=e?.theme?.primaryColor||"#2563eb",z=e?.theme?.backgroundColor||"#ffffff",O=e?.theme?.tintColor||"#000000",H=e?.theme?.tintAlpha??.5,y=(e?.componentType||"modal")==="drawer",T=e?.position||"bottom-right",_="#111827",N="#6b7280";Pe(()=>{l?(i||ee(),C.parallel([C.timing(s,{toValue:1,duration:300,useNativeDriver:!0}),C.spring(f,{toValue:1,useNativeDriver:!0,tension:50,friction:8})]).start()):(f.setValue(0),s.setValue(0))},[l]);let I=()=>{C.parallel([C.timing(s,{toValue:0,duration:250,useNativeDriver:!0}),C.timing(f,{toValue:0,duration:250,useNativeDriver:!0})]).start(()=>{r()})},ee=async()=>{d(!0);try{if(p.isUserReady()){let D=await p.createReferralLink();c(D.referralLink)}}catch(D){console.error("GrowthRail: Failed to load referral link",D)}finally{d(!1)}},te=()=>{i&&(Se.setString(i),w(!0),setTimeout(()=>w(!1),2e3))},k=D=>{if(!i)return;let P="",V=encodeURIComponent(i),re=encodeURIComponent("Check this out!");switch(D){case"twitter":P=`https://twitter.com/intent/tweet?url=${V}&text=${re}`;break;case"facebook":P=`https://www.facebook.com/sharer/sharer.php?u=${V}`;break;case"linkedin":P=`https://www.linkedin.com/sharing/share-offsite/?url=${V}`;break;case"whatsapp":P=`whatsapp://send?text=${re}%20${V}`;break;case"email":P=`mailto:?subject=Check this out&body=${re}%20${V}`;break}P&&de.openURL(P).catch(()=>{})},m=()=>{if(O.startsWith("#")){let D=parseInt(O.slice(1,3),16),P=parseInt(O.slice(3,5),16),V=parseInt(O.slice(5,7),16);return`rgba(${D}, ${P}, ${V}, ${H})`}return`rgba(0, 0, 0, ${H})`},M=[];y?T.includes("right")?M=[{translateX:f.interpolate({inputRange:[0,1],outputRange:[pe,0]})}]:T.includes("left")?M=[{translateX:f.interpolate({inputRange:[0,1],outputRange:[-pe,0]})}]:M=[{translateY:f.interpolate({inputRange:[0,1],outputRange:[oe,0]})}]:M=[{scale:f.interpolate({inputRange:[0,1],outputRange:[.9,1]})},{translateY:f.interpolate({inputRange:[0,1],outputRange:[20,0]})}];let Re=T.includes("top"),B=T.includes("right"),E=T.includes("left"),ke=y?{position:"absolute",...Re?{top:100}:{bottom:100},...B?{right:0}:E?{left:0}:{left:0,right:0},width:B||E?"85%":"100%",maxHeight:B||E?oe-200:"80%"}:{};return o.createElement(Ue,{visible:l,transparent:!0,animationType:"none",onRequestClose:I},o.createElement(b,{style:n.fullScreen},o.createElement(C.View,{style:[n.overlay,{backgroundColor:m(),opacity:s}]},o.createElement(Y,{style:n.fullScreen,activeOpacity:1,onPress:I})),o.createElement(C.View,{style:[y?ke:n.centeredModalContainer,{backgroundColor:z,transform:M},y&&B&&{borderTopLeftRadius:24,borderBottomLeftRadius:24},y&&E&&{borderTopRightRadius:24,borderBottomRightRadius:24},y&&!B&&!E&&T.includes("bottom")&&{borderTopLeftRadius:24,borderTopRightRadius:24},y&&!B&&!E&&T.includes("top")&&{borderBottomLeftRadius:24,borderBottomRightRadius:24},!y&&{borderRadius:24,opacity:f}]},o.createElement(b,{style:n.contentWrapper},y&&!B&&!E&&T.includes("bottom")&&o.createElement(b,{style:n.drawerHandle}),o.createElement(Y,{style:n.closeBtn,onPress:I},o.createElement(R,{style:n.closeIcon},"\u2715")),o.createElement(Oe,{contentContainerStyle:n.scrollContent,showsVerticalScrollIndicator:!1},o.createElement(b,{style:n.header},o.createElement(R,{style:n.iconLg},"\u{1F381}"),o.createElement(R,{style:[n.title,{color:_}]},g),o.createElement(R,{style:[n.subtitle,{color:N}]},e?.description||"Share your unique link and earn rewards for every friend who signs up.")),p.isUserReady()?a?o.createElement(Le,{size:"large",color:h,style:n.loader}):o.createElement(b,{style:n.mainContent},o.createElement(R,{style:n.label},"YOUR UNIQUE LINK"),o.createElement(b,{style:n.inputGroup},o.createElement(R,{numberOfLines:1,style:n.input},i||"Initializing..."),o.createElement(Y,{style:[n.copyBtn,{backgroundColor:u?"#10b981":h}],onPress:te},o.createElement(R,{style:n.copyBtnText},u?"Copied!":"Copy"))),o.createElement(b,{style:n.shareLabelContainer},o.createElement(b,{style:n.divider}),o.createElement(R,{style:n.shareLabel},"Share via"),o.createElement(b,{style:n.divider})),o.createElement(b,{style:n.socialContainer},o.createElement(W,{platform:"twitter",color:"#000000",onPress:()=>k("twitter"),icon:"\u{1D54F}"}),o.createElement(W,{platform:"facebook",color:"#1877F2",onPress:()=>k("facebook"),icon:"f"}),o.createElement(W,{platform:"linkedin",color:"#0A66C2",onPress:()=>k("linkedin"),icon:"in"}),o.createElement(W,{platform:"whatsapp",color:"#25D366",onPress:()=>k("whatsapp"),icon:"W"}),o.createElement(W,{platform:"email",color:"#888888",onPress:()=>k("email"),icon:"\u2709"}))):o.createElement(b,{style:n.loadingBox},o.createElement(R,{style:{color:N,textAlign:"center"}},"Please log in to view your referral dashboard.")),o.createElement(b,{style:n.footer},o.createElement(R,{style:n.poweredBy},"Powered by ",o.createElement(R,{style:n.brand,onPress:()=>de.openURL("https://growthrail.com")},"Growth Rail"))))))))},W=({color:l,onPress:e,icon:r})=>o.createElement(Y,{style:[n.socialBtn,{borderColor:"#e5e7eb"}],onPress:e},o.createElement(R,{style:[n.socialIcon,{color:l}]},r)),n=ce.create({fullScreen:{flex:1},overlay:{...ce.absoluteFillObject},centeredModalContainer:{width:"90%",maxWidth:400,alignSelf:"center",marginTop:oe*.15,overflow:"hidden",shadowColor:"#000",shadowOffset:{width:0,height:20},shadowOpacity:.25,shadowRadius:30,elevation:20},contentWrapper:{paddingTop:fe.OS==="ios"?20:0},drawerHandle:{width:40,height:4,backgroundColor:"#e5e7eb",borderRadius:2,alignSelf:"center",marginTop:12},scrollContent:{padding:32,alignItems:"center"},closeBtn:{position:"absolute",top:20,right:20,zIndex:10,width:32,height:32,borderRadius:16,backgroundColor:"#f3f4f6",justifyContent:"center",alignItems:"center"},closeIcon:{fontSize:14,color:"#9ca3af"},header:{alignItems:"center",marginBottom:28},iconLg:{fontSize:32,marginBottom:12},title:{fontSize:22,fontWeight:"700",letterSpacing:-.5,marginBottom:8,textAlign:"center"},subtitle:{fontSize:14,lineHeight:20,textAlign:"center",paddingHorizontal:10},loadingBox:{padding:16,backgroundColor:"#f9fafb",borderRadius:12,width:"100%",alignItems:"center"},loader:{marginVertical:20},mainContent:{width:"100%"},label:{fontSize:12,fontWeight:"600",color:"#6b7280",marginBottom:8,letterSpacing:.5},inputGroup:{flexDirection:"row",alignItems:"center",backgroundColor:"#f9fafb",borderWidth:1,borderColor:"#e5e7eb",borderRadius:12,padding:6,marginBottom:24},input:{flex:1,paddingHorizontal:12,fontSize:14,color:"#111827",fontFamily:fe.OS==="ios"?"Menlo":"monospace"},copyBtn:{paddingVertical:8,paddingHorizontal:16,borderRadius:8},copyBtnText:{color:"#fff",fontSize:13,fontWeight:"600"},shareLabelContainer:{flexDirection:"row",alignItems:"center",marginBottom:16},divider:{flex:1,height:1,backgroundColor:"#e5e7eb"},shareLabel:{marginHorizontal:12,fontSize:13,fontWeight:"500",color:"#6b7280"},socialContainer:{flexDirection:"row",justifyContent:"center",gap:12},socialBtn:{width:44,height:44,borderRadius:22,backgroundColor:"#fff",borderWidth:1,justifyContent:"center",alignItems:"center"},socialIcon:{fontSize:18,fontWeight:"bold"},footer:{marginTop:32,alignItems:"center"},poweredBy:{fontSize:11,color:"#9ca3af"},brand:{fontWeight:"600",textDecorationLine:"underline"}});import S,{useEffect as Ee,useRef as De}from"react";import{TouchableOpacity as Ve,View as F,StyleSheet as ze,Animated as ne,Easing as Ae}from"react-native";var ge=({onPress:l,options:e})=>{let r=e?.modal?.theme?.primaryColor||"#2563eb",i=e?.trigger?.position||"bottom-right",a=(e?.trigger?.displayMode||"floating")==="edge",d=i.includes("right"),u=i.includes("top"),w=De(new ne.Value(-1)).current;Ee(()=>{let h=()=>{w.setValue(-1),ne.timing(w,{toValue:2,duration:3e3,easing:Ae.linear,useNativeDriver:!0}).start(()=>{setTimeout(h,1e3)})};h()},[]);let f=w.interpolate({inputRange:[-1,2],outputRange:a?[-50,100]:[-60,120]}),s={"bottom-right":{bottom:100,right:0},"bottom-left":{bottom:100,left:0},"top-right":{top:100,right:0},"top-left":{top:100,left:0}};a||(s["bottom-right"]={bottom:30,right:20},s["bottom-left"]={bottom:30,left:20},s["top-right"]={top:60,right:20},s["top-left"]={top:60,left:20});let g=()=>S.createElement(F,{style:x.iconContainer},S.createElement(F,{style:x.giftBody},S.createElement(F,{style:x.giftLid}),S.createElement(F,{style:x.giftRibbonV}),S.createElement(F,{style:x.giftRibbonH})));return S.createElement(Ve,{style:[a?x.edgeButton:x.floatingButton,{backgroundColor:r},s[i],a&&(d?x.edgeRight:x.edgeLeft)],onPress:l,activeOpacity:.9},S.createElement(F,{style:x.content},g()),S.createElement(ne.View,{style:[x.shimmer,{transform:[{translateX:f},{skewX:"-15deg"}]}]}))},x=ze.create({floatingButton:{position:"absolute",width:60,height:60,borderRadius:30,justifyContent:"center",alignItems:"center",overflow:"hidden",shadowColor:"#000",shadowOffset:{width:0,height:8},shadowOpacity:.2,shadowRadius:12,elevation:8,zIndex:2147483646},edgeButton:{position:"absolute",width:50,height:50,justifyContent:"center",alignItems:"center",overflow:"hidden",shadowColor:"#000",shadowOffset:{width:0,height:4},shadowOpacity:.1,shadowRadius:8,elevation:4,zIndex:2147483646},edgeRight:{borderTopLeftRadius:8,borderBottomLeftRadius:8,paddingLeft:4},edgeLeft:{borderTopRightRadius:8,borderBottomRightRadius:8,paddingRight:4},content:{justifyContent:"center",alignItems:"center"},iconContainer:{width:24,height:24,justifyContent:"center",alignItems:"center"},giftBody:{width:16,height:14,backgroundColor:"rgba(255, 255, 255, 0.9)",borderRadius:1.5,marginTop:3,position:"relative"},giftLid:{position:"absolute",top:-3,left:-1.5,width:19,height:3,backgroundColor:"#fff",borderRadius:.5},giftRibbonV:{position:"absolute",top:-3,left:7,width:2.5,height:17,backgroundColor:"rgba(0, 0, 0, 0.1)"},giftRibbonH:{position:"absolute",top:5,left:0,width:16,height:2,backgroundColor:"rgba(0, 0, 0, 0.05)"},shimmer:{position:"absolute",top:0,left:0,width:50,height:"100%",backgroundColor:"rgba(255, 255, 255, 0.25)"}});import G,{useEffect as Fe,useRef as Ge,useState as Ne}from"react";import{View as Me,Text as ae,StyleSheet as We,Animated as J,Dimensions as $e,TouchableOpacity as je,Platform as He}from"react-native";var{width:Ke}=$e.get("window"),he=({visible:l,options:e,onClose:r})=>{let i=Ge(new J.Value(0)).current,[c,a]=Ne(l),d=e.position.includes("bottom")?"bottom":"top",u=e.position.includes("left")?"left":e.position.includes("right")?"right":"center";if(Fe(()=>{l?(a(!0),J.spring(i,{toValue:1,useNativeDriver:!0,tension:50,friction:8}).start()):J.timing(i,{toValue:0,duration:250,useNativeDriver:!0}).start(()=>{a(!1)})},[l]),!c)return null;let w=i.interpolate({inputRange:[0,1],outputRange:[d==="top"?-100:100,0]}),f=i.interpolate({inputRange:[0,1],outputRange:[0,1]}),s={position:"absolute",[d]:He.OS==="ios"?60:40,zIndex:9999};return u==="center"?(s.left=20,s.right=20,s.alignItems="center"):s[u]=20,G.createElement(J.View,{style:[s,{transform:[{translateY:w}],opacity:f}]},G.createElement(Me,{style:[$.banner,{backgroundColor:e.themeColor||"#2563eb"}]},G.createElement(ae,{style:$.icon},"\u{1F381}"),G.createElement(ae,{style:$.text},e.text),G.createElement(je,{onPress:r,style:$.closeBtn},G.createElement(ae,{style:$.closeIcon},"\u2715"))))},$=We.create({banner:{flexDirection:"row",alignItems:"center",padding:12,paddingHorizontal:16,borderRadius:12,shadowColor:"#000",shadowOffset:{width:0,height:4},shadowOpacity:.15,shadowRadius:10,elevation:5,maxWidth:Ke-40},icon:{fontSize:18,marginRight:10},text:{color:"#fff",fontSize:14,fontWeight:"600",flex:1},closeBtn:{marginLeft:10,padding:4},closeIcon:{color:"rgba(255, 255, 255, 0.8)",fontSize:14,fontWeight:"bold"}});var we=qe(void 0),Tt=({children:l,userId:e,...r})=>{let[i,c]=L(p.isInitialized()),[a,d]=L(p.isUserReady()),u=Ye(!1),[w,f]=L(!1),[s,g]=L(),[h,z]=L(!1),[O,H]=L(),[Z,y]=L(!1),[T,_]=L();me(()=>{if(u.current)return;u.current=!0,(async()=>{if(await p.init(r),e)try{let m=await p.initAppUser(e);d(!0),m.referrerExperience?.trigger?.show&&z(!0)}catch(m){console.error("GrowthRail: User init failed",m)}try{let m=await p.getNewUserExperience();m.banner?.show&&(_(m.banner),y(!0))}catch{}c(!0)})()},[]),me(()=>{(async()=>{if(u.current&&e&&p.getUserId()!==e)try{let m=await p.initAppUser(e);d(!0),m.referrerExperience?.trigger?.show&&z(!0)}catch(m){console.error("GrowthRail: User init failed",m)}})()},[e]);let N={isInitialized:i,isUserReady:a,showDashboard:k=>{g(k),f(!0)},hideDashboard:()=>f(!1),showFloatingButton:k=>{H({trigger:k}),z(!0)},hideFloatingButton:()=>z(!1)};if(!i)return null;let I=p.getReferrerExperience(),ee={...I?.modal,...s,position:I?.trigger?.position||s?.position||"bottom-right",theme:{...I?.modal?.theme||{},...s?.theme||{}}},te={...I,...O,trigger:{...I?.trigger||{},...O?.trigger||{}}};return Q.createElement(we.Provider,{value:N},l,Q.createElement(ue,{visible:w,options:ee,onClose:()=>f(!1)}),h&&Q.createElement(ge,{options:te,onPress:()=>N.showDashboard()}),Z&&Q.createElement(he,{visible:Z,options:T,onClose:()=>y(!1)}))},ye=()=>{let l=Xe(we);if(!l)throw new Error("useGrowthRail must be used within a GrowthRailProvider");return l};import{useState as be,useCallback as j}from"react";var St=()=>{let[l,e]=be(!1),[r,i]=be(null),c=ye(),a=j(async s=>{e(!0),i(null);try{return await p.initAppUser(s)}catch(g){let h=g instanceof Error?g:new Error(String(g));throw i(h),h}finally{e(!1)}},[]),d=j(async s=>{e(!0),i(null);try{await p.trackRewardEvent(s)}catch(g){let h=g instanceof Error?g:new Error(String(g));throw i(h),h}finally{e(!1)}},[]),u=j(s=>{c.showDashboard(s)},[c]),w=j(s=>{c.showFloatingButton(s)},[c]),f=j(()=>{c.hideFloatingButton()},[c]);return{initUser:a,trackReward:d,showReferralDashboard:u,showFloatingButton:w,hideFloatingButton:f,isLoading:l,isInitialized:c.isInitialized,error:r}};export{K as APIClient,p as GrowthRail,Tt as GrowthRailProvider,ue as ReferralDashboard,U as StorageManager,ge as TriggerButton,St as useGrowthRail,ye as useGrowthRailContext};
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "@growth-rail/react-native",
3
+ "version": "0.0.0",
4
+ "description": "Growth Rail SDK for React Native",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "require": "./dist/index.js",
12
+ "import": "./dist/index.mjs"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "README.md",
18
+ "CHANGELOG.md"
19
+ ],
20
+ "scripts": {
21
+ "build": "tsup",
22
+ "dev": "tsup --watch",
23
+ "lint": "eslint src/",
24
+ "type-check": "tsc --noEmit"
25
+ },
26
+ "dependencies": {
27
+ "@react-native-async-storage/async-storage": "^2.1.0",
28
+ "react-native-play-install-referrer": "^1.1.9"
29
+ },
30
+ "peerDependencies": {
31
+ "react": ">=16.8.0",
32
+ "react-native": ">=0.60.0"
33
+ },
34
+ "devDependencies": {
35
+ "@growth-rail/eslint-config": "*",
36
+ "@growth-rail/tsconfig": "*",
37
+ "@types/react": "^18.0.0",
38
+ "@types/react-native": "^0.72.0",
39
+ "tsup": "^8.0.0",
40
+ "typescript": "^5.0.0"
41
+ },
42
+ "publishConfig": {
43
+ "access": "public"
44
+ }
45
+ }