@rubixscript/react-native-onboarding 1.1.2 → 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.
@@ -3,25 +3,35 @@
3
3
  * @description A simple, beautiful onboarding screen with customizable slides, colors, and styling
4
4
  *
5
5
  * @props
6
- * - onComplete: () => void - Handler called when onboarding is finished
6
+ * - onComplete: (userData?: UserData) => void - Handler called when onboarding is finished with optional user data
7
7
  * - slides: SimpleSlide[] - Array of slides to display (optional, has default)
8
+ * - showForm: boolean - Whether to show a form slide at the end (default: true)
9
+ * - formFields: FormField[] - Custom form fields (optional, has default)
10
+ * - allowSkipForm: boolean - Allow skipping the form (default: true)
8
11
  * - primaryColor: string - Primary color for buttons and active dots (default: '#FF6B6B')
9
12
  * - backgroundColor: string - Background color of the screen (default: '#F6F6F6')
10
13
  * - iconBackgroundColor: string - Background color for icon container (default: 'rgba(255, 107, 107, 0.1)')
11
14
  * - textColor: string - Color for titles (default: '#000000')
12
15
  * - descriptionColor: string - Color for descriptions (default: '#666666')
16
+ * - inputBackgroundColor: string - Background color for form inputs (default: '#FFFFFF')
17
+ * - inputBorderColor: string - Border color for form inputs (default: '#E0E0E0')
13
18
  * - buttonTextNext: string - Text for next button (default: 'Next')
14
19
  * - buttonTextDone: string - Text for done button (default: 'Get Started')
20
+ * - buttonTextSkip: string - Text for skip button (default: 'Skip')
21
+ * - buttonTextSubmit: string - Text for submit button (default: 'Get Started')
15
22
  * - testID?: string - Test identifier for testing
16
23
  *
17
24
  * @states
18
25
  * - currentIndex: number - Current onboarding screen index
26
+ * - formData: UserData - Form data collected from user
19
27
  *
20
28
  * @features
21
29
  * - Step-by-step app introduction
22
30
  * - Interactive animations
23
31
  * - Feature highlights
24
32
  * - Progress indication
33
+ * - User data collection (name, purpose)
34
+ * - Skip functionality
25
35
  * - Fully customizable styling
26
36
  *
27
37
  * @dependencies
@@ -37,18 +47,38 @@ export interface SimpleSlide {
37
47
  description: string;
38
48
  icon: keyof typeof MaterialCommunityIcons.glyphMap;
39
49
  }
50
+ export interface FormField {
51
+ key: string;
52
+ label: string;
53
+ placeholder: string;
54
+ multiline?: boolean;
55
+ autoCapitalize?: 'none' | 'sentences' | 'words' | 'characters';
56
+ }
57
+ export interface UserData {
58
+ name?: string;
59
+ purpose?: string;
60
+ [key: string]: string | undefined;
61
+ }
40
62
  interface SimpleOnboardingScreenProps {
41
- onComplete: () => Promise<void>;
63
+ onComplete: (userData?: UserData) => Promise<void>;
42
64
  slides?: SimpleSlide[];
65
+ showForm?: boolean;
66
+ formFields?: FormField[];
67
+ allowSkipForm?: boolean;
43
68
  primaryColor?: string;
44
69
  backgroundColor?: string;
45
70
  iconBackgroundColor?: string;
46
71
  textColor?: string;
47
72
  descriptionColor?: string;
73
+ inputBackgroundColor?: string;
74
+ inputBorderColor?: string;
75
+ inputTextColor?: string;
48
76
  buttonTextNext?: string;
49
77
  buttonTextDone?: string;
78
+ buttonTextSkip?: string;
79
+ buttonTextSubmit?: string;
50
80
  testID?: string;
51
81
  }
52
- export default function SimpleOnboardingScreen({ onComplete, slides, primaryColor, backgroundColor, iconBackgroundColor, textColor, descriptionColor, buttonTextNext, buttonTextDone, testID, }: SimpleOnboardingScreenProps): React.JSX.Element;
82
+ export default function SimpleOnboardingScreen({ onComplete, slides, showForm, formFields, allowSkipForm, primaryColor, backgroundColor, iconBackgroundColor, textColor, descriptionColor, inputBackgroundColor, inputBorderColor, inputTextColor, buttonTextNext, buttonTextDone, buttonTextSkip, buttonTextSubmit, testID, }: SimpleOnboardingScreenProps): React.JSX.Element;
53
83
  export {};
54
84
  //# sourceMappingURL=SimpleOnboardingScreen.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SimpleOnboardingScreen.d.ts","sourceRoot":"","sources":["../../src/components/SimpleOnboardingScreen.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,KAA2B,MAAM,OAAO,CAAC;AAahD,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAK5D,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,OAAO,sBAAsB,CAAC,QAAQ,CAAC;CACpD;AAuBD,UAAU,2BAA2B;IACnC,UAAU,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAChC,MAAM,CAAC,EAAE,WAAW,EAAE,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,CAAC,OAAO,UAAU,sBAAsB,CAAC,EAC7C,UAAU,EACV,MAAsB,EACtB,YAAwB,EACxB,eAA2B,EAC3B,mBAAgD,EAChD,SAAqB,EACrB,gBAA4B,EAC5B,cAAuB,EACvB,cAA8B,EAC9B,MAAM,GACP,EAAE,2BAA2B,qBAuF7B"}
