@growth-rail/react 1.0.1

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.
@@ -0,0 +1,29 @@
1
+ import React, { ReactNode } from 'react';
2
+ import { GrowthRailOptions, AppUserType, GrowthRail, ReferrerTriggerButton, ReferrerModalOptions } from '@growth-rail/core';
3
+ export { AppUserType, GrowthRailOptions } from '@growth-rail/core';
4
+
5
+ interface GrowthRailProviderProps extends GrowthRailOptions {
6
+ userId?: string;
7
+ children: ReactNode;
8
+ }
9
+ declare const GrowthRailProvider: React.FC<GrowthRailProviderProps>;
10
+
11
+ interface UseGrowthRailReturn {
12
+ initUser: (userId: string) => Promise<AppUserType>;
13
+ trackReward: (eventName?: string) => Promise<void>;
14
+ showReferralDashboard: (options?: Parameters<typeof GrowthRail.showReferralDashboard>[0]) => void;
15
+ showFloatingButton: (options: Partial<ReferrerTriggerButton>) => void;
16
+ hideFloatingButton: () => void;
17
+ isLoading: boolean;
18
+ error: Error | null;
19
+ }
20
+ declare const useGrowthRail: () => UseGrowthRailReturn;
21
+
22
+ interface ReferralDashboardProps {
23
+ title?: string;
24
+ appearance?: ReferrerModalOptions;
25
+ onLinkCopied?: () => void;
26
+ }
27
+ declare const ReferralDashboard: React.FC<ReferralDashboardProps>;
28
+
29
+ export { GrowthRailProvider, ReferralDashboard, type ReferralDashboardProps, type UseGrowthRailReturn, useGrowthRail };
@@ -0,0 +1,29 @@
1
+ import React, { ReactNode } from 'react';
2
+ import { GrowthRailOptions, AppUserType, GrowthRail, ReferrerTriggerButton, ReferrerModalOptions } from '@growth-rail/core';
3
+ export { AppUserType, GrowthRailOptions } from '@growth-rail/core';
4
+
5
+ interface GrowthRailProviderProps extends GrowthRailOptions {
6
+ userId?: string;
7
+ children: ReactNode;
8
+ }
9
+ declare const GrowthRailProvider: React.FC<GrowthRailProviderProps>;
10
+
11
+ interface UseGrowthRailReturn {
12
+ initUser: (userId: string) => Promise<AppUserType>;
13
+ trackReward: (eventName?: string) => Promise<void>;
14
+ showReferralDashboard: (options?: Parameters<typeof GrowthRail.showReferralDashboard>[0]) => void;
15
+ showFloatingButton: (options: Partial<ReferrerTriggerButton>) => void;
16
+ hideFloatingButton: () => void;
17
+ isLoading: boolean;
18
+ error: Error | null;
19
+ }
20
+ declare const useGrowthRail: () => UseGrowthRailReturn;
21
+
22
+ interface ReferralDashboardProps {
23
+ title?: string;
24
+ appearance?: ReferrerModalOptions;
25
+ onLinkCopied?: () => void;
26
+ }
27
+ declare const ReferralDashboard: React.FC<ReferralDashboardProps>;
28
+
29
+ export { GrowthRailProvider, ReferralDashboard, type ReferralDashboardProps, type UseGrowthRailReturn, useGrowthRail };
package/dist/index.js ADDED
@@ -0,0 +1,177 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.tsx
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ GrowthRailProvider: () => GrowthRailProvider,
24
+ ReferralDashboard: () => ReferralDashboard,
25
+ useGrowthRail: () => useGrowthRail
26
+ });
27
+ module.exports = __toCommonJS(index_exports);
28
+
29
+ // src/GrowthRailProvider.tsx
30
+ var import_react = require("react");
31
+ var import_core = require("@growth-rail/core");
32
+ var import_jsx_runtime = require("react/jsx-runtime");
33
+ var GrowthRailProvider = ({
34
+ children,
35
+ userId,
36
+ ...options
37
+ }) => {
38
+ const [isReady, setIsReady] = (0, import_react.useState)(import_core.GrowthRail.isInitialized());
39
+ const initialized = (0, import_react.useRef)(false);
40
+ (0, import_react.useEffect)(() => {
41
+ if (initialized.current) return;
42
+ initialized.current = true;
43
+ import_core.GrowthRail.init(options);
44
+ if (userId) {
45
+ import_core.GrowthRail.initAppUser(userId).catch(console.error);
46
+ }
47
+ setIsReady(true);
48
+ }, []);
49
+ (0, import_react.useEffect)(() => {
50
+ if (initialized.current && userId && import_core.GrowthRail.getUserId() !== userId) {
51
+ import_core.GrowthRail.initAppUser(userId).catch(console.error);
52
+ }
53
+ }, [userId]);
54
+ if (!isReady) return null;
55
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children });
56
+ };
57
+
58
+ // src/useGrowthRail.ts
59
+ var import_react2 = require("react");
60
+ var import_core2 = require("@growth-rail/core");
61
+ var useGrowthRail = () => {
62
+ const [isLoading, setIsLoading] = (0, import_react2.useState)(false);
63
+ const [error, setError] = (0, import_react2.useState)(null);
64
+ const initUser = (0, import_react2.useCallback)(async (userId) => {
65
+ setIsLoading(true);
66
+ setError(null);
67
+ try {
68
+ const user = await import_core2.GrowthRail.initAppUser(userId);
69
+ return user;
70
+ } catch (err) {
71
+ const error2 = err instanceof Error ? err : new Error(String(err));
72
+ setError(error2);
73
+ throw error2;
74
+ } finally {
75
+ setIsLoading(false);
76
+ }
77
+ }, []);
78
+ const trackReward = (0, import_react2.useCallback)(async (eventName) => {
79
+ setIsLoading(true);
80
+ setError(null);
81
+ try {
82
+ await import_core2.GrowthRail.trackRewardEvent(eventName);
83
+ } catch (err) {
84
+ const error2 = err instanceof Error ? err : new Error(String(err));
85
+ setError(error2);
86
+ throw error2;
87
+ } finally {
88
+ setIsLoading(false);
89
+ }
90
+ }, []);
91
+ const showReferralDashboard = (0, import_react2.useCallback)((options) => {
92
+ import_core2.GrowthRail.showReferralDashboard(options);
93
+ }, []);
94
+ const showFloatingButton = (0, import_react2.useCallback)((options) => {
95
+ import_core2.GrowthRail.createTriggerButton(options);
96
+ }, []);
97
+ const hideFloatingButton = (0, import_react2.useCallback)(() => {
98
+ import_core2.GrowthRail.destroyTriggerButton();
99
+ }, []);
100
+ return {
101
+ initUser,
102
+ trackReward,
103
+ showReferralDashboard,
104
+ showFloatingButton,
105
+ hideFloatingButton,
106
+ isLoading,
107
+ error
108
+ };
109
+ };
110
+
111
+ // src/ReferralDashboard.tsx
112
+ var import_react3 = require("react");
113
+ var import_core3 = require("@growth-rail/core");
114
+ var import_jsx_runtime2 = require("react/jsx-runtime");
115
+ var ReferralDashboard = ({
116
+ title,
117
+ appearance = {},
118
+ onLinkCopied
119
+ }) => {
120
+ const containerRef = (0, import_react3.useRef)(null);
121
+ const modalRef = (0, import_react3.useRef)(null);
122
+ (0, import_react3.useEffect)(() => {
123
+ let mounted = true;
124
+ if (!containerRef.current) return;
125
+ import_core3.GrowthRail.ensureUserReady().then((user) => {
126
+ if (!mounted || !containerRef.current) return;
127
+ const deps = {
128
+ isUserReady: () => import_core3.GrowthRail.isUserReady(),
129
+ getReferralLink: () => {
130
+ try {
131
+ return import_core3.GrowthRail.getReferralLink();
132
+ } catch {
133
+ return "";
134
+ }
135
+ }
136
+ };
137
+ const experience = {
138
+ trigger: user.referrerExperience.trigger,
139
+ modal: {
140
+ ...user.referrerExperience.modal,
141
+ ...title ? { title } : {},
142
+ ...appearance
143
+ }
144
+ };
145
+ modalRef.current = new import_core3.ReferralModal(deps, experience);
146
+ modalRef.current.show(appearance, containerRef.current);
147
+ }).catch((err) => {
148
+ console.error("GrowthRail: User initialization failed", err);
149
+ });
150
+ return () => {
151
+ mounted = false;
152
+ if (modalRef.current) {
153
+ modalRef.current.hide();
154
+ modalRef.current = null;
155
+ }
156
+ };
157
+ }, [title, appearance]);
158
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
159
+ "div",
160
+ {
161
+ ref: containerRef,
162
+ style: {
163
+ width: "100%",
164
+ height: "100%",
165
+ minHeight: "400px",
166
+ position: "relative"
167
+ }
168
+ }
169
+ );
170
+ };
171
+ // Annotate the CommonJS export names for ESM import in node:
172
+ 0 && (module.exports = {
173
+ GrowthRailProvider,
174
+ ReferralDashboard,
175
+ useGrowthRail
176
+ });
177
+ //# sourceMappingURL=index.js.map
@@ -0,0 +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"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,148 @@
1
+ // src/GrowthRailProvider.tsx
2
+ import { useEffect, useRef, useState } from "react";
3
+ import { GrowthRail } from "@growth-rail/core";
4
+ import { Fragment, jsx } from "react/jsx-runtime";
5
+ var GrowthRailProvider = ({
6
+ children,
7
+ userId,
8
+ ...options
9
+ }) => {
10
+ const [isReady, setIsReady] = useState(GrowthRail.isInitialized());
11
+ const initialized = useRef(false);
12
+ useEffect(() => {
13
+ if (initialized.current) return;
14
+ initialized.current = true;
15
+ GrowthRail.init(options);
16
+ if (userId) {
17
+ GrowthRail.initAppUser(userId).catch(console.error);
18
+ }
19
+ setIsReady(true);
20
+ }, []);
21
+ useEffect(() => {
22
+ if (initialized.current && userId && GrowthRail.getUserId() !== userId) {
23
+ GrowthRail.initAppUser(userId).catch(console.error);
24
+ }
25
+ }, [userId]);
26
+ if (!isReady) return null;
27
+ return /* @__PURE__ */ jsx(Fragment, { children });
28
+ };
29
+
30
+ // src/useGrowthRail.ts
31
+ import { useState as useState2, useCallback } from "react";
32
+ import { GrowthRail as GrowthRail2 } from "@growth-rail/core";
33
+ var useGrowthRail = () => {
34
+ const [isLoading, setIsLoading] = useState2(false);
35
+ const [error, setError] = useState2(null);
36
+ const initUser = useCallback(async (userId) => {
37
+ setIsLoading(true);
38
+ setError(null);
39
+ try {
40
+ const user = await GrowthRail2.initAppUser(userId);
41
+ return user;
42
+ } catch (err) {
43
+ const error2 = err instanceof Error ? err : new Error(String(err));
44
+ setError(error2);
45
+ throw error2;
46
+ } finally {
47
+ setIsLoading(false);
48
+ }
49
+ }, []);
50
+ const trackReward = useCallback(async (eventName) => {
51
+ setIsLoading(true);
52
+ setError(null);
53
+ try {
54
+ await GrowthRail2.trackRewardEvent(eventName);
55
+ } catch (err) {
56
+ const error2 = err instanceof Error ? err : new Error(String(err));
57
+ setError(error2);
58
+ throw error2;
59
+ } finally {
60
+ setIsLoading(false);
61
+ }
62
+ }, []);
63
+ const showReferralDashboard = useCallback((options) => {
64
+ GrowthRail2.showReferralDashboard(options);
65
+ }, []);
66
+ const showFloatingButton = useCallback((options) => {
67
+ GrowthRail2.createTriggerButton(options);
68
+ }, []);
69
+ const hideFloatingButton = useCallback(() => {
70
+ GrowthRail2.destroyTriggerButton();
71
+ }, []);
72
+ return {
73
+ initUser,
74
+ trackReward,
75
+ showReferralDashboard,
76
+ showFloatingButton,
77
+ hideFloatingButton,
78
+ isLoading,
79
+ error
80
+ };
81
+ };
82
+
83
+ // src/ReferralDashboard.tsx
84
+ import { useEffect as useEffect2, useRef as useRef2 } from "react";
85
+ import { GrowthRail as GrowthRail3, ReferralModal } from "@growth-rail/core";
86
+ import { jsx as jsx2 } from "react/jsx-runtime";
87
+ var ReferralDashboard = ({
88
+ title,
89
+ appearance = {},
90
+ onLinkCopied
91
+ }) => {
92
+ const containerRef = useRef2(null);
93
+ const modalRef = useRef2(null);
94
+ useEffect2(() => {
95
+ let mounted = true;
96
+ if (!containerRef.current) return;
97
+ GrowthRail3.ensureUserReady().then((user) => {
98
+ if (!mounted || !containerRef.current) return;
99
+ const deps = {
100
+ isUserReady: () => GrowthRail3.isUserReady(),
101
+ getReferralLink: () => {
102
+ try {
103
+ return GrowthRail3.getReferralLink();
104
+ } catch {
105
+ return "";
106
+ }
107
+ }
108
+ };
109
+ const experience = {
110
+ trigger: user.referrerExperience.trigger,
111
+ modal: {
112
+ ...user.referrerExperience.modal,
113
+ ...title ? { title } : {},
114
+ ...appearance
115
+ }
116
+ };
117
+ modalRef.current = new ReferralModal(deps, experience);
118
+ modalRef.current.show(appearance, containerRef.current);
119
+ }).catch((err) => {
120
+ console.error("GrowthRail: User initialization failed", err);
121
+ });
122
+ return () => {
123
+ mounted = false;
124
+ if (modalRef.current) {
125
+ modalRef.current.hide();
126
+ modalRef.current = null;
127
+ }
128
+ };
129
+ }, [title, appearance]);
130
+ return /* @__PURE__ */ jsx2(
131
+ "div",
132
+ {
133
+ ref: containerRef,
134
+ style: {
135
+ width: "100%",
136
+ height: "100%",
137
+ minHeight: "400px",
138
+ position: "relative"
139
+ }
140
+ }
141
+ );
142
+ };
143
+ export {
144
+ GrowthRailProvider,
145
+ ReferralDashboard,
146
+ useGrowthRail
147
+ };
148
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +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"]}
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@growth-rail/react",
3
+ "version": "1.0.1",
4
+ "description": "Growth Rail React SDK",
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
+ ],
18
+ "scripts": {
19
+ "build": "tsup",
20
+ "dev": "tsup --watch",
21
+ "lint": "eslint src/",
22
+ "test": "vitest run",
23
+ "type-check": "tsc --noEmit"
24
+ },
25
+ "peerDependencies": {
26
+ "react": ">=16.8"
27
+ },
28
+ "dependencies": {
29
+ "@growth-rail/core": "workspace:*"
30
+ },
31
+ "devDependencies": {
32
+ "@growth-rail/eslint-config": "*",
33
+ "@growth-rail/tsconfig": "*",
34
+ "@testing-library/dom": "^10.0.0",
35
+ "@testing-library/react": "^16.2.0",
36
+ "@types/react": "^18.0.0",
37
+ "jsdom": "^26.0.0",
38
+ "react": "^18.0.0",
39
+ "tsup": "^8.0.0",
40
+ "typescript": "^5.0.0",
41
+ "vitest": "^1.0.0"
42
+ },
43
+ "publishConfig": {
44
+ "access": "public"
45
+ }
46
+ }