Modernize confetti
This commit is contained in:
5 files changed
+179
-53
No files matched your search
@@ -81,7 +81,6 @@ history, code and binary blobs related to React Native functionality filtered ou
|
|||||||
- replace [moment](https://momentjs.com/docs/#/-project-status/) (maintenance mode) with
|
- replace [moment](https://momentjs.com/docs/#/-project-status/) (maintenance mode) with
|
||||||
`date-fns`
|
`date-fns`
|
||||||
- replace unmaintained UI packages:
|
- replace unmaintained UI packages:
|
||||||
- `react-native-confetti` (last release 2017, mocked out in tests)
|
|
||||||
- `react-native-simple-radio-button` (react-native-ui-lib already ships RadioButton/RadioGroup)
|
- `react-native-simple-radio-button` (react-native-ui-lib already ships RadioButton/RadioGroup)
|
||||||
- migrate ESLint 8 + airbnb config (both EOL) to ESLint 9 flat config or
|
- migrate ESLint 8 + airbnb config (both EOL) to ESLint 9 flat config or
|
||||||
[eslint-config-expo](https://docs.expo.dev/guides/using-eslint/)
|
[eslint-config-expo](https://docs.expo.dev/guides/using-eslint/)
|
||||||
|
|||||||
+23
-10
@@ -37,16 +37,29 @@ jest.mock('expo-notifications', () => ({
|
|||||||
scheduleNotificationAsync: jest.fn(async () => 'notification-id'),
|
scheduleNotificationAsync: jest.fn(async () => 'notification-id'),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Visual only, and old enough that it fights with the test renderer.
|
// Visual only, and Skia's native canvas isn't available in Jest.
|
||||||
jest.mock('react-native-confetti', () => {
|
jest.mock('react-native-fast-confetti', () => {
|
||||||
const React = require('react');
|
const React = require('react');
|
||||||
return class Confetti extends React.Component {
|
const Confetti = React.forwardRef(function Confetti(props, ref) {
|
||||||
startConfetti() {}
|
React.useImperativeHandle(ref, () => ({
|
||||||
|
restart() {},
|
||||||
stopConfetti() {}
|
pause() {},
|
||||||
|
resume() {},
|
||||||
render() {
|
reset() {},
|
||||||
return null;
|
}));
|
||||||
}
|
return null;
|
||||||
|
});
|
||||||
|
const PIConfetti = React.forwardRef(function PIConfetti(props, ref) {
|
||||||
|
React.useImperativeHandle(ref, () => ({
|
||||||
|
restart() {},
|
||||||
|
pause() {},
|
||||||
|
resume() {},
|
||||||
|
reset() {},
|
||||||
|
}));
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
PIConfetti.Origin = function Origin() {
|
||||||
|
return null;
|
||||||
};
|
};
|
||||||
|
return { Confetti, PIConfetti };
|
||||||
});
|
});
|
||||||
Generated
+81
-17
@@ -15,6 +15,7 @@
|
|||||||
"@react-navigation/native": "^7.1.17",
|
"@react-navigation/native": "^7.1.17",
|
||||||
"@react-navigation/native-stack": "^7.3.26",
|
"@react-navigation/native-stack": "^7.3.26",
|
||||||
"@sentry/react-native": "~7.11.0",
|
"@sentry/react-native": "~7.11.0",
|
||||||
|
"@shopify/react-native-skia": "2.4.18",
|
||||||
"@stripe/stripe-react-native": "0.63.0",
|
"@stripe/stripe-react-native": "0.63.0",
|
||||||
"email-validator": "^2.0.4",
|
"email-validator": "^2.0.4",
|
||||||
"expo": "^55.0.0",
|
"expo": "^55.0.0",
|
||||||
@@ -29,7 +30,7 @@
|
|||||||
"react": "19.2.0",
|
"react": "19.2.0",
|
||||||
"react-hook-form": "^7.52.1",
|
"react-hook-form": "^7.52.1",
|
||||||
"react-native": "0.83.6",
|
"react-native": "0.83.6",
|
||||||
"react-native-confetti": "^0.1.0",
|
"react-native-fast-confetti": "^2.0.2",
|
||||||
"react-native-gesture-handler": "~2.30.0",
|
"react-native-gesture-handler": "~2.30.0",
|
||||||
"react-native-reanimated": "4.2.1",
|
"react-native-reanimated": "4.2.1",
|
||||||
"react-native-safe-area-context": "~5.6.0",
|
"react-native-safe-area-context": "~5.6.0",
|
||||||
@@ -49,7 +50,6 @@
|
|||||||
"@testing-library/react-native": "^13.3.3",
|
"@testing-library/react-native": "^13.3.3",
|
||||||
"@types/jest": "^29.5.14",
|
"@types/jest": "^29.5.14",
|
||||||
"@types/react": "~19.2.10",
|
"@types/react": "~19.2.10",
|
||||||
"@types/react-native-confetti": "^0.1.4",
|
|
||||||
"@types/react-native-simple-radio-button": "^2.7.7",
|
"@types/react-native-simple-radio-button": "^2.7.7",
|
||||||
"eslint": "^8.57.0",
|
"eslint": "^8.57.0",
|
||||||
"eslint-config-airbnb": "^19.0.4",
|
"eslint-config-airbnb": "^19.0.4",
|
||||||
@@ -3776,6 +3776,33 @@
|
|||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@shopify/react-native-skia": {
|
||||||
|
"version": "2.4.18",
|
||||||
|
"resolved": "https://registry.npmjs.org/@shopify/react-native-skia/-/react-native-skia-2.4.18.tgz",
|
||||||
|
"integrity": "sha512-/AB/mvb2dGSQVIJTxyG9ZMFn2PjwWlVcFxHU4TV+K25LCU49ntJXl4xda2ghXxdENMggKgO9R5pA+P/AQ0UUrA==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"canvaskit-wasm": "0.40.0",
|
||||||
|
"react-reconciler": "0.31.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"setup-skia-web": "scripts/setup-canvaskit.js"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">=19.0",
|
||||||
|
"react-native": ">=0.78",
|
||||||
|
"react-native-reanimated": ">=3.19.1"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"react-native": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react-native-reanimated": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@sinclair/typebox": {
|
"node_modules/@sinclair/typebox": {
|
||||||
"version": "0.27.12",
|
"version": "0.27.12",
|
||||||
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.12.tgz",
|
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.12.tgz",
|
||||||
@@ -4297,16 +4324,6 @@
|
|||||||
"csstype": "^3.2.2"
|
"csstype": "^3.2.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/react-native-confetti": {
|
|
||||||
"version": "0.1.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/react-native-confetti/-/react-native-confetti-0.1.4.tgz",
|
|
||||||
"integrity": "sha512-StgW1o0dw8ZLCVZ7v6ZVOBu+RYT+PFjtQAhF9k7uLn/avor4UtKhB9cDrF377+JfRw0aHeo3gg9dawZNzM/jOg==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@types/react": "*"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@types/react-native-simple-radio-button": {
|
"node_modules/@types/react-native-simple-radio-button": {
|
||||||
"version": "2.7.7",
|
"version": "2.7.7",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react-native-simple-radio-button/-/react-native-simple-radio-button-2.7.7.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react-native-simple-radio-button/-/react-native-simple-radio-button-2.7.7.tgz",
|
||||||
@@ -4927,6 +4944,12 @@
|
|||||||
"win32"
|
"win32"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"node_modules/@webgpu/types": {
|
||||||
|
"version": "0.1.21",
|
||||||
|
"resolved": "https://registry.npmjs.org/@webgpu/types/-/types-0.1.21.tgz",
|
||||||
|
"integrity": "sha512-pUrWq3V5PiSGFLeLxoGqReTZmiiXwY3jRkIG5sLLKjyqNxrwm/04b4nw7LSmGWJcKk59XOM/YRTUwOzo4MMlow==",
|
||||||
|
"license": "BSD-3-Clause"
|
||||||
|
},
|
||||||
"node_modules/@wry/caches": {
|
"node_modules/@wry/caches": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@wry/caches/-/caches-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@wry/caches/-/caches-1.0.1.tgz",
|
||||||
@@ -5918,6 +5941,15 @@
|
|||||||
],
|
],
|
||||||
"license": "CC-BY-4.0"
|
"license": "CC-BY-4.0"
|
||||||
},
|
},
|
||||||
|
"node_modules/canvaskit-wasm": {
|
||||||
|
"version": "0.40.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/canvaskit-wasm/-/canvaskit-wasm-0.40.0.tgz",
|
||||||
|
"integrity": "sha512-Od2o+ZmoEw9PBdN/yCGvzfu0WVqlufBPEWNG452wY7E9aT8RBE+ChpZF526doOlg7zumO4iCS+RAeht4P0Gbpw==",
|
||||||
|
"license": "BSD-3-Clause",
|
||||||
|
"dependencies": {
|
||||||
|
"@webgpu/types": "0.1.21"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/chalk": {
|
"node_modules/chalk": {
|
||||||
"version": "4.1.2",
|
"version": "4.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
||||||
@@ -14291,11 +14323,22 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-native-confetti": {
|
"node_modules/react-native-fast-confetti": {
|
||||||
"version": "0.1.0",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/react-native-confetti/-/react-native-confetti-0.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-fast-confetti/-/react-native-fast-confetti-2.0.2.tgz",
|
||||||
"integrity": "sha512-+cXJvnPXKc0i/eTQcuzcjrlfIxmn/xFw4UyuVKQOWNK6BfWABvO6Ms6Zp6ivF1E8Vxt2vJkzJlNyoBvMh9FxKA==",
|
"integrity": "sha512-g/so5kYCQFMFNuD3ui10hMCXZTA8pPzOhwUJgzfslxI2WHuYb4SjdOxV0I9xPv7ts8Sqch6bS7oCJZMX2DM0Yw==",
|
||||||
"license": "MIT"
|
"license": "MIT",
|
||||||
|
"workspaces": [
|
||||||
|
"example",
|
||||||
|
"kitchen-sink"
|
||||||
|
],
|
||||||
|
"peerDependencies": {
|
||||||
|
"@shopify/react-native-skia": ">=2.0.0 <3",
|
||||||
|
"react": "*",
|
||||||
|
"react-native": "*",
|
||||||
|
"react-native-reanimated": ">=4.1.0 <5",
|
||||||
|
"react-native-worklets": ">=0.7.0 <1"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-native-gesture-handler": {
|
"node_modules/react-native-gesture-handler": {
|
||||||
"version": "2.30.1",
|
"version": "2.30.1",
|
||||||
@@ -14596,6 +14639,27 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-reconciler": {
|
||||||
|
"version": "0.31.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.31.0.tgz",
|
||||||
|
"integrity": "sha512-7Ob7Z+URmesIsIVRjnLoDGwBEG/tVitidU0nMsqX/eeJaLY89RISO/10ERe0MqmzuKUUB1rmY+h1itMbUHg9BQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"scheduler": "^0.25.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^19.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/react-reconciler/node_modules/scheduler": {
|
||||||
|
"version": "0.25.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.25.0.tgz",
|
||||||
|
"integrity": "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/react-redux": {
|
"node_modules/react-redux": {
|
||||||
"version": "9.3.0",
|
"version": "9.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.3.0.tgz",
|
||||||
|
|||||||
+2
-2
@@ -22,6 +22,7 @@
|
|||||||
"@react-navigation/native": "^7.1.17",
|
"@react-navigation/native": "^7.1.17",
|
||||||
"@react-navigation/native-stack": "^7.3.26",
|
"@react-navigation/native-stack": "^7.3.26",
|
||||||
"@sentry/react-native": "~7.11.0",
|
"@sentry/react-native": "~7.11.0",
|
||||||
|
"@shopify/react-native-skia": "2.4.18",
|
||||||
"@stripe/stripe-react-native": "0.63.0",
|
"@stripe/stripe-react-native": "0.63.0",
|
||||||
"email-validator": "^2.0.4",
|
"email-validator": "^2.0.4",
|
||||||
"expo": "^55.0.0",
|
"expo": "^55.0.0",
|
||||||
@@ -36,7 +37,7 @@
|
|||||||
"react": "19.2.0",
|
"react": "19.2.0",
|
||||||
"react-hook-form": "^7.52.1",
|
"react-hook-form": "^7.52.1",
|
||||||
"react-native": "0.83.6",
|
"react-native": "0.83.6",
|
||||||
"react-native-confetti": "^0.1.0",
|
"react-native-fast-confetti": "^2.0.2",
|
||||||
"react-native-gesture-handler": "~2.30.0",
|
"react-native-gesture-handler": "~2.30.0",
|
||||||
"react-native-reanimated": "4.2.1",
|
"react-native-reanimated": "4.2.1",
|
||||||
"react-native-safe-area-context": "~5.6.0",
|
"react-native-safe-area-context": "~5.6.0",
|
||||||
@@ -56,7 +57,6 @@
|
|||||||
"@testing-library/react-native": "^13.3.3",
|
"@testing-library/react-native": "^13.3.3",
|
||||||
"@types/jest": "^29.5.14",
|
"@types/jest": "^29.5.14",
|
||||||
"@types/react": "~19.2.10",
|
"@types/react": "~19.2.10",
|
||||||
"@types/react-native-confetti": "^0.1.4",
|
|
||||||
"@types/react-native-simple-radio-button": "^2.7.7",
|
"@types/react-native-simple-radio-button": "^2.7.7",
|
||||||
"eslint": "^8.57.0",
|
"eslint": "^8.57.0",
|
||||||
"eslint-config-airbnb": "^19.0.4",
|
"eslint-config-airbnb": "^19.0.4",
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import * as Notifications from 'expo-notifications';
|
import * as Notifications from 'expo-notifications';
|
||||||
import React, { useEffect, useRef, useState } from 'react';
|
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
||||||
import {
|
import {
|
||||||
Image,
|
Image,
|
||||||
ScrollView,
|
ScrollView,
|
||||||
@@ -13,7 +13,9 @@ import {
|
|||||||
GestureResponderEvent,
|
GestureResponderEvent,
|
||||||
Switch,
|
Switch,
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import Confetti from 'react-native-confetti';
|
import { Confetti, PIConfetti } from 'react-native-fast-confetti';
|
||||||
|
import type { ConfettiMethods, PIConfettiMethods } from 'react-native-fast-confetti';
|
||||||
|
import { Easing } from 'react-native-reanimated';
|
||||||
|
|
||||||
import Button from '@/components/Button';
|
import Button from '@/components/Button';
|
||||||
import RadioButton from '@/components/RadioButton';
|
import RadioButton from '@/components/RadioButton';
|
||||||
@@ -130,14 +132,42 @@ const PurchaseButton = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
const UserConfetti = ({
|
||||||
const UserConfetti = ({ user, confettiRef }: { user: UserType; confettiRef: any }) => {
|
user,
|
||||||
|
confettiRef,
|
||||||
|
burstRef,
|
||||||
|
containerRef,
|
||||||
|
onRainStart,
|
||||||
|
onRainEnd,
|
||||||
|
}: {
|
||||||
|
user: UserType;
|
||||||
|
confettiRef: React.RefObject<ConfettiMethods | null>;
|
||||||
|
burstRef: React.RefObject<PIConfettiMethods | null>;
|
||||||
|
containerRef: React.RefObject<React.ComponentRef<typeof View> | null>;
|
||||||
|
onRainStart: () => void;
|
||||||
|
onRainEnd: () => void;
|
||||||
|
}) => {
|
||||||
if (!user.is_member) {
|
if (!user.is_member) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Confetti!!!!
|
// Confetti!!!!
|
||||||
return <Confetti ref={confettiRef} confettiCount={Number.MAX_SAFE_INTEGER} />;
|
return (
|
||||||
|
<View ref={containerRef} pointerEvents="none" style={styles.confetti}>
|
||||||
|
<Confetti
|
||||||
|
ref={confettiRef}
|
||||||
|
autoplay={false}
|
||||||
|
count={400}
|
||||||
|
gravity={0.24}
|
||||||
|
easing={Easing.linear}
|
||||||
|
onAnimationStart={onRainStart}
|
||||||
|
onAnimationEnd={onRainEnd}
|
||||||
|
/>
|
||||||
|
<PIConfetti ref={burstRef} autoplay={false} fadeOutOnEnd>
|
||||||
|
<PIConfetti.Origin blastPosition="center" count={80} initialSpeed={2} />
|
||||||
|
</PIConfetti>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
const Logo = ({ user }: { user: UserType }) => {
|
const Logo = ({ user }: { user: UserType }) => {
|
||||||
if (!user.is_member) {
|
if (!user.is_member) {
|
||||||
@@ -216,8 +246,10 @@ interface ProofProps {
|
|||||||
onDeletePress: () => void;
|
onDeletePress: () => void;
|
||||||
}
|
}
|
||||||
const Proof = ({ onLogoutPress, fetchUser, isFetchingUserData, onDeletePress }: ProofProps) => {
|
const Proof = ({ onLogoutPress, fetchUser, isFetchingUserData, onDeletePress }: ProofProps) => {
|
||||||
const CONFETTI_TIMEOUT = 15000;
|
const confettiRef = useRef<ConfettiMethods>(null);
|
||||||
const confettiRef = useRef<Confetti>(null);
|
const burstRef = useRef<PIConfettiMethods>(null);
|
||||||
|
const confettiContainerRef = useRef<React.ComponentRef<typeof View>>(null);
|
||||||
|
const isRaining = useRef(false);
|
||||||
const {
|
const {
|
||||||
paymentLoading,
|
paymentLoading,
|
||||||
isLoadingMembershipType,
|
isLoadingMembershipType,
|
||||||
@@ -231,22 +263,25 @@ const Proof = ({ onLogoutPress, fetchUser, isFetchingUserData, onDeletePress }:
|
|||||||
fetchUser,
|
fetchUser,
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
const onRainStart = useCallback(() => {
|
||||||
const currentRef = confettiRef.current;
|
isRaining.current = true;
|
||||||
return () => {
|
}, []);
|
||||||
if (currentRef) {
|
const onRainEnd = useCallback(() => {
|
||||||
currentRef.stopConfetti();
|
isRaining.current = false;
|
||||||
}
|
}, []);
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
const onMembershipPress = () => {
|
const onMembershipPress = (event: GestureResponderEvent) => {
|
||||||
confettiRef.current?.startConfetti();
|
const { pageX, pageY } = event.nativeEvent;
|
||||||
setTimeout(() => {
|
// measure() reports pageX/pageY in the same coordinate space as the touch,
|
||||||
if (confettiRef && confettiRef.current) {
|
// which measureInWindow does not on Android.
|
||||||
confettiRef.current.stopConfetti();
|
confettiContainerRef.current?.measure((x, y, width, height, originX, originY) => {
|
||||||
}
|
burstRef.current?.restart({
|
||||||
}, CONFETTI_TIMEOUT);
|
origins: [{ blastPosition: { x: pageX - originX, y: pageY - originY } }],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
if (!isRaining.current) {
|
||||||
|
confettiRef.current?.restart();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
@@ -259,7 +294,14 @@ const Proof = ({ onLogoutPress, fetchUser, isFetchingUserData, onDeletePress }:
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<UserConfetti user={user} confettiRef={confettiRef} />
|
<UserConfetti
|
||||||
|
user={user}
|
||||||
|
confettiRef={confettiRef}
|
||||||
|
burstRef={burstRef}
|
||||||
|
containerRef={confettiContainerRef}
|
||||||
|
onRainStart={onRainStart}
|
||||||
|
onRainEnd={onRainEnd}
|
||||||
|
/>
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
<ScrollView refreshControl={<RefreshControl refreshing={isFetchingUserData} onRefresh={fetchUser} />}>
|
<ScrollView refreshControl={<RefreshControl refreshing={isFetchingUserData} onRefresh={fetchUser} />}>
|
||||||
<View style={[theme.card, { paddingVertical: 16, backgroundColor: 'transparent' }]}>
|
<View style={[theme.card, { paddingVertical: 16, backgroundColor: 'transparent' }]}>
|
||||||
@@ -302,6 +344,14 @@ const Proof = ({ onLogoutPress, fetchUser, isFetchingUserData, onDeletePress }:
|
|||||||
export default Proof;
|
export default Proof;
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
|
confetti: {
|
||||||
|
position: 'absolute',
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
zIndex: 1,
|
||||||
|
},
|
||||||
membershipStatus: {
|
membershipStatus: {
|
||||||
marginVertical: 16,
|
marginVertical: 16,
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in new issue
Block a user