1
+ {"version":3,"file":"SimpleOnboardingScreen.d.ts","sourceRoot":"","sources":["../../src/components/SimpleOnboardingScreen.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH,OAAO,KAA2B,MAAM,OAAO,CAAC;AAgBhD,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAK5D,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,OAAO,sBAAsB,CAAC,QAAQ,CAAC;CACpD;AAED,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,OAAO,GAAG,YAAY,CAAC;CAChE;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CACnC;AAuCD,UAAU,2BAA2B;IACnC,UAAU,EAAE,CAAC,QAAQ,CAAC,EAAE,QAAQ,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,MAAM,CAAC,EAAE,WAAW,EAAE,CAAC;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,SAAS,EAAE,CAAC;IACzB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,CAAC,OAAO,UAAU,sBAAsB,CAAC,EAC7C,UAAU,EACV,MAAsB,EACtB,QAAe,EACf,UAA8B,EAC9B,aAAoB,EACpB,YAAwB,EACxB,eAA2B,EAC3B,mBAAgD,EAChD,SAAqB,EACrB,gBAA4B,EAC5B,oBAAgC,EAChC,gBAA4B,EAC5B,cAA0B,EAC1B,cAAuB,EACvB,cAA8B,EAC9B,cAAuB,EACvB,gBAAgC,EAChC,MAAM,GACP,EAAE,2BAA2B,qBAuL7B"}
@@ -3,25 +3,35 @@
3
3
  * @description A simple, beautiful onboarding screen with customizable slides, colors, and styling
4
4
  *
5
5
  * @props
6
- * - onComplete: () => void - Handler called when onboarding is finished
6
+ * - onComplete: (userData?: UserData) => void - Handler called when onboarding is finished with optional user data
7
7
  * - slides: SimpleSlide[] - Array of slides to display (optional, has default)
8
+ * - showForm: boolean - Whether to show a form slide at the end (default: true)
9
+ * - formFields: FormField[] - Custom form fields (optional, has default)
10
+ * - allowSkipForm: boolean - Allow skipping the form (default: true)
8
11
  * - primaryColor: string - Primary color for buttons and active dots (default: '#FF6B6B')
9
12
  * - backgroundColor: string - Background color of the screen (default: '#F6F6F6')
10
13
  * - iconBackgroundColor: string - Background color for icon container (default: 'rgba(255, 107, 107, 0.1)')
11
14
  * - textColor: string - Color for titles (default: '#000000')
12
15
  * - descriptionColor: string - Color for descriptions (default: '#666666')
16
+ * - inputBackgroundColor: string - Background color for form inputs (default: '#FFFFFF')
17
+ * - inputBorderColor: string - Border color for form inputs (default: '#E0E0E0')
13
18
  * - buttonTextNext: string - Text for next button (default: 'Next')
14
19
  * - buttonTextDone: string - Text for done button (default: 'Get Started')
20
+ * - buttonTextSkip: string - Text for skip button (default: 'Skip')
21
+ * - buttonTextSubmit: string - Text for submit button (default: 'Get Started')
15
22
  * - testID?: string - Test identifier for testing
16
23
  *
17
24
  * @states
18
25
  * - currentIndex: number - Current onboarding screen index
26
+ * - formData: UserData - Form data collected from user
19
27
  *
20
28
  * @features
21
29
  * - Step-by-step app introduction
22
30
  * - Interactive animations
23
31
  * - Feature highlights
24
32
  * - Progress indication
33
+ * - User data collection (name, purpose)
34
+ * - Skip functionality
25
35
  * - Fully customizable styling
26
36
  *
27
37
  * @dependencies
@@ -30,7 +40,7 @@
30
40
  * - react-native components
31
41
  */
32
42
  import React, { useRef, useState } from 'react';
33
- import { View, Text, StyleSheet, Dimensions, TouchableOpacity, FlatList, Platform, StatusBar, } from 'react-native';
43
+ import { View, Text, StyleSheet, Dimensions, TouchableOpacity, FlatList, Platform, StatusBar, TextInput, KeyboardAvoidingView, ScrollView, } from 'react-native';
34
44
  import { SafeAreaView } from 'react-native-safe-area-context';
35
45
  import { BlurView } from 'expo-blur';
36
46
  import { MaterialCommunityIcons } from '@expo/vector-icons';
@@ -56,10 +66,33 @@ const defaultSlides = [
56
66
  icon: 'chart-line',
57
67
  },
58
68
  ];
