@umituz/react-native-onboarding 3.6.23 → 3.6.25
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 -3
- package/src/domain/entities/OnboardingOptions.ts +3 -3
- package/src/domain/entities/OnboardingSlide.ts +6 -8
- package/src/infrastructure/utils/backgroundUtils.ts +38 -0
- package/src/presentation/components/OnboardingBackground.tsx +13 -13
- package/src/presentation/components/OnboardingScreenContent.tsx +5 -5
- package/src/presentation/hooks/useOnboardingContainerStyle.ts +4 -4
- package/src/presentation/hooks/useOnboardingScreenState.ts +7 -7
- package/src/presentation/providers/OnboardingProvider.tsx +4 -4
- package/src/presentation/screens/OnboardingScreen.tsx +5 -5
- package/src/presentation/types/OnboardingProps.ts +1 -1
- package/src/presentation/types/OnboardingTheme.ts +1 -1
- package/src/infrastructure/utils/gradientUtils.ts +0 -41
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-onboarding",
|
|
3
|
-
"version": "3.6.
|
|
3
|
+
"version": "3.6.25",
|
|
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",
|
|
@@ -33,7 +33,6 @@
|
|
|
33
33
|
"@umituz/react-native-localization": ">=1.0.0",
|
|
34
34
|
"@umituz/react-native-storage": ">=2.6.0",
|
|
35
35
|
"expo-image": ">=2.0.0",
|
|
36
|
-
"expo-linear-gradient": ">=13.0.0",
|
|
37
36
|
"expo-video": ">=1.0.0",
|
|
38
37
|
"react": ">=18.2.0",
|
|
39
38
|
"react-native": ">=0.74.0",
|
|
@@ -56,7 +55,6 @@
|
|
|
56
55
|
"eslint-plugin-react": "^7.37.5",
|
|
57
56
|
"eslint-plugin-react-hooks": "^7.0.1",
|
|
58
57
|
"expo-image": "~2.0.0",
|
|
59
|
-
"expo-linear-gradient": "^15.0.7",
|
|
60
58
|
"expo-video": "~2.0.0",
|
|
61
59
|
"react": "19.1.0",
|
|
62
60
|
"react-native": "0.81.5",
|
|
@@ -87,10 +87,10 @@ export interface OnboardingOptions {
|
|
|
87
87
|
showPaywallOnComplete?: boolean;
|
|
88
88
|
|
|
89
89
|
/**
|
|
90
|
-
* Use
|
|
91
|
-
* When true, all slides will use
|
|
90
|
+
* Use custom background for all slides (default: false)
|
|
91
|
+
* When true, all slides will use custom backgrounds if available
|
|
92
92
|
*/
|
|
93
|
-
|
|
93
|
+
useCustomBackground?: boolean;
|
|
94
94
|
|
|
95
95
|
/**
|
|
96
96
|
* Visual theme variant (default: "default")
|
|
@@ -62,18 +62,16 @@ export interface OnboardingSlide {
|
|
|
62
62
|
contentPosition?: ContentPosition;
|
|
63
63
|
|
|
64
64
|
/**
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
* Only used if useGradient is true
|
|
65
|
+
* Background color for the slide background (optional)
|
|
66
|
+
* Only used if useCustomBackground is true
|
|
68
67
|
*/
|
|
69
|
-
|
|
68
|
+
backgroundColor?: string;
|
|
70
69
|
|
|
71
70
|
/**
|
|
72
|
-
* Use
|
|
73
|
-
* If true and
|
|
74
|
-
* If false or gradient not provided, theme background colors will be used
|
|
71
|
+
* Use custom background color instead of theme defaults (default: false)
|
|
72
|
+
* If true and backgroundColor is provided, it will be used
|
|
75
73
|
*/
|
|
76
|
-
|
|
74
|
+
useCustomBackground?: boolean;
|
|
77
75
|
|
|
78
76
|
/**
|
|
79
77
|
* Optional image URL (alternative to icon)
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Background Utilities
|
|
3
|
+
*
|
|
4
|
+
* Utility functions for background-related operations
|
|
5
|
+
* Follows Single Responsibility Principle
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { OnboardingSlide } from "../../domain/entities/OnboardingSlide";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Check if slide should use custom background or overlay
|
|
12
|
+
* Indicates that we are not using the default theme background.
|
|
13
|
+
*
|
|
14
|
+
* @param slide - The slide to check
|
|
15
|
+
* @param globalUseCustomBackground - Global option from OnboardingOptions
|
|
16
|
+
* @returns true if custom background/media should be used, false otherwise
|
|
17
|
+
*/
|
|
18
|
+
export function shouldUseCustomBackground(
|
|
19
|
+
slide: OnboardingSlide | undefined,
|
|
20
|
+
globalUseCustomBackground?: boolean
|
|
21
|
+
): boolean {
|
|
22
|
+
if (!slide) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// If there is background media, we always treat it as custom (needs overlay for readability)
|
|
27
|
+
if (slide.backgroundImage || slide.backgroundVideo || (slide.backgroundImages && slide.backgroundImages.length > 0)) {
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// If global custom background is enabled, use it if slide has color defined
|
|
32
|
+
if (globalUseCustomBackground === true) {
|
|
33
|
+
return !!slide.backgroundColor;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Otherwise, check slide's own useCustomBackground prop
|
|
37
|
+
return slide.useCustomBackground === true && !!slide.backgroundColor;
|
|
38
|
+
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Onboarding Background Component
|
|
3
|
-
* Handles rendering of video, image or
|
|
3
|
+
* Handles rendering of video, image or solid backgrounds
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import React from "react";
|
|
7
7
|
import { View, StyleSheet } from "react-native";
|
|
8
|
-
|
|
8
|
+
|
|
9
9
|
import { Image } from "expo-image";
|
|
10
10
|
import type { OnboardingSlide } from "../../domain/entities/OnboardingSlide";
|
|
11
11
|
import { BackgroundVideo } from "./BackgroundVideo";
|
|
@@ -13,15 +13,15 @@ import { BackgroundImageCollage } from "./BackgroundImageCollage";
|
|
|
13
13
|
|
|
14
14
|
interface OnboardingBackgroundProps {
|
|
15
15
|
currentSlide: OnboardingSlide | undefined;
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
useCustomBackground: boolean;
|
|
17
|
+
showOverlay: boolean;
|
|
18
18
|
overlayOpacity: number;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
export const OnboardingBackground: React.FC<OnboardingBackgroundProps> = ({
|
|
22
22
|
currentSlide,
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
useCustomBackground,
|
|
24
|
+
showOverlay,
|
|
25
25
|
overlayOpacity,
|
|
26
26
|
}) => {
|
|
27
27
|
if (!currentSlide) return null;
|
|
@@ -59,13 +59,13 @@ export const OnboardingBackground: React.FC<OnboardingBackgroundProps> = ({
|
|
|
59
59
|
);
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
if (
|
|
62
|
+
if (useCustomBackground && currentSlide.backgroundColor) {
|
|
63
63
|
return (
|
|
64
|
-
<
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
64
|
+
<View
|
|
65
|
+
style={[
|
|
66
|
+
StyleSheet.absoluteFill,
|
|
67
|
+
{ backgroundColor: currentSlide.backgroundColor }
|
|
68
|
+
]}
|
|
69
69
|
/>
|
|
70
70
|
);
|
|
71
71
|
}
|
|
@@ -80,7 +80,7 @@ export const OnboardingBackground: React.FC<OnboardingBackgroundProps> = ({
|
|
|
80
80
|
style={[
|
|
81
81
|
StyleSheet.absoluteFill,
|
|
82
82
|
{
|
|
83
|
-
backgroundColor:
|
|
83
|
+
backgroundColor: showOverlay
|
|
84
84
|
? `rgba(0,0,0,${overlayOpacity})`
|
|
85
85
|
: "transparent",
|
|
86
86
|
},
|
|
@@ -16,7 +16,7 @@ import type { OnboardingScreenContentProps } from "../types/OnboardingProps";
|
|
|
16
16
|
|
|
17
17
|
export const OnboardingScreenContent = ({
|
|
18
18
|
containerStyle,
|
|
19
|
-
|
|
19
|
+
useCustomBackground,
|
|
20
20
|
currentSlide,
|
|
21
21
|
isFirstSlide,
|
|
22
22
|
isLastSlide,
|
|
@@ -57,7 +57,7 @@ export const OnboardingScreenContent = ({
|
|
|
57
57
|
!!currentSlide?.backgroundVideo ||
|
|
58
58
|
(!!currentSlide?.backgroundImages && currentSlide.backgroundImages.length > 0);
|
|
59
59
|
const overlayOpacity = currentSlide?.overlayOpacity ?? 0.5;
|
|
60
|
-
const
|
|
60
|
+
const showOverlay = useCustomBackground || hasMedia;
|
|
61
61
|
|
|
62
62
|
return (
|
|
63
63
|
<View
|
|
@@ -66,7 +66,7 @@ export const OnboardingScreenContent = ({
|
|
|
66
66
|
>
|
|
67
67
|
<StatusBar
|
|
68
68
|
barStyle={
|
|
69
|
-
themeMode === "dark" ||
|
|
69
|
+
themeMode === "dark" || showOverlay
|
|
70
70
|
? "light-content"
|
|
71
71
|
: "dark-content"
|
|
72
72
|
}
|
|
@@ -74,8 +74,8 @@ export const OnboardingScreenContent = ({
|
|
|
74
74
|
|
|
75
75
|
<OnboardingBackground
|
|
76
76
|
currentSlide={currentSlide}
|
|
77
|
-
|
|
78
|
-
|
|
77
|
+
useCustomBackground={useCustomBackground}
|
|
78
|
+
showOverlay={showOverlay}
|
|
79
79
|
overlayOpacity={overlayOpacity}
|
|
80
80
|
/>
|
|
81
81
|
|
|
@@ -8,7 +8,7 @@ import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
|
8
8
|
import { useAppDesignTokens } from "@umituz/react-native-design-system";
|
|
9
9
|
|
|
10
10
|
export interface UseOnboardingContainerStyleProps {
|
|
11
|
-
|
|
11
|
+
useCustomBackground: boolean;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
export interface UseOnboardingContainerStyleReturn {
|
|
@@ -16,7 +16,7 @@ export interface UseOnboardingContainerStyleReturn {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
export function useOnboardingContainerStyle({
|
|
19
|
-
|
|
19
|
+
useCustomBackground,
|
|
20
20
|
}: UseOnboardingContainerStyleProps): UseOnboardingContainerStyleReturn {
|
|
21
21
|
const insets = useSafeAreaInsets();
|
|
22
22
|
const tokens = useAppDesignTokens();
|
|
@@ -25,10 +25,10 @@ export function useOnboardingContainerStyle({
|
|
|
25
25
|
() => [
|
|
26
26
|
{
|
|
27
27
|
paddingTop: insets.top,
|
|
28
|
-
backgroundColor:
|
|
28
|
+
backgroundColor: useCustomBackground ? "transparent" : tokens.colors.backgroundPrimary,
|
|
29
29
|
},
|
|
30
30
|
],
|
|
31
|
-
[insets.top,
|
|
31
|
+
[insets.top, useCustomBackground, tokens.colors.backgroundPrimary],
|
|
32
32
|
);
|
|
33
33
|
|
|
34
34
|
return {
|
|
@@ -12,14 +12,14 @@ import { useOnboardingContainerStyle } from "./useOnboardingContainerStyle";
|
|
|
12
12
|
import { useOnboardingScreenHandlers } from "./useOnboardingScreenHandlers";
|
|
13
13
|
import { SlideManager } from "../../infrastructure/services/SlideManager";
|
|
14
14
|
import { ValidationManager } from "../../infrastructure/services/ValidationManager";
|
|
15
|
-
import {
|
|
15
|
+
import { shouldUseCustomBackground } from "../../infrastructure/utils/backgroundUtils";
|
|
16
16
|
|
|
17
17
|
export interface UseOnboardingScreenStateProps {
|
|
18
18
|
slides: OnboardingSlide[] | undefined;
|
|
19
19
|
storageKey?: string;
|
|
20
20
|
onComplete?: () => void | Promise<void>;
|
|
21
21
|
onSkip?: () => void | Promise<void>;
|
|
22
|
-
|
|
22
|
+
globalUseCustomBackground?: boolean;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
export interface UseOnboardingScreenStateReturn {
|
|
@@ -30,7 +30,7 @@ export interface UseOnboardingScreenStateReturn {
|
|
|
30
30
|
isLastSlide: boolean;
|
|
31
31
|
currentAnswer: unknown;
|
|
32
32
|
isAnswerValid: boolean;
|
|
33
|
-
|
|
33
|
+
useCustomBackground: boolean;
|
|
34
34
|
containerStyle: unknown;
|
|
35
35
|
handleNext: () => Promise<void>;
|
|
36
36
|
handlePrevious: () => void;
|
|
@@ -43,7 +43,7 @@ export function useOnboardingScreenState({
|
|
|
43
43
|
storageKey,
|
|
44
44
|
onComplete,
|
|
45
45
|
onSkip,
|
|
46
|
-
|
|
46
|
+
globalUseCustomBackground = false,
|
|
47
47
|
}: UseOnboardingScreenStateProps): UseOnboardingScreenStateReturn {
|
|
48
48
|
const onboardingStore = useOnboarding();
|
|
49
49
|
|
|
@@ -106,7 +106,7 @@ export function useOnboardingScreenState({
|
|
|
106
106
|
}
|
|
107
107
|
);
|
|
108
108
|
|
|
109
|
-
const
|
|
109
|
+
const useCustomBackground = shouldUseCustomBackground(currentSlide, globalUseCustomBackground);
|
|
110
110
|
|
|
111
111
|
const isAnswerValid = useMemo(() => {
|
|
112
112
|
if (!currentSlide?.question) {
|
|
@@ -118,7 +118,7 @@ export function useOnboardingScreenState({
|
|
|
118
118
|
);
|
|
119
119
|
}, [currentSlide, currentAnswer]);
|
|
120
120
|
|
|
121
|
-
const { containerStyle } = useOnboardingContainerStyle({
|
|
121
|
+
const { containerStyle } = useOnboardingContainerStyle({ useCustomBackground });
|
|
122
122
|
|
|
123
123
|
useEffect(() => {
|
|
124
124
|
return () => {
|
|
@@ -136,7 +136,7 @@ export function useOnboardingScreenState({
|
|
|
136
136
|
isLastSlide,
|
|
137
137
|
currentAnswer,
|
|
138
138
|
isAnswerValid,
|
|
139
|
-
|
|
139
|
+
useCustomBackground,
|
|
140
140
|
containerStyle,
|
|
141
141
|
handleNext,
|
|
142
142
|
handlePrevious,
|
|
@@ -16,23 +16,23 @@ const OnboardingScope = createContext<OnboardingProviderValue | undefined>(undef
|
|
|
16
16
|
|
|
17
17
|
export interface OnboardingProviderProps {
|
|
18
18
|
children: React.ReactNode;
|
|
19
|
-
|
|
19
|
+
useCustomBackground: boolean;
|
|
20
20
|
colors: OnboardingColors;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
export const OnboardingProvider = ({
|
|
24
24
|
children,
|
|
25
|
-
|
|
25
|
+
useCustomBackground,
|
|
26
26
|
colors,
|
|
27
27
|
}: OnboardingProviderProps) => {
|
|
28
28
|
const value = useMemo(
|
|
29
29
|
() => ({
|
|
30
30
|
theme: {
|
|
31
31
|
colors,
|
|
32
|
-
|
|
32
|
+
useCustomBackground,
|
|
33
33
|
},
|
|
34
34
|
}),
|
|
35
|
-
[colors,
|
|
35
|
+
[colors, useCustomBackground]
|
|
36
36
|
);
|
|
37
37
|
|
|
38
38
|
return (
|
|
@@ -80,7 +80,7 @@ export const OnboardingScreen = ({
|
|
|
80
80
|
renderSlide,
|
|
81
81
|
onUpgrade,
|
|
82
82
|
showPaywallOnComplete = false,
|
|
83
|
-
|
|
83
|
+
useCustomBackground: globalUseCustomBackground = false,
|
|
84
84
|
themeVariant = "default",
|
|
85
85
|
themeColors: providedThemeColors,
|
|
86
86
|
}: OnboardingScreenProps) => {
|
|
@@ -121,7 +121,7 @@ export const OnboardingScreen = ({
|
|
|
121
121
|
isLastSlide,
|
|
122
122
|
currentAnswer,
|
|
123
123
|
isAnswerValid,
|
|
124
|
-
|
|
124
|
+
useCustomBackground,
|
|
125
125
|
containerStyle,
|
|
126
126
|
handleNext,
|
|
127
127
|
handlePrevious,
|
|
@@ -132,7 +132,7 @@ export const OnboardingScreen = ({
|
|
|
132
132
|
storageKey,
|
|
133
133
|
onComplete,
|
|
134
134
|
onSkip,
|
|
135
|
-
|
|
135
|
+
globalUseCustomBackground,
|
|
136
136
|
});
|
|
137
137
|
|
|
138
138
|
if (__DEV__) {
|
|
@@ -148,10 +148,10 @@ export const OnboardingScreen = ({
|
|
|
148
148
|
}
|
|
149
149
|
|
|
150
150
|
return (
|
|
151
|
-
<OnboardingProvider
|
|
151
|
+
<OnboardingProvider useCustomBackground={useCustomBackground} colors={themeColors}>
|
|
152
152
|
<OnboardingScreenContent
|
|
153
153
|
containerStyle={[styles.container, containerStyle]}
|
|
154
|
-
|
|
154
|
+
useCustomBackground={useCustomBackground}
|
|
155
155
|
currentSlide={currentSlide}
|
|
156
156
|
isFirstSlide={isFirstSlide}
|
|
157
157
|
isLastSlide={isLastSlide}
|
|
@@ -6,7 +6,7 @@ import type { OnboardingSlide } from "../../domain/entities/OnboardingSlide";
|
|
|
6
6
|
|
|
7
7
|
export interface OnboardingScreenContentProps {
|
|
8
8
|
containerStyle?: any;
|
|
9
|
-
|
|
9
|
+
useCustomBackground: boolean;
|
|
10
10
|
currentSlide: OnboardingSlide | undefined;
|
|
11
11
|
isFirstSlide: boolean;
|
|
12
12
|
isLastSlide: boolean;
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Gradient Utilities
|
|
3
|
-
*
|
|
4
|
-
* Utility functions for gradient-related operations
|
|
5
|
-
* Follows Single Responsibility Principle
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import type { OnboardingSlide } from "../../domain/entities/OnboardingSlide";
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Check if slide should use gradient background
|
|
12
|
-
* @param slide - The slide to check
|
|
13
|
-
* @param globalUseGradient - Global useGradient option from OnboardingOptions
|
|
14
|
-
* @returns true if gradient should be used, false otherwise
|
|
15
|
-
*/
|
|
16
|
-
export function shouldUseGradient(
|
|
17
|
-
slide: OnboardingSlide | undefined,
|
|
18
|
-
globalUseGradient?: boolean
|
|
19
|
-
): boolean {
|
|
20
|
-
if (!slide) {
|
|
21
|
-
return false;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// If there is background media, we always treat it as "dark mode" for accessibility (white text)
|
|
25
|
-
if (slide.backgroundImage || slide.backgroundVideo) {
|
|
26
|
-
return true;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// If global useGradient is true, use gradient if slide has gradient defined
|
|
30
|
-
if (globalUseGradient === true) {
|
|
31
|
-
return !!slide.gradient && slide.gradient.length > 0;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// Otherwise, check slide's own useGradient prop
|
|
35
|
-
return (
|
|
36
|
-
slide.useGradient === true &&
|
|
37
|
-
!!slide.gradient &&
|
|
38
|
-
slide.gradient.length > 0
|
|
39
|
-
);
|
|
40
|
-
}
|
|
41
|
-
|