@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-onboarding",
3
- "version": "3.6.23",
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 gradient background for all slides (default: false)
91
- * When true, all slides will use gradient backgrounds if available
90
+ * Use custom background for all slides (default: false)
91
+ * When true, all slides will use custom backgrounds if available
92
92
  */
93
- useGradient?: boolean;
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
- * Gradient colors for the slide background (optional)
66
- * [startColor, endColor] or [color1, color2, color3] for multi-stop gradients
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
- gradient?: string[];
68
+ backgroundColor?: string;
70
69
 
71
70
  /**
72
- * Use gradient background instead of theme colors (default: false)
73
- * If true and gradient is provided, gradient will be used
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
- useGradient?: boolean;
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 gradient backgrounds
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
- import { LinearGradient } from "expo-linear-gradient";
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
- useGradient: boolean;
17
- effectivelyUseGradient: boolean;
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
- useGradient,
24
- effectivelyUseGradient,
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 (useGradient && currentSlide.gradient) {
62
+ if (useCustomBackground && currentSlide.backgroundColor) {
63
63
  return (
64
- <LinearGradient
65
- colors={currentSlide.gradient as [string, string, ...string[]]}
66
- start={{ x: 0, y: 0 }}
67
- end={{ x: 1, y: 1 }}
68
- style={StyleSheet.absoluteFill}
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: effectivelyUseGradient
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
- useGradient,
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 effectivelyUseGradient = useGradient || hasMedia;
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" || effectivelyUseGradient
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
- useGradient={useGradient}
78
- effectivelyUseGradient={effectivelyUseGradient}
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
- useGradient: boolean;
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
- useGradient,
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: useGradient ? "transparent" : tokens.colors.backgroundPrimary,
28
+ backgroundColor: useCustomBackground ? "transparent" : tokens.colors.backgroundPrimary,
29
29
  },
30
30
  ],
31
- [insets.top, useGradient, tokens.colors.backgroundPrimary],
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 { shouldUseGradient } from "../../infrastructure/utils/gradientUtils";
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
- globalUseGradient?: boolean;
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
- useGradient: boolean;
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
- globalUseGradient = false,
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 useGradient = shouldUseGradient(currentSlide, globalUseGradient);
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({ useGradient });
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
- useGradient,
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
- useGradient: boolean;
19
+ useCustomBackground: boolean;
20
20
  colors: OnboardingColors;
21
21
  }
22
22
 
23
23
  export const OnboardingProvider = ({
24
24
  children,
25
- useGradient,
25
+ useCustomBackground,
26
26
  colors,
27
27
  }: OnboardingProviderProps) => {
28
28
  const value = useMemo(
29
29
  () => ({
30
30
  theme: {
31
31
  colors,
32
- useGradient,
32
+ useCustomBackground,
33
33
  },
34
34
  }),
35
- [colors, useGradient]
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
- useGradient: globalUseGradient = false,
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
- useGradient,
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
- globalUseGradient,
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 useGradient={useGradient} colors={themeColors}>
151
+ <OnboardingProvider useCustomBackground={useCustomBackground} colors={themeColors}>
152
152
  <OnboardingScreenContent
153
153
  containerStyle={[styles.container, containerStyle]}
154
- useGradient={useGradient}
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
- useGradient: boolean;
9
+ useCustomBackground: boolean;
10
10
  currentSlide: OnboardingSlide | undefined;
11
11
  isFirstSlide: boolean;
12
12
  isLastSlide: boolean;
@@ -23,5 +23,5 @@ export interface OnboardingColors {
23
23
 
24
24
  export interface OnboardingTheme {
25
25
  colors: OnboardingColors;
26
- useGradient: boolean;
26
+ useCustomBackground: boolean;
27
27
  }
@@ -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
-