Skip to content

Commit fd54c92

Browse files
feat: add loading and loader props to GooglePayButton
1 parent 2bf73b7 commit fd54c92

3 files changed

Lines changed: 90 additions & 7 deletions

File tree

src/GooglePayButton.tsx

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1-
import { StyleSheet, Pressable } from 'react-native';
1+
import { StyleSheet, Pressable, View } from 'react-native';
22
import type { ViewProps, StyleProp, ViewStyle } from 'react-native';
3+
import type { ReactNode } from 'react';
34
import GooglePayButtonComponent from './specs/NativeGooglePayButtonComponent';
45
import GooglePayButtonConstantsModule from './specs/NativeGooglePayButtonConstantsModule';
5-
import type { GooglePayPaymentMethod } from './specs/NativeGooglePayButtonComponent'
6+
import type { GooglePayPaymentMethod } from './specs/NativeGooglePayButtonComponent';
7+
import { Loader } from './Loader';
8+
9+
const GooglePayButtonConstants =
10+
GooglePayButtonConstantsModule?.loadConstants();
611

712
export interface Props extends ViewProps {
813
allowedPaymentMethods: GooglePayPaymentMethod[];
@@ -12,6 +17,8 @@ export interface Props extends ViewProps {
1217
onPress: () => void;
1318
disabled: boolean;
1419
style: StyleProp<ViewStyle>;
20+
loading?: boolean;
21+
loader?: ReactNode;
1522
}
1623

1724
const GooglePayButton = ({
@@ -22,13 +29,15 @@ const GooglePayButton = ({
2229
type,
2330
radius,
2431
style,
32+
loading,
33+
loader,
2534
}: Props) => {
2635
return (
2736
<Pressable
2837
onPress={onPress}
29-
disabled={disabled}
38+
disabled={disabled || loading}
3039
style={[
31-
disabled ? styles.disabled : styles.enabled,
40+
disabled || loading ? styles.disabled : styles.enabled,
3241
styles.overridable,
3342
style,
3443
styles.fixed,
@@ -40,8 +49,13 @@ const GooglePayButton = ({
4049
type={type}
4150
theme={theme}
4251
radius={radius}
43-
style={[styles.button, styles.nobg]}
52+
style={[styles.button, styles.nobg, loading && styles.hidden]}
4453
/>
54+
{loading && (
55+
<View style={styles.loaderContainer}>
56+
{loader || <Loader theme={theme} />}
57+
</View>
58+
)}
4559
</Pressable>
4660
);
4761
};
@@ -67,8 +81,14 @@ const styles = StyleSheet.create({
6781
nobg: {
6882
backgroundColor: 'rgba(0, 0, 0, 0)',
6983
},
84+
hidden: {
85+
opacity: 0,
86+
},
87+
loaderContainer: {
88+
...StyleSheet.absoluteFillObject,
89+
justifyContent: 'center',
90+
alignItems: 'center',
91+
},
7092
});
7193

72-
const GooglePayButtonConstants = GooglePayButtonConstantsModule?.loadConstants();
73-
7494
export { GooglePayButton, GooglePayButtonConstants };

src/Loader.tsx

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import { useEffect, useRef } from 'react';
2+
import { StyleSheet, Animated, Easing } from 'react-native';
3+
import type { ViewStyle, StyleProp } from 'react-native';
4+
5+
export interface LoaderProps {
6+
theme?: number;
7+
color?: string;
8+
style?: StyleProp<ViewStyle>;
9+
}
10+
11+
/**
12+
* A custom Google Pay style loading spinner.
13+
* Features a smooth rotating arc.
14+
*/
15+
export const Loader = ({ theme, color, style }: LoaderProps) => {
16+
const spinValue = useRef(new Animated.Value(0)).current;
17+
18+
useEffect(() => {
19+
const animation = Animated.loop(
20+
Animated.timing(spinValue, {
21+
toValue: 1,
22+
duration: 800,
23+
easing: Easing.linear,
24+
useNativeDriver: true,
25+
})
26+
);
27+
animation.start();
28+
return () => animation.stop();
29+
}, [spinValue]);
30+
31+
const spin = spinValue.interpolate({
32+
inputRange: [0, 1],
33+
outputRange: ['0deg', '360deg'],
34+
});
35+
36+
// Default color logic based on theme if no explicit color provided
37+
// theme === 1 is usually Dark (GooglePayButtonConstants.Themes.Dark)
38+
const finalColor = color || (theme === 1 ? 'white' : 'black');
39+
40+
return (
41+
<Animated.View
42+
style={[
43+
styles.loader,
44+
{
45+
borderColor: finalColor,
46+
transform: [{ rotate: spin }],
47+
},
48+
style,
49+
]}
50+
/>
51+
);
52+
};
53+
54+
const styles = StyleSheet.create({
55+
loader: {
56+
width: 24,
57+
height: 24,
58+
borderRadius: 12,
59+
borderWidth: 2,
60+
borderTopColor: 'transparent',
61+
},
62+
});

src/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export * from './PaymentRequest';
22
export { GooglePayButton, GooglePayButtonConstants } from './GooglePayButton';
3+
export { Loader } from './Loader';
34
export type * from './specs/NativeMakePaymentModule';
45
export * from './constants';

0 commit comments

Comments
 (0)