@towsila/expo-ui-library 2.6.0 → 2.7.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/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { Text, TouchableOpacity, View, StyleSheet } from "react-native";
|
|
2
|
-
import
|
|
1
|
+
import { Text, TouchableOpacity, View, StyleSheet, I18nManager, Pressable } from "react-native";
|
|
2
|
+
import {Arrow, ArrowBack} from "@towsila/icons";
|
|
3
3
|
import { useAppTheme } from "../../context/ThemeContext";
|
|
4
4
|
import { Fonts, textSize } from "../../tokens/typography";
|
|
5
|
-
import
|
|
5
|
+
import PageIndicator from "../ui/pageIndicator";
|
|
6
6
|
import SharpButton from "../ui/sharpButton";
|
|
7
|
-
import { I18nManager } from "react-native";
|
|
8
7
|
|
|
9
8
|
interface OnBoardingProps {
|
|
10
9
|
onSkip: () => void;
|
|
11
10
|
onNext: () => void;
|
|
11
|
+
onBack?: () => void;
|
|
12
12
|
image: React.ReactNode;
|
|
13
13
|
title: string;
|
|
14
14
|
description: string;
|
|
@@ -16,11 +16,13 @@ interface OnBoardingProps {
|
|
|
16
16
|
nextLabel: string;
|
|
17
17
|
currentIndex: number;
|
|
18
18
|
total: number;
|
|
19
|
+
stepsLabel?: string;
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
export default function OnBoarding({
|
|
22
23
|
onSkip,
|
|
23
24
|
onNext,
|
|
25
|
+
onBack,
|
|
24
26
|
image,
|
|
25
27
|
title,
|
|
26
28
|
description,
|
|
@@ -28,8 +30,9 @@ export default function OnBoarding({
|
|
|
28
30
|
nextLabel,
|
|
29
31
|
currentIndex,
|
|
30
32
|
total,
|
|
33
|
+
stepsLabel,
|
|
31
34
|
}: OnBoardingProps) {
|
|
32
|
-
const { colors
|
|
35
|
+
const { colors } = useAppTheme();
|
|
33
36
|
|
|
34
37
|
return (
|
|
35
38
|
<View
|
|
@@ -39,27 +42,51 @@ export default function OnBoarding({
|
|
|
39
42
|
]}
|
|
40
43
|
>
|
|
41
44
|
{/* ---------- Header ---------- */}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
45
|
+
<View style={{minHeight: 40,}}>
|
|
46
|
+
<View style={{ height: 44, flexDirection: "row", alignItems: "center", gap: 15}}>
|
|
47
|
+
<TouchableOpacity onPress={onBack} disabled={!onBack}
|
|
48
|
+
style={{
|
|
49
|
+
// position: "absolute",
|
|
50
|
+
// left: I18nManager.isRTL ? undefined : 0,
|
|
51
|
+
// right: I18nManager.isRTL ? 0 : undefined,
|
|
52
|
+
borderWidth: 1,
|
|
53
|
+
borderColor: colors.text.primary,
|
|
54
|
+
borderRadius: 100,
|
|
55
|
+
paddingVertical: 11,
|
|
56
|
+
paddingHorizontal: 11,
|
|
57
|
+
// zIndex: 1,
|
|
58
|
+
opacity: onBack ? 1: 0.5
|
|
59
|
+
}}
|
|
60
|
+
>
|
|
61
|
+
<ArrowBack
|
|
62
|
+
width={19}
|
|
63
|
+
height={19}
|
|
64
|
+
color={colors.text.primary}
|
|
65
|
+
style={I18nManager.isRTL && { transform: [{ scaleX: -1 }] }}
|
|
66
|
+
/>
|
|
67
|
+
</TouchableOpacity>
|
|
68
|
+
|
|
69
|
+
<Text
|
|
70
|
+
style={{
|
|
71
|
+
fontSize: textSize.xl,
|
|
72
|
+
fontFamily: Fonts.montserrat.bold,
|
|
73
|
+
color: colors.text.primary,
|
|
74
|
+
}}
|
|
75
|
+
>
|
|
76
|
+
{title}
|
|
77
|
+
</Text>
|
|
78
|
+
</View>
|
|
79
|
+
<TouchableOpacity onPress={onSkip}>
|
|
80
|
+
<Text
|
|
81
|
+
style={[
|
|
82
|
+
styles.skipLabel,
|
|
83
|
+
{ color: colors.text.primary, textAlign: I18nManager.isRTL ? "left" : "right" },
|
|
84
|
+
]}
|
|
85
|
+
>
|
|
86
|
+
{skipLabel}
|
|
87
|
+
</Text>
|
|
88
|
+
</TouchableOpacity>
|
|
89
|
+
</View>
|
|
63
90
|
|
|
64
91
|
{/* ---------- Content ---------- */}
|
|
65
92
|
<View style={styles.content}>
|
|
@@ -68,17 +95,17 @@ export default function OnBoarding({
|
|
|
68
95
|
{image}
|
|
69
96
|
</View>
|
|
70
97
|
|
|
98
|
+
<View style={styles.indicatorContainer}>
|
|
99
|
+
<PageIndicator
|
|
100
|
+
total={total}
|
|
101
|
+
current={currentIndex}
|
|
102
|
+
color={colors.primary}
|
|
103
|
+
textColor={colors.text.primary}
|
|
104
|
+
defaultColor={colors.semantic.border}
|
|
105
|
+
stepsLabel={stepsLabel}
|
|
106
|
+
/>
|
|
107
|
+
</View>
|
|
71
108
|
{/* Text */}
|
|
72
|
-
<View style={styles.textContainer}>
|
|
73
|
-
<Text
|
|
74
|
-
style={[
|
|
75
|
-
styles.title,
|
|
76
|
-
{ color: colors.text.primary },
|
|
77
|
-
]}
|
|
78
|
-
>
|
|
79
|
-
{title}
|
|
80
|
-
</Text>
|
|
81
|
-
|
|
82
109
|
<Text
|
|
83
110
|
style={[
|
|
84
111
|
styles.description,
|
|
@@ -87,27 +114,14 @@ export default function OnBoarding({
|
|
|
87
114
|
>
|
|
88
115
|
{description}
|
|
89
116
|
</Text>
|
|
90
|
-
|
|
91
|
-
<View style={styles.indicatorContainer}>
|
|
92
|
-
<PageIndicator
|
|
93
|
-
total={total}
|
|
94
|
-
current={currentIndex}
|
|
95
|
-
color={colors.primary}
|
|
96
|
-
borderColor={colors.text.primary}
|
|
97
|
-
defaultColor={colors.background.main}
|
|
98
|
-
/>
|
|
99
|
-
</View>
|
|
100
|
-
</View>
|
|
101
117
|
</View>
|
|
102
118
|
|
|
103
119
|
{/* ---------- Footer ---------- */}
|
|
104
|
-
<View style={styles.footer}>
|
|
105
120
|
<SharpButton
|
|
106
121
|
text={nextLabel}
|
|
107
122
|
bgColor={colors.primary}
|
|
108
123
|
onPress={onNext}
|
|
109
124
|
/>
|
|
110
|
-
</View>
|
|
111
125
|
</View>
|
|
112
126
|
);
|
|
113
127
|
}
|
|
@@ -119,25 +133,12 @@ const styles = StyleSheet.create({
|
|
|
119
133
|
paddingVertical: 60,
|
|
120
134
|
},
|
|
121
135
|
|
|
122
|
-
header: {
|
|
123
|
-
alignItems: "flex-end",
|
|
124
|
-
minHeight: 40,
|
|
125
|
-
},
|
|
126
|
-
|
|
127
|
-
skipButton: {
|
|
128
|
-
flexDirection: "row",
|
|
129
|
-
alignItems: "center",
|
|
130
|
-
paddingVertical: 8,
|
|
131
|
-
},
|
|
132
|
-
|
|
133
136
|
skipLabel: {
|
|
134
137
|
fontSize: textSize.md,
|
|
135
138
|
fontFamily: Fonts.montserrat.regular,
|
|
136
139
|
},
|
|
137
140
|
|
|
138
|
-
|
|
139
|
-
marginLeft: 6,
|
|
140
|
-
},
|
|
141
|
+
|
|
141
142
|
|
|
142
143
|
content: {
|
|
143
144
|
flex: 1,
|
|
@@ -145,40 +146,20 @@ const styles = StyleSheet.create({
|
|
|
145
146
|
},
|
|
146
147
|
|
|
147
148
|
imageContainer: {
|
|
148
|
-
flex: 0.58,
|
|
149
149
|
justifyContent: "center",
|
|
150
150
|
alignItems: "center",
|
|
151
|
-
overflow: "hidden",
|
|
152
|
-
},
|
|
153
|
-
|
|
154
|
-
textContainer: {
|
|
155
|
-
flex: 0.42,
|
|
156
|
-
justifyContent: "center",
|
|
157
|
-
alignItems: "center",
|
|
158
|
-
paddingHorizontal: 12,
|
|
159
|
-
},
|
|
160
|
-
|
|
161
|
-
title: {
|
|
162
|
-
fontSize: textSize.xxl,
|
|
163
|
-
fontFamily: Fonts.montserrat.bold,
|
|
164
|
-
textAlign: "center",
|
|
165
|
-
marginBottom: 14,
|
|
166
151
|
},
|
|
167
152
|
|
|
168
153
|
description: {
|
|
169
154
|
fontSize: textSize.sm,
|
|
170
155
|
fontFamily: Fonts.montserrat.regular,
|
|
171
|
-
textAlign: "
|
|
172
|
-
lineHeight: 22,
|
|
173
|
-
marginBottom: 28,
|
|
174
|
-
paddingHorizontal: 10,
|
|
156
|
+
textAlign: I18nManager.isRTL ? "right" : "left",
|
|
175
157
|
},
|
|
176
158
|
|
|
177
159
|
indicatorContainer: {
|
|
178
|
-
marginTop:
|
|
160
|
+
marginTop: 10,
|
|
161
|
+
marginBottom: 25,
|
|
179
162
|
},
|
|
180
163
|
|
|
181
|
-
|
|
182
|
-
paddingTop: 24,
|
|
183
|
-
},
|
|
164
|
+
|
|
184
165
|
});
|
|
@@ -1,58 +1,45 @@
|
|
|
1
|
-
import { View, StyleSheet } from "react-native";
|
|
1
|
+
import { View, StyleSheet, Text, I18nManager, useWindowDimensions } from "react-native";
|
|
2
2
|
import Svg, { Circle } from "react-native-svg";
|
|
3
|
+
import { Fonts, textSize } from "../../tokens/typography";
|
|
3
4
|
|
|
4
5
|
type Props = {
|
|
6
|
+
stepsLabel?: string;
|
|
5
7
|
total?: number;
|
|
6
8
|
current?: number;
|
|
7
|
-
|
|
9
|
+
textColor: string;
|
|
8
10
|
color?: string;
|
|
9
11
|
defaultColor:string;
|
|
10
12
|
};
|
|
11
13
|
|
|
12
|
-
const
|
|
13
|
-
const CENTER = SIZE / 2;
|
|
14
|
+
const BAR_HEIGHT = 6;
|
|
14
15
|
|
|
15
16
|
export default function PageIndicator({
|
|
17
|
+
stepsLabel="Steps",
|
|
16
18
|
total = 3,
|
|
17
19
|
current = 1,
|
|
18
|
-
|
|
20
|
+
textColor = "black",
|
|
19
21
|
color = "white",
|
|
20
22
|
defaultColor,
|
|
21
23
|
}: Props) {
|
|
22
24
|
return (
|
|
23
|
-
<View style={
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
width={SIZE}
|
|
28
|
-
height={SIZE}
|
|
29
|
-
viewBox={`0 0 ${SIZE} ${SIZE}`}
|
|
30
|
-
>
|
|
31
|
-
{/* Outer circle (border) */}
|
|
32
|
-
<Circle
|
|
33
|
-
cx={CENTER}
|
|
34
|
-
cy={CENTER}
|
|
35
|
-
r={CENTER - 0.5}
|
|
36
|
-
fill={borderColor}
|
|
37
|
-
/>
|
|
25
|
+
<View style={{ alignItems: I18nManager.isRTL ? "flex-end" : "flex-start", gap: 15, width: "100%" }}>
|
|
26
|
+
<Text style={{ color: textColor, fontSize: textSize.md, fontFamily: Fonts.montserrat.semiBold }}>
|
|
27
|
+
{stepsLabel}
|
|
28
|
+
</Text>
|
|
38
29
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
30
|
+
<View style={{ flexDirection: I18nManager.isRTL ? "row-reverse" : "row", gap: 8, width: "100%" }}>
|
|
31
|
+
{Array.from({ length: total }).map((_, index) => (
|
|
32
|
+
<View
|
|
33
|
+
key={index}
|
|
34
|
+
style={{
|
|
35
|
+
flex: 1,
|
|
36
|
+
height: BAR_HEIGHT,
|
|
37
|
+
borderRadius: BAR_HEIGHT / 2,
|
|
38
|
+
backgroundColor: current === index ? color : defaultColor,
|
|
39
|
+
}}
|
|
40
|
+
/>
|
|
41
|
+
))}
|
|
42
|
+
</View>
|
|
43
|
+
</View>
|
|
49
44
|
);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const styles = StyleSheet.create({
|
|
53
|
-
container: {
|
|
54
|
-
flexDirection: "row",
|
|
55
|
-
justifyContent: "center",
|
|
56
|
-
gap: 8,
|
|
57
|
-
},
|
|
58
|
-
});
|
|
45
|
+
}
|