@umituz/react-native-splash 1.10.1 → 1.12.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 +7 -5
- package/src/domain/entities/SplashOptions.ts +10 -48
- package/src/index.ts +0 -1
- package/src/presentation/components/SplashScreen.tsx +68 -120
- package/src/presentation/components/SplashDecorations.tsx +0 -56
- package/src/presentation/components/SplashErrorBoundary.tsx +0 -58
- package/src/presentation/components/SplashLoading.tsx +0 -66
- package/src/presentation/components/SplashLogo.tsx +0 -70
- package/src/presentation/components/SplashTypography.tsx +0 -66
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-splash",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.12.0",
|
|
4
4
|
"description": "Generic splash screen for React Native apps with animations, gradients, and customizable branding. SOLID, DRY, KISS principles applied.",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "./src/index.ts",
|
|
@@ -28,17 +28,19 @@
|
|
|
28
28
|
"url": "https://github.com/umituz/react-native-splash"
|
|
29
29
|
},
|
|
30
30
|
"peerDependencies": {
|
|
31
|
-
"@umituz/react-native-icons": "latest",
|
|
32
|
-
"@umituz/react-native-design-system-atoms": "latest",
|
|
33
|
-
"@umituz/react-native-design-system-theme": "latest",
|
|
34
|
-
"@umituz/react-native-localization": "latest",
|
|
35
31
|
"expo-linear-gradient": ">=14.0.0",
|
|
36
32
|
"react": ">=18.2.0",
|
|
37
33
|
"react-native": ">=0.74.0",
|
|
38
34
|
"react-native-safe-area-context": ">=4.0.0"
|
|
39
35
|
},
|
|
40
36
|
"devDependencies": {
|
|
37
|
+
"@types/node": "^20.0.0",
|
|
41
38
|
"@types/react": "~19.1.0",
|
|
39
|
+
"@types/react-native": "^0.73.0",
|
|
40
|
+
"expo-linear-gradient": "^14.0.0",
|
|
41
|
+
"react": "^19.0.0",
|
|
42
|
+
"react-native": "^0.76.0",
|
|
43
|
+
"react-native-safe-area-context": "^5.0.0",
|
|
42
44
|
"typescript": "~5.9.2"
|
|
43
45
|
},
|
|
44
46
|
"publishConfig": {
|
|
@@ -1,74 +1,36 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Splash Options
|
|
3
|
-
*
|
|
4
|
-
* Configuration options for splash screen
|
|
2
|
+
* Splash Options - Minimal Configuration
|
|
5
3
|
*/
|
|
6
4
|
|
|
7
5
|
import { ReactNode } from "react";
|
|
8
6
|
|
|
9
|
-
/**
|
|
10
|
-
* Splash Options
|
|
11
|
-
* Customize the splash screen experience
|
|
12
|
-
*/
|
|
13
7
|
export interface SplashOptions {
|
|
14
|
-
/**
|
|
15
|
-
* App name to display
|
|
16
|
-
*/
|
|
8
|
+
/** App name to display */
|
|
17
9
|
appName?: string;
|
|
18
10
|
|
|
19
|
-
/**
|
|
20
|
-
* Tagline or subtitle
|
|
21
|
-
*/
|
|
11
|
+
/** Tagline or subtitle */
|
|
22
12
|
tagline?: string;
|
|
23
13
|
|
|
24
|
-
/**
|
|
25
|
-
* Logo/icon component or name
|
|
26
|
-
*/
|
|
27
|
-
logo?: ReactNode | string;
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Background color (will generate gradient automatically)
|
|
31
|
-
*/
|
|
14
|
+
/** Background color */
|
|
32
15
|
backgroundColor?: string;
|
|
33
16
|
|
|
34
|
-
/**
|
|
35
|
-
* Custom gradient colors (overrides backgroundColor)
|
|
36
|
-
* If provided, backgroundColor is ignored
|
|
37
|
-
*/
|
|
17
|
+
/** Custom gradient colors (overrides backgroundColor) */
|
|
38
18
|
gradientColors?: readonly string[];
|
|
39
19
|
|
|
40
|
-
/**
|
|
41
|
-
* Loading text
|
|
42
|
-
*/
|
|
20
|
+
/** Loading text */
|
|
43
21
|
loadingText?: string;
|
|
44
22
|
|
|
45
|
-
/**
|
|
46
|
-
* Show loading indicator (default: true)
|
|
47
|
-
*/
|
|
23
|
+
/** Show loading indicator (default: true) */
|
|
48
24
|
showLoading?: boolean;
|
|
49
25
|
|
|
50
|
-
/**
|
|
51
|
-
* Minimum display time in milliseconds (default: 1500)
|
|
52
|
-
*/
|
|
26
|
+
/** Minimum display time in ms (default: 1500) */
|
|
53
27
|
minimumDisplayTime?: number;
|
|
54
28
|
|
|
55
|
-
/**
|
|
56
|
-
* Callback when splash is ready to hide
|
|
57
|
-
*/
|
|
29
|
+
/** Callback when splash is ready */
|
|
58
30
|
onReady?: () => void | Promise<void>;
|
|
59
31
|
|
|
60
|
-
/**
|
|
61
|
-
* Custom render functions
|
|
62
|
-
*/
|
|
32
|
+
/** Custom render functions */
|
|
63
33
|
renderLogo?: () => ReactNode;
|
|
64
34
|
renderContent?: () => ReactNode;
|
|
65
35
|
renderFooter?: () => ReactNode;
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Custom colors for dynamic theming
|
|
69
|
-
*/
|
|
70
|
-
textColor?: string;
|
|
71
|
-
iconColor?: string;
|
|
72
|
-
decorationColor?: string;
|
|
73
36
|
}
|
|
74
|
-
|
package/src/index.ts
CHANGED
|
@@ -26,6 +26,5 @@ export type { SplashOptions } from "./domain/entities/SplashOptions";
|
|
|
26
26
|
// =============================================================================
|
|
27
27
|
|
|
28
28
|
export { SplashScreen, type SplashScreenProps } from "./presentation/components/SplashScreen";
|
|
29
|
-
export { SplashErrorBoundary } from "./presentation/components/SplashErrorBoundary";
|
|
30
29
|
export { useSplash } from "./presentation/hooks/useSplash";
|
|
31
30
|
|
|
@@ -1,38 +1,30 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Splash Screen Component
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
|
+
* ULTRA MINIMAL - No external dependencies
|
|
5
|
+
* Only basic React Native + expo-linear-gradient + safe-area
|
|
4
6
|
*/
|
|
5
7
|
|
|
6
|
-
import React, { useEffect, useRef } from "react";
|
|
7
|
-
import { View, StyleSheet } from "react-native";
|
|
8
|
+
import React, { useEffect, useRef, useCallback } from "react";
|
|
9
|
+
import { View, Text, StyleSheet, ActivityIndicator } from "react-native";
|
|
8
10
|
import { LinearGradient } from "expo-linear-gradient";
|
|
9
11
|
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
10
|
-
import { useLocalization } from "@umituz/react-native-localization";
|
|
11
|
-
import { useAppDesignTokens } from "@umituz/react-native-design-system-theme";
|
|
12
|
-
import { SplashLogo } from "./SplashLogo";
|
|
13
|
-
import { SplashTypography } from "./SplashTypography";
|
|
14
|
-
import { SplashLoading } from "./SplashLoading";
|
|
15
|
-
import { SplashDecorations } from "./SplashDecorations";
|
|
16
|
-
import { SplashErrorBoundary } from "./SplashErrorBoundary";
|
|
17
12
|
import type { SplashOptions } from "../../domain/entities/SplashOptions";
|
|
18
13
|
|
|
19
14
|
export interface SplashScreenProps extends SplashOptions {
|
|
20
15
|
visible?: boolean;
|
|
21
16
|
textColor?: string;
|
|
22
|
-
iconColor?: string;
|
|
23
|
-
decorationColor?: string;
|
|
24
17
|
}
|
|
25
18
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
19
|
+
const DEFAULT_BG = "#6366F1";
|
|
20
|
+
const DEFAULT_TEXT = "#FFFFFF";
|
|
21
|
+
|
|
29
22
|
export const SplashScreen: React.FC<SplashScreenProps> = ({
|
|
30
|
-
appName,
|
|
31
|
-
tagline,
|
|
32
|
-
|
|
33
|
-
backgroundColor,
|
|
23
|
+
appName = "",
|
|
24
|
+
tagline = "",
|
|
25
|
+
backgroundColor = DEFAULT_BG,
|
|
34
26
|
gradientColors,
|
|
35
|
-
loadingText,
|
|
27
|
+
loadingText = "",
|
|
36
28
|
showLoading = true,
|
|
37
29
|
minimumDisplayTime = 1500,
|
|
38
30
|
onReady,
|
|
@@ -40,136 +32,92 @@ export const SplashScreen: React.FC<SplashScreenProps> = ({
|
|
|
40
32
|
renderContent,
|
|
41
33
|
renderFooter,
|
|
42
34
|
visible = true,
|
|
43
|
-
textColor,
|
|
44
|
-
iconColor,
|
|
45
|
-
decorationColor,
|
|
35
|
+
textColor = DEFAULT_TEXT,
|
|
46
36
|
}) => {
|
|
47
37
|
const insets = useSafeAreaInsets();
|
|
48
|
-
const
|
|
49
|
-
const
|
|
38
|
+
const timerRef = useRef<NodeJS.Timeout | null>(null);
|
|
39
|
+
const onReadyRef = useRef(onReady);
|
|
40
|
+
const hasCalledOnReady = useRef(false);
|
|
50
41
|
|
|
51
|
-
|
|
42
|
+
// Keep onReady ref updated but don't trigger re-render
|
|
43
|
+
useEffect(() => {
|
|
44
|
+
onReadyRef.current = onReady;
|
|
45
|
+
}, [onReady]);
|
|
52
46
|
|
|
53
|
-
|
|
47
|
+
// Stable callback that uses ref
|
|
48
|
+
const handleReady = useCallback(() => {
|
|
49
|
+
if (hasCalledOnReady.current) return;
|
|
50
|
+
hasCalledOnReady.current = true;
|
|
51
|
+
onReadyRef.current?.();
|
|
52
|
+
}, []);
|
|
54
53
|
|
|
55
54
|
useEffect(() => {
|
|
56
55
|
if (!visible) return;
|
|
57
56
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}, minimumDisplayTime);
|
|
57
|
+
// Reset when becoming visible again
|
|
58
|
+
hasCalledOnReady.current = false;
|
|
59
|
+
|
|
60
|
+
timerRef.current = setTimeout(handleReady, minimumDisplayTime);
|
|
63
61
|
|
|
64
62
|
return () => {
|
|
65
|
-
if (timerRef.current)
|
|
66
|
-
clearTimeout(timerRef.current);
|
|
67
|
-
}
|
|
63
|
+
if (timerRef.current) clearTimeout(timerRef.current);
|
|
68
64
|
};
|
|
69
|
-
}, [visible, minimumDisplayTime,
|
|
65
|
+
}, [visible, minimumDisplayTime, handleReady]);
|
|
70
66
|
|
|
71
67
|
if (!visible) return null;
|
|
72
68
|
|
|
73
|
-
const displayAppName = appName || t("branding.appName", "");
|
|
74
|
-
const displayTagline = tagline || t("branding.tagline", "");
|
|
75
|
-
const displayLoadingText = loadingText || t("general.loading", "");
|
|
76
|
-
|
|
77
|
-
// Use gradientColors if provided, otherwise use backgroundColor as solid color
|
|
78
|
-
const finalBackgroundColor = gradientColors
|
|
79
|
-
? undefined
|
|
80
|
-
: backgroundColor || tokens.colors.primary;
|
|
81
|
-
|
|
82
|
-
// Use LinearGradient only if gradientColors provided (length > 1)
|
|
83
69
|
const hasGradient = gradientColors && gradientColors.length > 1;
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
? (gradientColors.length >= 2
|
|
88
|
-
? (gradientColors as [string, string, ...string[]])
|
|
89
|
-
: [gradientColors[0], gradientColors[0] || finalBackgroundColor!])
|
|
90
|
-
: [finalBackgroundColor!, finalBackgroundColor!];
|
|
70
|
+
const colors: [string, string, ...string[]] = hasGradient
|
|
71
|
+
? (gradientColors as [string, string, ...string[]])
|
|
72
|
+
: [backgroundColor, backgroundColor];
|
|
91
73
|
|
|
92
74
|
const content = (
|
|
93
|
-
|
|
94
|
-
<
|
|
95
|
-
|
|
96
|
-
<View style={styles.content}>
|
|
97
|
-
{renderLogo ? (
|
|
98
|
-
renderLogo()
|
|
99
|
-
) : (
|
|
100
|
-
<SplashLogo logo={logo} iconColor={iconColor} />
|
|
101
|
-
)}
|
|
75
|
+
<View style={[styles.inner, { paddingTop: insets.top, paddingBottom: insets.bottom }]}>
|
|
76
|
+
<View style={styles.center}>
|
|
77
|
+
{renderLogo ? renderLogo() : <View style={styles.logo} />}
|
|
102
78
|
|
|
103
79
|
{renderContent ? (
|
|
104
80
|
renderContent()
|
|
105
81
|
) : (
|
|
106
|
-
|
|
107
|
-
appName={
|
|
108
|
-
tagline={
|
|
109
|
-
|
|
110
|
-
textColor={textColor}
|
|
111
|
-
/>
|
|
82
|
+
<>
|
|
83
|
+
{appName ? <Text style={[styles.title, { color: textColor }]}>{appName}</Text> : null}
|
|
84
|
+
{tagline ? <Text style={[styles.subtitle, { color: textColor }]}>{tagline}</Text> : null}
|
|
85
|
+
</>
|
|
112
86
|
)}
|
|
113
87
|
</View>
|
|
114
88
|
|
|
115
89
|
{showLoading && (
|
|
116
|
-
<
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
textColor={textColor}
|
|
121
|
-
/>
|
|
90
|
+
<View style={styles.loading}>
|
|
91
|
+
<ActivityIndicator color={textColor} />
|
|
92
|
+
{loadingText ? <Text style={[styles.loadingText, { color: textColor }]}>{loadingText}</Text> : null}
|
|
93
|
+
</View>
|
|
122
94
|
)}
|
|
123
95
|
|
|
124
|
-
{renderFooter
|
|
125
|
-
|
|
96
|
+
{renderFooter?.()}
|
|
97
|
+
</View>
|
|
126
98
|
);
|
|
127
99
|
|
|
128
100
|
return (
|
|
129
|
-
<
|
|
130
|
-
|
|
131
|
-
{
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
{content}
|
|
139
|
-
</LinearGradient>
|
|
140
|
-
) : (
|
|
141
|
-
<View
|
|
142
|
-
style={[styles.gradient, { backgroundColor: finalBackgroundColor }]}
|
|
143
|
-
>
|
|
144
|
-
{content}
|
|
145
|
-
</View>
|
|
146
|
-
)}
|
|
147
|
-
</View>
|
|
148
|
-
</SplashErrorBoundary>
|
|
101
|
+
<View style={styles.container}>
|
|
102
|
+
{hasGradient ? (
|
|
103
|
+
<LinearGradient colors={colors} start={{ x: 0, y: 0 }} end={{ x: 1, y: 1 }} style={styles.fill}>
|
|
104
|
+
{content}
|
|
105
|
+
</LinearGradient>
|
|
106
|
+
) : (
|
|
107
|
+
<View style={[styles.fill, { backgroundColor }]}>{content}</View>
|
|
108
|
+
)}
|
|
109
|
+
</View>
|
|
149
110
|
);
|
|
150
111
|
};
|
|
151
112
|
|
|
152
|
-
const
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
paddingBottom: insets.bottom,
|
|
164
|
-
position: "relative",
|
|
165
|
-
overflow: "hidden",
|
|
166
|
-
},
|
|
167
|
-
content: {
|
|
168
|
-
flex: 1,
|
|
169
|
-
alignItems: "center",
|
|
170
|
-
justifyContent: "center",
|
|
171
|
-
paddingHorizontal: spacing.xl,
|
|
172
|
-
zIndex: 1,
|
|
173
|
-
},
|
|
174
|
-
});
|
|
175
|
-
};
|
|
113
|
+
const styles = StyleSheet.create({
|
|
114
|
+
container: { flex: 1 },
|
|
115
|
+
fill: { flex: 1 },
|
|
116
|
+
inner: { flex: 1, justifyContent: "space-between" },
|
|
117
|
+
center: { flex: 1, alignItems: "center", justifyContent: "center", paddingHorizontal: 24 },
|
|
118
|
+
logo: { width: 100, height: 100, borderRadius: 50, backgroundColor: "rgba(255,255,255,0.2)", marginBottom: 24 },
|
|
119
|
+
title: { fontSize: 32, fontWeight: "700", textAlign: "center", marginBottom: 8 },
|
|
120
|
+
subtitle: { fontSize: 16, textAlign: "center", opacity: 0.9 },
|
|
121
|
+
loading: { alignItems: "center", paddingBottom: 48 },
|
|
122
|
+
loadingText: { fontSize: 14, marginTop: 12, opacity: 0.8 },
|
|
123
|
+
});
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Splash Decorations Component
|
|
3
|
-
* Single Responsibility: Render decorative background elements
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import React from "react";
|
|
7
|
-
import { View, StyleSheet } from "react-native";
|
|
8
|
-
|
|
9
|
-
export interface SplashDecorationsProps {
|
|
10
|
-
decorationColor?: string;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export const SplashDecorations: React.FC<SplashDecorationsProps> = ({
|
|
14
|
-
decorationColor = "rgba(255, 255, 255, 0.05)",
|
|
15
|
-
}) => {
|
|
16
|
-
const styles = getStyles(decorationColor);
|
|
17
|
-
|
|
18
|
-
return (
|
|
19
|
-
<>
|
|
20
|
-
<View style={styles.circle1} />
|
|
21
|
-
<View style={styles.circle2} />
|
|
22
|
-
<View style={styles.circle3} />
|
|
23
|
-
</>
|
|
24
|
-
);
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
const getStyles = (decorationColor: string) => StyleSheet.create({
|
|
28
|
-
circle1: {
|
|
29
|
-
position: "absolute",
|
|
30
|
-
width: 300,
|
|
31
|
-
height: 300,
|
|
32
|
-
borderRadius: 150,
|
|
33
|
-
backgroundColor: decorationColor,
|
|
34
|
-
top: -100,
|
|
35
|
-
right: -100,
|
|
36
|
-
},
|
|
37
|
-
circle2: {
|
|
38
|
-
position: "absolute",
|
|
39
|
-
width: 200,
|
|
40
|
-
height: 200,
|
|
41
|
-
borderRadius: 100,
|
|
42
|
-
backgroundColor: decorationColor.replace("0.05", "0.03"),
|
|
43
|
-
bottom: -50,
|
|
44
|
-
left: -50,
|
|
45
|
-
},
|
|
46
|
-
circle3: {
|
|
47
|
-
position: "absolute",
|
|
48
|
-
width: 150,
|
|
49
|
-
height: 150,
|
|
50
|
-
borderRadius: 75,
|
|
51
|
-
backgroundColor: decorationColor.replace("0.05", "0.04"),
|
|
52
|
-
top: "30%",
|
|
53
|
-
right: "10%",
|
|
54
|
-
},
|
|
55
|
-
});
|
|
56
|
-
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Splash Error Boundary
|
|
3
|
-
* Single Responsibility: Handle splash screen errors gracefully
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import React, { Component, ReactNode } from "react";
|
|
7
|
-
import { View, StyleSheet } from "react-native";
|
|
8
|
-
|
|
9
|
-
interface Props {
|
|
10
|
-
children: ReactNode;
|
|
11
|
-
fallback?: ReactNode;
|
|
12
|
-
backgroundColor?: string;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
interface State {
|
|
16
|
-
hasError: boolean;
|
|
17
|
-
error?: Error;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export class SplashErrorBoundary extends Component<Props, State> {
|
|
21
|
-
constructor(props: Props) {
|
|
22
|
-
super(props);
|
|
23
|
-
this.state = { hasError: false };
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
static getDerivedStateFromError(error: Error): State {
|
|
27
|
-
return { hasError: true, error };
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
|
|
31
|
-
if (__DEV__) {
|
|
32
|
-
console.error("Splash Screen Error:", error, errorInfo);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
render() {
|
|
37
|
-
if (this.state.hasError) {
|
|
38
|
-
if (this.props.fallback) {
|
|
39
|
-
return this.props.fallback;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const dynamicStyles = getStyles(this.props.backgroundColor);
|
|
43
|
-
return <View style={dynamicStyles.container} />;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
return this.props.children;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const getStyles = (backgroundColor?: string) =>
|
|
51
|
-
StyleSheet.create({
|
|
52
|
-
container: {
|
|
53
|
-
flex: 1,
|
|
54
|
-
alignItems: "center",
|
|
55
|
-
justifyContent: "center",
|
|
56
|
-
backgroundColor: backgroundColor ?? "transparent",
|
|
57
|
-
},
|
|
58
|
-
});
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Splash Loading Component
|
|
3
|
-
* Single Responsibility: Render splash screen loading indicator
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import React from "react";
|
|
7
|
-
import { View, Text, StyleSheet } from "react-native";
|
|
8
|
-
import type { DesignTokens } from "@umituz/react-native-design-system-theme";
|
|
9
|
-
|
|
10
|
-
export interface SplashLoadingProps {
|
|
11
|
-
loadingText: string;
|
|
12
|
-
tokens: DesignTokens;
|
|
13
|
-
bottomInset: number;
|
|
14
|
-
textColor?: string;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export const SplashLoading: React.FC<SplashLoadingProps> = ({
|
|
18
|
-
loadingText,
|
|
19
|
-
tokens,
|
|
20
|
-
bottomInset,
|
|
21
|
-
textColor = "#FFFFFF",
|
|
22
|
-
}) => {
|
|
23
|
-
const styles = getStyles(tokens, bottomInset, textColor);
|
|
24
|
-
|
|
25
|
-
return (
|
|
26
|
-
<View style={styles.container}>
|
|
27
|
-
<View style={styles.barContainer}>
|
|
28
|
-
<View style={styles.bar} />
|
|
29
|
-
</View>
|
|
30
|
-
<Text style={styles.text}>{loadingText}</Text>
|
|
31
|
-
</View>
|
|
32
|
-
);
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
const getStyles = (tokens: DesignTokens, bottomInset: number, textColor: string) => {
|
|
36
|
-
return StyleSheet.create({
|
|
37
|
-
container: {
|
|
38
|
-
alignItems: "center",
|
|
39
|
-
justifyContent: "center",
|
|
40
|
-
paddingBottom: tokens.spacing.xxxl + bottomInset,
|
|
41
|
-
zIndex: 1,
|
|
42
|
-
},
|
|
43
|
-
barContainer: {
|
|
44
|
-
width: 120,
|
|
45
|
-
height: 4,
|
|
46
|
-
backgroundColor: "rgba(255, 255, 255, 0.2)",
|
|
47
|
-
borderRadius: 2,
|
|
48
|
-
overflow: "hidden",
|
|
49
|
-
marginBottom: tokens.spacing.md,
|
|
50
|
-
},
|
|
51
|
-
bar: {
|
|
52
|
-
width: "60%",
|
|
53
|
-
height: "100%",
|
|
54
|
-
backgroundColor: textColor,
|
|
55
|
-
borderRadius: 2,
|
|
56
|
-
},
|
|
57
|
-
text: {
|
|
58
|
-
fontSize: 13,
|
|
59
|
-
color: textColor,
|
|
60
|
-
opacity: 0.9,
|
|
61
|
-
fontWeight: "500" as const,
|
|
62
|
-
letterSpacing: 0.8,
|
|
63
|
-
},
|
|
64
|
-
});
|
|
65
|
-
};
|
|
66
|
-
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Splash Logo Component
|
|
3
|
-
* Single Responsibility: Render splash screen logo
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import React from "react";
|
|
7
|
-
import { View, StyleSheet } from "react-native";
|
|
8
|
-
import { AtomicIcon } from "@umituz/react-native-design-system-atoms";
|
|
9
|
-
|
|
10
|
-
export interface SplashLogoProps {
|
|
11
|
-
logo?: string | React.ReactNode;
|
|
12
|
-
logoSize?: number;
|
|
13
|
-
glowSize?: number;
|
|
14
|
-
iconColor?: string;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export const SplashLogo: React.FC<SplashLogoProps> = ({
|
|
18
|
-
logo,
|
|
19
|
-
logoSize = 140,
|
|
20
|
-
glowSize = 160,
|
|
21
|
-
iconColor = "#FFFFFF",
|
|
22
|
-
}) => {
|
|
23
|
-
const styles = getStyles(logoSize, glowSize);
|
|
24
|
-
|
|
25
|
-
return (
|
|
26
|
-
<View style={styles.container}>
|
|
27
|
-
<View style={styles.glow} />
|
|
28
|
-
<View style={styles.background}>
|
|
29
|
-
{typeof logo === "string" ? (
|
|
30
|
-
<AtomicIcon name={logo || "sparkles"} size="xxl" customColor={iconColor} />
|
|
31
|
-
) : logo ? (
|
|
32
|
-
logo
|
|
33
|
-
) : (
|
|
34
|
-
<AtomicIcon name="sparkles" size="xxl" customColor={iconColor} />
|
|
35
|
-
)}
|
|
36
|
-
</View>
|
|
37
|
-
</View>
|
|
38
|
-
);
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
const getStyles = (logoSize: number, glowSize: number) => {
|
|
42
|
-
const radius = logoSize / 2;
|
|
43
|
-
const glowRadius = glowSize / 2;
|
|
44
|
-
|
|
45
|
-
return StyleSheet.create({
|
|
46
|
-
container: {
|
|
47
|
-
alignItems: "center",
|
|
48
|
-
justifyContent: "center",
|
|
49
|
-
position: "relative",
|
|
50
|
-
},
|
|
51
|
-
glow: {
|
|
52
|
-
position: "absolute",
|
|
53
|
-
width: glowSize,
|
|
54
|
-
height: glowSize,
|
|
55
|
-
borderRadius: glowRadius,
|
|
56
|
-
backgroundColor: "rgba(255, 255, 255, 0.15)",
|
|
57
|
-
},
|
|
58
|
-
background: {
|
|
59
|
-
width: logoSize,
|
|
60
|
-
height: logoSize,
|
|
61
|
-
borderRadius: radius,
|
|
62
|
-
backgroundColor: "rgba(255, 255, 255, 0.2)",
|
|
63
|
-
alignItems: "center",
|
|
64
|
-
justifyContent: "center",
|
|
65
|
-
borderWidth: 2,
|
|
66
|
-
borderColor: "rgba(255, 255, 255, 0.3)",
|
|
67
|
-
},
|
|
68
|
-
});
|
|
69
|
-
};
|
|
70
|
-
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Splash Typography Component
|
|
3
|
-
* Single Responsibility: Render splash screen typography
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import React from "react";
|
|
7
|
-
import { View, Text, StyleSheet } from "react-native";
|
|
8
|
-
import type { DesignTokens } from "@umituz/react-native-design-system-theme";
|
|
9
|
-
|
|
10
|
-
export interface SplashTypographyProps {
|
|
11
|
-
appName: string;
|
|
12
|
-
tagline?: string;
|
|
13
|
-
tokens: DesignTokens;
|
|
14
|
-
textColor?: string;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export const SplashTypography: React.FC<SplashTypographyProps> = ({
|
|
18
|
-
appName,
|
|
19
|
-
tagline,
|
|
20
|
-
tokens,
|
|
21
|
-
textColor = "#FFFFFF",
|
|
22
|
-
}) => {
|
|
23
|
-
const styles = getStyles(tokens, textColor);
|
|
24
|
-
|
|
25
|
-
return (
|
|
26
|
-
<View style={styles.container}>
|
|
27
|
-
<Text style={styles.appName} numberOfLines={1}>
|
|
28
|
-
{appName}
|
|
29
|
-
</Text>
|
|
30
|
-
{tagline && (
|
|
31
|
-
<Text style={styles.tagline} numberOfLines={2}>
|
|
32
|
-
{tagline}
|
|
33
|
-
</Text>
|
|
34
|
-
)}
|
|
35
|
-
</View>
|
|
36
|
-
);
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
const getStyles = (tokens: DesignTokens, textColor: string) => {
|
|
40
|
-
return StyleSheet.create({
|
|
41
|
-
container: {
|
|
42
|
-
alignItems: "center",
|
|
43
|
-
marginTop: tokens.spacing.xl,
|
|
44
|
-
},
|
|
45
|
-
appName: {
|
|
46
|
-
fontSize: 48,
|
|
47
|
-
fontWeight: "800" as const,
|
|
48
|
-
color: textColor,
|
|
49
|
-
textAlign: "center" as const,
|
|
50
|
-
marginBottom: tokens.spacing.md,
|
|
51
|
-
letterSpacing: -1.2,
|
|
52
|
-
lineHeight: 56,
|
|
53
|
-
},
|
|
54
|
-
tagline: {
|
|
55
|
-
fontSize: 17,
|
|
56
|
-
color: textColor,
|
|
57
|
-
textAlign: "center" as const,
|
|
58
|
-
opacity: 0.95,
|
|
59
|
-
maxWidth: 320,
|
|
60
|
-
lineHeight: 24,
|
|
61
|
-
fontWeight: "500" as const,
|
|
62
|
-
letterSpacing: 0.2,
|
|
63
|
-
},
|
|
64
|
-
});
|
|
65
|
-
};
|
|
66
|
-
|