@umituz/react-native-onboarding 2.6.7 → 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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-onboarding",
3
- "version": "2.6.7",
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",
@@ -15,12 +15,24 @@ export interface QuestionRendererProps {
15
15
  question: OnboardingQuestion;
16
16
  value: any;
17
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
+ }>;
18
29
  }
19
30
 
20
31
  export const QuestionRenderer: React.FC<QuestionRendererProps> = ({
21
32
  question,
22
33
  value,
23
34
  onChange,
35
+ SliderComponent,
24
36
  }) => {
25
37
  switch (question.type) {
26
38
  case "single_choice":
@@ -48,11 +60,15 @@ export const QuestionRenderer: React.FC<QuestionRendererProps> = ({
48
60
  />
49
61
  );
50
62
  case "slider":
63
+ if (!SliderComponent) {
64
+ return null;
65
+ }
51
66
  return (
52
67
  <SliderQuestion
53
68
  question={question}
54
69
  value={value}
55
70
  onChange={onChange}
71
+ SliderComponent={SliderComponent}
56
72
  />
57
73
  );
58
74
  case "rating":
@@ -67,4 +83,3 @@ export const QuestionRenderer: React.FC<QuestionRendererProps> = ({
67
83
  return null;
68
84
  }
69
85
  };
70
-
@@ -15,6 +15,17 @@ export interface QuestionSlideProps {
15
15
  value: any;
16
16
  onChange: (value: any) => void;
17
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
+ }>;
18
29
  }
19
30
 
20
31
  export const QuestionSlide: React.FC<QuestionSlideProps> = ({
@@ -22,6 +33,7 @@ export const QuestionSlide: React.FC<QuestionSlideProps> = ({
22
33
  value,
23
34
  onChange,
24
35
  useGradient = false,
36
+ SliderComponent,
25
37
  }) => {
26
38
  const tokens = useAppDesignTokens();
27
39
  const styles = useMemo(() => getStyles(tokens, useGradient), [tokens, useGradient]);
@@ -36,7 +48,12 @@ export const QuestionSlide: React.FC<QuestionSlideProps> = ({
36
48
  <QuestionSlideHeader slide={slide} useGradient={useGradient} />
37
49
 
38
50
  <View style={styles.questionContainer}>
39
- <QuestionRenderer question={question} value={value} onChange={onChange} />
51
+ <QuestionRenderer
52
+ question={question}
53
+ value={value}
54
+ onChange={onChange}
55
+ SliderComponent={SliderComponent}
56
+ />
40
57
  </View>
41
58
 
42
59
  {question.validation?.required && !value && (
@@ -4,22 +4,24 @@
4
4
  */
5
5
 
6
6
  import React, { useMemo } from "react";
7
- import { View, Text, TouchableOpacity, StyleSheet } from "react-native";
7
+ import { View, Text, StyleSheet } from "react-native";
8
8
  import type { OnboardingQuestion } from "../../../domain/entities/OnboardingQuestion";
9
9
 
10
- // Lazy import slider to handle peer dependency gracefully
11
- let SliderComponent: any = null;
12
- try {
13
- // eslint-disable-next-line @typescript-eslint/no-require-imports
14
- SliderComponent = require("@react-native-community/slider").default;
15
- } catch {
16
- // Slider not available - will show fallback
17
- }
18
-
19
10
  export interface SliderQuestionProps {
20
11
  question: OnboardingQuestion;
21
12
  value: number | undefined;
22
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
+ }>;
23
25
  }
24
26
 
25
27
  const getSliderConfig = (question: OnboardingQuestion) => {
@@ -29,87 +31,35 @@ const getSliderConfig = (question: OnboardingQuestion) => {
29
31
  return { min, max };
30
32
  };
31
33
 
32
- const SliderFallback: React.FC<{
33
- min: number;
34
- max: number;
35
- value: number;
36
- onChange: (value: number) => void;
37
- }> = ({ min, max, value, onChange }) => {
38
- const handleIncrement = () => {
39
- if (value < max) {
40
- onChange(value + 1);
41
- }
42
- };
43
-
44
- const handleDecrement = () => {
45
- if (value > min) {
46
- onChange(value - 1);
47
- }
48
- };
49
-
50
- return (
51
- <View style={styles.fallbackContainer}>
52
- <View style={styles.fallbackControls}>
53
- <TouchableOpacity
54
- style={styles.fallbackButton}
55
- onPress={handleDecrement}
56
- activeOpacity={0.7}
57
- >
58
- <Text style={styles.fallbackButtonText}>−</Text>
59
- </TouchableOpacity>
60
- <Text style={styles.fallbackValue}>{value}</Text>
61
- <TouchableOpacity
62
- style={styles.fallbackButton}
63
- onPress={handleIncrement}
64
- activeOpacity={0.7}
65
- >
66
- <Text style={styles.fallbackButtonText}>+</Text>
67
- </TouchableOpacity>
68
- </View>
69
- <View style={styles.fallbackLabels}>
70
- <Text style={styles.label}>{min}</Text>
71
- <Text style={styles.label}>{max}</Text>
72
- </View>
73
- </View>
74
- );
75
- };
76
-
77
34
  export const SliderQuestion: React.FC<SliderQuestionProps> = ({
78
35
  question,
79
36
  value,
80
37
  onChange,
38
+ SliderComponent,
81
39
  }) => {
82
40
  const { min, max } = useMemo(() => getSliderConfig(question), [question]);
83
41
  const currentValue = value ?? min;
84
42
 
85
- const sliderProps = {
86
- style: styles.slider,
87
- minimumValue: min,
88
- maximumValue: max,
89
- value: currentValue,
90
- onValueChange: onChange,
91
- minimumTrackTintColor: "#FFFFFF",
92
- maximumTrackTintColor: "rgba(255, 255, 255, 0.3)",
93
- thumbTintColor: "#FFFFFF",
94
- step: 1,
95
- };
96
-
97
43
  return (
98
44
  <View style={styles.container}>
99
45
  <View style={styles.valueContainer}>
100
46
  <Text style={styles.valueText}>{currentValue}</Text>
101
47
  </View>
102
- {SliderComponent ? (
103
- <>
104
- <SliderComponent {...sliderProps} />
105
- <View style={styles.labels}>
106
- <Text style={styles.label}>{min}</Text>
107
- <Text style={styles.label}>{max}</Text>
108
- </View>
109
- </>
110
- ) : (
111
- <SliderFallback min={min} max={max} value={currentValue} onChange={onChange} />
112
- )}
48
+ <SliderComponent
49
+ style={styles.slider}
50
+ minimumValue={min}
51
+ maximumValue={max}
52
+ value={currentValue}
53
+ onValueChange={onChange}
54
+ minimumTrackTintColor="#FFFFFF"
55
+ maximumTrackTintColor="rgba(255, 255, 255, 0.3)"
56
+ thumbTintColor="#FFFFFF"
57
+ step={1}
58
+ />
59
+ <View style={styles.labels}>
60
+ <Text style={styles.label}>{min}</Text>
61
+ <Text style={styles.label}>{max}</Text>
62
+ </View>
113
63
  </View>
114
64
  );
115
65
  };
@@ -142,39 +92,4 @@ const styles = StyleSheet.create({
142
92
  color: "rgba(255, 255, 255, 0.7)",
143
93
  fontWeight: "500",
144
94
  },
145
- fallbackContainer: {
146
- width: "100%",
147
- },
148
- fallbackControls: {
149
- flexDirection: "row",
150
- alignItems: "center",
151
- justifyContent: "center",
152
- gap: 24,
153
- },
154
- fallbackButton: {
155
- width: 60,
156
- height: 60,
157
- backgroundColor: "rgba(255, 255, 255, 0.2)",
158
- borderRadius: 30,
159
- alignItems: "center",
160
- justifyContent: "center",
161
- },
162
- fallbackButtonText: {
163
- fontSize: 48,
164
- fontWeight: "bold",
165
- color: "#FFFFFF",
166
- lineHeight: 60,
167
- },
168
- fallbackValue: {
169
- fontSize: 36,
170
- fontWeight: "bold",
171
- color: "#FFFFFF",
172
- minWidth: 80,
173
- textAlign: "center",
174
- },
175
- fallbackLabels: {
176
- flexDirection: "row",
177
- justifyContent: "space-between",
178
- marginTop: 16,
179
- },
180
95
  });
@@ -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} />