@umituz/react-native-onboarding 2.5.3 → 2.6.1
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 +4 -3
- package/src/presentation/components/QuestionSlide.tsx +25 -13
- package/src/presentation/components/questions/MultipleChoiceQuestion.tsx +57 -62
- package/src/presentation/components/questions/SingleChoiceQuestion.tsx +55 -60
- package/src/presentation/screens/OnboardingScreen.tsx +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-onboarding",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.6.1",
|
|
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",
|
|
@@ -30,13 +30,15 @@
|
|
|
30
30
|
"type": "git",
|
|
31
31
|
"url": "https://github.com/umituz/react-native-onboarding"
|
|
32
32
|
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@react-native-community/slider": "^4.5.0"
|
|
35
|
+
},
|
|
33
36
|
"peerDependencies": {
|
|
34
37
|
"@umituz/react-native-storage": "latest",
|
|
35
38
|
"@umituz/react-native-localization": "latest",
|
|
36
39
|
"@umituz/react-native-design-system-theme": "latest",
|
|
37
40
|
"@umituz/react-native-design-system": "latest",
|
|
38
41
|
"@umituz/react-native-design-system-atoms": "latest",
|
|
39
|
-
"@react-native-community/slider": "^4.5.0",
|
|
40
42
|
"expo-linear-gradient": "^15.0.0",
|
|
41
43
|
"lucide-react-native": "^0.344.0",
|
|
42
44
|
"react": ">=18.2.0",
|
|
@@ -51,7 +53,6 @@
|
|
|
51
53
|
"@umituz/react-native-localization": "latest",
|
|
52
54
|
"@umituz/react-native-design-system-theme": "latest",
|
|
53
55
|
"@umituz/react-native-design-system-atoms": "latest",
|
|
54
|
-
"@react-native-community/slider": "^4.5.0",
|
|
55
56
|
"expo-linear-gradient": "^15.0.7",
|
|
56
57
|
"lucide-react-native": "^0.344.0",
|
|
57
58
|
"react": "^18.2.0",
|
|
@@ -19,15 +19,17 @@ export interface QuestionSlideProps {
|
|
|
19
19
|
slide: OnboardingSlide;
|
|
20
20
|
value: any;
|
|
21
21
|
onChange: (value: any) => void;
|
|
22
|
+
useGradient?: boolean;
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
export const QuestionSlide: React.FC<QuestionSlideProps> = ({
|
|
25
26
|
slide,
|
|
26
27
|
value,
|
|
27
28
|
onChange,
|
|
29
|
+
useGradient = false,
|
|
28
30
|
}) => {
|
|
29
31
|
const tokens = useAppDesignTokens();
|
|
30
|
-
const styles = useMemo(() => getStyles(tokens), [tokens]);
|
|
32
|
+
const styles = useMemo(() => getStyles(tokens, useGradient), [tokens, useGradient]);
|
|
31
33
|
const { question } = slide;
|
|
32
34
|
|
|
33
35
|
if (!question) {
|
|
@@ -98,7 +100,7 @@ export const QuestionSlide: React.FC<QuestionSlideProps> = ({
|
|
|
98
100
|
<AtomicIcon
|
|
99
101
|
name={slide.icon as any}
|
|
100
102
|
customSize={48}
|
|
101
|
-
customColor={tokens.colors.textPrimary}
|
|
103
|
+
customColor={useGradient ? "#FFFFFF" : tokens.colors.textPrimary}
|
|
102
104
|
/>
|
|
103
105
|
)}
|
|
104
106
|
</View>
|
|
@@ -123,7 +125,7 @@ export const QuestionSlide: React.FC<QuestionSlideProps> = ({
|
|
|
123
125
|
);
|
|
124
126
|
};
|
|
125
127
|
|
|
126
|
-
const getStyles = (tokens: ReturnType<typeof useAppDesignTokens
|
|
128
|
+
const getStyles = (tokens: ReturnType<typeof useAppDesignTokens>, useGradient: boolean) =>
|
|
127
129
|
StyleSheet.create({
|
|
128
130
|
content: {
|
|
129
131
|
flexGrow: 1,
|
|
@@ -136,31 +138,41 @@ const getStyles = (tokens: ReturnType<typeof useAppDesignTokens>) =>
|
|
|
136
138
|
alignItems: "center",
|
|
137
139
|
maxWidth: 500,
|
|
138
140
|
width: "100%",
|
|
139
|
-
//
|
|
140
|
-
backgroundColor:
|
|
141
|
+
// Gradient kullanıldığında yarı şeffaf, değilse solid
|
|
142
|
+
backgroundColor: useGradient
|
|
143
|
+
? "rgba(255, 255, 255, 0.15)"
|
|
144
|
+
: tokens.colors.surface,
|
|
141
145
|
padding: 30,
|
|
142
146
|
borderRadius: 24,
|
|
143
|
-
borderWidth: 1,
|
|
144
|
-
borderColor: tokens.colors.borderLight,
|
|
147
|
+
borderWidth: useGradient ? 0 : 1,
|
|
148
|
+
borderColor: useGradient ? "transparent" : tokens.colors.borderLight,
|
|
145
149
|
shadowColor: tokens.colors.textPrimary,
|
|
146
150
|
shadowOffset: {
|
|
147
151
|
width: 0,
|
|
148
152
|
height: 4,
|
|
149
153
|
},
|
|
150
|
-
shadowOpacity: 0.1,
|
|
154
|
+
shadowOpacity: useGradient ? 0.3 : 0.1,
|
|
151
155
|
shadowRadius: 8,
|
|
152
156
|
elevation: 4,
|
|
157
|
+
// Gradient için backdrop blur efekti
|
|
158
|
+
...(useGradient && {
|
|
159
|
+
backdropFilter: "blur(10px)",
|
|
160
|
+
}),
|
|
153
161
|
},
|
|
154
162
|
iconContainer: {
|
|
155
163
|
width: 96,
|
|
156
164
|
height: 96,
|
|
157
165
|
borderRadius: 48,
|
|
158
|
-
backgroundColor:
|
|
166
|
+
backgroundColor: useGradient
|
|
167
|
+
? "rgba(255, 255, 255, 0.25)"
|
|
168
|
+
: withAlpha(tokens.colors.primary, 0.2),
|
|
159
169
|
alignItems: "center",
|
|
160
170
|
justifyContent: "center",
|
|
161
171
|
marginBottom: 24,
|
|
162
172
|
borderWidth: 2,
|
|
163
|
-
borderColor:
|
|
173
|
+
borderColor: useGradient
|
|
174
|
+
? "rgba(255, 255, 255, 0.4)"
|
|
175
|
+
: withAlpha(tokens.colors.primary, 0.4),
|
|
164
176
|
},
|
|
165
177
|
icon: {
|
|
166
178
|
fontSize: 48,
|
|
@@ -168,13 +180,13 @@ const getStyles = (tokens: ReturnType<typeof useAppDesignTokens>) =>
|
|
|
168
180
|
title: {
|
|
169
181
|
fontSize: 24,
|
|
170
182
|
fontWeight: "bold",
|
|
171
|
-
color: tokens.colors.textPrimary,
|
|
183
|
+
color: useGradient ? "#FFFFFF" : tokens.colors.textPrimary,
|
|
172
184
|
textAlign: "center",
|
|
173
185
|
marginBottom: 12,
|
|
174
186
|
},
|
|
175
187
|
description: {
|
|
176
188
|
fontSize: 15,
|
|
177
|
-
color: tokens.colors.textSecondary,
|
|
189
|
+
color: useGradient ? "rgba(255, 255, 255, 0.9)" : tokens.colors.textSecondary,
|
|
178
190
|
textAlign: "center",
|
|
179
191
|
lineHeight: 22,
|
|
180
192
|
marginBottom: 24,
|
|
@@ -185,7 +197,7 @@ const getStyles = (tokens: ReturnType<typeof useAppDesignTokens>) =>
|
|
|
185
197
|
},
|
|
186
198
|
requiredHint: {
|
|
187
199
|
fontSize: 13,
|
|
188
|
-
color: tokens.colors.textSecondary,
|
|
200
|
+
color: useGradient ? "rgba(255, 255, 255, 0.8)" : tokens.colors.textSecondary,
|
|
189
201
|
fontStyle: "italic",
|
|
190
202
|
marginTop: 12,
|
|
191
203
|
},
|
|
@@ -4,10 +4,9 @@
|
|
|
4
4
|
* Checkbox style question for multiple selections
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import React
|
|
7
|
+
import React from "react";
|
|
8
8
|
import { View, Text, TouchableOpacity, StyleSheet } from "react-native";
|
|
9
9
|
import { AtomicIcon } from "@umituz/react-native-design-system-atoms";
|
|
10
|
-
import { useAppDesignTokens, withAlpha } from "@umituz/react-native-design-system-theme";
|
|
11
10
|
import type { OnboardingQuestion, QuestionOption } from "../../../domain/entities/OnboardingQuestion";
|
|
12
11
|
|
|
13
12
|
export interface MultipleChoiceQuestionProps {
|
|
@@ -21,9 +20,6 @@ export const MultipleChoiceQuestion: React.FC<MultipleChoiceQuestionProps> = ({
|
|
|
21
20
|
value = [],
|
|
22
21
|
onChange,
|
|
23
22
|
}) => {
|
|
24
|
-
const tokens = useAppDesignTokens();
|
|
25
|
-
const styles = useMemo(() => getStyles(tokens), [tokens]);
|
|
26
|
-
|
|
27
23
|
const isEmoji = (icon: string) =>
|
|
28
24
|
/[\u{1F300}-\u{1F9FF}]|[\u{2600}-\u{26FF}]|[\u{2700}-\u{27BF}]/u.test(icon);
|
|
29
25
|
|
|
@@ -61,7 +57,7 @@ export const MultipleChoiceQuestion: React.FC<MultipleChoiceQuestionProps> = ({
|
|
|
61
57
|
<AtomicIcon
|
|
62
58
|
name={option.icon as any}
|
|
63
59
|
customSize={24}
|
|
64
|
-
customColor={isSelected ?
|
|
60
|
+
customColor={isSelected ? "#FFFFFF" : "rgba(255, 255, 255, 0.8)"}
|
|
65
61
|
/>
|
|
66
62
|
)}
|
|
67
63
|
</View>
|
|
@@ -71,7 +67,7 @@ export const MultipleChoiceQuestion: React.FC<MultipleChoiceQuestionProps> = ({
|
|
|
71
67
|
</Text>
|
|
72
68
|
<View style={[styles.checkbox, isSelected && styles.checkboxSelected]}>
|
|
73
69
|
{isSelected && (
|
|
74
|
-
<AtomicIcon name="Check" customSize={16} customColor=
|
|
70
|
+
<AtomicIcon name="Check" customSize={16} customColor="#FFFFFF" />
|
|
75
71
|
)}
|
|
76
72
|
</View>
|
|
77
73
|
</TouchableOpacity>
|
|
@@ -90,59 +86,58 @@ export const MultipleChoiceQuestion: React.FC<MultipleChoiceQuestionProps> = ({
|
|
|
90
86
|
);
|
|
91
87
|
};
|
|
92
88
|
|
|
93
|
-
const
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
});
|
|
89
|
+
const styles = StyleSheet.create({
|
|
90
|
+
container: {
|
|
91
|
+
width: "100%",
|
|
92
|
+
gap: 12,
|
|
93
|
+
},
|
|
94
|
+
option: {
|
|
95
|
+
flexDirection: "row",
|
|
96
|
+
alignItems: "center",
|
|
97
|
+
backgroundColor: "rgba(255, 255, 255, 0.1)",
|
|
98
|
+
borderRadius: 12,
|
|
99
|
+
padding: 16,
|
|
100
|
+
borderWidth: 2,
|
|
101
|
+
borderColor: "rgba(255, 255, 255, 0.2)",
|
|
102
|
+
},
|
|
103
|
+
optionSelected: {
|
|
104
|
+
backgroundColor: "rgba(255, 255, 255, 0.25)",
|
|
105
|
+
borderColor: "rgba(255, 255, 255, 0.5)",
|
|
106
|
+
},
|
|
107
|
+
optionIcon: {
|
|
108
|
+
marginRight: 12,
|
|
109
|
+
},
|
|
110
|
+
emoji: {
|
|
111
|
+
fontSize: 24,
|
|
112
|
+
},
|
|
113
|
+
optionLabel: {
|
|
114
|
+
flex: 1,
|
|
115
|
+
fontSize: 16,
|
|
116
|
+
color: "rgba(255, 255, 255, 0.9)",
|
|
117
|
+
fontWeight: "500",
|
|
118
|
+
},
|
|
119
|
+
optionLabelSelected: {
|
|
120
|
+
color: "#FFFFFF",
|
|
121
|
+
fontWeight: "600",
|
|
122
|
+
},
|
|
123
|
+
checkbox: {
|
|
124
|
+
width: 24,
|
|
125
|
+
height: 24,
|
|
126
|
+
borderRadius: 6,
|
|
127
|
+
borderWidth: 2,
|
|
128
|
+
borderColor: "rgba(255, 255, 255, 0.5)",
|
|
129
|
+
alignItems: "center",
|
|
130
|
+
justifyContent: "center",
|
|
131
|
+
},
|
|
132
|
+
checkboxSelected: {
|
|
133
|
+
borderColor: "#FFFFFF",
|
|
134
|
+
backgroundColor: "rgba(255, 255, 255, 0.3)",
|
|
135
|
+
},
|
|
136
|
+
hint: {
|
|
137
|
+
fontSize: 13,
|
|
138
|
+
color: "rgba(255, 255, 255, 0.7)",
|
|
139
|
+
textAlign: "center",
|
|
140
|
+
marginTop: 4,
|
|
141
|
+
},
|
|
142
|
+
});
|
|
148
143
|
|
|
@@ -4,10 +4,9 @@
|
|
|
4
4
|
* Radio button style question for single selection
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import React
|
|
7
|
+
import React from "react";
|
|
8
8
|
import { View, Text, TouchableOpacity, StyleSheet } from "react-native";
|
|
9
9
|
import { AtomicIcon } from "@umituz/react-native-design-system-atoms";
|
|
10
|
-
import { useAppDesignTokens, withAlpha } from "@umituz/react-native-design-system-theme";
|
|
11
10
|
import type { OnboardingQuestion, QuestionOption } from "../../../domain/entities/OnboardingQuestion";
|
|
12
11
|
|
|
13
12
|
export interface SingleChoiceQuestionProps {
|
|
@@ -21,9 +20,6 @@ export const SingleChoiceQuestion: React.FC<SingleChoiceQuestionProps> = ({
|
|
|
21
20
|
value,
|
|
22
21
|
onChange,
|
|
23
22
|
}) => {
|
|
24
|
-
const tokens = useAppDesignTokens();
|
|
25
|
-
const styles = useMemo(() => getStyles(tokens), [tokens]);
|
|
26
|
-
|
|
27
23
|
const isEmoji = (icon: string) =>
|
|
28
24
|
/[\u{1F300}-\u{1F9FF}]|[\u{2600}-\u{26FF}]|[\u{2700}-\u{27BF}]/u.test(icon);
|
|
29
25
|
|
|
@@ -45,7 +41,7 @@ export const SingleChoiceQuestion: React.FC<SingleChoiceQuestionProps> = ({
|
|
|
45
41
|
<AtomicIcon
|
|
46
42
|
name={option.icon as any}
|
|
47
43
|
customSize={24}
|
|
48
|
-
customColor={isSelected ?
|
|
44
|
+
customColor={isSelected ? "#FFFFFF" : "rgba(255, 255, 255, 0.8)"}
|
|
49
45
|
/>
|
|
50
46
|
)}
|
|
51
47
|
</View>
|
|
@@ -67,58 +63,57 @@ export const SingleChoiceQuestion: React.FC<SingleChoiceQuestionProps> = ({
|
|
|
67
63
|
);
|
|
68
64
|
};
|
|
69
65
|
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
});
|
|
66
|
+
const styles = StyleSheet.create({
|
|
67
|
+
container: {
|
|
68
|
+
width: "100%",
|
|
69
|
+
gap: 12,
|
|
70
|
+
},
|
|
71
|
+
option: {
|
|
72
|
+
flexDirection: "row",
|
|
73
|
+
alignItems: "center",
|
|
74
|
+
backgroundColor: "rgba(255, 255, 255, 0.1)",
|
|
75
|
+
borderRadius: 12,
|
|
76
|
+
padding: 16,
|
|
77
|
+
borderWidth: 2,
|
|
78
|
+
borderColor: "rgba(255, 255, 255, 0.2)",
|
|
79
|
+
},
|
|
80
|
+
optionSelected: {
|
|
81
|
+
backgroundColor: "rgba(255, 255, 255, 0.25)",
|
|
82
|
+
borderColor: "rgba(255, 255, 255, 0.5)",
|
|
83
|
+
},
|
|
84
|
+
optionIcon: {
|
|
85
|
+
marginRight: 12,
|
|
86
|
+
},
|
|
87
|
+
emoji: {
|
|
88
|
+
fontSize: 24,
|
|
89
|
+
},
|
|
90
|
+
optionLabel: {
|
|
91
|
+
flex: 1,
|
|
92
|
+
fontSize: 16,
|
|
93
|
+
color: "rgba(255, 255, 255, 0.9)",
|
|
94
|
+
fontWeight: "500",
|
|
95
|
+
},
|
|
96
|
+
optionLabelSelected: {
|
|
97
|
+
color: "#FFFFFF",
|
|
98
|
+
fontWeight: "600",
|
|
99
|
+
},
|
|
100
|
+
radio: {
|
|
101
|
+
width: 24,
|
|
102
|
+
height: 24,
|
|
103
|
+
borderRadius: 12,
|
|
104
|
+
borderWidth: 2,
|
|
105
|
+
borderColor: "rgba(255, 255, 255, 0.5)",
|
|
106
|
+
alignItems: "center",
|
|
107
|
+
justifyContent: "center",
|
|
108
|
+
},
|
|
109
|
+
radioSelected: {
|
|
110
|
+
borderColor: "#FFFFFF",
|
|
111
|
+
},
|
|
112
|
+
radioInner: {
|
|
113
|
+
width: 12,
|
|
114
|
+
height: 12,
|
|
115
|
+
borderRadius: 6,
|
|
116
|
+
backgroundColor: "#FFFFFF",
|
|
117
|
+
},
|
|
118
|
+
});
|
|
124
119
|
|