@umituz/react-native-onboarding 2.6.6 → 2.6.8
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/package.json +1 -1
- package/src/presentation/components/QuestionRenderer.tsx +85 -0
- package/src/presentation/components/QuestionSlide.tsx +40 -154
- package/src/presentation/components/QuestionSlideHeader.tsx +86 -0
- package/src/presentation/components/questions/SliderQuestion.tsx +23 -9
- package/src/presentation/screens/OnboardingScreen.tsx +19 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-onboarding",
|
|
3
|
-
"version": "2.6.
|
|
3
|
+
"version": "2.6.8",
|
|
4
4
|
"description": "Advanced onboarding flow for React Native apps with personalization questions, theme-aware colors, animations, and customizable slides. SOLID, DRY, KISS principles applied.",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "./src/index.ts",
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Question Renderer Component
|
|
3
|
+
* Single Responsibility: Render appropriate question component based on type
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import React from "react";
|
|
7
|
+
import type { OnboardingQuestion } from "../../domain/entities/OnboardingQuestion";
|
|
8
|
+
import { SingleChoiceQuestion } from "./questions/SingleChoiceQuestion";
|
|
9
|
+
import { MultipleChoiceQuestion } from "./questions/MultipleChoiceQuestion";
|
|
10
|
+
import { TextInputQuestion } from "./questions/TextInputQuestion";
|
|
11
|
+
import { SliderQuestion } from "./questions/SliderQuestion";
|
|
12
|
+
import { RatingQuestion } from "./questions/RatingQuestion";
|
|
13
|
+
|
|
14
|
+
export interface QuestionRendererProps {
|
|
15
|
+
question: OnboardingQuestion;
|
|
16
|
+
value: any;
|
|
17
|
+
onChange: (value: any) => void;
|
|
18
|
+
SliderComponent?: React.ComponentType<{
|
|
19
|
+
style?: any;
|
|
20
|
+
minimumValue: number;
|
|
21
|
+
maximumValue: number;
|
|
22
|
+
value: number;
|
|
23
|
+
onValueChange: (value: number) => void;
|
|
24
|
+
minimumTrackTintColor?: string;
|
|
25
|
+
maximumTrackTintColor?: string;
|
|
26
|
+
thumbTintColor?: string;
|
|
27
|
+
step?: number;
|
|
28
|
+
}>;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export const QuestionRenderer: React.FC<QuestionRendererProps> = ({
|
|
32
|
+
question,
|
|
33
|
+
value,
|
|
34
|
+
onChange,
|
|
35
|
+
SliderComponent,
|
|
36
|
+
}) => {
|
|
37
|
+
switch (question.type) {
|
|
38
|
+
case "single_choice":
|
|
39
|
+
return (
|
|
40
|
+
<SingleChoiceQuestion
|
|
41
|
+
question={question}
|
|
42
|
+
value={value}
|
|
43
|
+
onChange={onChange}
|
|
44
|
+
/>
|
|
45
|
+
);
|
|
46
|
+
case "multiple_choice":
|
|
47
|
+
return (
|
|
48
|
+
<MultipleChoiceQuestion
|
|
49
|
+
question={question}
|
|
50
|
+
value={value}
|
|
51
|
+
onChange={onChange}
|
|
52
|
+
/>
|
|
53
|
+
);
|
|
54
|
+
case "text_input":
|
|
55
|
+
return (
|
|
56
|
+
<TextInputQuestion
|
|
57
|
+
question={question}
|
|
58
|
+
value={value}
|
|
59
|
+
onChange={onChange}
|
|
60
|
+
/>
|
|
61
|
+
);
|
|
62
|
+
case "slider":
|
|
63
|
+
if (!SliderComponent) {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
return (
|
|
67
|
+
<SliderQuestion
|
|
68
|
+
question={question}
|
|
69
|
+
value={value}
|
|
70
|
+
onChange={onChange}
|
|
71
|
+
SliderComponent={SliderComponent}
|
|
72
|
+
/>
|
|
73
|
+
);
|
|
74
|
+
case "rating":
|
|
75
|
+
return (
|
|
76
|
+
<RatingQuestion
|
|
77
|
+
question={question}
|
|
78
|
+
value={value}
|
|
79
|
+
onChange={onChange}
|
|
80
|
+
/>
|
|
81
|
+
);
|
|
82
|
+
default:
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
};
|
|
@@ -1,25 +1,31 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Question Slide Component
|
|
3
|
-
*
|
|
4
|
-
* Displays a personalization question slide
|
|
3
|
+
* Single Responsibility: Display question slide with header and question
|
|
5
4
|
*/
|
|
6
5
|
|
|
7
6
|
import React, { useMemo } from "react";
|
|
8
7
|
import { View, Text, StyleSheet, ScrollView } from "react-native";
|
|
9
|
-
import {
|
|
10
|
-
import { useAppDesignTokens, withAlpha } from "@umituz/react-native-design-system-theme";
|
|
8
|
+
import { useAppDesignTokens } from "@umituz/react-native-design-system-theme";
|
|
11
9
|
import type { OnboardingSlide } from "../../domain/entities/OnboardingSlide";
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import { TextInputQuestion } from "./questions/TextInputQuestion";
|
|
15
|
-
import { SliderQuestion } from "./questions/SliderQuestion";
|
|
16
|
-
import { RatingQuestion } from "./questions/RatingQuestion";
|
|
10
|
+
import { QuestionSlideHeader } from "./QuestionSlideHeader";
|
|
11
|
+
import { QuestionRenderer } from "./QuestionRenderer";
|
|
17
12
|
|
|
18
13
|
export interface QuestionSlideProps {
|
|
19
14
|
slide: OnboardingSlide;
|
|
20
15
|
value: any;
|
|
21
16
|
onChange: (value: any) => void;
|
|
22
17
|
useGradient?: boolean;
|
|
18
|
+
SliderComponent?: React.ComponentType<{
|
|
19
|
+
style?: any;
|
|
20
|
+
minimumValue: number;
|
|
21
|
+
maximumValue: number;
|
|
22
|
+
value: number;
|
|
23
|
+
onValueChange: (value: number) => void;
|
|
24
|
+
minimumTrackTintColor?: string;
|
|
25
|
+
maximumTrackTintColor?: string;
|
|
26
|
+
thumbTintColor?: string;
|
|
27
|
+
step?: number;
|
|
28
|
+
}>;
|
|
23
29
|
}
|
|
24
30
|
|
|
25
31
|
export const QuestionSlide: React.FC<QuestionSlideProps> = ({
|
|
@@ -27,6 +33,7 @@ export const QuestionSlide: React.FC<QuestionSlideProps> = ({
|
|
|
27
33
|
value,
|
|
28
34
|
onChange,
|
|
29
35
|
useGradient = false,
|
|
36
|
+
SliderComponent,
|
|
30
37
|
}) => {
|
|
31
38
|
const tokens = useAppDesignTokens();
|
|
32
39
|
const styles = useMemo(() => getStyles(tokens, useGradient), [tokens, useGradient]);
|
|
@@ -36,55 +43,24 @@ export const QuestionSlide: React.FC<QuestionSlideProps> = ({
|
|
|
36
43
|
return null;
|
|
37
44
|
}
|
|
38
45
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
onChange={onChange}
|
|
58
|
-
/>
|
|
59
|
-
);
|
|
60
|
-
case "text_input":
|
|
61
|
-
return (
|
|
62
|
-
<TextInputQuestion
|
|
63
|
-
question={question}
|
|
64
|
-
value={value}
|
|
65
|
-
onChange={onChange}
|
|
66
|
-
/>
|
|
67
|
-
);
|
|
68
|
-
case "slider":
|
|
69
|
-
return (
|
|
70
|
-
<SliderQuestion
|
|
71
|
-
question={question}
|
|
72
|
-
value={value}
|
|
73
|
-
onChange={onChange}
|
|
74
|
-
/>
|
|
75
|
-
);
|
|
76
|
-
case "rating":
|
|
77
|
-
return (
|
|
78
|
-
<RatingQuestion
|
|
79
|
-
question={question}
|
|
80
|
-
value={value}
|
|
81
|
-
onChange={onChange}
|
|
82
|
-
/>
|
|
83
|
-
);
|
|
84
|
-
default:
|
|
85
|
-
return null;
|
|
86
|
-
}
|
|
87
|
-
};
|
|
46
|
+
const content = (
|
|
47
|
+
<>
|
|
48
|
+
<QuestionSlideHeader slide={slide} useGradient={useGradient} />
|
|
49
|
+
|
|
50
|
+
<View style={styles.questionContainer}>
|
|
51
|
+
<QuestionRenderer
|
|
52
|
+
question={question}
|
|
53
|
+
value={value}
|
|
54
|
+
onChange={onChange}
|
|
55
|
+
SliderComponent={SliderComponent}
|
|
56
|
+
/>
|
|
57
|
+
</View>
|
|
58
|
+
|
|
59
|
+
{question.validation?.required && !value && (
|
|
60
|
+
<Text style={styles.requiredHint}>* This field is required</Text>
|
|
61
|
+
)}
|
|
62
|
+
</>
|
|
63
|
+
);
|
|
88
64
|
|
|
89
65
|
return (
|
|
90
66
|
<ScrollView
|
|
@@ -92,75 +68,18 @@ export const QuestionSlide: React.FC<QuestionSlideProps> = ({
|
|
|
92
68
|
showsVerticalScrollIndicator={false}
|
|
93
69
|
>
|
|
94
70
|
{useGradient ? (
|
|
95
|
-
|
|
96
|
-
<>
|
|
97
|
-
{/* Icon */}
|
|
98
|
-
<View style={styles.iconContainer}>
|
|
99
|
-
{isEmoji ? (
|
|
100
|
-
<Text style={styles.icon}>{slide.icon}</Text>
|
|
101
|
-
) : (
|
|
102
|
-
<AtomicIcon
|
|
103
|
-
name={slide.icon as any}
|
|
104
|
-
customSize={48}
|
|
105
|
-
customColor="#FFFFFF"
|
|
106
|
-
/>
|
|
107
|
-
)}
|
|
108
|
-
</View>
|
|
109
|
-
|
|
110
|
-
{/* Title */}
|
|
111
|
-
<Text style={styles.title}>{slide.title}</Text>
|
|
112
|
-
|
|
113
|
-
{/* Description */}
|
|
114
|
-
{slide.description && (
|
|
115
|
-
<Text style={styles.description}>{slide.description}</Text>
|
|
116
|
-
)}
|
|
117
|
-
|
|
118
|
-
{/* Question */}
|
|
119
|
-
<View style={styles.questionContainer}>{renderQuestion()}</View>
|
|
120
|
-
|
|
121
|
-
{/* Validation hint */}
|
|
122
|
-
{question.validation?.required && !value && (
|
|
123
|
-
<Text style={styles.requiredHint}>* This field is required</Text>
|
|
124
|
-
)}
|
|
125
|
-
</>
|
|
71
|
+
content
|
|
126
72
|
) : (
|
|
127
|
-
|
|
128
|
-
<View style={styles.slideContent}>
|
|
129
|
-
{/* Icon */}
|
|
130
|
-
<View style={styles.iconContainer}>
|
|
131
|
-
{isEmoji ? (
|
|
132
|
-
<Text style={styles.icon}>{slide.icon}</Text>
|
|
133
|
-
) : (
|
|
134
|
-
<AtomicIcon
|
|
135
|
-
name={slide.icon as any}
|
|
136
|
-
customSize={48}
|
|
137
|
-
customColor={tokens.colors.textPrimary}
|
|
138
|
-
/>
|
|
139
|
-
)}
|
|
140
|
-
</View>
|
|
141
|
-
|
|
142
|
-
{/* Title */}
|
|
143
|
-
<Text style={styles.title}>{slide.title}</Text>
|
|
144
|
-
|
|
145
|
-
{/* Description */}
|
|
146
|
-
{slide.description && (
|
|
147
|
-
<Text style={styles.description}>{slide.description}</Text>
|
|
148
|
-
)}
|
|
149
|
-
|
|
150
|
-
{/* Question */}
|
|
151
|
-
<View style={styles.questionContainer}>{renderQuestion()}</View>
|
|
152
|
-
|
|
153
|
-
{/* Validation hint */}
|
|
154
|
-
{question.validation?.required && !value && (
|
|
155
|
-
<Text style={styles.requiredHint}>* This field is required</Text>
|
|
156
|
-
)}
|
|
157
|
-
</View>
|
|
73
|
+
<View style={styles.slideContent}>{content}</View>
|
|
158
74
|
)}
|
|
159
75
|
</ScrollView>
|
|
160
76
|
);
|
|
161
77
|
};
|
|
162
78
|
|
|
163
|
-
const getStyles = (
|
|
79
|
+
const getStyles = (
|
|
80
|
+
tokens: ReturnType<typeof useAppDesignTokens>,
|
|
81
|
+
useGradient: boolean,
|
|
82
|
+
) =>
|
|
164
83
|
StyleSheet.create({
|
|
165
84
|
content: {
|
|
166
85
|
flexGrow: 1,
|
|
@@ -187,38 +106,6 @@ const getStyles = (tokens: ReturnType<typeof useAppDesignTokens>, useGradient: b
|
|
|
187
106
|
shadowRadius: 8,
|
|
188
107
|
elevation: 4,
|
|
189
108
|
},
|
|
190
|
-
iconContainer: {
|
|
191
|
-
width: 96,
|
|
192
|
-
height: 96,
|
|
193
|
-
borderRadius: 48,
|
|
194
|
-
backgroundColor: useGradient
|
|
195
|
-
? "rgba(255, 255, 255, 0.25)"
|
|
196
|
-
: withAlpha(tokens.colors.primary, 0.2),
|
|
197
|
-
alignItems: "center",
|
|
198
|
-
justifyContent: "center",
|
|
199
|
-
marginBottom: 24,
|
|
200
|
-
borderWidth: 2,
|
|
201
|
-
borderColor: useGradient
|
|
202
|
-
? "rgba(255, 255, 255, 0.4)"
|
|
203
|
-
: withAlpha(tokens.colors.primary, 0.4),
|
|
204
|
-
},
|
|
205
|
-
icon: {
|
|
206
|
-
fontSize: 48,
|
|
207
|
-
},
|
|
208
|
-
title: {
|
|
209
|
-
fontSize: 24,
|
|
210
|
-
fontWeight: "bold",
|
|
211
|
-
color: useGradient ? "#FFFFFF" : tokens.colors.textPrimary,
|
|
212
|
-
textAlign: "center",
|
|
213
|
-
marginBottom: 12,
|
|
214
|
-
},
|
|
215
|
-
description: {
|
|
216
|
-
fontSize: 15,
|
|
217
|
-
color: useGradient ? "rgba(255, 255, 255, 0.9)" : tokens.colors.textSecondary,
|
|
218
|
-
textAlign: "center",
|
|
219
|
-
lineHeight: 22,
|
|
220
|
-
marginBottom: 24,
|
|
221
|
-
},
|
|
222
109
|
questionContainer: {
|
|
223
110
|
width: "100%",
|
|
224
111
|
marginTop: 8,
|
|
@@ -230,4 +117,3 @@ const getStyles = (tokens: ReturnType<typeof useAppDesignTokens>, useGradient: b
|
|
|
230
117
|
marginTop: 12,
|
|
231
118
|
},
|
|
232
119
|
});
|
|
233
|
-
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Question Slide Header Component
|
|
3
|
+
* Single Responsibility: Display slide header (icon, title, description)
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import React from "react";
|
|
7
|
+
import { View, Text, StyleSheet } from "react-native";
|
|
8
|
+
import { AtomicIcon } from "@umituz/react-native-design-system-atoms";
|
|
9
|
+
import { useAppDesignTokens, withAlpha } from "@umituz/react-native-design-system-theme";
|
|
10
|
+
import type { OnboardingSlide } from "../../domain/entities/OnboardingSlide";
|
|
11
|
+
|
|
12
|
+
export interface QuestionSlideHeaderProps {
|
|
13
|
+
slide: OnboardingSlide;
|
|
14
|
+
useGradient: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const isEmoji = (icon: string): boolean =>
|
|
18
|
+
/[\u{1F300}-\u{1F9FF}]|[\u{2600}-\u{26FF}]|[\u{2700}-\u{27BF}]/u.test(icon);
|
|
19
|
+
|
|
20
|
+
export const QuestionSlideHeader: React.FC<QuestionSlideHeaderProps> = ({
|
|
21
|
+
slide,
|
|
22
|
+
useGradient,
|
|
23
|
+
}) => {
|
|
24
|
+
const tokens = useAppDesignTokens();
|
|
25
|
+
const styles = getStyles(tokens, useGradient);
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<>
|
|
29
|
+
<View style={styles.iconContainer}>
|
|
30
|
+
{isEmoji(slide.icon) ? (
|
|
31
|
+
<Text style={styles.icon}>{slide.icon}</Text>
|
|
32
|
+
) : (
|
|
33
|
+
<AtomicIcon
|
|
34
|
+
name={slide.icon as any}
|
|
35
|
+
customSize={48}
|
|
36
|
+
customColor={useGradient ? "#FFFFFF" : tokens.colors.textPrimary}
|
|
37
|
+
/>
|
|
38
|
+
)}
|
|
39
|
+
</View>
|
|
40
|
+
|
|
41
|
+
<Text style={styles.title}>{slide.title}</Text>
|
|
42
|
+
|
|
43
|
+
{slide.description && <Text style={styles.description}>{slide.description}</Text>}
|
|
44
|
+
</>
|
|
45
|
+
);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const getStyles = (
|
|
49
|
+
tokens: ReturnType<typeof useAppDesignTokens>,
|
|
50
|
+
useGradient: boolean,
|
|
51
|
+
) =>
|
|
52
|
+
StyleSheet.create({
|
|
53
|
+
iconContainer: {
|
|
54
|
+
width: 96,
|
|
55
|
+
height: 96,
|
|
56
|
+
borderRadius: 48,
|
|
57
|
+
backgroundColor: useGradient
|
|
58
|
+
? "rgba(255, 255, 255, 0.25)"
|
|
59
|
+
: withAlpha(tokens.colors.primary, 0.2),
|
|
60
|
+
alignItems: "center",
|
|
61
|
+
justifyContent: "center",
|
|
62
|
+
marginBottom: 24,
|
|
63
|
+
borderWidth: 2,
|
|
64
|
+
borderColor: useGradient
|
|
65
|
+
? "rgba(255, 255, 255, 0.4)"
|
|
66
|
+
: withAlpha(tokens.colors.primary, 0.4),
|
|
67
|
+
},
|
|
68
|
+
icon: {
|
|
69
|
+
fontSize: 48,
|
|
70
|
+
},
|
|
71
|
+
title: {
|
|
72
|
+
fontSize: 24,
|
|
73
|
+
fontWeight: "bold",
|
|
74
|
+
color: useGradient ? "#FFFFFF" : tokens.colors.textPrimary,
|
|
75
|
+
textAlign: "center",
|
|
76
|
+
marginBottom: 12,
|
|
77
|
+
},
|
|
78
|
+
description: {
|
|
79
|
+
fontSize: 15,
|
|
80
|
+
color: useGradient ? "rgba(255, 255, 255, 0.9)" : tokens.colors.textSecondary,
|
|
81
|
+
textAlign: "center",
|
|
82
|
+
lineHeight: 22,
|
|
83
|
+
marginBottom: 24,
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
|
|
@@ -1,28 +1,43 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Slider Question Component
|
|
3
|
-
*
|
|
4
|
-
* Slider for numeric value selection
|
|
3
|
+
* Single Responsibility: Display slider for numeric value selection
|
|
5
4
|
*/
|
|
6
5
|
|
|
7
|
-
import React from "react";
|
|
6
|
+
import React, { useMemo } from "react";
|
|
8
7
|
import { View, Text, StyleSheet } from "react-native";
|
|
9
|
-
import Slider from "@react-native-community/slider";
|
|
10
8
|
import type { OnboardingQuestion } from "../../../domain/entities/OnboardingQuestion";
|
|
11
9
|
|
|
12
10
|
export interface SliderQuestionProps {
|
|
13
11
|
question: OnboardingQuestion;
|
|
14
12
|
value: number | undefined;
|
|
15
13
|
onChange: (value: number) => void;
|
|
14
|
+
SliderComponent: React.ComponentType<{
|
|
15
|
+
style?: any;
|
|
16
|
+
minimumValue: number;
|
|
17
|
+
maximumValue: number;
|
|
18
|
+
value: number;
|
|
19
|
+
onValueChange: (value: number) => void;
|
|
20
|
+
minimumTrackTintColor?: string;
|
|
21
|
+
maximumTrackTintColor?: string;
|
|
22
|
+
thumbTintColor?: string;
|
|
23
|
+
step?: number;
|
|
24
|
+
}>;
|
|
16
25
|
}
|
|
17
26
|
|
|
27
|
+
const getSliderConfig = (question: OnboardingQuestion) => {
|
|
28
|
+
const { validation } = question;
|
|
29
|
+
const min = validation?.min ?? 0;
|
|
30
|
+
const max = validation?.max ?? 100;
|
|
31
|
+
return { min, max };
|
|
32
|
+
};
|
|
33
|
+
|
|
18
34
|
export const SliderQuestion: React.FC<SliderQuestionProps> = ({
|
|
19
35
|
question,
|
|
20
36
|
value,
|
|
21
37
|
onChange,
|
|
38
|
+
SliderComponent,
|
|
22
39
|
}) => {
|
|
23
|
-
const {
|
|
24
|
-
const min = validation?.min ?? 0;
|
|
25
|
-
const max = validation?.max ?? 100;
|
|
40
|
+
const { min, max } = useMemo(() => getSliderConfig(question), [question]);
|
|
26
41
|
const currentValue = value ?? min;
|
|
27
42
|
|
|
28
43
|
return (
|
|
@@ -30,7 +45,7 @@ export const SliderQuestion: React.FC<SliderQuestionProps> = ({
|
|
|
30
45
|
<View style={styles.valueContainer}>
|
|
31
46
|
<Text style={styles.valueText}>{currentValue}</Text>
|
|
32
47
|
</View>
|
|
33
|
-
<
|
|
48
|
+
<SliderComponent
|
|
34
49
|
style={styles.slider}
|
|
35
50
|
minimumValue={min}
|
|
36
51
|
maximumValue={max}
|
|
@@ -78,4 +93,3 @@ const styles = StyleSheet.create({
|
|
|
78
93
|
fontWeight: "500",
|
|
79
94
|
},
|
|
80
95
|
});
|
|
81
|
-
|
|
@@ -62,6 +62,23 @@ export interface OnboardingScreenProps extends OnboardingOptions {
|
|
|
62
62
|
* When true, shows premium paywall before completing onboarding
|
|
63
63
|
*/
|
|
64
64
|
showPaywallOnComplete?: boolean;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Slider component for slider questions
|
|
68
|
+
* Required if using slider question type
|
|
69
|
+
* Import from @react-native-community/slider
|
|
70
|
+
*/
|
|
71
|
+
SliderComponent?: React.ComponentType<{
|
|
72
|
+
style?: any;
|
|
73
|
+
minimumValue: number;
|
|
74
|
+
maximumValue: number;
|
|
75
|
+
value: number;
|
|
76
|
+
onValueChange: (value: number) => void;
|
|
77
|
+
minimumTrackTintColor?: string;
|
|
78
|
+
maximumTrackTintColor?: string;
|
|
79
|
+
thumbTintColor?: string;
|
|
80
|
+
step?: number;
|
|
81
|
+
}>;
|
|
65
82
|
}
|
|
66
83
|
|
|
67
84
|
/**
|
|
@@ -89,6 +106,7 @@ export const OnboardingScreen: React.FC<OnboardingScreenProps> = ({
|
|
|
89
106
|
onUpgrade,
|
|
90
107
|
showPaywallOnComplete = false,
|
|
91
108
|
useGradient: globalUseGradient = false,
|
|
109
|
+
SliderComponent,
|
|
92
110
|
}) => {
|
|
93
111
|
const insets = useSafeAreaInsets();
|
|
94
112
|
const tokens = useAppDesignTokens();
|
|
@@ -231,6 +249,7 @@ export const OnboardingScreen: React.FC<OnboardingScreenProps> = ({
|
|
|
231
249
|
value={currentAnswer}
|
|
232
250
|
onChange={setCurrentAnswer}
|
|
233
251
|
useGradient={useGradient}
|
|
252
|
+
SliderComponent={SliderComponent}
|
|
234
253
|
/>
|
|
235
254
|
) : (
|
|
236
255
|
<OnboardingSlideComponent slide={currentSlide} useGradient={useGradient} />
|