@rubixscript/react-native-onboarding 1.0.0 → 1.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/LICENSE +21 -21
- package/README.md +383 -383
- package/dist/components/NavigationButtons.d.ts +23 -0
- package/dist/components/NavigationButtons.d.ts.map +1 -0
- package/dist/components/NavigationButtons.js +106 -0
- package/dist/components/Onboarding.d.ts +11 -0
- package/dist/components/Onboarding.d.ts.map +1 -0
- package/dist/components/Onboarding.js +219 -0
- package/dist/components/Pagination.d.ts +5 -0
- package/dist/components/Pagination.d.ts.map +1 -0
- package/dist/components/Pagination.js +269 -0
- package/dist/components/SimpleOnboardingScreen.d.ts +54 -0
- package/dist/components/SimpleOnboardingScreen.d.ts.map +1 -0
- package/dist/components/SimpleOnboardingScreen.js +184 -0
- package/dist/components/index.d.ts +7 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +5 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/presets/index.d.ts +27 -0
- package/dist/presets/index.d.ts.map +1 -0
- package/dist/presets/index.js +370 -0
- package/dist/slides/FormSlide.d.ts +12 -0
- package/dist/slides/FormSlide.d.ts.map +1 -0
- package/dist/slides/FormSlide.js +227 -0
- package/dist/slides/IconSlide.d.ts +10 -0
- package/dist/slides/IconSlide.d.ts.map +1 -0
- package/dist/slides/IconSlide.js +133 -0
- package/dist/slides/ImageSlide.d.ts +10 -0
- package/dist/slides/ImageSlide.d.ts.map +1 -0
- package/dist/slides/ImageSlide.js +99 -0
- package/dist/slides/VideoSlide.d.ts +10 -0
- package/dist/slides/VideoSlide.d.ts.map +1 -0
- package/dist/slides/VideoSlide.js +101 -0
- package/dist/slides/index.d.ts +14 -0
- package/dist/slides/index.d.ts.map +1 -0
- package/dist/slides/index.js +25 -0
- package/dist/themes/index.d.ts +35 -0
- package/dist/themes/index.d.ts.map +1 -0
- package/dist/themes/index.js +547 -0
- package/dist/types/index.d.ts +191 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +1 -0
- package/package.json +73 -60
- package/src/components/NavigationButtons.tsx +198 -198
- package/src/components/Onboarding.tsx +337 -340
- package/src/components/Pagination.tsx +337 -337
- package/src/components/SimpleOnboardingScreen.tsx +266 -0
- package/src/components/index.ts +7 -5
- package/src/index.ts +69 -65
- package/src/presets/index.ts +391 -394
- package/src/slides/FormSlide.tsx +314 -314
- package/src/slides/IconSlide.tsx +166 -166
- package/src/slides/ImageSlide.tsx +132 -132
- package/src/slides/VideoSlide.tsx +146 -146
- package/src/slides/{index.ts → index.tsx} +37 -44
- package/src/themes/index.ts +576 -574
- package/src/types/index.ts +247 -247
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// ONEPAGE PRESET SLIDES
|
|
3
|
+
// ============================================================================
|
|
4
|
+
export const onepageSlides = [
|
|
5
|
+
{
|
|
6
|
+
id: 'welcome',
|
|
7
|
+
type: 'image',
|
|
8
|
+
title: 'Welcome to 1Page',
|
|
9
|
+
description: 'Your personal reading companion for tracking and discovering amazing books.',
|
|
10
|
+
image: require('../../assets/images/onboarding/welcome.png'),
|
|
11
|
+
gradientColors: ['#667EEA', '#764BA2'],
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
id: 'library',
|
|
15
|
+
type: 'image',
|
|
16
|
+
title: 'Smart Library',
|
|
17
|
+
description: 'Organize your books effortlessly and discover insights about your reading habits.',
|
|
18
|
+
image: require('../../assets/images/onboarding/library.png'),
|
|
19
|
+
gradientColors: ['#667EEA', '#06D6A0'],
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
id: 'progress',
|
|
23
|
+
type: 'image',
|
|
24
|
+
title: 'Track Progress',
|
|
25
|
+
description: 'Monitor your reading journey with beautiful statistics and achievements.',
|
|
26
|
+
image: require('../../assets/images/onboarding/progress.png'),
|
|
27
|
+
gradientColors: ['#06D6A0', '#764BA2'],
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
id: 'profile',
|
|
31
|
+
type: 'form',
|
|
32
|
+
title: 'Let\'s Get Started',
|
|
33
|
+
description: 'Tell us a bit about yourself to personalize your experience.',
|
|
34
|
+
fields: [
|
|
35
|
+
{
|
|
36
|
+
key: 'name',
|
|
37
|
+
label: 'What should we call you?',
|
|
38
|
+
placeholder: 'Enter your name',
|
|
39
|
+
type: 'text',
|
|
40
|
+
required: true,
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
key: 'readerLevel',
|
|
44
|
+
label: 'Reader Level',
|
|
45
|
+
placeholder: 'Select your level',
|
|
46
|
+
type: 'select',
|
|
47
|
+
required: true,
|
|
48
|
+
options: [
|
|
49
|
+
{ value: 'novice', label: 'Novice', icon: 'book-outline' },
|
|
50
|
+
{ value: 'reader', label: 'Reader', icon: 'book' },
|
|
51
|
+
{ value: 'bookworm', label: 'Bookworm', icon: 'library' },
|
|
52
|
+
{ value: 'scholar', label: 'Scholar', icon: 'school' },
|
|
53
|
+
{ value: 'sage', label: 'Sage', icon: 'sparkles' },
|
|
54
|
+
{ value: 'master', label: 'Master', icon: 'trophy' },
|
|
55
|
+
],
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
key: 'yearlyPages',
|
|
59
|
+
label: 'Yearly Reading Goal',
|
|
60
|
+
placeholder: 'Select your goal',
|
|
61
|
+
type: 'select',
|
|
62
|
+
required: true,
|
|
63
|
+
options: [
|
|
64
|
+
{ value: '0-500', label: '0-500 pages' },
|
|
65
|
+
{ value: '500-1500', label: '500-1500 pages' },
|
|
66
|
+
{ value: '1500-3000', label: '1500-3000 pages' },
|
|
67
|
+
{ value: '3000-5000', label: '3000-5000 pages' },
|
|
68
|
+
{ value: '5000+', label: '5000+ pages' },
|
|
69
|
+
],
|
|
70
|
+
},
|
|
71
|
+
],
|
|
72
|
+
submitLabel: 'Start Reading',
|
|
73
|
+
gradientColors: ['#667EEA', '#764BA2'],
|
|
74
|
+
},
|
|
75
|
+
];
|
|
76
|
+
// ============================================================================
|
|
77
|
+
// ZAPRECIPE PRESET SLIDES
|
|
78
|
+
// ============================================================================
|
|
79
|
+
export const zaprecipeSlides = [
|
|
80
|
+
{
|
|
81
|
+
id: 'discover',
|
|
82
|
+
type: 'image',
|
|
83
|
+
title: 'Find Perfect Recipes',
|
|
84
|
+
description: 'Discover thousands of recipes tailored to your taste and dietary preferences.',
|
|
85
|
+
image: require('../../assets/images/onboarding/recipes.jpg'),
|
|
86
|
+
overlayIcon: { name: 'search', size: 40 },
|
|
87
|
+
gradientColors: ['#667eea', '#764ba2', '#6B4EFF'],
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
id: 'save',
|
|
91
|
+
type: 'image',
|
|
92
|
+
title: 'Save Your Favorites',
|
|
93
|
+
description: 'Build your personal cookbook with recipes you love and want to try.',
|
|
94
|
+
image: require('../../assets/images/onboarding/favorites.jpg'),
|
|
95
|
+
overlayIcon: { name: 'heart', size: 40 },
|
|
96
|
+
gradientColors: ['#667eea', '#764ba2', '#6B4EFF'],
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
id: 'cook',
|
|
100
|
+
type: 'image',
|
|
101
|
+
title: 'Cook with Confidence',
|
|
102
|
+
description: 'Step-by-step instructions make cooking easy and enjoyable for everyone.',
|
|
103
|
+
image: require('../../assets/images/onboarding/cooking.jpg'),
|
|
104
|
+
overlayIcon: { name: 'restaurant', size: 40 },
|
|
105
|
+
gradientColors: ['#667eea', '#764ba2', '#6B4EFF'],
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
id: 'profile',
|
|
109
|
+
type: 'form',
|
|
110
|
+
title: 'Tell Us About Yourself',
|
|
111
|
+
description: 'Help us personalize your cooking experience.',
|
|
112
|
+
fields: [
|
|
113
|
+
{
|
|
114
|
+
key: 'name',
|
|
115
|
+
label: 'Your Name',
|
|
116
|
+
placeholder: 'Enter your name',
|
|
117
|
+
type: 'text',
|
|
118
|
+
required: true,
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
key: 'cookingLevel',
|
|
122
|
+
label: 'Cooking Level',
|
|
123
|
+
placeholder: 'Select your level',
|
|
124
|
+
type: 'select',
|
|
125
|
+
required: true,
|
|
126
|
+
options: [
|
|
127
|
+
{ value: 'beginner', label: 'Beginner', icon: 'leaf' },
|
|
128
|
+
{ value: 'intermediate', label: 'Intermediate', icon: 'flame' },
|
|
129
|
+
{ value: 'advanced', label: 'Advanced', icon: 'star' },
|
|
130
|
+
],
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
key: 'improveHabits',
|
|
134
|
+
label: 'What cooking habits do you want to improve?',
|
|
135
|
+
placeholder: 'e.g., Faster prep, Better seasoning',
|
|
136
|
+
type: 'text',
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
key: 'masterSkill',
|
|
140
|
+
label: 'What culinary skill do you want to master?',
|
|
141
|
+
placeholder: 'e.g., Knife skills, Baking',
|
|
142
|
+
type: 'text',
|
|
143
|
+
},
|
|
144
|
+
],
|
|
145
|
+
submitLabel: "Let's Start Cooking!",
|
|
146
|
+
gradientColors: ['#667eea', '#764ba2', '#6B4EFF'],
|
|
147
|
+
},
|
|
148
|
+
];
|
|
149
|
+
// ============================================================================
|
|
150
|
+
// POMODO PRESET SLIDES
|
|
151
|
+
// ============================================================================
|
|
152
|
+
export const pomodoSlides = [
|
|
153
|
+
{
|
|
154
|
+
id: '1',
|
|
155
|
+
type: 'icon',
|
|
156
|
+
title: 'Focus Timer',
|
|
157
|
+
description: 'Stay productive with our Pomodoro timer. Work in focused intervals for better results.',
|
|
158
|
+
icon: {
|
|
159
|
+
name: 'timer-outline',
|
|
160
|
+
type: 'material-community',
|
|
161
|
+
size: 80,
|
|
162
|
+
color: '#000000',
|
|
163
|
+
backgroundColor: 'rgba(255, 107, 107, 0.1)',
|
|
164
|
+
backgroundSize: 160,
|
|
165
|
+
},
|
|
166
|
+
backgroundColor: '#F6F6F6',
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
id: '2',
|
|
170
|
+
type: 'icon',
|
|
171
|
+
title: 'Task Management',
|
|
172
|
+
description: 'Organize your tasks efficiently. Track progress and set priorities with ease.',
|
|
173
|
+
icon: {
|
|
174
|
+
name: 'checkbox-marked-circle-outline',
|
|
175
|
+
type: 'material-community',
|
|
176
|
+
size: 80,
|
|
177
|
+
color: '#000000',
|
|
178
|
+
backgroundColor: 'rgba(255, 107, 107, 0.1)',
|
|
179
|
+
backgroundSize: 160,
|
|
180
|
+
},
|
|
181
|
+
backgroundColor: '#F6F6F6',
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
id: '3',
|
|
185
|
+
type: 'icon',
|
|
186
|
+
title: 'Statistics',
|
|
187
|
+
description: 'Monitor your productivity with detailed statistics and insights.',
|
|
188
|
+
icon: {
|
|
189
|
+
name: 'chart-line',
|
|
190
|
+
type: 'material-community',
|
|
191
|
+
size: 80,
|
|
192
|
+
color: '#000000',
|
|
193
|
+
backgroundColor: 'rgba(255, 107, 107, 0.1)',
|
|
194
|
+
backgroundSize: 160,
|
|
195
|
+
},
|
|
196
|
+
backgroundColor: '#F6F6F6',
|
|
197
|
+
},
|
|
198
|
+
];
|
|
199
|
+
// ============================================================================
|
|
200
|
+
// MODERN PRESET SLIDES
|
|
201
|
+
// ============================================================================
|
|
202
|
+
export const modernSlides = [
|
|
203
|
+
{
|
|
204
|
+
id: 'welcome',
|
|
205
|
+
type: 'icon',
|
|
206
|
+
title: 'Welcome Aboard',
|
|
207
|
+
description: 'Get started with an amazing experience tailored just for you.',
|
|
208
|
+
icon: {
|
|
209
|
+
name: 'rocket',
|
|
210
|
+
type: 'ionicons',
|
|
211
|
+
size: 72,
|
|
212
|
+
color: '#FFFFFF',
|
|
213
|
+
backgroundColor: '#8B5CF6',
|
|
214
|
+
backgroundSize: 180,
|
|
215
|
+
},
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
id: 'features',
|
|
219
|
+
type: 'icon',
|
|
220
|
+
title: 'Powerful Features',
|
|
221
|
+
description: 'Discover tools and features designed to help you achieve more.',
|
|
222
|
+
icon: {
|
|
223
|
+
name: 'apps',
|
|
224
|
+
type: 'ionicons',
|
|
225
|
+
size: 72,
|
|
226
|
+
color: '#FFFFFF',
|
|
227
|
+
backgroundColor: '#EC4899',
|
|
228
|
+
backgroundSize: 180,
|
|
229
|
+
},
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
id: 'ready',
|
|
233
|
+
type: 'icon',
|
|
234
|
+
title: 'Ready to Go?',
|
|
235
|
+
description: 'Let\'s set up your account and get started on your journey.',
|
|
236
|
+
icon: {
|
|
237
|
+
name: 'checkmark-done',
|
|
238
|
+
type: 'ionicons',
|
|
239
|
+
size: 72,
|
|
240
|
+
color: '#FFFFFF',
|
|
241
|
+
backgroundColor: '#10B981',
|
|
242
|
+
backgroundSize: 180,
|
|
243
|
+
},
|
|
244
|
+
},
|
|
245
|
+
];
|
|
246
|
+
// ============================================================================
|
|
247
|
+
// MINIMAL PRESET SLIDES
|
|
248
|
+
// ============================================================================
|
|
249
|
+
export const minimalSlides = [
|
|
250
|
+
{
|
|
251
|
+
id: 'one',
|
|
252
|
+
type: 'icon',
|
|
253
|
+
title: 'Simple',
|
|
254
|
+
description: 'Clean and intuitive interface that\'s easy to use.',
|
|
255
|
+
icon: {
|
|
256
|
+
name: 'remove',
|
|
257
|
+
type: 'ionicons',
|
|
258
|
+
size: 48,
|
|
259
|
+
color: '#111827',
|
|
260
|
+
backgroundColor: '#F3F4F6',
|
|
261
|
+
backgroundSize: 120,
|
|
262
|
+
},
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
id: 'two',
|
|
266
|
+
type: 'icon',
|
|
267
|
+
title: 'Fast',
|
|
268
|
+
description: 'Lightning quick performance for a smooth experience.',
|
|
269
|
+
icon: {
|
|
270
|
+
name: 'flash',
|
|
271
|
+
type: 'ionicons',
|
|
272
|
+
size: 48,
|
|
273
|
+
color: '#111827',
|
|
274
|
+
backgroundColor: '#F3F4F6',
|
|
275
|
+
backgroundSize: 120,
|
|
276
|
+
},
|
|
277
|
+
},
|
|
278
|
+
{
|
|
279
|
+
id: 'three',
|
|
280
|
+
type: 'icon',
|
|
281
|
+
title: 'Yours',
|
|
282
|
+
description: 'Personalized to fit your needs perfectly.',
|
|
283
|
+
icon: {
|
|
284
|
+
name: 'person',
|
|
285
|
+
type: 'ionicons',
|
|
286
|
+
size: 48,
|
|
287
|
+
color: '#111827',
|
|
288
|
+
backgroundColor: '#F3F4F6',
|
|
289
|
+
backgroundSize: 120,
|
|
290
|
+
},
|
|
291
|
+
},
|
|
292
|
+
];
|
|
293
|
+
// ============================================================================
|
|
294
|
+
// GRADIENT PRESET SLIDES
|
|
295
|
+
// ============================================================================
|
|
296
|
+
export const gradientSlides = [
|
|
297
|
+
{
|
|
298
|
+
id: 'discover',
|
|
299
|
+
type: 'image',
|
|
300
|
+
title: 'Discover',
|
|
301
|
+
description: 'Explore new possibilities and unlock your potential.',
|
|
302
|
+
image: require('../../assets/images/onboarding/gradient1.jpg'),
|
|
303
|
+
gradientColors: ['#667EEA', '#764BA2'],
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
id: 'create',
|
|
307
|
+
type: 'image',
|
|
308
|
+
title: 'Create',
|
|
309
|
+
description: 'Build something amazing with powerful tools at your fingertips.',
|
|
310
|
+
image: require('../../assets/images/onboarding/gradient2.jpg'),
|
|
311
|
+
gradientColors: ['#f093fb', '#f5576c'],
|
|
312
|
+
},
|
|
313
|
+
{
|
|
314
|
+
id: 'share',
|
|
315
|
+
type: 'image',
|
|
316
|
+
title: 'Share',
|
|
317
|
+
description: 'Connect with others and share your journey.',
|
|
318
|
+
image: require('../../assets/images/onboarding/gradient3.jpg'),
|
|
319
|
+
gradientColors: ['#4facfe', '#00f2fe'],
|
|
320
|
+
},
|
|
321
|
+
];
|
|
322
|
+
// ============================================================================
|
|
323
|
+
// PRESET CONFIGURATIONS
|
|
324
|
+
// ============================================================================
|
|
325
|
+
export const getPresetSlides = (preset) => {
|
|
326
|
+
const slidesMap = {
|
|
327
|
+
onepage: onepageSlides,
|
|
328
|
+
zaprecipe: zaprecipeSlides,
|
|
329
|
+
pomodo: pomodoSlides,
|
|
330
|
+
modern: modernSlides,
|
|
331
|
+
minimal: minimalSlides,
|
|
332
|
+
gradient: gradientSlides,
|
|
333
|
+
};
|
|
334
|
+
return slidesMap[preset] || modernSlides;
|
|
335
|
+
};
|
|
336
|
+
export const getPresetConfig = (preset) => {
|
|
337
|
+
return {
|
|
338
|
+
slides: getPresetSlides(preset),
|
|
339
|
+
// Theme and navigation presets are applied via theme prop
|
|
340
|
+
};
|
|
341
|
+
};
|
|
342
|
+
// ============================================================================
|
|
343
|
+
// QUICK START CONFIGS
|
|
344
|
+
// ============================================================================
|
|
345
|
+
export const onepageConfig = {
|
|
346
|
+
slides: onepageSlides,
|
|
347
|
+
storage: { key: '@1page:onboarding_complete', enabled: true },
|
|
348
|
+
};
|
|
349
|
+
export const zaprecipeConfig = {
|
|
350
|
+
slides: zaprecipeSlides,
|
|
351
|
+
storage: { key: '@zaprecipe:onboarding_complete', enabled: true },
|
|
352
|
+
};
|
|
353
|
+
export const pomodoConfig = {
|
|
354
|
+
slides: pomodoSlides,
|
|
355
|
+
storage: { key: '@pomodo:onboarding_complete', enabled: true },
|
|
356
|
+
navigation: { showSkip: false },
|
|
357
|
+
};
|
|
358
|
+
export default {
|
|
359
|
+
onepageSlides,
|
|
360
|
+
zaprecipeSlides,
|
|
361
|
+
pomodoSlides,
|
|
362
|
+
modernSlides,
|
|
363
|
+
minimalSlides,
|
|
364
|
+
gradientSlides,
|
|
365
|
+
getPresetSlides,
|
|
366
|
+
getPresetConfig,
|
|
367
|
+
onepageConfig,
|
|
368
|
+
zaprecipeConfig,
|
|
369
|
+
pomodoConfig,
|
|
370
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { FormSlideData, OnboardingTheme } from '../types';
|
|
3
|
+
interface FormSlideProps {
|
|
4
|
+
data: FormSlideData;
|
|
5
|
+
theme: OnboardingTheme;
|
|
6
|
+
onSubmit: (formData: Record<string, any>) => void;
|
|
7
|
+
darkMode?: boolean;
|
|
8
|
+
isSubmitting?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare const FormSlide: React.FC<FormSlideProps>;
|
|
11
|
+
export default FormSlide;
|
|
12
|
+
//# sourceMappingURL=FormSlide.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FormSlide.d.ts","sourceRoot":"","sources":["../../src/slides/FormSlide.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4B,MAAM,OAAO,CAAC;AAejD,OAAO,EAAE,aAAa,EAAE,eAAe,EAAmB,MAAM,UAAU,CAAC;AAE3E,UAAU,cAAc;IACtB,IAAI,EAAE,aAAa,CAAC;IACpB,KAAK,EAAE,eAAe,CAAC;IACvB,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,IAAI,CAAC;IAClD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,cAAc,CA+L9C,CAAC;AAiGF,eAAe,SAAS,CAAC"}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import React, { useMemo, useState } from 'react';
|
|
2
|
+
import { View, Text, TextInput, TouchableOpacity, StyleSheet, ScrollView, KeyboardAvoidingView, Platform, } from 'react-native';
|
|
3
|
+
import Animated, { FadeIn } from 'react-native-reanimated';
|
|
4
|
+
import { LinearGradient } from 'expo-linear-gradient';
|
|
5
|
+
import { Ionicons } from '@expo/vector-icons';
|
|
6
|
+
export const FormSlide = ({ data, theme, onSubmit, darkMode, isSubmitting = false, }) => {
|
|
7
|
+
const { title, description, fields, submitLabel = 'Get Started', gradientColors } = data;
|
|
8
|
+
const [formData, setFormData] = useState({});
|
|
9
|
+
const [errors, setErrors] = useState({});
|
|
10
|
+
const containerStyle = useMemo(() => {
|
|
11
|
+
const styles = {
|
|
12
|
+
flex: 1,
|
|
13
|
+
};
|
|
14
|
+
if (data.backgroundColor) {
|
|
15
|
+
styles.backgroundColor = data.backgroundColor;
|
|
16
|
+
}
|
|
17
|
+
else if (gradientColors && gradientColors.length > 0) {
|
|
18
|
+
// Will use LinearGradient
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
styles.backgroundColor = theme.colors.background;
|
|
22
|
+
}
|
|
23
|
+
return styles;
|
|
24
|
+
}, [data, theme]);
|
|
25
|
+
const updateField = (key, value) => {
|
|
26
|
+
setFormData(prev => ({ ...prev, [key]: value }));
|
|
27
|
+
// Clear error when user starts typing
|
|
28
|
+
if (errors[key]) {
|
|
29
|
+
setErrors(prev => {
|
|
30
|
+
const newErrors = { ...prev };
|
|
31
|
+
delete newErrors[key];
|
|
32
|
+
return newErrors;
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
const validateForm = () => {
|
|
37
|
+
const newErrors = {};
|
|
38
|
+
fields.forEach(field => {
|
|
39
|
+
if (field.required && !formData[field.key]) {
|
|
40
|
+
newErrors[field.key] = `${field.label} is required`;
|
|
41
|
+
}
|
|
42
|
+
else if (field.validation && formData[field.key]) {
|
|
43
|
+
const validationResult = field.validation(formData[field.key]);
|
|
44
|
+
if (typeof validationResult === 'string') {
|
|
45
|
+
newErrors[field.key] = validationResult;
|
|
46
|
+
}
|
|
47
|
+
else if (!validationResult) {
|
|
48
|
+
newErrors[field.key] = `${field.label} is invalid`;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
setErrors(newErrors);
|
|
53
|
+
return Object.keys(newErrors).length === 0;
|
|
54
|
+
};
|
|
55
|
+
const handleSubmit = () => {
|
|
56
|
+
if (validateForm()) {
|
|
57
|
+
onSubmit(formData);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
const renderField = (field) => {
|
|
61
|
+
const value = formData[field.key];
|
|
62
|
+
const error = errors[field.key];
|
|
63
|
+
if (field.type === 'select') {
|
|
64
|
+
return (<View key={field.key} style={styles.fieldContainer}>
|
|
65
|
+
<Text style={styles.label}>{field.label}</Text>
|
|
66
|
+
<View style={styles.optionsContainer}>
|
|
67
|
+
{field.options?.map(option => (<TouchableOpacity key={option.value} style={[
|
|
68
|
+
styles.optionCard,
|
|
69
|
+
value === option.value && styles.optionCardActive,
|
|
70
|
+
{ borderColor: theme.colors.border },
|
|
71
|
+
]} onPress={() => updateField(field.key, option.value)}>
|
|
72
|
+
{option.icon && (<Ionicons name={option.icon} size={20} color={value === option.value ? theme.colors.text.inverse : theme.colors.text.secondary} style={{ marginRight: 8 }}/>)}
|
|
73
|
+
<Text style={[
|
|
74
|
+
styles.optionLabel,
|
|
75
|
+
value === option.value && { color: theme.colors.text.inverse },
|
|
76
|
+
]}>
|
|
77
|
+
{option.label}
|
|
78
|
+
</Text>
|
|
79
|
+
</TouchableOpacity>))}
|
|
80
|
+
</View>
|
|
81
|
+
{error && <Text style={styles.errorText}>{error}</Text>}
|
|
82
|
+
</View>);
|
|
83
|
+
}
|
|
84
|
+
return (<View key={field.key} style={styles.fieldContainer}>
|
|
85
|
+
<Text style={styles.label}>{field.label}</Text>
|
|
86
|
+
<TextInput style={[
|
|
87
|
+
styles.input,
|
|
88
|
+
{ borderColor: error ? theme.colors.text.secondary : theme.colors.border },
|
|
89
|
+
]} placeholder={field.placeholder} placeholderTextColor={theme.colors.text.secondary} value={value} onChangeText={text => updateField(field.key, text)} keyboardType={field.type === 'number' ? 'numeric' : field.type === 'email' ? 'email-address' : 'default'} secureTextEntry={field.type === 'password'} multiline={field.multiline} numberOfLines={field.numberOfLines}/>
|
|
90
|
+
{error && <Text style={styles.errorText}>{error}</Text>}
|
|
91
|
+
</View>);
|
|
92
|
+
};
|
|
93
|
+
const headerStyle = useMemo(() => ({
|
|
94
|
+
...styles.header,
|
|
95
|
+
backgroundColor: 'transparent',
|
|
96
|
+
}), []);
|
|
97
|
+
const titleStyle = useMemo(() => ({
|
|
98
|
+
...styles.title,
|
|
99
|
+
color: gradientColors?.length ? theme.colors.text.primary : theme.colors.text.primary,
|
|
100
|
+
}), [gradientColors, theme]);
|
|
101
|
+
const descriptionStyle = useMemo(() => ({
|
|
102
|
+
...styles.description,
|
|
103
|
+
color: gradientColors?.length ? theme.colors.text.secondary : theme.colors.text.secondary,
|
|
104
|
+
}), [gradientColors, theme]);
|
|
105
|
+
const content = (<KeyboardAvoidingView style={styles.keyboardContainer} behavior={Platform.OS === 'ios' ? 'padding' : 'height'} keyboardVerticalOffset={Platform.OS === 'ios' ? 0 : 20}>
|
|
106
|
+
<ScrollView style={styles.scrollView} contentContainerStyle={styles.scrollContent} showsVerticalScrollIndicator={false}>
|
|
107
|
+
{/* Header */}
|
|
108
|
+
<Animated.View entering={FadeIn.duration(300)} style={headerStyle}>
|
|
109
|
+
{title && <Text style={titleStyle}>{title}</Text>}
|
|
110
|
+
{description && <Text style={descriptionStyle}>{description}</Text>}
|
|
111
|
+
</Animated.View>
|
|
112
|
+
|
|
113
|
+
{/* Form Fields */}
|
|
114
|
+
<View style={styles.formContainer}>
|
|
115
|
+
{fields.map(renderField)}
|
|
116
|
+
</View>
|
|
117
|
+
|
|
118
|
+
{/* Submit Button */}
|
|
119
|
+
<Animated.View entering={FadeIn.delay(300).duration(300)} style={styles.buttonContainer}>
|
|
120
|
+
<TouchableOpacity style={[styles.submitButton, { backgroundColor: theme.colors.primary }]} onPress={handleSubmit} disabled={isSubmitting} activeOpacity={0.8}>
|
|
121
|
+
<Text style={styles.submitButtonText}>{isSubmitting ? 'Submitting...' : submitLabel}</Text>
|
|
122
|
+
</TouchableOpacity>
|
|
123
|
+
</Animated.View>
|
|
124
|
+
</ScrollView>
|
|
125
|
+
</KeyboardAvoidingView>);
|
|
126
|
+
if (gradientColors && gradientColors.length > 0) {
|
|
127
|
+
return (<LinearGradient colors={gradientColors} style={StyleSheet.absoluteFillObject}>
|
|
128
|
+
<View style={containerStyle}>{content}</View>
|
|
129
|
+
</LinearGradient>);
|
|
130
|
+
}
|
|
131
|
+
return <View style={containerStyle}>{content}</View>;
|
|
132
|
+
};
|
|
133
|
+
const styles = StyleSheet.create({
|
|
134
|
+
keyboardContainer: {
|
|
135
|
+
flex: 1,
|
|
136
|
+
},
|
|
137
|
+
scrollView: {
|
|
138
|
+
flex: 1,
|
|
139
|
+
},
|
|
140
|
+
scrollContent: {
|
|
141
|
+
padding: 24,
|
|
142
|
+
paddingBottom: 40,
|
|
143
|
+
},
|
|
144
|
+
header: {
|
|
145
|
+
marginBottom: 32,
|
|
146
|
+
alignItems: 'center',
|
|
147
|
+
},
|
|
148
|
+
title: {
|
|
149
|
+
fontSize: 28,
|
|
150
|
+
fontWeight: '700',
|
|
151
|
+
textAlign: 'center',
|
|
152
|
+
marginBottom: 12,
|
|
153
|
+
},
|
|
154
|
+
description: {
|
|
155
|
+
fontSize: 15,
|
|
156
|
+
textAlign: 'center',
|
|
157
|
+
paddingHorizontal: 20,
|
|
158
|
+
lineHeight: 22,
|
|
159
|
+
},
|
|
160
|
+
formContainer: {
|
|
161
|
+
width: '100%',
|
|
162
|
+
gap: 20,
|
|
163
|
+
},
|
|
164
|
+
fieldContainer: {
|
|
165
|
+
width: '100%',
|
|
166
|
+
},
|
|
167
|
+
label: {
|
|
168
|
+
fontSize: 14,
|
|
169
|
+
fontWeight: '600',
|
|
170
|
+
marginBottom: 8,
|
|
171
|
+
marginLeft: 4,
|
|
172
|
+
},
|
|
173
|
+
input: {
|
|
174
|
+
borderWidth: 1.5,
|
|
175
|
+
borderRadius: 12,
|
|
176
|
+
paddingHorizontal: 16,
|
|
177
|
+
paddingVertical: 14,
|
|
178
|
+
fontSize: 16,
|
|
179
|
+
backgroundColor: 'rgba(255, 255, 255, 0.9)',
|
|
180
|
+
},
|
|
181
|
+
optionsContainer: {
|
|
182
|
+
flexDirection: 'row',
|
|
183
|
+
flexWrap: 'wrap',
|
|
184
|
+
gap: 12,
|
|
185
|
+
},
|
|
186
|
+
optionCard: {
|
|
187
|
+
flexDirection: 'row',
|
|
188
|
+
alignItems: 'center',
|
|
189
|
+
paddingHorizontal: 16,
|
|
190
|
+
paddingVertical: 12,
|
|
191
|
+
borderRadius: 12,
|
|
192
|
+
borderWidth: 1.5,
|
|
193
|
+
backgroundColor: 'rgba(255, 255, 255, 0.9)',
|
|
194
|
+
minWidth: 100,
|
|
195
|
+
},
|
|
196
|
+
optionCardActive: {
|
|
197
|
+
backgroundColor: '#6B4EFF',
|
|
198
|
+
borderColor: '#6B4EFF',
|
|
199
|
+
},
|
|
200
|
+
optionLabel: {
|
|
201
|
+
fontSize: 14,
|
|
202
|
+
fontWeight: '500',
|
|
203
|
+
},
|
|
204
|
+
errorText: {
|
|
205
|
+
fontSize: 12,
|
|
206
|
+
color: '#EF4444',
|
|
207
|
+
marginTop: 4,
|
|
208
|
+
marginLeft: 4,
|
|
209
|
+
},
|
|
210
|
+
buttonContainer: {
|
|
211
|
+
marginTop: 24,
|
|
212
|
+
alignItems: 'center',
|
|
213
|
+
},
|
|
214
|
+
submitButton: {
|
|
215
|
+
paddingHorizontal: 48,
|
|
216
|
+
paddingVertical: 16,
|
|
217
|
+
borderRadius: 9999,
|
|
218
|
+
minWidth: 200,
|
|
219
|
+
alignItems: 'center',
|
|
220
|
+
},
|
|
221
|
+
submitButtonText: {
|
|
222
|
+
color: '#FFFFFF',
|
|
223
|
+
fontSize: 16,
|
|
224
|
+
fontWeight: '600',
|
|
225
|
+
},
|
|
226
|
+
});
|
|
227
|
+
export default FormSlide;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { IconSlideData, OnboardingTheme } from '../types';
|
|
3
|
+
interface IconSlideProps {
|
|
4
|
+
data: IconSlideData;
|
|
5
|
+
theme: OnboardingTheme;
|
|
6
|
+
darkMode?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare const IconSlide: React.FC<IconSlideProps>;
|
|
9
|
+
export default IconSlide;
|
|
10
|
+
//# sourceMappingURL=IconSlide.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IconSlide.d.ts","sourceRoot":"","sources":["../../src/slides/IconSlide.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkB,MAAM,OAAO,CAAC;AAKvC,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAE1D,UAAU,cAAc;IACtB,IAAI,EAAE,aAAa,CAAC;IACpB,KAAK,EAAE,eAAe,CAAC;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,cAAc,CA+H9C,CAAC;AAyBF,eAAe,SAAS,CAAC"}
|