59
- export default function SimpleOnboardingScreen({ onComplete, slides = defaultSlides, primaryColor = '#FF6B6B', backgroundColor = '#F6F6F6', iconBackgroundColor = 'rgba(255, 107, 107, 0.1)', textColor = '#000000', descriptionColor = '#666666', buttonTextNext = 'Next', buttonTextDone = 'Get Started', testID, }) {
69
+ const defaultFormFields = [
70
+ {
71
+ key: 'name',
72
+ label: 'What should we call you?',
73
+ placeholder: 'Enter your name',
74
+ autoCapitalize: 'words',
75
+ },
76
+ {
77
+ key: 'purpose',
78
+ label: 'What are you looking to use this app for?',
79
+ placeholder: 'e.g., Focus on work, Study, Track goals...',
80
+ multiline: true,
81
+ autoCapitalize: 'sentences',
82
+ },
83
+ ];
84
+ export default function SimpleOnboardingScreen({ onComplete, slides = defaultSlides, showForm = true, formFields = defaultFormFields, allowSkipForm = true, primaryColor = '#FF6B6B', backgroundColor = '#F6F6F6', iconBackgroundColor = 'rgba(255, 107, 107, 0.1)', textColor = '#000000', descriptionColor = '#666666', inputBackgroundColor = '#FFFFFF', inputBorderColor = '#E0E0E0', inputTextColor = '#000000', buttonTextNext = 'Next', buttonTextDone = 'Get Started', buttonTextSkip = 'Skip', buttonTextSubmit = 'Get Started', testID, }) {
60
85
  const [currentIndex, setCurrentIndex] = useState(0);
86
+ const [formData, setFormData] = useState({});
61
87
  const flatListRef = useRef(null);
62
- const renderSlide = ({ item }) => (<View style={styles.slide}>
88
+ // Create display data: info slides + optional form slide
89
+ const displaySlides = showForm
90
+ ? [...slides, { id: 'form', type: 'form' }]
91
+ : slides;
92
+ const totalSlides = displaySlides.length;
93
+ const isLastSlide = currentIndex === totalSlides - 1;
94
+ const isFormSlide = showForm && isLastSlide;
95
+ const renderInfoSlide = ({ item }) => (<View style={styles.slide}>
63
96
  <Animated.View entering={FadeIn.duration(500)} style={[styles.iconContainer, { backgroundColor: iconBackgroundColor }]}>
64
97
  <MaterialCommunityIcons name={item.icon} size={80} color={textColor}/>
65
98
  </Animated.View>
@@ -70,8 +103,41 @@ export default function SimpleOnboardingScreen({ onComplete, slides = defaultSli
70
103
  {item.description}
71
104
  </Text>
72
105
  </View>);
106
+ const renderFormSlide = () => (<KeyboardAvoidingView style={styles.slide} behavior="padding" keyboardVerticalOffset={100}>
107
+ <ScrollView style={styles.formContainer} contentContainerStyle={styles.formContentContainer} showsVerticalScrollIndicator={false}>
108
+ <Animated.View entering={FadeIn.duration(500)} style={[styles.iconContainer, { backgroundColor: iconBackgroundColor }]}>
109
+ <MaterialCommunityIcons name="account-outline" size={80} color={textColor}/>
110
+ </Animated.View>
111
+ <Text style={[styles.title, { color: textColor }]}>
112
+ Let's Get Started
113
+ </Text>
114
+ <Text style={[styles.formDescription, { color: descriptionColor }]}>
115
+ Tell us a bit about yourself (optional)
116
+ </Text>
117
+
118
+ {formFields.map((field) => (<View key={field.key} style={styles.inputWrapper}>
119
+ <Text style={[styles.inputLabel, { color: textColor }]}>
120
+ {field.label}
121
+ </Text>
122
+ <TextInput style={[
123
+ styles.input,
124
+ {
125
+ backgroundColor: inputBackgroundColor,
126
+ borderColor: inputBorderColor,
127
+ color: inputTextColor,
128
+ },
129
+ ]} placeholder={field.placeholder} placeholderTextColor="#999999" value={formData[field.key] || ''} onChangeText={(text) => setFormData({ ...formData, [field.key]: text })} multiline={field.multiline} numberOfLines={field.multiline ? 4 : 1} autoCapitalize={field.autoCapitalize || 'sentences'}/>
130
+ </View>))}
131
+ </ScrollView>
132
+ </KeyboardAvoidingView>);
133
+ const renderSlide = ({ item, index }) => {
134
+ if (item.type === 'form') {
135
+ return renderFormSlide();
136
+ }
137
+ return renderInfoSlide({ item });
138
+ };
73
139
  const handleNext = () => {
74
- if (currentIndex < slides.length - 1) {
140
+ if (currentIndex < totalSlides - 1) {
75
141
  flatListRef.current?.scrollToIndex({
76
142
  index: currentIndex + 1,
77
143
  animated: true,
@@ -79,31 +145,44 @@ export default function SimpleOnboardingScreen({ onComplete, slides = defaultSli
79
145
  setCurrentIndex(currentIndex + 1);
80
146
  }
81
147
  else {
82
- onComplete();
148
+ // Submit form data
149
+ onComplete(formData);
83
150
  }
84
151
  };
152
+ const handleSkip = () => {
153
+ onComplete();
154
+ };
155
+ const isFormDataValid = () => {
156
+ return true; // Form is optional, so always valid
157
+ };
85
158
  return (<SafeAreaView testID={testID} style={[styles.container, { backgroundColor }]} edges={['top', 'bottom']}>
86
159
  <StatusBar barStyle="dark-content" backgroundColor="transparent" translucent/>
87
160
 
88
- <FlatList ref={flatListRef} data={slides} renderItem={renderSlide} horizontal pagingEnabled showsHorizontalScrollIndicator={false} onMomentumScrollEnd={(event) => {
161
+ <FlatList ref={flatListRef} data={displaySlides} renderItem={renderSlide} horizontal pagingEnabled showsHorizontalScrollIndicator={false} onMomentumScrollEnd={(event) => {
89
162
  const index = Math.round(event.nativeEvent.contentOffset.x / width);
90
163
  setCurrentIndex(index);
91
- }}/>
164
+ }} scrollEnabled={!isFormSlide}/>
92
165
 
93
166
  <BlurView intensity={80} tint="light" style={styles.footer}>
94
- <View style={styles.pagination}>
95
- {slides.map((_, index) => (<View key={index} style={[
96
- styles.paginationDot,
97
- index === currentIndex && styles.paginationDotActive,
98
- index === currentIndex && { backgroundColor: primaryColor },
99
- ]}/>))}
100
- </View>
167
+ <View style={styles.footerContent}>
168
+ {isFormSlide && allowSkipForm ? (<TouchableOpacity style={styles.skipButton} onPress={handleSkip}>
169
+ <Text style={[styles.skipButtonText, { color: descriptionColor }]}>
170
+ {buttonTextSkip}
171
+ </Text>
172
+ </TouchableOpacity>) : (<View style={styles.pagination}>
173
+ {displaySlides.slice(0, showForm ? totalSlides - 1 : totalSlides).map((_, index) => (<View key={index} style={[
174
+ styles.paginationDot,
175
+ index === currentIndex && styles.paginationDotActive,
176
+ index === currentIndex && { backgroundColor: primaryColor },
177
+ ]}/>))}
178
+ </View>)}
101
179
 
102
- <TouchableOpacity style={[styles.button, { backgroundColor: primaryColor }]} onPress={handleNext}>
103
- <Text style={styles.buttonText}>
104
- {currentIndex === slides.length - 1 ? buttonTextDone : buttonTextNext}
105
- </Text>
106
- </TouchableOpacity>
180
+ <TouchableOpacity style={[styles.button, { backgroundColor: primaryColor }]} onPress={handleNext}>
181
+ <Text style={styles.buttonText}>
182
+ {isFormSlide ? buttonTextSubmit : isLastSlide ? buttonTextDone : buttonTextNext}
183
+ </Text>
184
+ </TouchableOpacity>
185
+ </View>
107
186
  </BlurView>
108
187
  </SafeAreaView>);
109
188
  }
@@ -136,6 +215,38 @@ const styles = StyleSheet.create({
136
215
  textAlign: 'center',
137
216
  lineHeight: 24,
138
217
  },
218
+ formContainer: {
219
+ flex: 1,
220
+ width: '100%',
221
+ },
222
+ formContentContainer: {
223
+ alignItems: 'center',
224
+ paddingBottom: 100,
225
+ },
226
+ formDescription: {
227
+ fontSize: 17,
228
+ textAlign: 'center',
229
+ lineHeight: 24,
230
+ marginBottom: 32,
231
+ },
232
+ inputWrapper: {
233
+ width: '100%',
234
+ marginBottom: 20,
235
+ },
236
+ inputLabel: {
237
+ fontSize: 16,
238
+ fontWeight: '600',
239
+ marginBottom: 8,
240
+ },
241
+ input: {
242
+ width: '100%',
243
+ paddingHorizontal: 16,
244
+ paddingVertical: 14,
245
+ borderRadius: 12,
246
+ borderWidth: 1,
247
+ fontSize: 16,
248
+ textAlignVertical: 'top',
249
+ },
139
250
  footer: {
140
251
  position: 'absolute',
141
252
  bottom: 0,
@@ -143,6 +254,8 @@ const styles = StyleSheet.create({
143
254
  right: 0,
144
255
  paddingHorizontal: 20,
145
256
  paddingVertical: 20,
257
+ },
258
+ footerContent: {
146
259
  flexDirection: 'row',
147
260
  justifyContent: 'space-between',
148
261
  alignItems: 'center',
@@ -181,4 +294,12 @@ const styles = StyleSheet.create({
181
294
  fontSize: 17,
182
295
  fontWeight: '600',
183
296
  },
297
+ skipButton: {
298
+ paddingHorizontal: 16,
299
+ paddingVertical: 8,
300
+ },
301
+ skipButtonText: {
302
+ fontSize: 16,
303
+ fontWeight: '500',
304
+ },
184
305
  });
@@ -2,6 +2,6 @@ export { Pagination } from './Pagination';
2
2
  export { NavigationButton, NavigationButtons } from './NavigationButtons';
3
3
  export { Onboarding, useOnboarding } from './Onboarding';
4
4
  export { default as SimpleOnboardingScreen } from './SimpleOnboardingScreen';
5
- export type { SimpleSlide } from './SimpleOnboardingScreen';
5
+ export type { SimpleSlide, FormField, UserData } from './SimpleOnboardingScreen';
6
6
  export { default } from './Onboarding';
7
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC1E,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EAAE,OAAO,IAAI,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAC7E,YAAY,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAE5D,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC1E,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EAAE,OAAO,IAAI,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAC7E,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEjF,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export { Onboarding, useOnboarding } from './components/Onboarding';
2
2
  export { SimpleOnboardingScreen } from './components';
3
- export type { SimpleSlide } from './components';
3
+ export type { SimpleSlide, FormField, UserData } from './components';
4
4
  export { ImageSlide, IconSlide, FormSlide, VideoSlide, SlideRenderer, } from './slides';
5
5
  export { Pagination, NavigationButton, NavigationButtons, } from './components';
6
6
  export { onepageTheme, zaprecipeTheme, pomodoTheme, modernTheme, minimalTheme, gradientTheme, onepagePreset, zaprecipePreset, pomodoPreset, modernPreset, minimalPreset, gradientPreset, getTheme, getPreset, mergeTheme, } from './themes';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAGpE,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AACtD,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGhD,OAAO,EACL,UAAU,EACV,SAAS,EACT,SAAS,EACT,UAAU,EACV,aAAa,GACd,MAAM,UAAU,CAAC;AAGlB,OAAO,EACL,UAAU,EACV,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,cAAc,CAAC;AAGtB,OAAO,EACL,YAAY,EACZ,cAAc,EACd,WAAW,EACX,WAAW,EACX,YAAY,EACZ,aAAa,EACb,aAAa,EACb,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,cAAc,EACd,QAAQ,EACR,SAAS,EACT,UAAU,GACX,MAAM,UAAU,CAAC;AAGlB,YAAY,EACV,SAAS,EACT,aAAa,EACb,cAAc,EACd,aAAa,EACb,aAAa,EACb,cAAc,EACd,eAAe,EACf,SAAS,EACT,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,eAAe,EACf,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,oBAAoB,EACpB,eAAe,EACf,qBAAqB,EACrB,gBAAgB,EAChB,YAAY,GACb,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAGpE,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AACtD,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAGrE,OAAO,EACL,UAAU,EACV,SAAS,EACT,SAAS,EACT,UAAU,EACV,aAAa,GACd,MAAM,UAAU,CAAC;AAGlB,OAAO,EACL,UAAU,EACV,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,cAAc,CAAC;AAGtB,OAAO,EACL,YAAY,EACZ,cAAc,EACd,WAAW,EACX,WAAW,EACX,YAAY,EACZ,aAAa,EACb,aAAa,EACb,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,cAAc,EACd,QAAQ,EACR,SAAS,EACT,UAAU,GACX,MAAM,UAAU,CAAC;AAGlB,YAAY,EACV,SAAS,EACT,aAAa,EACb,cAAc,EACd,aAAa,EACb,aAAa,EACb,cAAc,EACd,eAAe,EACf,SAAS,EACT,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,eAAe,EACf,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,oBAAoB,EACpB,eAAe,EACf,qBAAqB,EACrB,gBAAgB,EAChB,YAAY,GACb,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rubixscript/react-native-onboarding",
3
- "version": "1.1.2",
3
+ "version": "1.2.0",
4
4
  "description": "A comprehensive React Native onboarding library with customizable slide types, animations, and themes",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -3,25 +3,35 @@
3
3
  * @description A simple, beautiful onboarding screen with customizable slides, colors, and styling
4
4
  *
5
5
  * @props
6
- * - onComplete: () => void - Handler called when onboarding is finished
6
+ * - onComplete: (userData?: UserData) => void - Handler called when onboarding is finished with optional user data
7
7
  * - slides: SimpleSlide[] - Array of slides to display (optional, has default)
8
+ * - showForm: boolean - Whether to show a form slide at the end (default: true)
9
+ * - formFields: FormField[] - Custom form fields (optional, has default)
10
+ * - allowSkipForm: boolean - Allow skipping the form (default: true)
8
11
  * - primaryColor: string - Primary color for buttons and active dots (default: '#FF6B6B')
9
12
  * - backgroundColor: string - Background color of the screen (default: '#F6F6F6')
10
13
  * - iconBackgroundColor: string - Background color for icon container (default: 'rgba(255, 107, 107, 0.1)')
11
14
  * - textColor: string - Color for titles (default: '#000000')
12
15
  * - descriptionColor: string - Color for descriptions (default: '#666666')
16
+ * - inputBackgroundColor: string - Background color for form inputs (default: '#FFFFFF')
17
+ * - inputBorderColor: string - Border color for form inputs (default: '#E0E0E0')
13
18
  * - buttonTextNext: string - Text for next button (default: 'Next')
14
19
  * - buttonTextDone: string - Text for done button (default: 'Get Started')
20
+ * - buttonTextSkip: string - Text for skip button (default: 'Skip')
21
+ * - buttonTextSubmit: string - Text for submit button (default: 'Get Started')
15
22
  * - testID?: string - Test identifier for testing
16
23
  *
17
24
  * @states
18
25
  * - currentIndex: number - Current onboarding screen index
26
+ * - formData: UserData - Form data collected from user
19
27
  *
20
28
  * @features
21
29
  * - Step-by-step app introduction
22
30
  * - Interactive animations
23
31
  * - Feature highlights
24
32
  * - Progress indication
33
+ * - User data collection (name, purpose)
34
+ * - Skip functionality
25
35
  * - Fully customizable styling
26
36
  *
27
37
  * @dependencies
@@ -40,6 +50,9 @@ import {
40
50
  FlatList,
41
51
  Platform,
42
52
  StatusBar,
53
+ TextInput,
54
+ KeyboardAvoidingView,
55
+ ScrollView,
43
56
  } from 'react-native';
44
57
  import { SafeAreaView } from 'react-native-safe-area-context';
45
58
  import { BlurView } from 'expo-blur';
@@ -55,6 +68,20 @@ export interface SimpleSlide {
55
68
  icon: keyof typeof MaterialCommunityIcons.glyphMap;
56
69
  }
57
70
 
71
+ export interface FormField {
72
+ key: string;
73
+ label: string;
74
+ placeholder: string;
75
+ multiline?: boolean;
76
+ autoCapitalize?: 'none' | 'sentences' | 'words' | 'characters';
77
+ }
78
+
79
+ export interface UserData {
80
+ name?: string;
81
+ purpose?: string;
82
+ [key: string]: string | undefined;
83
+ }
84
+
58
85
  const defaultSlides: SimpleSlide[] = [
59
86
  {
60
87
  id: '1',
@@ -76,35 +103,77 @@ const defaultSlides: SimpleSlide[] = [
76
103
  },
77
104
  ];
78
105
 
106
+ const defaultFormFields: FormField[] = [
107
+ {
108
+ key: 'name',
109
+ label: 'What should we call you?',
110
+ placeholder: 'Enter your name',
111
+ autoCapitalize: 'words',
112
+ },
113
+ {
114
+ key: 'purpose',
115
+ label: 'What are you looking to use this app for?',
116
+ placeholder: 'e.g., Focus on work, Study, Track goals...',
117
+ multiline: true,
118
+ autoCapitalize: 'sentences',
119
+ },
120
+ ];
121
+
79
122
  interface SimpleOnboardingScreenProps {
80
- onComplete: () => Promise<void>;
123
+ onComplete: (userData?: UserData) => Promise<void>;
81
124
  slides?: SimpleSlide[];
125
+ showForm?: boolean;
126
+ formFields?: FormField[];
127
+ allowSkipForm?: boolean;
82
128
  primaryColor?: string;
83
129
  backgroundColor?: string;
84
130
  iconBackgroundColor?: string;
85
131
  textColor?: string;
86
132
  descriptionColor?: string;
133
+ inputBackgroundColor?: string;
134
+ inputBorderColor?: string;
135
+ inputTextColor?: string;
87
136
  buttonTextNext?: string;
88
137
  buttonTextDone?: string;
138
+ buttonTextSkip?: string;
139
+ buttonTextSubmit?: string;
89
140
  testID?: string;
90
141
  }
91
142
 
92
143
  export default function SimpleOnboardingScreen({
93
144
  onComplete,
94
145
  slides = defaultSlides,
146
+ showForm = true,
147
+ formFields = defaultFormFields,
148
+ allowSkipForm = true,
95
149
  primaryColor = '#FF6B6B',
96
150
  backgroundColor = '#F6F6F6',
97
151
  iconBackgroundColor = 'rgba(255, 107, 107, 0.1)',
98
152
  textColor = '#000000',
99
153
  descriptionColor = '#666666',
154
+ inputBackgroundColor = '#FFFFFF',
155
+ inputBorderColor = '#E0E0E0',
156
+ inputTextColor = '#000000',
100
157
  buttonTextNext = 'Next',
101
158
  buttonTextDone = 'Get Started',
159
+ buttonTextSkip = 'Skip',
160
+ buttonTextSubmit = 'Get Started',
102
161
  testID,
103
162
  }: SimpleOnboardingScreenProps) {
104
163
  const [currentIndex, setCurrentIndex] = useState(0);
164
+ const [formData, setFormData] = useState<UserData>({});
105
165
  const flatListRef = useRef<FlatList>(null);
106
166
 
107
- const renderSlide = ({ item }: { item: SimpleSlide }) => (
167
+ // Create display data: info slides + optional form slide
168
+ const displaySlides = showForm
169
+ ? [...slides, { id: 'form', type: 'form' } as any]
170
+ : slides;
171
+
172
+ const totalSlides = displaySlides.length;
173
+ const isLastSlide = currentIndex === totalSlides - 1;
174
+ const isFormSlide = showForm && isLastSlide;
175
+
176
+ const renderInfoSlide = ({ item }: { item: SimpleSlide }) => (
108
177
  <View style={styles.slide}>
109
178
  <Animated.View
110
179
  entering={FadeIn.duration(500)}
@@ -125,18 +194,90 @@ export default function SimpleOnboardingScreen({
125
194
  </View>
126
195
  );
127
196
 
197
+ const renderFormSlide = () => (
198
+ <KeyboardAvoidingView
199
+ style={styles.slide}
200
+ behavior="padding"
201
+ keyboardVerticalOffset={100}
202
+ >
203
+ <ScrollView
204
+ style={styles.formContainer}
205
+ contentContainerStyle={styles.formContentContainer}
206
+ showsVerticalScrollIndicator={false}
207
+ >
208
+ <Animated.View
209
+ entering={FadeIn.duration(500)}
210
+ style={[styles.iconContainer, { backgroundColor: iconBackgroundColor }]}
211
+ >
212
+ <MaterialCommunityIcons
213
+ name="account-outline"
214
+ size={80}
215
+ color={textColor}
216
+ />
217
+ </Animated.View>
218
+ <Text style={[styles.title, { color: textColor }]}>
219
+ Let's Get Started
220
+ </Text>
221
+ <Text style={[styles.formDescription, { color: descriptionColor }]}>
222
+ Tell us a bit about yourself (optional)
223
+ </Text>
224
+
225
+ {formFields.map((field) => (
226
+ <View key={field.key} style={styles.inputWrapper}>
227
+ <Text style={[styles.inputLabel, { color: textColor }]}>
228
+ {field.label}
229
+ </Text>
230
+ <TextInput
231
+ style={[
232
+ styles.input,
233
+ {
234
+ backgroundColor: inputBackgroundColor,
235
+ borderColor: inputBorderColor,
236
+ color: inputTextColor,
237
+ },
238
+ ]}
239
+ placeholder={field.placeholder}
240
+ placeholderTextColor="#999999"
241
+ value={formData[field.key] || ''}
242
+ onChangeText={(text) => setFormData({ ...formData, [field.key]: text })}
243
+ multiline={field.multiline}
244
+ numberOfLines={field.multiline ? 4 : 1}
245
+ autoCapitalize={field.autoCapitalize || 'sentences'}
246
+ />
247
+ </View>
248
+ ))}
249
+ </ScrollView>
250
+ </KeyboardAvoidingView>
251
+ );
252
+
253
+ const renderSlide = ({ item, index }: { item: any; index: number }) => {
254
+ if (item.type === 'form') {
255
+ return renderFormSlide();
256
+ }
257
+ return renderInfoSlide({ item });
258
+ };
259
+
128
260
  const handleNext = () => {
129
- if (currentIndex < slides.length - 1) {
261
+ if (currentIndex < totalSlides - 1) {
130
262
  flatListRef.current?.scrollToIndex({
131
263
  index: currentIndex + 1,
132
264
  animated: true,
133
265
  });
134
266
  setCurrentIndex(currentIndex + 1);
135
267
  } else {
136
- onComplete();
268
+ // Submit form data
269
+ onComplete(formData);
137
270
  }
138
271
  };
139
272
 
273
+ const handleSkip = () => {
274
+ onComplete();
275
+ };
276
+
277
+ const isFormDataValid = () => {
278
+ return true; // Form is optional, so always valid
279
+ };
280
+
140
281
  return (
141
282
  <SafeAreaView testID={testID} style={[styles.container, { backgroundColor }]} edges={['top', 'bottom']}>
142
283
  <StatusBar
@@ -147,7 +288,7 @@ export default function SimpleOnboardingScreen({
147
288
 
148
289
  <FlatList
149
290
  ref={flatListRef}
150
- data={slides}
291
+ data={displaySlides}
151
292
  renderItem={renderSlide}
152
293
  horizontal
153
294
  pagingEnabled
@@ -156,6 +297,7 @@ export default function SimpleOnboardingScreen({
156
297
  const index = Math.round(event.nativeEvent.contentOffset.x / width);
157
298
  setCurrentIndex(index);
158
299
  }}
300
+ scrollEnabled={!isFormSlide}
159
301
  />
160
302
 
161
303
  <BlurView
@@ -163,27 +305,40 @@ export default function SimpleOnboardingScreen({
163
305
  tint="light"
164
306
  style={styles.footer}
165
307
  >
166
- <View style={styles.pagination}>
167
- {slides.map((_, index) => (
168
- <View
169
- key={index}
170
- style={[
171
- styles.paginationDot,
172
- index === currentIndex && styles.paginationDotActive,
173
- index === currentIndex && { backgroundColor: primaryColor },
174
- ]}
175
- />
176
- ))}
177
- </View>
308
+ <View style={styles.footerContent}>
309
+ {isFormSlide && allowSkipForm ? (
310
+ <TouchableOpacity
311
+ style={styles.skipButton}
312
+ onPress={handleSkip}
313
+ >
314
+ <Text style={[styles.skipButtonText, { color: descriptionColor }]}>
315
+ {buttonTextSkip}
316
+ </Text>
317
+ </TouchableOpacity>
318
+ ) : (
319
+ <View style={styles.pagination}>
320
+ {displaySlides.slice(0, showForm ? totalSlides - 1 : totalSlides).map((_, index) => (
321
+ <View
322
+ key={index}
323
+ style={[
324
+ styles.paginationDot,
325
+ index === currentIndex && styles.paginationDotActive,
326
+ index === currentIndex && { backgroundColor: primaryColor },
327
+ ]}
328
+ />
329
+ ))}
330
+ </View>
331
+ )}
178
332
 
179
- <TouchableOpacity
180
- style={[styles.button, { backgroundColor: primaryColor }]}
181
- onPress={handleNext}
182
- >
183
- <Text style={styles.buttonText}>
184
- {currentIndex === slides.length - 1 ? buttonTextDone : buttonTextNext}
185
- </Text>
186
- </TouchableOpacity>
333
+ <TouchableOpacity
334
+ style={[styles.button, { backgroundColor: primaryColor }]}
335
+ onPress={handleNext}
336
+ >
337
+ <Text style={styles.buttonText}>
338
+ {isFormSlide ? buttonTextSubmit : isLastSlide ? buttonTextDone : buttonTextNext}
339
+ </Text>
340
+ </TouchableOpacity>
341
+ </View>
187
342
  </BlurView>
188
343
  </SafeAreaView>
189
344
  );
@@ -218,6 +373,38 @@ const styles = StyleSheet.create({
218
373
  textAlign: 'center',
219
374
  lineHeight: 24,
220
375
  },
376
+ formContainer: {
377
+ flex: 1,
378
+ width: '100%',
379
+ },
380
+ formContentContainer: {
381
+ alignItems: 'center',
382
+ paddingBottom: 100,
383
+ },
384
+ formDescription: {
385
+ fontSize: 17,
386
+ textAlign: 'center',
387
+ lineHeight: 24,
388
+ marginBottom: 32,
389
+ },
390
+ inputWrapper: {
391
+ width: '100%',
392
+ marginBottom: 20,
393
+ },
394
+ inputLabel: {
395
+ fontSize: 16,
396
+ fontWeight: '600',
397
+ marginBottom: 8,
398
+ },
399
+ input: {
400
+ width: '100%',
401
+ paddingHorizontal: 16,
402
+ paddingVertical: 14,
403
+ borderRadius: 12,
404
+ borderWidth: 1,
405
+ fontSize: 16,
406
+ textAlignVertical: 'top',
407
+ },
221
408
  footer: {
222
409
  position: 'absolute',
223
410
  bottom: 0,
@@ -225,6 +412,8 @@ const styles = StyleSheet.create({
225
412
  right: 0,
226
413
  paddingHorizontal: 20,
227
414
  paddingVertical: 20,
415
+ },
416
+ footerContent: {
228
417
  flexDirection: 'row',
229
418
  justifyContent: 'space-between',
230
419
  alignItems: 'center',
@@ -263,4 +452,12 @@ const styles = StyleSheet.create({
263
452
  fontSize: 17,
264
453
  fontWeight: '600',
265
454
  },
455
+ skipButton: {
456
+ paddingHorizontal: 16,
457
+ paddingVertical: 8,
458
+ },
459
+ skipButtonText: {
460
+ fontSize: 16,
461
+ fontWeight: '500',
462
+ },
266
463
  });
@@ -2,6 +2,6 @@ export { Pagination } from './Pagination';
2
2
  export { NavigationButton, NavigationButtons } from './NavigationButtons';
3
3
  export { Onboarding, useOnboarding } from './Onboarding';
4
4
  export { default as SimpleOnboardingScreen } from './SimpleOnboardingScreen';
5
- export type { SimpleSlide } from './SimpleOnboardingScreen';
5
+ export type { SimpleSlide, FormField, UserData } from './SimpleOnboardingScreen';
6
6
 
7
7
  export { default } from './Onboarding';
package/src/index.ts CHANGED
@@ -3,7 +3,7 @@ export { Onboarding, useOnboarding } from './components/Onboarding';
3
3
 
4
4
  // Simple Onboarding Screen - A simple, customizable onboarding component
5
5
  export { SimpleOnboardingScreen } from './components';
6
- export type { SimpleSlide } from './components';
6
+ export type { SimpleSlide, FormField, UserData } from './components';
7
7
 
8
8
  // Slide Components
9
9
  export {