@influto/react-native-sdk 1.1.0 → 1.2.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/README.md +50 -2
- package/lib/InfluTo.d.ts +82 -1
- package/lib/InfluTo.js +179 -0
- package/lib/components/ReferralCodeInput.d.ts +125 -0
- package/lib/components/ReferralCodeInput.js +397 -0
- package/lib/components/index.d.ts +7 -0
- package/lib/components/index.js +10 -0
- package/lib/index.js +2 -0
- package/lib/types.d.ts +65 -0
- package/lib/ui.d.ts +11 -0
- package/lib/ui.js +27 -0
- package/package.json +13 -1
- package/src/InfluTo.ts +199 -1
- package/src/components/ReferralCodeInput.tsx +596 -0
- package/src/components/index.ts +8 -0
- package/src/index.ts +3 -0
- package/src/types.ts +77 -0
- package/src/ui.ts +12 -0
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ReferralCodeInput - Pre-built UI component for promo code entry
|
|
4
|
+
*
|
|
5
|
+
* Features:
|
|
6
|
+
* - Auto-prefills if user came via attribution link
|
|
7
|
+
* - Real-time validation
|
|
8
|
+
* - Customizable styling (colors, fonts, spacing)
|
|
9
|
+
* - Loading & success/error states
|
|
10
|
+
* - Optional skip button
|
|
11
|
+
* - Callback on validation
|
|
12
|
+
* - Fully accessible
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* import { ReferralCodeInput } from '@influto/react-native-sdk/ui';
|
|
17
|
+
*
|
|
18
|
+
* <ReferralCodeInput
|
|
19
|
+
* onValidated={(result) => {
|
|
20
|
+
* if (result.valid) {
|
|
21
|
+
* navigation.navigate('Paywall', { campaign: result.campaign });
|
|
22
|
+
* }
|
|
23
|
+
* }}
|
|
24
|
+
* onSkip={() => navigation.navigate('Paywall')}
|
|
25
|
+
* />
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
29
|
+
if (k2 === undefined) k2 = k;
|
|
30
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
31
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
32
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
33
|
+
}
|
|
34
|
+
Object.defineProperty(o, k2, desc);
|
|
35
|
+
}) : (function(o, m, k, k2) {
|
|
36
|
+
if (k2 === undefined) k2 = k;
|
|
37
|
+
o[k2] = m[k];
|
|
38
|
+
}));
|
|
39
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
40
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
41
|
+
}) : function(o, v) {
|
|
42
|
+
o["default"] = v;
|
|
43
|
+
});
|
|
44
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
45
|
+
var ownKeys = function(o) {
|
|
46
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
47
|
+
var ar = [];
|
|
48
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
49
|
+
return ar;
|
|
50
|
+
};
|
|
51
|
+
return ownKeys(o);
|
|
52
|
+
};
|
|
53
|
+
return function (mod) {
|
|
54
|
+
if (mod && mod.__esModule) return mod;
|
|
55
|
+
var result = {};
|
|
56
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
57
|
+
__setModuleDefault(result, mod);
|
|
58
|
+
return result;
|
|
59
|
+
};
|
|
60
|
+
})();
|
|
61
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
62
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
63
|
+
};
|
|
64
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
65
|
+
exports.ReferralCodeInput = void 0;
|
|
66
|
+
const react_1 = __importStar(require("react"));
|
|
67
|
+
const react_native_1 = require("react-native");
|
|
68
|
+
const InfluTo_1 = __importDefault(require("../InfluTo"));
|
|
69
|
+
const ReferralCodeInput = ({ autoPrefill = true, autoValidate = false, onValidated, onSkip, onApplied, appUserId, colors = {}, fonts = {}, labels = {}, style = {}, showSkipButton = true, validateOnBlur = true }) => {
|
|
70
|
+
const [code, setCode] = (0, react_1.useState)('');
|
|
71
|
+
const [state, setState] = (0, react_1.useState)('idle');
|
|
72
|
+
const [validationResult, setValidationResult] = (0, react_1.useState)(null);
|
|
73
|
+
const [isPrefilled, setIsPrefilled] = (0, react_1.useState)(false);
|
|
74
|
+
// Default colors
|
|
75
|
+
const colorScheme = {
|
|
76
|
+
primary: colors.primary || '#3B82F6',
|
|
77
|
+
success: colors.success || '#10B981',
|
|
78
|
+
error: colors.error || '#EF4444',
|
|
79
|
+
text: colors.text || '#1F2937',
|
|
80
|
+
textSecondary: colors.textSecondary || '#6B7280',
|
|
81
|
+
background: colors.background || '#FFFFFF',
|
|
82
|
+
border: colors.border || '#D1D5DB',
|
|
83
|
+
inputBackground: colors.inputBackground || '#F9FAFB'
|
|
84
|
+
};
|
|
85
|
+
// Default fonts
|
|
86
|
+
const fontScheme = {
|
|
87
|
+
family: fonts.family || (react_native_1.Platform.OS === 'ios' ? 'System' : 'Roboto'),
|
|
88
|
+
sizeTitle: fonts.sizeTitle || 18,
|
|
89
|
+
sizeInput: fonts.sizeInput || 16,
|
|
90
|
+
sizeButton: fonts.sizeButton || 16,
|
|
91
|
+
sizeMessage: fonts.sizeMessage || 14
|
|
92
|
+
};
|
|
93
|
+
// Default labels
|
|
94
|
+
const labelScheme = {
|
|
95
|
+
title: labels.title || 'Have a promo code?',
|
|
96
|
+
subtitle: labels.subtitle || 'Enter your referral code to unlock special offers',
|
|
97
|
+
placeholder: labels.placeholder || 'Enter code (e.g., FITGURU30)',
|
|
98
|
+
validateButton: labels.validateButton || 'Apply Code',
|
|
99
|
+
skipButton: labels.skipButton || 'Skip',
|
|
100
|
+
validatingMessage: labels.validatingMessage || 'Validating code...',
|
|
101
|
+
validMessage: labels.validMessage || 'Code applied successfully!',
|
|
102
|
+
invalidMessage: labels.invalidMessage || 'Invalid code. Please try again.',
|
|
103
|
+
errorMessage: labels.errorMessage || 'Unable to validate code. Check your connection.',
|
|
104
|
+
prefilledMessage: labels.prefilledMessage || 'Code detected from your referral link'
|
|
105
|
+
};
|
|
106
|
+
// Auto-prefill on mount
|
|
107
|
+
(0, react_1.useEffect)(() => {
|
|
108
|
+
if (autoPrefill) {
|
|
109
|
+
loadPrefilledCode();
|
|
110
|
+
}
|
|
111
|
+
}, [autoPrefill]);
|
|
112
|
+
const loadPrefilledCode = async () => {
|
|
113
|
+
try {
|
|
114
|
+
const prefilledCode = await InfluTo_1.default.getPrefilledCode();
|
|
115
|
+
if (prefilledCode) {
|
|
116
|
+
setCode(prefilledCode);
|
|
117
|
+
setIsPrefilled(true);
|
|
118
|
+
// Auto-validate if enabled
|
|
119
|
+
if (autoValidate) {
|
|
120
|
+
await handleValidate(prefilledCode);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
catch (error) {
|
|
125
|
+
console.error('[ReferralCodeInput] Failed to load prefilled code:', error);
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
const handleValidate = async (codeToValidate = code) => {
|
|
129
|
+
if (!codeToValidate || codeToValidate.length < 4) {
|
|
130
|
+
setState('invalid');
|
|
131
|
+
setValidationResult({
|
|
132
|
+
valid: false,
|
|
133
|
+
error: 'Please enter a valid code',
|
|
134
|
+
error_code: 'INVALID_FORMAT'
|
|
135
|
+
});
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
setState('validating');
|
|
139
|
+
setValidationResult(null);
|
|
140
|
+
try {
|
|
141
|
+
const result = await InfluTo_1.default.validateCode(codeToValidate);
|
|
142
|
+
setValidationResult(result);
|
|
143
|
+
if (result.valid) {
|
|
144
|
+
setState('valid');
|
|
145
|
+
// Automatically set the code if valid
|
|
146
|
+
const setResult = await InfluTo_1.default.setReferralCode(codeToValidate, appUserId);
|
|
147
|
+
if (setResult.success) {
|
|
148
|
+
onApplied?.(result);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
setState('invalid');
|
|
153
|
+
}
|
|
154
|
+
// Notify parent
|
|
155
|
+
onValidated?.(result);
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
setState('error');
|
|
159
|
+
setValidationResult({
|
|
160
|
+
valid: false,
|
|
161
|
+
error: 'Network error',
|
|
162
|
+
error_code: 'NETWORK_ERROR'
|
|
163
|
+
});
|
|
164
|
+
onValidated?.({
|
|
165
|
+
valid: false,
|
|
166
|
+
error: 'Network error',
|
|
167
|
+
error_code: 'NETWORK_ERROR'
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
const handleSkip = () => {
|
|
172
|
+
onSkip?.();
|
|
173
|
+
};
|
|
174
|
+
const handleBlur = () => {
|
|
175
|
+
if (validateOnBlur && code && state === 'idle') {
|
|
176
|
+
handleValidate();
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
// Get message based on state
|
|
180
|
+
const getMessage = () => {
|
|
181
|
+
if (isPrefilled && state === 'idle') {
|
|
182
|
+
return { text: labelScheme.prefilledMessage, color: colorScheme.primary };
|
|
183
|
+
}
|
|
184
|
+
switch (state) {
|
|
185
|
+
case 'validating':
|
|
186
|
+
return { text: labelScheme.validatingMessage, color: colorScheme.textSecondary };
|
|
187
|
+
case 'valid':
|
|
188
|
+
return {
|
|
189
|
+
text: validationResult?.message || labelScheme.validMessage,
|
|
190
|
+
color: colorScheme.success
|
|
191
|
+
};
|
|
192
|
+
case 'invalid':
|
|
193
|
+
return {
|
|
194
|
+
text: validationResult?.error || labelScheme.invalidMessage,
|
|
195
|
+
color: colorScheme.error
|
|
196
|
+
};
|
|
197
|
+
case 'error':
|
|
198
|
+
return { text: labelScheme.errorMessage, color: colorScheme.error };
|
|
199
|
+
default:
|
|
200
|
+
return null;
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
const message = getMessage();
|
|
204
|
+
return (react_1.default.createElement(react_native_1.View, { style: [styles.container, style.container] },
|
|
205
|
+
react_1.default.createElement(react_native_1.View, { style: [styles.titleContainer, style.titleContainer] },
|
|
206
|
+
react_1.default.createElement(react_native_1.Text, { style: [
|
|
207
|
+
styles.title,
|
|
208
|
+
{ color: colorScheme.text, fontFamily: fontScheme.family, fontSize: fontScheme.sizeTitle },
|
|
209
|
+
style.title
|
|
210
|
+
] }, labelScheme.title),
|
|
211
|
+
labelScheme.subtitle && (react_1.default.createElement(react_native_1.Text, { style: [
|
|
212
|
+
styles.subtitle,
|
|
213
|
+
{ color: colorScheme.textSecondary, fontFamily: fontScheme.family, fontSize: fontScheme.sizeMessage },
|
|
214
|
+
style.subtitle
|
|
215
|
+
] }, labelScheme.subtitle))),
|
|
216
|
+
react_1.default.createElement(react_native_1.View, { style: [styles.inputContainer, style.inputContainer] },
|
|
217
|
+
react_1.default.createElement(react_native_1.TextInput, { style: [
|
|
218
|
+
styles.input,
|
|
219
|
+
{
|
|
220
|
+
backgroundColor: colorScheme.inputBackground,
|
|
221
|
+
borderColor: state === 'valid' ? colorScheme.success : state === 'invalid' || state === 'error' ? colorScheme.error : colorScheme.border,
|
|
222
|
+
color: colorScheme.text,
|
|
223
|
+
fontFamily: fontScheme.family,
|
|
224
|
+
fontSize: fontScheme.sizeInput
|
|
225
|
+
},
|
|
226
|
+
style.input
|
|
227
|
+
], value: code, onChangeText: (text) => {
|
|
228
|
+
setCode(text.toUpperCase());
|
|
229
|
+
if (state !== 'idle' && state !== 'validating') {
|
|
230
|
+
setState('idle');
|
|
231
|
+
setValidationResult(null);
|
|
232
|
+
}
|
|
233
|
+
}, onBlur: handleBlur, placeholder: labelScheme.placeholder, placeholderTextColor: colorScheme.textSecondary, autoCapitalize: "characters", autoCorrect: false, autoComplete: "off", maxLength: 20, editable: state !== 'validating', accessibilityLabel: "Referral code input", accessibilityHint: "Enter your promo or referral code" }),
|
|
234
|
+
state === 'valid' && (react_1.default.createElement(react_native_1.View, { style: styles.iconContainer },
|
|
235
|
+
react_1.default.createElement(react_native_1.Text, { style: [styles.icon, { color: colorScheme.success }] }, "\u2713"))),
|
|
236
|
+
(state === 'invalid' || state === 'error') && (react_1.default.createElement(react_native_1.View, { style: styles.iconContainer },
|
|
237
|
+
react_1.default.createElement(react_native_1.Text, { style: [styles.icon, { color: colorScheme.error }] }, "\u2717")))),
|
|
238
|
+
message && (react_1.default.createElement(react_native_1.View, { style: [styles.messageContainer, style.messageContainer] },
|
|
239
|
+
react_1.default.createElement(react_native_1.Text, { style: [
|
|
240
|
+
styles.messageText,
|
|
241
|
+
{ color: message.color, fontFamily: fontScheme.family, fontSize: fontScheme.sizeMessage },
|
|
242
|
+
style.messageText
|
|
243
|
+
] }, message.text))),
|
|
244
|
+
react_1.default.createElement(react_native_1.View, { style: [styles.buttonContainer, style.buttonContainer] },
|
|
245
|
+
react_1.default.createElement(react_native_1.TouchableOpacity, { style: [
|
|
246
|
+
styles.validateButton,
|
|
247
|
+
{
|
|
248
|
+
backgroundColor: state === 'valid' ? colorScheme.success : colorScheme.primary,
|
|
249
|
+
opacity: state === 'validating' || !code ? 0.6 : 1
|
|
250
|
+
},
|
|
251
|
+
style.validateButton
|
|
252
|
+
], onPress: () => handleValidate(), disabled: state === 'validating' || !code, accessibilityLabel: labelScheme.validateButton, accessibilityRole: "button" }, state === 'validating' ? (react_1.default.createElement(react_native_1.ActivityIndicator, { color: "#FFFFFF", size: "small" })) : (react_1.default.createElement(react_native_1.Text, { style: [
|
|
253
|
+
styles.validateButtonText,
|
|
254
|
+
{ fontFamily: fontScheme.family, fontSize: fontScheme.sizeButton },
|
|
255
|
+
style.validateButtonText
|
|
256
|
+
] },
|
|
257
|
+
state === 'valid' ? '✓ ' : '',
|
|
258
|
+
labelScheme.validateButton))),
|
|
259
|
+
showSkipButton && onSkip && (react_1.default.createElement(react_native_1.TouchableOpacity, { style: [styles.skipButton, style.skipButton], onPress: handleSkip, disabled: state === 'validating', accessibilityLabel: labelScheme.skipButton, accessibilityRole: "button" },
|
|
260
|
+
react_1.default.createElement(react_native_1.Text, { style: [
|
|
261
|
+
styles.skipButtonText,
|
|
262
|
+
{ color: colorScheme.textSecondary, fontFamily: fontScheme.family, fontSize: fontScheme.sizeButton },
|
|
263
|
+
style.skipButtonText
|
|
264
|
+
] }, labelScheme.skipButton)))),
|
|
265
|
+
state === 'valid' && validationResult?.campaign && (react_1.default.createElement(react_native_1.View, { style: styles.campaignInfo },
|
|
266
|
+
react_1.default.createElement(react_native_1.Text, { style: [
|
|
267
|
+
styles.campaignTitle,
|
|
268
|
+
{ color: colorScheme.text, fontFamily: fontScheme.family }
|
|
269
|
+
] }, validationResult.campaign.name),
|
|
270
|
+
validationResult.campaign.description && (react_1.default.createElement(react_native_1.Text, { style: [
|
|
271
|
+
styles.campaignDescription,
|
|
272
|
+
{ color: colorScheme.textSecondary, fontFamily: fontScheme.family }
|
|
273
|
+
] }, validationResult.campaign.description)),
|
|
274
|
+
validationResult.influencer && (react_1.default.createElement(react_native_1.Text, { style: [
|
|
275
|
+
styles.influencerInfo,
|
|
276
|
+
{ color: colorScheme.textSecondary, fontFamily: fontScheme.family }
|
|
277
|
+
] },
|
|
278
|
+
"Referred by ",
|
|
279
|
+
validationResult.influencer.name,
|
|
280
|
+
validationResult.influencer.social_handle && ` (@${validationResult.influencer.social_handle})`))))));
|
|
281
|
+
};
|
|
282
|
+
exports.ReferralCodeInput = ReferralCodeInput;
|
|
283
|
+
const styles = react_native_1.StyleSheet.create({
|
|
284
|
+
container: {
|
|
285
|
+
padding: 20,
|
|
286
|
+
backgroundColor: '#FFFFFF',
|
|
287
|
+
borderRadius: 12,
|
|
288
|
+
shadowColor: '#000',
|
|
289
|
+
shadowOffset: { width: 0, height: 2 },
|
|
290
|
+
shadowOpacity: 0.1,
|
|
291
|
+
shadowRadius: 8,
|
|
292
|
+
elevation: 4
|
|
293
|
+
},
|
|
294
|
+
titleContainer: {
|
|
295
|
+
marginBottom: 16
|
|
296
|
+
},
|
|
297
|
+
title: {
|
|
298
|
+
fontSize: 18,
|
|
299
|
+
fontWeight: '600',
|
|
300
|
+
marginBottom: 4
|
|
301
|
+
},
|
|
302
|
+
subtitle: {
|
|
303
|
+
fontSize: 14,
|
|
304
|
+
lineHeight: 20
|
|
305
|
+
},
|
|
306
|
+
inputContainer: {
|
|
307
|
+
position: 'relative',
|
|
308
|
+
marginBottom: 12
|
|
309
|
+
},
|
|
310
|
+
input: {
|
|
311
|
+
height: 50,
|
|
312
|
+
borderWidth: 2,
|
|
313
|
+
borderRadius: 8,
|
|
314
|
+
paddingHorizontal: 16,
|
|
315
|
+
paddingRight: 48, // Space for icon
|
|
316
|
+
fontSize: 16,
|
|
317
|
+
fontWeight: '500'
|
|
318
|
+
},
|
|
319
|
+
iconContainer: {
|
|
320
|
+
position: 'absolute',
|
|
321
|
+
right: 16,
|
|
322
|
+
top: 12,
|
|
323
|
+
width: 24,
|
|
324
|
+
height: 24,
|
|
325
|
+
justifyContent: 'center',
|
|
326
|
+
alignItems: 'center'
|
|
327
|
+
},
|
|
328
|
+
icon: {
|
|
329
|
+
fontSize: 20,
|
|
330
|
+
fontWeight: 'bold'
|
|
331
|
+
},
|
|
332
|
+
messageContainer: {
|
|
333
|
+
marginBottom: 12,
|
|
334
|
+
padding: 12,
|
|
335
|
+
backgroundColor: '#F9FAFB',
|
|
336
|
+
borderRadius: 6
|
|
337
|
+
},
|
|
338
|
+
messageText: {
|
|
339
|
+
fontSize: 14,
|
|
340
|
+
lineHeight: 18,
|
|
341
|
+
textAlign: 'center'
|
|
342
|
+
},
|
|
343
|
+
buttonContainer: {
|
|
344
|
+
flexDirection: 'row',
|
|
345
|
+
gap: 12
|
|
346
|
+
},
|
|
347
|
+
validateButton: {
|
|
348
|
+
flex: 1,
|
|
349
|
+
height: 50,
|
|
350
|
+
borderRadius: 8,
|
|
351
|
+
justifyContent: 'center',
|
|
352
|
+
alignItems: 'center',
|
|
353
|
+
shadowColor: '#000',
|
|
354
|
+
shadowOffset: { width: 0, height: 2 },
|
|
355
|
+
shadowOpacity: 0.1,
|
|
356
|
+
shadowRadius: 4,
|
|
357
|
+
elevation: 2
|
|
358
|
+
},
|
|
359
|
+
validateButtonText: {
|
|
360
|
+
color: '#FFFFFF',
|
|
361
|
+
fontSize: 16,
|
|
362
|
+
fontWeight: '600'
|
|
363
|
+
},
|
|
364
|
+
skipButton: {
|
|
365
|
+
height: 50,
|
|
366
|
+
paddingHorizontal: 20,
|
|
367
|
+
justifyContent: 'center',
|
|
368
|
+
alignItems: 'center'
|
|
369
|
+
},
|
|
370
|
+
skipButtonText: {
|
|
371
|
+
fontSize: 16,
|
|
372
|
+
fontWeight: '500'
|
|
373
|
+
},
|
|
374
|
+
campaignInfo: {
|
|
375
|
+
marginTop: 16,
|
|
376
|
+
padding: 12,
|
|
377
|
+
backgroundColor: '#F0FDF4',
|
|
378
|
+
borderRadius: 8,
|
|
379
|
+
borderLeftWidth: 3,
|
|
380
|
+
borderLeftColor: '#10B981'
|
|
381
|
+
},
|
|
382
|
+
campaignTitle: {
|
|
383
|
+
fontSize: 15,
|
|
384
|
+
fontWeight: '600',
|
|
385
|
+
marginBottom: 4
|
|
386
|
+
},
|
|
387
|
+
campaignDescription: {
|
|
388
|
+
fontSize: 13,
|
|
389
|
+
lineHeight: 18,
|
|
390
|
+
marginBottom: 4
|
|
391
|
+
},
|
|
392
|
+
influencerInfo: {
|
|
393
|
+
fontSize: 12,
|
|
394
|
+
fontStyle: 'italic'
|
|
395
|
+
}
|
|
396
|
+
});
|
|
397
|
+
exports.default = exports.ReferralCodeInput;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* InfluTo SDK UI Components
|
|
4
|
+
*
|
|
5
|
+
* Pre-built React Native components for easy integration
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.ReferralCodeInput = void 0;
|
|
9
|
+
var ReferralCodeInput_1 = require("./ReferralCodeInput");
|
|
10
|
+
Object.defineProperty(exports, "ReferralCodeInput", { enumerable: true, get: function () { return ReferralCodeInput_1.ReferralCodeInput; } });
|
package/lib/index.js
CHANGED
|
@@ -25,3 +25,5 @@ exports.default = void 0;
|
|
|
25
25
|
var InfluTo_1 = require("./InfluTo");
|
|
26
26
|
Object.defineProperty(exports, "default", { enumerable: true, get: function () { return __importDefault(InfluTo_1).default; } });
|
|
27
27
|
__exportStar(require("./types"), exports);
|
|
28
|
+
// Note: UI components are exported separately via './ui' to keep bundle size small
|
|
29
|
+
// Import with: import { ReferralCodeInput } from '@influto/react-native-sdk/ui';
|
package/lib/types.d.ts
CHANGED
|
@@ -74,3 +74,68 @@ export interface DeviceInfo {
|
|
|
74
74
|
timezone?: string;
|
|
75
75
|
language?: string;
|
|
76
76
|
}
|
|
77
|
+
export interface CodeValidationResult {
|
|
78
|
+
/**
|
|
79
|
+
* Whether the code is valid
|
|
80
|
+
*/
|
|
81
|
+
valid: boolean;
|
|
82
|
+
/**
|
|
83
|
+
* Normalized code (uppercase)
|
|
84
|
+
*/
|
|
85
|
+
code?: string;
|
|
86
|
+
/**
|
|
87
|
+
* Campaign information if valid
|
|
88
|
+
*/
|
|
89
|
+
campaign?: {
|
|
90
|
+
id: string;
|
|
91
|
+
name: string;
|
|
92
|
+
description?: string;
|
|
93
|
+
commission_percentage: number;
|
|
94
|
+
campaign_type: string;
|
|
95
|
+
};
|
|
96
|
+
/**
|
|
97
|
+
* Influencer information if available
|
|
98
|
+
*/
|
|
99
|
+
influencer?: {
|
|
100
|
+
name: string;
|
|
101
|
+
social_handle?: string;
|
|
102
|
+
follower_count?: number;
|
|
103
|
+
};
|
|
104
|
+
/**
|
|
105
|
+
* Custom campaign data (for conditional offers)
|
|
106
|
+
*/
|
|
107
|
+
custom_data?: Record<string, any>;
|
|
108
|
+
/**
|
|
109
|
+
* Success message
|
|
110
|
+
*/
|
|
111
|
+
message?: string;
|
|
112
|
+
/**
|
|
113
|
+
* Error message if invalid
|
|
114
|
+
*/
|
|
115
|
+
error?: string;
|
|
116
|
+
/**
|
|
117
|
+
* Error code for programmatic handling
|
|
118
|
+
*/
|
|
119
|
+
error_code?: 'INVALID_FORMAT' | 'CODE_NOT_FOUND' | 'NETWORK_ERROR';
|
|
120
|
+
}
|
|
121
|
+
export interface SetCodeResult {
|
|
122
|
+
/**
|
|
123
|
+
* Whether code was set successfully
|
|
124
|
+
*/
|
|
125
|
+
success: boolean;
|
|
126
|
+
/**
|
|
127
|
+
* Normalized code
|
|
128
|
+
*/
|
|
129
|
+
code?: string;
|
|
130
|
+
/**
|
|
131
|
+
* Success/error message
|
|
132
|
+
*/
|
|
133
|
+
message: string;
|
|
134
|
+
/**
|
|
135
|
+
* Campaign info
|
|
136
|
+
*/
|
|
137
|
+
campaign?: {
|
|
138
|
+
id: string;
|
|
139
|
+
name: string;
|
|
140
|
+
};
|
|
141
|
+
}
|
package/lib/ui.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* InfluTo SDK - UI Components Entry Point
|
|
3
|
+
*
|
|
4
|
+
* Import UI components separately to keep main SDK bundle small.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* import { ReferralCodeInput } from '@influto/react-native-sdk/ui';
|
|
9
|
+
* ```
|
|
10
|
+
*/
|
|
11
|
+
export * from './components';
|
package/lib/ui.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* InfluTo SDK - UI Components Entry Point
|
|
4
|
+
*
|
|
5
|
+
* Import UI components separately to keep main SDK bundle small.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { ReferralCodeInput } from '@influto/react-native-sdk/ui';
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
12
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
15
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
16
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
17
|
+
}
|
|
18
|
+
Object.defineProperty(o, k2, desc);
|
|
19
|
+
}) : (function(o, m, k, k2) {
|
|
20
|
+
if (k2 === undefined) k2 = k;
|
|
21
|
+
o[k2] = m[k];
|
|
22
|
+
}));
|
|
23
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
24
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
25
|
+
};
|
|
26
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
27
|
+
__exportStar(require("./components"), exports);
|
package/package.json
CHANGED
|
@@ -1,9 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@influto/react-native-sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "InfluTo SDK for React Native - Track influencer referrals and conversions",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"import": "./lib/index.js",
|
|
10
|
+
"require": "./lib/index.js",
|
|
11
|
+
"types": "./lib/index.d.ts"
|
|
12
|
+
},
|
|
13
|
+
"./ui": {
|
|
14
|
+
"import": "./lib/ui.js",
|
|
15
|
+
"require": "./lib/ui.js",
|
|
16
|
+
"types": "./lib/ui.d.ts"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
7
19
|
"files": [
|
|
8
20
|
"lib",
|
|
9
21
|
"src",
|