@growth-rail/react 2.0.2 → 2.1.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 +11 -0
- package/README.md +39 -11
- package/dist/index.d.mts +64 -3
- package/dist/index.d.ts +64 -3
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +4 -4
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -29,7 +29,7 @@ pnpm add @growth-rail/react @growth-rail/core
|
|
|
29
29
|
|
|
30
30
|
### 1. Wrap your App with `GrowthRailProvider`
|
|
31
31
|
|
|
32
|
-
Initialize the SDK at the root of your application. Provide your
|
|
32
|
+
Initialize the SDK at the root of your application. Provide your Project Secret Key and optionally a `userId` if the user is already authenticated.
|
|
33
33
|
|
|
34
34
|
```tsx
|
|
35
35
|
import { GrowthRailProvider } from '@growth-rail/react';
|
|
@@ -37,7 +37,7 @@ import { GrowthRailProvider } from '@growth-rail/react';
|
|
|
37
37
|
function App() {
|
|
38
38
|
return (
|
|
39
39
|
<GrowthRailProvider
|
|
40
|
-
|
|
40
|
+
projectSecretKey="your_project_secret_key_here"
|
|
41
41
|
userId="user_123" // Optional: initialize for a specific user
|
|
42
42
|
>
|
|
43
43
|
<your-application-code />
|
|
@@ -48,20 +48,24 @@ function App() {
|
|
|
48
48
|
|
|
49
49
|
### 2. Track Events and Get User Info
|
|
50
50
|
|
|
51
|
-
Use the `useGrowthRail` hook in any child component to track
|
|
51
|
+
Use the `useGrowthRail` hook in any child component to track events or initialize users.
|
|
52
52
|
|
|
53
53
|
```tsx
|
|
54
54
|
import { useGrowthRail } from '@growth-rail/react';
|
|
55
55
|
|
|
56
|
-
export function
|
|
57
|
-
const {
|
|
56
|
+
export function ActionButton() {
|
|
57
|
+
const { trackRewardEvent, isLoading } = useGrowthRail();
|
|
58
58
|
|
|
59
|
-
const
|
|
60
|
-
await
|
|
61
|
-
console.log('
|
|
59
|
+
const handleAction = async () => {
|
|
60
|
+
await trackRewardEvent('purchase_completed');
|
|
61
|
+
console.log('Action tracked!');
|
|
62
62
|
};
|
|
63
63
|
|
|
64
|
-
return
|
|
64
|
+
return (
|
|
65
|
+
<button onClick={handleAction} disabled={isLoading}>
|
|
66
|
+
{isLoading ? 'Processing...' : 'Complete Action'}
|
|
67
|
+
</button>
|
|
68
|
+
);
|
|
65
69
|
}
|
|
66
70
|
```
|
|
67
71
|
|
|
@@ -85,9 +89,33 @@ export function DashboardPage() {
|
|
|
85
89
|
}
|
|
86
90
|
```
|
|
87
91
|
|
|
88
|
-
## 📖
|
|
92
|
+
## 📖 API Reference
|
|
93
|
+
|
|
94
|
+
### `useGrowthRail()`
|
|
95
|
+
|
|
96
|
+
The main hook for interacting with the Growth Rail SDK.
|
|
97
|
+
|
|
98
|
+
**Methods:**
|
|
99
|
+
- `initAppUser(userId)`: Initializes the SDK for a specific user.
|
|
100
|
+
- `trackRewardEvent(eventName?)`: Tracks a custom event for attribution and rewards.
|
|
101
|
+
- `showReferralDashboard(options?)`: Programmatically triggers the referral dashboard modal.
|
|
102
|
+
- `showFloatingButton(options)`: Displays the floating referral trigger button.
|
|
103
|
+
- `hideFloatingButton()`: Removes the floating referral trigger button.
|
|
104
|
+
|
|
105
|
+
**State:**
|
|
106
|
+
- `isLoading`: Boolean indicating if an async operation is pending.
|
|
107
|
+
- `error`: The last error that occurred (if any).
|
|
108
|
+
|
|
109
|
+
### `ReferralDashboard`
|
|
110
|
+
|
|
111
|
+
An inline dashboard component for your application.
|
|
112
|
+
|
|
113
|
+
| Prop | Type | Description |
|
|
114
|
+
| :--- | :--- | :--- |
|
|
115
|
+
| `title` | `string` | Optional title for the dashboard. |
|
|
116
|
+
| `onLinkCopied` | `() => void` | Callback when the referral link is copied. |
|
|
89
117
|
|
|
90
|
-
For full documentation
|
|
118
|
+
For full documentation, visit [docs.growthrail.com](https://docs.growthrail.com).
|
|
91
119
|
|
|
92
120
|
## 📄 License
|
|
93
121
|
|
package/dist/index.d.mts
CHANGED
|
@@ -1,29 +1,90 @@
|
|
|
1
1
|
import React, { ReactNode } from 'react';
|
|
2
2
|
import { GrowthRailOptions, AppUserType, GrowthRail, ReferrerTriggerButton, ReferrerModalOptions } from '@growth-rail/core';
|
|
3
|
-
export { AppUserType, GrowthRailOptions } from '@growth-rail/core';
|
|
3
|
+
export { AppUserType, GrowthRailOptions, ReferrerExperience, ReferrerModalOptions, ReferrerTriggerButton } from '@growth-rail/core';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Props for the GrowthRailProvider component.
|
|
7
|
+
*/
|
|
5
8
|
interface GrowthRailProviderProps extends GrowthRailOptions {
|
|
9
|
+
/** The unique ID for the current application user. */
|
|
6
10
|
userId?: string;
|
|
11
|
+
/** Your application components. */
|
|
7
12
|
children: ReactNode;
|
|
8
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Root provider component for GrowthRail in React applications.
|
|
16
|
+
* This component initializes the SDK and manages the user's authentication state.
|
|
17
|
+
*
|
|
18
|
+
* Wrap your app (or a specific feature tree) with this provider.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* <GrowthRailProvider projectSecretKey="your-api-key" userId="user-123">
|
|
22
|
+
* <App />
|
|
23
|
+
* </GrowthRailProvider>
|
|
24
|
+
*/
|
|
9
25
|
declare const GrowthRailProvider: React.FC<GrowthRailProviderProps>;
|
|
10
26
|
|
|
27
|
+
/**
|
|
28
|
+
* The return type of the useGrowthRail hook.
|
|
29
|
+
*/
|
|
11
30
|
interface UseGrowthRailReturn {
|
|
12
|
-
|
|
13
|
-
|
|
31
|
+
/**
|
|
32
|
+
* Initializes a user in the GrowthRail system.
|
|
33
|
+
* @param userId - Unique identifier for the user.
|
|
34
|
+
*/
|
|
35
|
+
initAppUser: (userId: string) => Promise<AppUserType>;
|
|
36
|
+
/**
|
|
37
|
+
* Tracks a reward-eligible event for the current user.
|
|
38
|
+
* @param eventName - Optional name of the event.
|
|
39
|
+
*/
|
|
40
|
+
trackRewardEvent: (eventName?: string) => Promise<void>;
|
|
41
|
+
/**
|
|
42
|
+
* Manually triggers the referral dashboard modal.
|
|
43
|
+
* @param options - Customization options for the modal.
|
|
44
|
+
*/
|
|
14
45
|
showReferralDashboard: (options?: Parameters<typeof GrowthRail.showReferralDashboard>[0]) => void;
|
|
46
|
+
/**
|
|
47
|
+
* Manually shows or updates the floating referral trigger button.
|
|
48
|
+
* @param options - Configuration for the button.
|
|
49
|
+
*/
|
|
15
50
|
showFloatingButton: (options: Partial<ReferrerTriggerButton>) => void;
|
|
51
|
+
/** Hides the floating referral trigger button. */
|
|
16
52
|
hideFloatingButton: () => void;
|
|
53
|
+
/** Whether an asynchronous operation (like init or track) is in progress. */
|
|
17
54
|
isLoading: boolean;
|
|
55
|
+
/** The last error that occurred during an operation. */
|
|
18
56
|
error: Error | null;
|
|
19
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* A hook that provides access to GrowthRail SDK methods and state.
|
|
60
|
+
*
|
|
61
|
+
* @returns An object containing methods to manage referrals and track state.
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* const { showReferralDashboard, trackRewardEvent } = useGrowthRail();
|
|
65
|
+
*/
|
|
20
66
|
declare const useGrowthRail: () => UseGrowthRailReturn;
|
|
21
67
|
|
|
68
|
+
/**
|
|
69
|
+
* Props for the ReferralDashboard component.
|
|
70
|
+
*/
|
|
22
71
|
interface ReferralDashboardProps {
|
|
72
|
+
/** Optional override for the dashboard title. */
|
|
23
73
|
title?: string;
|
|
74
|
+
/** Customization options for the dashboard's appearance. */
|
|
24
75
|
appearance?: ReferrerModalOptions;
|
|
76
|
+
/** Callback fired when the referral link is copied to the clipboard. */
|
|
25
77
|
onLinkCopied?: () => void;
|
|
26
78
|
}
|
|
79
|
+
/**
|
|
80
|
+
* An inline referral dashboard component.
|
|
81
|
+
* Unlike the global modal, this component renders directly within your layout.
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* <div style={{ height: '500px' }}>
|
|
85
|
+
* <ReferralDashboard title="Invite your team" />
|
|
86
|
+
* </div>
|
|
87
|
+
*/
|
|
27
88
|
declare const ReferralDashboard: React.FC<ReferralDashboardProps>;
|
|
28
89
|
|
|
29
90
|
export { GrowthRailProvider, ReferralDashboard, type ReferralDashboardProps, type UseGrowthRailReturn, useGrowthRail };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,29 +1,90 @@
|
|
|
1
1
|
import React, { ReactNode } from 'react';
|
|
2
2
|
import { GrowthRailOptions, AppUserType, GrowthRail, ReferrerTriggerButton, ReferrerModalOptions } from '@growth-rail/core';
|
|
3
|
-
export { AppUserType, GrowthRailOptions } from '@growth-rail/core';
|
|
3
|
+
export { AppUserType, GrowthRailOptions, ReferrerExperience, ReferrerModalOptions, ReferrerTriggerButton } from '@growth-rail/core';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Props for the GrowthRailProvider component.
|
|
7
|
+
*/
|
|
5
8
|
interface GrowthRailProviderProps extends GrowthRailOptions {
|
|
9
|
+
/** The unique ID for the current application user. */
|
|
6
10
|
userId?: string;
|
|
11
|
+
/** Your application components. */
|
|
7
12
|
children: ReactNode;
|
|
8
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Root provider component for GrowthRail in React applications.
|
|
16
|
+
* This component initializes the SDK and manages the user's authentication state.
|
|
17
|
+
*
|
|
18
|
+
* Wrap your app (or a specific feature tree) with this provider.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* <GrowthRailProvider projectSecretKey="your-api-key" userId="user-123">
|
|
22
|
+
* <App />
|
|
23
|
+
* </GrowthRailProvider>
|
|
24
|
+
*/
|
|
9
25
|
declare const GrowthRailProvider: React.FC<GrowthRailProviderProps>;
|
|
10
26
|
|
|
27
|
+
/**
|
|
28
|
+
* The return type of the useGrowthRail hook.
|
|
29
|
+
*/
|
|
11
30
|
interface UseGrowthRailReturn {
|
|
12
|
-
|
|
13
|
-
|
|
31
|
+
/**
|
|
32
|
+
* Initializes a user in the GrowthRail system.
|
|
33
|
+
* @param userId - Unique identifier for the user.
|
|
34
|
+
*/
|
|
35
|
+
initAppUser: (userId: string) => Promise<AppUserType>;
|
|
36
|
+
/**
|
|
37
|
+
* Tracks a reward-eligible event for the current user.
|
|
38
|
+
* @param eventName - Optional name of the event.
|
|
39
|
+
*/
|
|
40
|
+
trackRewardEvent: (eventName?: string) => Promise<void>;
|
|
41
|
+
/**
|
|
42
|
+
* Manually triggers the referral dashboard modal.
|
|
43
|
+
* @param options - Customization options for the modal.
|
|
44
|
+
*/
|
|
14
45
|
showReferralDashboard: (options?: Parameters<typeof GrowthRail.showReferralDashboard>[0]) => void;
|
|
46
|
+
/**
|
|
47
|
+
* Manually shows or updates the floating referral trigger button.
|
|
48
|
+
* @param options - Configuration for the button.
|
|
49
|
+
*/
|
|
15
50
|
showFloatingButton: (options: Partial<ReferrerTriggerButton>) => void;
|
|
51
|
+
/** Hides the floating referral trigger button. */
|
|
16
52
|
hideFloatingButton: () => void;
|
|
53
|
+
/** Whether an asynchronous operation (like init or track) is in progress. */
|
|
17
54
|
isLoading: boolean;
|
|
55
|
+
/** The last error that occurred during an operation. */
|
|
18
56
|
error: Error | null;
|
|
19
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* A hook that provides access to GrowthRail SDK methods and state.
|
|
60
|
+
*
|
|
61
|
+
* @returns An object containing methods to manage referrals and track state.
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* const { showReferralDashboard, trackRewardEvent } = useGrowthRail();
|
|
65
|
+
*/
|
|
20
66
|
declare const useGrowthRail: () => UseGrowthRailReturn;
|
|
21
67
|
|
|
68
|
+
/**
|
|
69
|
+
* Props for the ReferralDashboard component.
|
|
70
|
+
*/
|
|
22
71
|
interface ReferralDashboardProps {
|
|
72
|
+
/** Optional override for the dashboard title. */
|
|
23
73
|
title?: string;
|
|
74
|
+
/** Customization options for the dashboard's appearance. */
|
|
24
75
|
appearance?: ReferrerModalOptions;
|
|
76
|
+
/** Callback fired when the referral link is copied to the clipboard. */
|
|
25
77
|
onLinkCopied?: () => void;
|
|
26
78
|
}
|
|
79
|
+
/**
|
|
80
|
+
* An inline referral dashboard component.
|
|
81
|
+
* Unlike the global modal, this component renders directly within your layout.
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* <div style={{ height: '500px' }}>
|
|
85
|
+
* <ReferralDashboard title="Invite your team" />
|
|
86
|
+
* </div>
|
|
87
|
+
*/
|
|
27
88
|
declare const ReferralDashboard: React.FC<ReferralDashboardProps>;
|
|
28
89
|
|
|
29
90
|
export { GrowthRailProvider, ReferralDashboard, type ReferralDashboardProps, type UseGrowthRailReturn, useGrowthRail };
|
package/dist/index.js
CHANGED
|
@@ -61,7 +61,7 @@ var import_core2 = require("@growth-rail/core");
|
|
|
61
61
|
var useGrowthRail = () => {
|
|
62
62
|
const [isLoading, setIsLoading] = (0, import_react2.useState)(false);
|
|
63
63
|
const [error, setError] = (0, import_react2.useState)(null);
|
|
64
|
-
const
|
|
64
|
+
const initAppUser = (0, import_react2.useCallback)(async (userId) => {
|
|
65
65
|
setIsLoading(true);
|
|
66
66
|
setError(null);
|
|
67
67
|
try {
|
|
@@ -75,7 +75,7 @@ var useGrowthRail = () => {
|
|
|
75
75
|
setIsLoading(false);
|
|
76
76
|
}
|
|
77
77
|
}, []);
|
|
78
|
-
const
|
|
78
|
+
const trackRewardEvent = (0, import_react2.useCallback)(async (eventName) => {
|
|
79
79
|
setIsLoading(true);
|
|
80
80
|
setError(null);
|
|
81
81
|
try {
|
|
@@ -98,8 +98,8 @@ var useGrowthRail = () => {
|
|
|
98
98
|
import_core2.GrowthRail.destroyTriggerButton();
|
|
99
99
|
}, []);
|
|
100
100
|
return {
|
|
101
|
-
|
|
102
|
-
|
|
101
|
+
initAppUser,
|
|
102
|
+
trackRewardEvent,
|
|
103
103
|
showReferralDashboard,
|
|
104
104
|
showFloatingButton,
|
|
105
105
|
hideFloatingButton,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.tsx","../src/GrowthRailProvider.tsx","../src/useGrowthRail.ts","../src/ReferralDashboard.tsx"],"sourcesContent":["export { GrowthRailProvider } from './GrowthRailProvider';\nexport { useGrowthRail, type UseGrowthRailReturn } from './useGrowthRail';\nexport { \n ReferralDashboard, \n type ReferralDashboardProps,\n} from './ReferralDashboard';\n\nexport type { GrowthRailOptions, AppUserType } from '@growth-rail/core';\n","import React, { useEffect, useRef, useState, ReactNode } from 'react';\nimport { GrowthRail, GrowthRailOptions } from '@growth-rail/core';\n\ninterface GrowthRailProviderProps extends GrowthRailOptions {\n userId?: string;\n children: ReactNode;\n}\n\nexport const GrowthRailProvider: React.FC<GrowthRailProviderProps> = ({ \n children, \n userId,\n ...options \n}) => {\n const [isReady, setIsReady] = useState(GrowthRail.isInitialized());\n const initialized = useRef(false);\n\n useEffect(() => {\n if (initialized.current) return;\n initialized.current = true;\n\n GrowthRail.init(options);\n if (userId) {\n GrowthRail.initAppUser(userId).catch(console.error);\n }\n setIsReady(true);\n }, []);\n\n useEffect(() => {\n if (initialized.current && userId && GrowthRail.getUserId() !== userId) {\n GrowthRail.initAppUser(userId).catch(console.error);\n }\n }, [userId]);\n\n if (!isReady) return null;\n\n return <>{children}</>;\n};\n","import { useState, useCallback } from 'react';\nimport { GrowthRail, AppUserType, ReferrerTriggerButton } from '@growth-rail/core';\n\nexport interface UseGrowthRailReturn {\n initUser: (userId: string) => Promise<AppUserType>;\n trackReward: (eventName?: string) => Promise<void>;\n showReferralDashboard: (options?: Parameters<typeof GrowthRail.showReferralDashboard>[0]) => void;\n showFloatingButton: (options: Partial<ReferrerTriggerButton>) => void;\n hideFloatingButton: () => void;\n isLoading: boolean;\n error: Error | null;\n}\n\nexport const useGrowthRail = (): UseGrowthRailReturn => {\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const initUser = useCallback(async (userId: string) => {\n setIsLoading(true);\n setError(null);\n try {\n const user = await GrowthRail.initAppUser(userId);\n return user;\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n setError(error);\n throw error;\n } finally {\n setIsLoading(false);\n }\n }, []);\n\n const trackReward = useCallback(async (eventName?: string) => {\n setIsLoading(true);\n setError(null);\n try {\n await GrowthRail.trackRewardEvent(eventName);\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n setError(error);\n throw error;\n } finally {\n setIsLoading(false);\n }\n }, []);\n\n const showReferralDashboard = useCallback((options?: Parameters<typeof GrowthRail.showReferralDashboard>[0]) => {\n GrowthRail.showReferralDashboard(options);\n }, []);\n\n const showFloatingButton = useCallback((options: Partial<ReferrerTriggerButton>) => {\n GrowthRail.createTriggerButton(options);\n }, []);\n\n const hideFloatingButton = useCallback(() => {\n GrowthRail.destroyTriggerButton();\n }, []);\n\n return {\n initUser,\n trackReward,\n showReferralDashboard,\n showFloatingButton,\n hideFloatingButton,\n isLoading,\n error,\n };\n};\n","import React, { useEffect, useRef } from 'react';\nimport { GrowthRail, ReferrerModalOptions, ReferralModal, ReferrerExperience } from '@growth-rail/core';\n\nexport interface ReferralDashboardProps {\n title?: string;\n appearance?: ReferrerModalOptions;\n onLinkCopied?: () => void;\n}\n\nexport const ReferralDashboard: React.FC<ReferralDashboardProps> = ({\n title,\n appearance = {},\n onLinkCopied,\n}) => {\n const containerRef = useRef<HTMLDivElement>(null);\n const modalRef = useRef<ReferralModal | null>(null);\n\n useEffect(() => {\n let mounted = true;\n if (!containerRef.current) return;\n\n GrowthRail.ensureUserReady().then((user) => {\n if (!mounted || !containerRef.current) return;\n\n const deps = {\n isUserReady: () => GrowthRail.isUserReady(),\n getReferralLink: () => {\n try {\n return GrowthRail.getReferralLink();\n } catch {\n return '';\n }\n },\n };\n\n // Construct experience config directly from BE\n const experience: ReferrerExperience = {\n trigger: user.referrerExperience.trigger,\n modal: {\n ...user.referrerExperience.modal,\n ...(title ? { title } : {}),\n ...appearance,\n },\n };\n\n modalRef.current = new ReferralModal(deps, experience);\n modalRef.current.show(appearance, containerRef.current);\n }).catch((err) => {\n console.error('GrowthRail: User initialization failed', err);\n });\n\n return () => {\n mounted = false;\n if (modalRef.current) {\n modalRef.current.hide();\n modalRef.current = null;\n }\n };\n }, [title, appearance]);\n\n return (\n <div \n ref={containerRef} \n style={{ \n width: '100%', \n height: '100%', \n minHeight: '400px',\n position: 'relative' \n }} \n />\n );\n};\n"],"mappings":"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","names":["import_react","import_core","error","import_react","import_core","import_jsx_runtime"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.tsx","../src/GrowthRailProvider.tsx","../src/useGrowthRail.ts","../src/ReferralDashboard.tsx"],"sourcesContent":["/**\n * GrowthRail React SDK\n * \n * This package provide React components and hooks for the GrowthRail referral system.\n * It is built on top of the `@growth-rail/core` package.\n */\n\n/** Root provider component for initializing GrowthRail. */\nexport { GrowthRailProvider } from './GrowthRailProvider';\n\n/** Hook for accessing GrowthRail methods and state. */\nexport { useGrowthRail, type UseGrowthRailReturn } from './useGrowthRail';\n\n/** Inline referral dashboard component. */\nexport { \n ReferralDashboard, \n type ReferralDashboardProps,\n} from './ReferralDashboard';\n\n/** Re-exported core types. */\nexport type { \n GrowthRailOptions, \n AppUserType,\n ReferrerModalOptions,\n ReferrerExperience,\n ReferrerTriggerButton \n} from '@growth-rail/core';\n","import React, { useEffect, useRef, useState, ReactNode } from 'react';\nimport { GrowthRail, GrowthRailOptions } from '@growth-rail/core';\n\n/**\n * Props for the GrowthRailProvider component.\n */\ninterface GrowthRailProviderProps extends GrowthRailOptions {\n /** The unique ID for the current application user. */\n userId?: string;\n /** Your application components. */\n children: ReactNode;\n}\n\n/**\n * Root provider component for GrowthRail in React applications.\n * This component initializes the SDK and manages the user's authentication state.\n * \n * Wrap your app (or a specific feature tree) with this provider.\n * \n * @example\n * <GrowthRailProvider projectSecretKey=\"your-api-key\" userId=\"user-123\">\n * <App />\n * </GrowthRailProvider>\n */\nexport const GrowthRailProvider: React.FC<GrowthRailProviderProps> = ({ \n children, \n userId,\n ...options \n}) => {\n\n const [isReady, setIsReady] = useState(GrowthRail.isInitialized());\n const initialized = useRef(false);\n\n useEffect(() => {\n if (initialized.current) return;\n initialized.current = true;\n\n GrowthRail.init(options);\n if (userId) {\n GrowthRail.initAppUser(userId).catch(console.error);\n }\n setIsReady(true);\n }, []);\n\n useEffect(() => {\n if (initialized.current && userId && GrowthRail.getUserId() !== userId) {\n GrowthRail.initAppUser(userId).catch(console.error);\n }\n }, [userId]);\n\n if (!isReady) return null;\n\n return <>{children}</>;\n};\n","import { useState, useCallback } from 'react';\nimport { GrowthRail, AppUserType, ReferrerTriggerButton } from '@growth-rail/core';\n\n/**\n * The return type of the useGrowthRail hook.\n */\nexport interface UseGrowthRailReturn {\n /** \n * Initializes a user in the GrowthRail system. \n * @param userId - Unique identifier for the user.\n */\n initAppUser: (userId: string) => Promise<AppUserType>;\n /** \n * Tracks a reward-eligible event for the current user.\n * @param eventName - Optional name of the event.\n */\n trackRewardEvent: (eventName?: string) => Promise<void>;\n /** \n * Manually triggers the referral dashboard modal.\n * @param options - Customization options for the modal.\n */\n showReferralDashboard: (options?: Parameters<typeof GrowthRail.showReferralDashboard>[0]) => void;\n /** \n * Manually shows or updates the floating referral trigger button.\n * @param options - Configuration for the button.\n */\n showFloatingButton: (options: Partial<ReferrerTriggerButton>) => void;\n /** Hides the floating referral trigger button. */\n hideFloatingButton: () => void;\n /** Whether an asynchronous operation (like init or track) is in progress. */\n isLoading: boolean;\n /** The last error that occurred during an operation. */\n error: Error | null;\n}\n\n/**\n * A hook that provides access to GrowthRail SDK methods and state.\n * \n * @returns An object containing methods to manage referrals and track state.\n * \n * @example\n * const { showReferralDashboard, trackRewardEvent } = useGrowthRail();\n */\nexport const useGrowthRail = (): UseGrowthRailReturn => {\n\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const initAppUser = useCallback(async (userId: string) => {\n setIsLoading(true);\n setError(null);\n try {\n const user = await GrowthRail.initAppUser(userId);\n return user;\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n setError(error);\n throw error;\n } finally {\n setIsLoading(false);\n }\n }, []);\n\n const trackRewardEvent = useCallback(async (eventName?: string) => {\n setIsLoading(true);\n setError(null);\n try {\n await GrowthRail.trackRewardEvent(eventName);\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n setError(error);\n throw error;\n } finally {\n setIsLoading(false);\n }\n }, []);\n\n const showReferralDashboard = useCallback((options?: Parameters<typeof GrowthRail.showReferralDashboard>[0]) => {\n GrowthRail.showReferralDashboard(options);\n }, []);\n\n const showFloatingButton = useCallback((options: Partial<ReferrerTriggerButton>) => {\n GrowthRail.createTriggerButton(options);\n }, []);\n\n const hideFloatingButton = useCallback(() => {\n GrowthRail.destroyTriggerButton();\n }, []);\n\n return {\n initAppUser,\n trackRewardEvent,\n showReferralDashboard,\n showFloatingButton,\n hideFloatingButton,\n isLoading,\n error,\n };\n};\n","import React, { useEffect, useRef } from 'react';\nimport { GrowthRail, ReferrerModalOptions, ReferralModal, ReferrerExperience } from '@growth-rail/core';\n\n/**\n * Props for the ReferralDashboard component.\n */\nexport interface ReferralDashboardProps {\n /** Optional override for the dashboard title. */\n title?: string;\n /** Customization options for the dashboard's appearance. */\n appearance?: ReferrerModalOptions;\n /** Callback fired when the referral link is copied to the clipboard. */\n onLinkCopied?: () => void;\n}\n\n/**\n * An inline referral dashboard component.\n * Unlike the global modal, this component renders directly within your layout.\n * \n * @example\n * <div style={{ height: '500px' }}>\n * <ReferralDashboard title=\"Invite your team\" />\n * </div>\n */\nexport const ReferralDashboard: React.FC<ReferralDashboardProps> = ({\n title,\n appearance = {},\n onLinkCopied,\n}) => {\n\n const containerRef = useRef<HTMLDivElement>(null);\n const modalRef = useRef<ReferralModal | null>(null);\n\n useEffect(() => {\n let mounted = true;\n if (!containerRef.current) return;\n\n GrowthRail.ensureUserReady().then((user) => {\n if (!mounted || !containerRef.current) return;\n\n const deps = {\n isUserReady: () => GrowthRail.isUserReady(),\n getReferralLink: () => {\n try {\n return GrowthRail.getReferralLink();\n } catch {\n return '';\n }\n },\n };\n\n // Construct experience config directly from BE\n const experience: ReferrerExperience = {\n trigger: user.referrerExperience.trigger,\n modal: {\n ...user.referrerExperience.modal,\n ...(title ? { title } : {}),\n ...appearance,\n },\n };\n\n modalRef.current = new ReferralModal(deps, experience);\n modalRef.current.show(appearance, containerRef.current);\n }).catch((err) => {\n console.error('GrowthRail: User initialization failed', err);\n });\n\n return () => {\n mounted = false;\n if (modalRef.current) {\n modalRef.current.hide();\n modalRef.current = null;\n }\n };\n }, [title, appearance]);\n\n return (\n <div \n ref={containerRef} \n style={{ \n width: '100%', \n height: '100%', \n minHeight: '400px',\n position: 'relative' \n }} \n />\n );\n};\n"],"mappings":"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","names":["import_react","import_core","error","import_react","import_core","import_jsx_runtime"]}
|
package/dist/index.mjs
CHANGED
|
@@ -33,7 +33,7 @@ import { GrowthRail as GrowthRail2 } from "@growth-rail/core";
|
|
|
33
33
|
var useGrowthRail = () => {
|
|
34
34
|
const [isLoading, setIsLoading] = useState2(false);
|
|
35
35
|
const [error, setError] = useState2(null);
|
|
36
|
-
const
|
|
36
|
+
const initAppUser = useCallback(async (userId) => {
|
|
37
37
|
setIsLoading(true);
|
|
38
38
|
setError(null);
|
|
39
39
|
try {
|
|
@@ -47,7 +47,7 @@ var useGrowthRail = () => {
|
|
|
47
47
|
setIsLoading(false);
|
|
48
48
|
}
|
|
49
49
|
}, []);
|
|
50
|
-
const
|
|
50
|
+
const trackRewardEvent = useCallback(async (eventName) => {
|
|
51
51
|
setIsLoading(true);
|
|
52
52
|
setError(null);
|
|
53
53
|
try {
|
|
@@ -70,8 +70,8 @@ var useGrowthRail = () => {
|
|
|
70
70
|
GrowthRail2.destroyTriggerButton();
|
|
71
71
|
}, []);
|
|
72
72
|
return {
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
initAppUser,
|
|
74
|
+
trackRewardEvent,
|
|
75
75
|
showReferralDashboard,
|
|
76
76
|
showFloatingButton,
|
|
77
77
|
hideFloatingButton,
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/GrowthRailProvider.tsx","../src/useGrowthRail.ts","../src/ReferralDashboard.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState, ReactNode } from 'react';\nimport { GrowthRail, GrowthRailOptions } from '@growth-rail/core';\n\ninterface GrowthRailProviderProps extends GrowthRailOptions {\n userId?: string;\n children: ReactNode;\n}\n\nexport const GrowthRailProvider: React.FC<GrowthRailProviderProps> = ({ \n children, \n userId,\n ...options \n}) => {\n const [isReady, setIsReady] = useState(GrowthRail.isInitialized());\n const initialized = useRef(false);\n\n useEffect(() => {\n if (initialized.current) return;\n initialized.current = true;\n\n GrowthRail.init(options);\n if (userId) {\n GrowthRail.initAppUser(userId).catch(console.error);\n }\n setIsReady(true);\n }, []);\n\n useEffect(() => {\n if (initialized.current && userId && GrowthRail.getUserId() !== userId) {\n GrowthRail.initAppUser(userId).catch(console.error);\n }\n }, [userId]);\n\n if (!isReady) return null;\n\n return <>{children}</>;\n};\n","import { useState, useCallback } from 'react';\nimport { GrowthRail, AppUserType, ReferrerTriggerButton } from '@growth-rail/core';\n\nexport interface UseGrowthRailReturn {\n initUser: (userId: string) => Promise<AppUserType>;\n trackReward: (eventName?: string) => Promise<void>;\n showReferralDashboard: (options?: Parameters<typeof GrowthRail.showReferralDashboard>[0]) => void;\n showFloatingButton: (options: Partial<ReferrerTriggerButton>) => void;\n hideFloatingButton: () => void;\n isLoading: boolean;\n error: Error | null;\n}\n\nexport const useGrowthRail = (): UseGrowthRailReturn => {\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const initUser = useCallback(async (userId: string) => {\n setIsLoading(true);\n setError(null);\n try {\n const user = await GrowthRail.initAppUser(userId);\n return user;\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n setError(error);\n throw error;\n } finally {\n setIsLoading(false);\n }\n }, []);\n\n const trackReward = useCallback(async (eventName?: string) => {\n setIsLoading(true);\n setError(null);\n try {\n await GrowthRail.trackRewardEvent(eventName);\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n setError(error);\n throw error;\n } finally {\n setIsLoading(false);\n }\n }, []);\n\n const showReferralDashboard = useCallback((options?: Parameters<typeof GrowthRail.showReferralDashboard>[0]) => {\n GrowthRail.showReferralDashboard(options);\n }, []);\n\n const showFloatingButton = useCallback((options: Partial<ReferrerTriggerButton>) => {\n GrowthRail.createTriggerButton(options);\n }, []);\n\n const hideFloatingButton = useCallback(() => {\n GrowthRail.destroyTriggerButton();\n }, []);\n\n return {\n initUser,\n trackReward,\n showReferralDashboard,\n showFloatingButton,\n hideFloatingButton,\n isLoading,\n error,\n };\n};\n","import React, { useEffect, useRef } from 'react';\nimport { GrowthRail, ReferrerModalOptions, ReferralModal, ReferrerExperience } from '@growth-rail/core';\n\nexport interface ReferralDashboardProps {\n title?: string;\n appearance?: ReferrerModalOptions;\n onLinkCopied?: () => void;\n}\n\nexport const ReferralDashboard: React.FC<ReferralDashboardProps> = ({\n title,\n appearance = {},\n onLinkCopied,\n}) => {\n const containerRef = useRef<HTMLDivElement>(null);\n const modalRef = useRef<ReferralModal | null>(null);\n\n useEffect(() => {\n let mounted = true;\n if (!containerRef.current) return;\n\n GrowthRail.ensureUserReady().then((user) => {\n if (!mounted || !containerRef.current) return;\n\n const deps = {\n isUserReady: () => GrowthRail.isUserReady(),\n getReferralLink: () => {\n try {\n return GrowthRail.getReferralLink();\n } catch {\n return '';\n }\n },\n };\n\n // Construct experience config directly from BE\n const experience: ReferrerExperience = {\n trigger: user.referrerExperience.trigger,\n modal: {\n ...user.referrerExperience.modal,\n ...(title ? { title } : {}),\n ...appearance,\n },\n };\n\n modalRef.current = new ReferralModal(deps, experience);\n modalRef.current.show(appearance, containerRef.current);\n }).catch((err) => {\n console.error('GrowthRail: User initialization failed', err);\n });\n\n return () => {\n mounted = false;\n if (modalRef.current) {\n modalRef.current.hide();\n modalRef.current = null;\n }\n };\n }, [title, appearance]);\n\n return (\n <div \n ref={containerRef} \n style={{ \n width: '100%', \n height: '100%', \n minHeight: '400px',\n position: 'relative' \n }} \n />\n );\n};\n"],"mappings":"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","names":["useState","GrowthRail","error","useEffect","useRef","GrowthRail","jsx"]}
|
|
1
|
+
{"version":3,"sources":["../src/GrowthRailProvider.tsx","../src/useGrowthRail.ts","../src/ReferralDashboard.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState, ReactNode } from 'react';\nimport { GrowthRail, GrowthRailOptions } from '@growth-rail/core';\n\n/**\n * Props for the GrowthRailProvider component.\n */\ninterface GrowthRailProviderProps extends GrowthRailOptions {\n /** The unique ID for the current application user. */\n userId?: string;\n /** Your application components. */\n children: ReactNode;\n}\n\n/**\n * Root provider component for GrowthRail in React applications.\n * This component initializes the SDK and manages the user's authentication state.\n * \n * Wrap your app (or a specific feature tree) with this provider.\n * \n * @example\n * <GrowthRailProvider projectSecretKey=\"your-api-key\" userId=\"user-123\">\n * <App />\n * </GrowthRailProvider>\n */\nexport const GrowthRailProvider: React.FC<GrowthRailProviderProps> = ({ \n children, \n userId,\n ...options \n}) => {\n\n const [isReady, setIsReady] = useState(GrowthRail.isInitialized());\n const initialized = useRef(false);\n\n useEffect(() => {\n if (initialized.current) return;\n initialized.current = true;\n\n GrowthRail.init(options);\n if (userId) {\n GrowthRail.initAppUser(userId).catch(console.error);\n }\n setIsReady(true);\n }, []);\n\n useEffect(() => {\n if (initialized.current && userId && GrowthRail.getUserId() !== userId) {\n GrowthRail.initAppUser(userId).catch(console.error);\n }\n }, [userId]);\n\n if (!isReady) return null;\n\n return <>{children}</>;\n};\n","import { useState, useCallback } from 'react';\nimport { GrowthRail, AppUserType, ReferrerTriggerButton } from '@growth-rail/core';\n\n/**\n * The return type of the useGrowthRail hook.\n */\nexport interface UseGrowthRailReturn {\n /** \n * Initializes a user in the GrowthRail system. \n * @param userId - Unique identifier for the user.\n */\n initAppUser: (userId: string) => Promise<AppUserType>;\n /** \n * Tracks a reward-eligible event for the current user.\n * @param eventName - Optional name of the event.\n */\n trackRewardEvent: (eventName?: string) => Promise<void>;\n /** \n * Manually triggers the referral dashboard modal.\n * @param options - Customization options for the modal.\n */\n showReferralDashboard: (options?: Parameters<typeof GrowthRail.showReferralDashboard>[0]) => void;\n /** \n * Manually shows or updates the floating referral trigger button.\n * @param options - Configuration for the button.\n */\n showFloatingButton: (options: Partial<ReferrerTriggerButton>) => void;\n /** Hides the floating referral trigger button. */\n hideFloatingButton: () => void;\n /** Whether an asynchronous operation (like init or track) is in progress. */\n isLoading: boolean;\n /** The last error that occurred during an operation. */\n error: Error | null;\n}\n\n/**\n * A hook that provides access to GrowthRail SDK methods and state.\n * \n * @returns An object containing methods to manage referrals and track state.\n * \n * @example\n * const { showReferralDashboard, trackRewardEvent } = useGrowthRail();\n */\nexport const useGrowthRail = (): UseGrowthRailReturn => {\n\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const initAppUser = useCallback(async (userId: string) => {\n setIsLoading(true);\n setError(null);\n try {\n const user = await GrowthRail.initAppUser(userId);\n return user;\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n setError(error);\n throw error;\n } finally {\n setIsLoading(false);\n }\n }, []);\n\n const trackRewardEvent = useCallback(async (eventName?: string) => {\n setIsLoading(true);\n setError(null);\n try {\n await GrowthRail.trackRewardEvent(eventName);\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n setError(error);\n throw error;\n } finally {\n setIsLoading(false);\n }\n }, []);\n\n const showReferralDashboard = useCallback((options?: Parameters<typeof GrowthRail.showReferralDashboard>[0]) => {\n GrowthRail.showReferralDashboard(options);\n }, []);\n\n const showFloatingButton = useCallback((options: Partial<ReferrerTriggerButton>) => {\n GrowthRail.createTriggerButton(options);\n }, []);\n\n const hideFloatingButton = useCallback(() => {\n GrowthRail.destroyTriggerButton();\n }, []);\n\n return {\n initAppUser,\n trackRewardEvent,\n showReferralDashboard,\n showFloatingButton,\n hideFloatingButton,\n isLoading,\n error,\n };\n};\n","import React, { useEffect, useRef } from 'react';\nimport { GrowthRail, ReferrerModalOptions, ReferralModal, ReferrerExperience } from '@growth-rail/core';\n\n/**\n * Props for the ReferralDashboard component.\n */\nexport interface ReferralDashboardProps {\n /** Optional override for the dashboard title. */\n title?: string;\n /** Customization options for the dashboard's appearance. */\n appearance?: ReferrerModalOptions;\n /** Callback fired when the referral link is copied to the clipboard. */\n onLinkCopied?: () => void;\n}\n\n/**\n * An inline referral dashboard component.\n * Unlike the global modal, this component renders directly within your layout.\n * \n * @example\n * <div style={{ height: '500px' }}>\n * <ReferralDashboard title=\"Invite your team\" />\n * </div>\n */\nexport const ReferralDashboard: React.FC<ReferralDashboardProps> = ({\n title,\n appearance = {},\n onLinkCopied,\n}) => {\n\n const containerRef = useRef<HTMLDivElement>(null);\n const modalRef = useRef<ReferralModal | null>(null);\n\n useEffect(() => {\n let mounted = true;\n if (!containerRef.current) return;\n\n GrowthRail.ensureUserReady().then((user) => {\n if (!mounted || !containerRef.current) return;\n\n const deps = {\n isUserReady: () => GrowthRail.isUserReady(),\n getReferralLink: () => {\n try {\n return GrowthRail.getReferralLink();\n } catch {\n return '';\n }\n },\n };\n\n // Construct experience config directly from BE\n const experience: ReferrerExperience = {\n trigger: user.referrerExperience.trigger,\n modal: {\n ...user.referrerExperience.modal,\n ...(title ? { title } : {}),\n ...appearance,\n },\n };\n\n modalRef.current = new ReferralModal(deps, experience);\n modalRef.current.show(appearance, containerRef.current);\n }).catch((err) => {\n console.error('GrowthRail: User initialization failed', err);\n });\n\n return () => {\n mounted = false;\n if (modalRef.current) {\n modalRef.current.hide();\n modalRef.current = null;\n }\n };\n }, [title, appearance]);\n\n return (\n <div \n ref={containerRef} \n style={{ \n width: '100%', \n height: '100%', \n minHeight: '400px',\n position: 'relative' \n }} \n />\n );\n};\n"],"mappings":"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","names":["useState","GrowthRail","error","useEffect","useRef","GrowthRail","jsx"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@growth-rail/react",
|
|
3
|
-
"version": "2.0
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Growth Rail React SDK",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"react-dom": ">=16.8"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@growth-rail/core": "^2.0
|
|
32
|
+
"@growth-rail/core": "^2.2.0"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@growth-rail/eslint-config": "*",
|
|
@@ -47,4 +47,4 @@
|
|
|
47
47
|
"publishConfig": {
|
|
48
48
|
"access": "public"
|
|
49
49
|
}
|
|
50
|
-
}
|
|
50
|
+
}
|