@oxyhq/services 5.3.11 → 5.4.1
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/README.md +21 -0
- package/lib/commonjs/assets/assets/icons/OxyServices.tsx +67 -0
- package/lib/commonjs/assets/assets/icons/logo_OxyServices.svg +1 -0
- package/lib/commonjs/assets/icons/OxyServices.js +53 -0
- package/lib/commonjs/assets/icons/OxyServices.js.map +1 -0
- package/lib/commonjs/assets/icons/logo_OxyServices.svg +1 -0
- package/lib/commonjs/core/index.js +119 -23
- package/lib/commonjs/core/index.js.map +1 -1
- package/lib/commonjs/index.js +2 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/lib/sonner.js +15 -11
- package/lib/commonjs/lib/sonner.js.map +1 -1
- package/lib/commonjs/node/index.js +2 -0
- package/lib/commonjs/node/index.js.map +1 -1
- package/lib/commonjs/ui/components/GroupedItem.js +109 -0
- package/lib/commonjs/ui/components/GroupedItem.js.map +1 -0
- package/lib/commonjs/ui/components/GroupedSection.js +33 -0
- package/lib/commonjs/ui/components/GroupedSection.js.map +1 -0
- package/lib/commonjs/ui/components/OxyProvider.js +95 -112
- package/lib/commonjs/ui/components/OxyProvider.js.map +1 -1
- package/lib/commonjs/ui/components/ProfileCard.js +124 -0
- package/lib/commonjs/ui/components/ProfileCard.js.map +1 -0
- package/lib/commonjs/ui/components/QuickActions.js +87 -0
- package/lib/commonjs/ui/components/QuickActions.js.map +1 -0
- package/lib/commonjs/ui/components/Section.js +36 -0
- package/lib/commonjs/ui/components/Section.js.map +1 -0
- package/lib/commonjs/ui/components/SectionTitle.js +35 -0
- package/lib/commonjs/ui/components/SectionTitle.js.map +1 -0
- package/lib/commonjs/ui/components/bottomSheet/index.js +6 -6
- package/lib/commonjs/ui/components/index.js +97 -0
- package/lib/commonjs/ui/components/index.js.map +1 -0
- package/lib/commonjs/ui/navigation/OxyRouter.js +20 -3
- package/lib/commonjs/ui/navigation/OxyRouter.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountCenterScreen.js +190 -207
- package/lib/commonjs/ui/screens/AccountCenterScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountManagementDemo.js +299 -0
- package/lib/commonjs/ui/screens/AccountManagementDemo.js.map +1 -0
- package/lib/commonjs/ui/screens/AccountOverviewScreen.js +669 -401
- package/lib/commonjs/ui/screens/AccountOverviewScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountSettingsScreen.js +695 -498
- package/lib/commonjs/ui/screens/AccountSettingsScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountSwitcherScreen.js +451 -488
- package/lib/commonjs/ui/screens/AccountSwitcherScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AppInfoScreen.js +498 -185
- package/lib/commonjs/ui/screens/AppInfoScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/BillingManagementScreen.js +636 -0
- package/lib/commonjs/ui/screens/BillingManagementScreen.js.map +1 -0
- package/lib/commonjs/ui/screens/FileManagementScreen.js +2497 -0
- package/lib/commonjs/ui/screens/FileManagementScreen.js.map +1 -0
- package/lib/commonjs/ui/screens/PremiumSubscriptionScreen.js +1620 -0
- package/lib/commonjs/ui/screens/PremiumSubscriptionScreen.js.map +1 -0
- package/lib/commonjs/ui/screens/ProfileScreen.js +117 -13
- package/lib/commonjs/ui/screens/ProfileScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/SessionManagementScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/SignInScreen.js +1 -1
- package/lib/commonjs/ui/screens/SignUpScreen.js +1 -1
- package/lib/commonjs/utils/polyfills.js +42 -0
- package/lib/commonjs/utils/polyfills.js.map +1 -0
- package/lib/module/assets/assets/icons/OxyServices.tsx +67 -0
- package/lib/module/assets/assets/icons/logo_OxyServices.svg +1 -0
- package/lib/module/assets/icons/OxyServices.js +46 -0
- package/lib/module/assets/icons/OxyServices.js.map +1 -0
- package/lib/module/assets/icons/logo_OxyServices.svg +1 -0
- package/lib/module/core/index.js +119 -23
- package/lib/module/core/index.js.map +1 -1
- package/lib/module/index.js +3 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/lib/sonner.js +13 -1
- package/lib/module/lib/sonner.js.map +1 -1
- package/lib/module/node/index.js +3 -0
- package/lib/module/node/index.js.map +1 -1
- package/lib/module/ui/components/GroupedItem.js +104 -0
- package/lib/module/ui/components/GroupedItem.js.map +1 -0
- package/lib/module/ui/components/GroupedSection.js +28 -0
- package/lib/module/ui/components/GroupedSection.js.map +1 -0
- package/lib/module/ui/components/OxyProvider.js +97 -114
- package/lib/module/ui/components/OxyProvider.js.map +1 -1
- package/lib/module/ui/components/ProfileCard.js +119 -0
- package/lib/module/ui/components/ProfileCard.js.map +1 -0
- package/lib/module/ui/components/QuickActions.js +82 -0
- package/lib/module/ui/components/QuickActions.js.map +1 -0
- package/lib/module/ui/components/Section.js +31 -0
- package/lib/module/ui/components/Section.js.map +1 -0
- package/lib/module/ui/components/SectionTitle.js +30 -0
- package/lib/module/ui/components/SectionTitle.js.map +1 -0
- package/lib/module/ui/components/bottomSheet/index.js +2 -5
- package/lib/module/ui/components/bottomSheet/index.js.map +1 -1
- package/lib/module/ui/components/index.js +18 -0
- package/lib/module/ui/components/index.js.map +1 -0
- package/lib/module/ui/navigation/OxyRouter.js +20 -3
- package/lib/module/ui/navigation/OxyRouter.js.map +1 -1
- package/lib/module/ui/screens/AccountCenterScreen.js +191 -208
- package/lib/module/ui/screens/AccountCenterScreen.js.map +1 -1
- package/lib/module/ui/screens/AccountManagementDemo.js +296 -0
- package/lib/module/ui/screens/AccountManagementDemo.js.map +1 -0
- package/lib/module/ui/screens/AccountOverviewScreen.js +671 -403
- package/lib/module/ui/screens/AccountOverviewScreen.js.map +1 -1
- package/lib/module/ui/screens/AccountSettingsScreen.js +698 -501
- package/lib/module/ui/screens/AccountSettingsScreen.js.map +1 -1
- package/lib/module/ui/screens/AccountSwitcherScreen.js +450 -488
- package/lib/module/ui/screens/AccountSwitcherScreen.js.map +1 -1
- package/lib/module/ui/screens/AppInfoScreen.js +498 -186
- package/lib/module/ui/screens/AppInfoScreen.js.map +1 -1
- package/lib/module/ui/screens/BillingManagementScreen.js +631 -0
- package/lib/module/ui/screens/BillingManagementScreen.js.map +1 -0
- package/lib/module/ui/screens/FileManagementScreen.js +2492 -0
- package/lib/module/ui/screens/FileManagementScreen.js.map +1 -0
- package/lib/module/ui/screens/PremiumSubscriptionScreen.js +1615 -0
- package/lib/module/ui/screens/PremiumSubscriptionScreen.js.map +1 -0
- package/lib/module/ui/screens/ProfileScreen.js +118 -14
- package/lib/module/ui/screens/ProfileScreen.js.map +1 -1
- package/lib/module/ui/screens/SessionManagementScreen.js.map +1 -1
- package/lib/module/ui/screens/SignInScreen.js +1 -1
- package/lib/module/ui/screens/SignInScreen.js.map +1 -1
- package/lib/module/ui/screens/SignUpScreen.js +1 -1
- package/lib/module/ui/screens/SignUpScreen.js.map +1 -1
- package/lib/module/utils/polyfills.js +36 -0
- package/lib/module/utils/polyfills.js.map +1 -0
- package/lib/typescript/assets/icons/OxyServices.d.ts +29 -0
- package/lib/typescript/assets/icons/OxyServices.d.ts.map +1 -0
- package/lib/typescript/core/index.d.ts +26 -1
- package/lib/typescript/core/index.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +1 -0
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/lib/sonner.d.ts +5 -1
- package/lib/typescript/lib/sonner.d.ts.map +1 -1
- package/lib/typescript/models/interfaces.d.ts +1 -2
- package/lib/typescript/models/interfaces.d.ts.map +1 -1
- package/lib/typescript/node/index.d.ts +1 -0
- package/lib/typescript/node/index.d.ts.map +1 -1
- package/lib/typescript/ui/components/GroupedItem.d.ts +17 -0
- package/lib/typescript/ui/components/GroupedItem.d.ts.map +1 -0
- package/lib/typescript/ui/components/GroupedSection.d.ts +19 -0
- package/lib/typescript/ui/components/GroupedSection.d.ts.map +1 -0
- package/lib/typescript/ui/components/OxyProvider.d.ts.map +1 -1
- package/lib/typescript/ui/components/ProfileCard.d.ts +20 -0
- package/lib/typescript/ui/components/ProfileCard.d.ts.map +1 -0
- package/lib/typescript/ui/components/QuickActions.d.ts +15 -0
- package/lib/typescript/ui/components/QuickActions.d.ts.map +1 -0
- package/lib/typescript/ui/components/Section.d.ts +11 -0
- package/lib/typescript/ui/components/Section.d.ts.map +1 -0
- package/lib/typescript/ui/components/SectionTitle.d.ts +9 -0
- package/lib/typescript/ui/components/SectionTitle.d.ts.map +1 -0
- package/lib/typescript/ui/components/bottomSheet/index.d.ts +3 -2
- package/lib/typescript/ui/components/bottomSheet/index.d.ts.map +1 -1
- package/lib/typescript/ui/components/index.d.ts +13 -0
- package/lib/typescript/ui/components/index.d.ts.map +1 -0
- package/lib/typescript/ui/navigation/OxyRouter.d.ts.map +1 -1
- package/lib/typescript/ui/navigation/types.d.ts +8 -0
- package/lib/typescript/ui/navigation/types.d.ts.map +1 -1
- package/lib/typescript/ui/screens/AccountCenterScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/AccountManagementDemo.d.ts +8 -0
- package/lib/typescript/ui/screens/AccountManagementDemo.d.ts.map +1 -0
- package/lib/typescript/ui/screens/AccountOverviewScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/AccountSettingsScreen.d.ts +1 -4
- package/lib/typescript/ui/screens/AccountSettingsScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/AccountSwitcherScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/AppInfoScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/BillingManagementScreen.d.ts +5 -0
- package/lib/typescript/ui/screens/BillingManagementScreen.d.ts.map +1 -0
- package/lib/typescript/ui/screens/FileManagementScreen.d.ts +8 -0
- package/lib/typescript/ui/screens/FileManagementScreen.d.ts.map +1 -0
- package/lib/typescript/ui/screens/PremiumSubscriptionScreen.d.ts +5 -0
- package/lib/typescript/ui/screens/PremiumSubscriptionScreen.d.ts.map +1 -0
- package/lib/typescript/ui/screens/ProfileScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/SessionManagementScreen.d.ts.map +1 -1
- package/lib/typescript/utils/polyfills.d.ts +6 -0
- package/lib/typescript/utils/polyfills.d.ts.map +1 -0
- package/package.json +11 -3
- package/src/__tests__/polyfills.test.ts +30 -0
- package/src/__tests__/setup.ts +43 -0
- package/src/__tests__/ui/screens/AccountSettingsScreen.test.tsx +8 -8
- package/src/assets/icons/OxyServices.tsx +67 -0
- package/src/assets/icons/logo_OxyServices.svg +1 -0
- package/src/core/index.ts +127 -19
- package/src/index.ts +3 -0
- package/src/lib/sonner.ts +10 -1
- package/src/models/interfaces.ts +1 -2
- package/src/node/index.ts +3 -0
- package/src/ui/components/GroupedItem.tsx +118 -0
- package/src/ui/components/GroupedSection.tsx +45 -0
- package/src/ui/components/OxyProvider.tsx +95 -120
- package/src/ui/components/ProfileCard.tsx +129 -0
- package/src/ui/components/QuickActions.tsx +90 -0
- package/src/ui/components/Section.tsx +37 -0
- package/src/ui/components/SectionTitle.tsx +31 -0
- package/src/ui/components/bottomSheet/index.tsx +13 -11
- package/src/ui/components/index.ts +15 -0
- package/src/ui/navigation/OxyRouter.tsx +20 -3
- package/src/ui/navigation/types.ts +10 -1
- package/src/ui/screens/AccountCenterScreen.tsx +188 -159
- package/src/ui/screens/AccountManagementDemo.tsx +297 -0
- package/src/ui/screens/AccountOverviewScreen.tsx +474 -310
- package/src/ui/screens/AccountSettingsScreen.tsx +648 -463
- package/src/ui/screens/AccountSwitcherScreen.tsx +385 -449
- package/src/ui/screens/AppInfoScreen.tsx +571 -140
- package/src/ui/screens/BillingManagementScreen.tsx +589 -0
- package/src/ui/screens/FileManagementScreen.tsx +2513 -0
- package/src/ui/screens/PremiumSubscriptionScreen.tsx +1628 -0
- package/src/ui/screens/ProfileScreen.tsx +101 -7
- package/src/ui/screens/SessionManagementScreen.tsx +1 -0
- package/src/ui/screens/SignInScreen.tsx +1 -1
- package/src/ui/screens/SignUpScreen.tsx +1 -1
- package/src/utils/polyfills.ts +34 -0
- package/lib/commonjs/lib/sonner.web.js +0 -17
- package/lib/commonjs/lib/sonner.web.js.map +0 -1
- package/lib/module/lib/sonner.web.js +0 -4
- package/lib/module/lib/sonner.web.js.map +0 -1
- package/lib/typescript/__tests__/ui/screens/AccountSettingsScreen.test.d.ts +0 -2
- package/lib/typescript/__tests__/ui/screens/AccountSettingsScreen.test.d.ts.map +0 -1
- package/lib/typescript/lib/sonner.web.d.ts +0 -2
- package/lib/typescript/lib/sonner.web.d.ts.map +0 -1
- package/src/lib/sonner.web.ts +0 -1
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';
|
|
3
|
+
import { Ionicons } from '@expo/vector-icons';
|
|
4
|
+
|
|
5
|
+
interface GroupedItemProps {
|
|
6
|
+
icon?: string;
|
|
7
|
+
iconColor?: string;
|
|
8
|
+
title: string;
|
|
9
|
+
subtitle?: string;
|
|
10
|
+
theme: 'light' | 'dark';
|
|
11
|
+
onPress?: () => void;
|
|
12
|
+
isFirst?: boolean;
|
|
13
|
+
isLast?: boolean;
|
|
14
|
+
showChevron?: boolean;
|
|
15
|
+
disabled?: boolean;
|
|
16
|
+
customContent?: React.ReactNode;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const GroupedItem: React.FC<GroupedItemProps> = ({
|
|
20
|
+
icon,
|
|
21
|
+
iconColor = '#007AFF',
|
|
22
|
+
title,
|
|
23
|
+
subtitle,
|
|
24
|
+
theme,
|
|
25
|
+
onPress,
|
|
26
|
+
isFirst = false,
|
|
27
|
+
isLast = false,
|
|
28
|
+
showChevron = true,
|
|
29
|
+
disabled = false,
|
|
30
|
+
customContent,
|
|
31
|
+
}) => {
|
|
32
|
+
const isDarkTheme = theme === 'dark';
|
|
33
|
+
const textColor = isDarkTheme ? '#FFFFFF' : '#000000';
|
|
34
|
+
const secondaryBackgroundColor = isDarkTheme ? '#222222' : '#FFFFFF';
|
|
35
|
+
|
|
36
|
+
const itemStyles = [
|
|
37
|
+
styles.groupedItem,
|
|
38
|
+
isFirst && styles.firstGroupedItem,
|
|
39
|
+
isLast && styles.lastGroupedItem,
|
|
40
|
+
{ backgroundColor: secondaryBackgroundColor },
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
const content = (
|
|
44
|
+
<View style={styles.groupedItemContent}>
|
|
45
|
+
{icon && (
|
|
46
|
+
<Ionicons name={icon as any} size={20} color={iconColor} style={styles.actionIcon} />
|
|
47
|
+
)}
|
|
48
|
+
<View style={styles.actionTextContainer}>
|
|
49
|
+
<Text style={[styles.actionButtonText, { color: textColor }]}>{title}</Text>
|
|
50
|
+
{subtitle && (
|
|
51
|
+
<Text style={[styles.actionButtonSubtext, { color: isDarkTheme ? '#BBBBBB' : '#666666' }]}>
|
|
52
|
+
{subtitle}
|
|
53
|
+
</Text>
|
|
54
|
+
)}
|
|
55
|
+
</View>
|
|
56
|
+
{customContent}
|
|
57
|
+
{showChevron && (
|
|
58
|
+
<Ionicons name="chevron-forward" size={16} color={isDarkTheme ? '#666666' : '#999999'} />
|
|
59
|
+
)}
|
|
60
|
+
</View>
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
if (onPress && !disabled) {
|
|
64
|
+
return (
|
|
65
|
+
<TouchableOpacity style={itemStyles} onPress={onPress}>
|
|
66
|
+
{content}
|
|
67
|
+
</TouchableOpacity>
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return (
|
|
72
|
+
<View style={itemStyles}>
|
|
73
|
+
{content}
|
|
74
|
+
</View>
|
|
75
|
+
);
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const styles = StyleSheet.create({
|
|
79
|
+
groupedItem: {
|
|
80
|
+
flexDirection: 'row',
|
|
81
|
+
alignItems: 'center',
|
|
82
|
+
justifyContent: 'space-between',
|
|
83
|
+
marginBottom: 2,
|
|
84
|
+
overflow: 'hidden',
|
|
85
|
+
},
|
|
86
|
+
firstGroupedItem: {
|
|
87
|
+
borderTopLeftRadius: 24,
|
|
88
|
+
borderTopRightRadius: 24,
|
|
89
|
+
},
|
|
90
|
+
lastGroupedItem: {
|
|
91
|
+
borderBottomLeftRadius: 24,
|
|
92
|
+
borderBottomRightRadius: 24,
|
|
93
|
+
marginBottom: 8,
|
|
94
|
+
},
|
|
95
|
+
groupedItemContent: {
|
|
96
|
+
flexDirection: 'row',
|
|
97
|
+
alignItems: 'center',
|
|
98
|
+
padding: 16,
|
|
99
|
+
width: '100%',
|
|
100
|
+
},
|
|
101
|
+
actionIcon: {
|
|
102
|
+
marginRight: 12,
|
|
103
|
+
},
|
|
104
|
+
actionTextContainer: {
|
|
105
|
+
flex: 1,
|
|
106
|
+
},
|
|
107
|
+
actionButtonText: {
|
|
108
|
+
fontSize: 16,
|
|
109
|
+
fontWeight: '500',
|
|
110
|
+
marginBottom: 2,
|
|
111
|
+
},
|
|
112
|
+
actionButtonSubtext: {
|
|
113
|
+
fontSize: 13,
|
|
114
|
+
lineHeight: 18,
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
export default GroupedItem;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { View } from 'react-native';
|
|
3
|
+
import GroupedItem from './GroupedItem';
|
|
4
|
+
|
|
5
|
+
interface GroupedSectionItem {
|
|
6
|
+
id: string;
|
|
7
|
+
icon?: string;
|
|
8
|
+
iconColor?: string;
|
|
9
|
+
title: string;
|
|
10
|
+
subtitle?: string;
|
|
11
|
+
onPress?: () => void;
|
|
12
|
+
showChevron?: boolean;
|
|
13
|
+
disabled?: boolean;
|
|
14
|
+
customContent?: React.ReactNode;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface GroupedSectionProps {
|
|
18
|
+
items: GroupedSectionItem[];
|
|
19
|
+
theme: 'light' | 'dark';
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const GroupedSection: React.FC<GroupedSectionProps> = ({ items, theme }) => {
|
|
23
|
+
return (
|
|
24
|
+
<View>
|
|
25
|
+
{items.map((item, index) => (
|
|
26
|
+
<GroupedItem
|
|
27
|
+
key={item.id}
|
|
28
|
+
icon={item.icon}
|
|
29
|
+
iconColor={item.iconColor}
|
|
30
|
+
title={item.title}
|
|
31
|
+
subtitle={item.subtitle}
|
|
32
|
+
theme={theme}
|
|
33
|
+
onPress={item.onPress}
|
|
34
|
+
isFirst={index === 0}
|
|
35
|
+
isLast={index === items.length - 1}
|
|
36
|
+
showChevron={item.showChevron}
|
|
37
|
+
disabled={item.disabled}
|
|
38
|
+
customContent={item.customContent}
|
|
39
|
+
/>
|
|
40
|
+
))}
|
|
41
|
+
</View>
|
|
42
|
+
);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export default GroupedSection;
|
|
@@ -1,27 +1,20 @@
|
|
|
1
|
-
// filepath: /home/nate/OxyServicesandApi/OxyHQServices/src/ui/components/OxyProvider.tsx
|
|
2
1
|
import React, { useCallback, useRef, useState, useEffect } from 'react';
|
|
3
2
|
import { View, Text, StyleSheet, Dimensions, Platform, Animated, StatusBar, Keyboard, KeyboardEvent } from 'react-native';
|
|
4
3
|
import { SafeAreaProvider, useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
5
4
|
import { GestureHandlerRootView } from 'react-native-gesture-handler';
|
|
6
|
-
import { OxyServices } from '../../core';
|
|
7
5
|
import { OxyProviderProps } from '../navigation/types';
|
|
8
|
-
import SignInScreen from '../screens/SignInScreen';
|
|
9
|
-
import SignUpScreen from '../screens/SignUpScreen';
|
|
10
|
-
import AccountCenterScreen from '../screens/AccountCenterScreen';
|
|
11
6
|
import { OxyContextProvider, useOxy } from '../context/OxyContext';
|
|
12
7
|
import OxyRouter from '../navigation/OxyRouter';
|
|
13
8
|
import { FontLoader, setupFonts } from './FontLoader';
|
|
14
9
|
import { Toaster } from '../../lib/sonner';
|
|
15
10
|
|
|
16
11
|
// Import bottom sheet components directly - no longer a peer dependency
|
|
17
|
-
import { BottomSheetModal, BottomSheetBackdrop, BottomSheetBackdropProps, BottomSheetModalProvider, BottomSheetView } from './bottomSheet';
|
|
18
|
-
import {
|
|
12
|
+
import { BottomSheetModal, BottomSheetBackdrop, BottomSheetBackdropProps, BottomSheetModalProvider, BottomSheetView, BottomSheetScrollView } from './bottomSheet';
|
|
13
|
+
import type { BottomSheetModalRef } from './bottomSheet';
|
|
19
14
|
|
|
20
15
|
// Initialize fonts automatically
|
|
21
16
|
setupFonts();
|
|
22
17
|
|
|
23
|
-
const { height, width } = Dimensions.get('window');
|
|
24
|
-
|
|
25
18
|
/**
|
|
26
19
|
* Enhanced OxyProvider component
|
|
27
20
|
*
|
|
@@ -36,11 +29,12 @@ const OxyProvider: React.FC<OxyProviderProps> = (props) => {
|
|
|
36
29
|
contextOnly = false,
|
|
37
30
|
onAuthStateChange,
|
|
38
31
|
storageKeyPrefix,
|
|
32
|
+
showInternalToaster = true,
|
|
39
33
|
...bottomSheetProps
|
|
40
34
|
} = props;
|
|
41
35
|
|
|
42
36
|
// Create internal bottom sheet ref
|
|
43
|
-
const internalBottomSheetRef = useRef<
|
|
37
|
+
const internalBottomSheetRef = useRef<BottomSheetModalRef>(null);
|
|
44
38
|
|
|
45
39
|
// If contextOnly is true, we just provide the context without the bottom sheet UI
|
|
46
40
|
if (contextOnly) {
|
|
@@ -72,10 +66,12 @@ const OxyProvider: React.FC<OxyProviderProps> = (props) => {
|
|
|
72
66
|
{children}
|
|
73
67
|
</SafeAreaProvider>
|
|
74
68
|
</BottomSheetModalProvider>
|
|
75
|
-
{/*
|
|
76
|
-
|
|
77
|
-
<
|
|
78
|
-
|
|
69
|
+
{/* Global Toaster for app-wide notifications outside of Modal contexts - only show if internal toaster is disabled */}
|
|
70
|
+
{!showInternalToaster && (
|
|
71
|
+
<View style={styles.toasterContainer}>
|
|
72
|
+
<Toaster position="top-center" swipeToDismissDirection="left" offset={15} />
|
|
73
|
+
</View>
|
|
74
|
+
)}
|
|
79
75
|
</GestureHandlerRootView>
|
|
80
76
|
</FontLoader>
|
|
81
77
|
</OxyContextProvider>
|
|
@@ -97,15 +93,17 @@ const OxyBottomSheet: React.FC<OxyProviderProps> = ({
|
|
|
97
93
|
customStyles = {},
|
|
98
94
|
bottomSheetRef,
|
|
99
95
|
autoPresent = false,
|
|
96
|
+
showInternalToaster = true,
|
|
100
97
|
}) => {
|
|
101
98
|
// Use the internal ref (which is passed as a prop from OxyProvider)
|
|
102
|
-
const modalRef = useRef<
|
|
99
|
+
const modalRef = useRef<BottomSheetModalRef>(null);
|
|
103
100
|
|
|
104
101
|
// Create a ref to store the navigation function from OxyRouter
|
|
105
102
|
const navigationRef = useRef<((screen: string, props?: Record<string, any>) => void) | null>(null);
|
|
106
103
|
|
|
107
104
|
// Track content height for dynamic sizing
|
|
108
105
|
const [contentHeight, setContentHeight] = useState<number>(0);
|
|
106
|
+
const [containerWidth, setContainerWidth] = useState<number>(800); // Track actual container width
|
|
109
107
|
const screenHeight = Dimensions.get('window').height;
|
|
110
108
|
|
|
111
109
|
// Set up effect to sync the internal ref with our modal ref
|
|
@@ -148,14 +146,14 @@ const OxyBottomSheet: React.FC<OxyProviderProps> = ({
|
|
|
148
146
|
} else {
|
|
149
147
|
// For React Native - use the global variable approach
|
|
150
148
|
console.log('Using React Native global navigation');
|
|
151
|
-
(
|
|
149
|
+
(globalThis as any).oxyNavigateEvent = { screen: screenName, props };
|
|
152
150
|
}
|
|
153
151
|
};
|
|
154
152
|
}
|
|
155
153
|
}, [bottomSheetRef, modalRef]);
|
|
156
154
|
|
|
157
155
|
// Use percentage-based snap points for better cross-platform compatibility
|
|
158
|
-
const [snapPoints, setSnapPoints] = useState<(string | number)[]>(['60%', '
|
|
156
|
+
const [snapPoints, setSnapPoints] = useState<(string | number)[]>(['60%', '90%']);
|
|
159
157
|
|
|
160
158
|
// Animation values - we'll use these for content animations
|
|
161
159
|
// Start with opacity 1 on Android to avoid visibility issues
|
|
@@ -176,15 +174,21 @@ const OxyBottomSheet: React.FC<OxyProviderProps> = ({
|
|
|
176
174
|
const keyboardWillShowListener = Keyboard.addListener(
|
|
177
175
|
Platform.OS === 'ios' ? 'keyboardWillShow' : 'keyboardDidShow',
|
|
178
176
|
(event: KeyboardEvent) => {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
177
|
+
// Debounce rapid keyboard events
|
|
178
|
+
if (!keyboardVisible) {
|
|
179
|
+
setKeyboardVisible(true);
|
|
180
|
+
// Get keyboard height from event
|
|
181
|
+
const keyboardHeightValue = event.endCoordinates.height;
|
|
182
|
+
setKeyboardHeight(keyboardHeightValue);
|
|
183
|
+
|
|
184
|
+
// Ensure the bottom sheet remains visible when keyboard opens
|
|
185
|
+
// by adjusting to the highest snap point
|
|
186
|
+
if (modalRef.current) {
|
|
187
|
+
// Use requestAnimationFrame to avoid conflicts
|
|
188
|
+
requestAnimationFrame(() => {
|
|
189
|
+
modalRef.current?.snapToIndex(1);
|
|
190
|
+
});
|
|
191
|
+
}
|
|
188
192
|
}
|
|
189
193
|
}
|
|
190
194
|
);
|
|
@@ -192,8 +196,10 @@ const OxyBottomSheet: React.FC<OxyProviderProps> = ({
|
|
|
192
196
|
const keyboardWillHideListener = Keyboard.addListener(
|
|
193
197
|
Platform.OS === 'ios' ? 'keyboardWillHide' : 'keyboardDidHide',
|
|
194
198
|
() => {
|
|
195
|
-
|
|
196
|
-
|
|
199
|
+
if (keyboardVisible) {
|
|
200
|
+
setKeyboardVisible(false);
|
|
201
|
+
setKeyboardHeight(0);
|
|
202
|
+
}
|
|
197
203
|
}
|
|
198
204
|
);
|
|
199
205
|
|
|
@@ -202,7 +208,7 @@ const OxyBottomSheet: React.FC<OxyProviderProps> = ({
|
|
|
202
208
|
keyboardWillShowListener.remove();
|
|
203
209
|
keyboardWillHideListener.remove();
|
|
204
210
|
};
|
|
205
|
-
}, []);
|
|
211
|
+
}, [keyboardVisible]);
|
|
206
212
|
|
|
207
213
|
// Present the modal when component mounts, but only if autoPresent is true
|
|
208
214
|
useEffect(() => {
|
|
@@ -229,27 +235,6 @@ const OxyBottomSheet: React.FC<OxyProviderProps> = ({
|
|
|
229
235
|
}),
|
|
230
236
|
]).start();
|
|
231
237
|
};
|
|
232
|
-
|
|
233
|
-
// Override present to also handle animations
|
|
234
|
-
// @ts-ignore - Dynamic method assignment
|
|
235
|
-
bottomSheetRef.current.present = () => {
|
|
236
|
-
modalRef.current?.present();
|
|
237
|
-
|
|
238
|
-
// Start content animations after presenting
|
|
239
|
-
Animated.parallel([
|
|
240
|
-
Animated.timing(fadeAnim, {
|
|
241
|
-
toValue: 1,
|
|
242
|
-
duration: 300,
|
|
243
|
-
useNativeDriver: Platform.OS === 'ios', // Only use native driver on iOS
|
|
244
|
-
}),
|
|
245
|
-
Animated.spring(slideAnim, {
|
|
246
|
-
toValue: 0,
|
|
247
|
-
friction: 8,
|
|
248
|
-
tension: 40,
|
|
249
|
-
useNativeDriver: Platform.OS === 'ios', // Only use native driver on iOS
|
|
250
|
-
}),
|
|
251
|
-
]).start();
|
|
252
|
-
};
|
|
253
238
|
}
|
|
254
239
|
|
|
255
240
|
// Auto-present if the autoPresent prop is true
|
|
@@ -346,20 +331,26 @@ const OxyBottomSheet: React.FC<OxyProviderProps> = ({
|
|
|
346
331
|
// If we have content height, use it as a constraint
|
|
347
332
|
if (contentHeight > 0) {
|
|
348
333
|
// Calculate content height as percentage of screen (plus some padding)
|
|
349
|
-
|
|
334
|
+
// Clamp to ensure we don't exceed 90% to leave space for UI elements
|
|
335
|
+
const contentHeightPercent = Math.min(Math.ceil((contentHeight) / screenHeight * 100), 90);
|
|
336
|
+
const contentHeightPercentStr = `${contentHeightPercent}%`;
|
|
350
337
|
// Use content height for first snap point if it's taller than the default
|
|
351
|
-
const firstPoint = contentHeight / screenHeight > 0.6 ?
|
|
352
|
-
setSnapPoints([firstPoint, points[1]]);
|
|
338
|
+
const firstPoint = contentHeight / screenHeight > 0.6 ? contentHeightPercentStr : points[0];
|
|
339
|
+
setSnapPoints([firstPoint, points[1] || '90%']);
|
|
353
340
|
} else {
|
|
354
341
|
setSnapPoints(points);
|
|
355
342
|
}
|
|
356
343
|
}
|
|
357
344
|
}, [keyboardVisible, contentHeight, screenHeight]);
|
|
358
345
|
|
|
359
|
-
// Handle content layout changes to measure height
|
|
346
|
+
// Handle content layout changes to measure height and width
|
|
360
347
|
const handleContentLayout = useCallback((event: any) => {
|
|
361
|
-
const layoutHeight = event.nativeEvent.layout
|
|
348
|
+
const { height: layoutHeight, width: layoutWidth } = event.nativeEvent.layout;
|
|
362
349
|
setContentHeight(layoutHeight);
|
|
350
|
+
setContainerWidth(layoutWidth);
|
|
351
|
+
|
|
352
|
+
// Debug: log container dimensions
|
|
353
|
+
console.log('[OxyProvider] Container dimensions (full):', { width: layoutWidth, height: layoutHeight });
|
|
363
354
|
|
|
364
355
|
// Update snap points based on new content height
|
|
365
356
|
if (keyboardVisible) {
|
|
@@ -368,8 +359,10 @@ const OxyBottomSheet: React.FC<OxyProviderProps> = ({
|
|
|
368
359
|
setSnapPoints([highestPoint, highestPoint]);
|
|
369
360
|
} else {
|
|
370
361
|
if (layoutHeight > 0) {
|
|
371
|
-
|
|
372
|
-
const
|
|
362
|
+
// Add padding and clamp to reasonable limits
|
|
363
|
+
const contentHeightPercent = Math.min(Math.ceil((layoutHeight + 40) / screenHeight * 100), 90);
|
|
364
|
+
const contentHeightPercentStr = `${contentHeightPercent}%`;
|
|
365
|
+
const firstPoint = layoutHeight / screenHeight > 0.6 ? contentHeightPercentStr : snapPoints[0];
|
|
373
366
|
setSnapPoints([firstPoint, snapPoints[1]]);
|
|
374
367
|
}
|
|
375
368
|
}
|
|
@@ -395,27 +388,6 @@ const OxyBottomSheet: React.FC<OxyProviderProps> = ({
|
|
|
395
388
|
|
|
396
389
|
// Handle sheet index changes
|
|
397
390
|
const handleSheetChanges = useCallback((index: number) => {
|
|
398
|
-
if (index === -1 && onClose) {
|
|
399
|
-
onClose();
|
|
400
|
-
} else if (index === 1) {
|
|
401
|
-
// Pulse animation when expanded to full height
|
|
402
|
-
Animated.sequence([
|
|
403
|
-
Animated.timing(handleScaleAnim, {
|
|
404
|
-
toValue: 1.2,
|
|
405
|
-
duration: 200,
|
|
406
|
-
useNativeDriver: Platform.OS === 'ios', // Only use native driver on iOS
|
|
407
|
-
}),
|
|
408
|
-
Animated.timing(handleScaleAnim, {
|
|
409
|
-
toValue: 1,
|
|
410
|
-
duration: 200,
|
|
411
|
-
useNativeDriver: Platform.OS === 'ios', // Only use native driver on iOS
|
|
412
|
-
}),
|
|
413
|
-
]).start();
|
|
414
|
-
} else if (index === 0 && keyboardVisible) {
|
|
415
|
-
// If keyboard is visible and user tries to go to a smaller snap point,
|
|
416
|
-
// force the sheet to stay at the highest point for better visibility
|
|
417
|
-
modalRef.current?.snapToIndex(1);
|
|
418
|
-
}
|
|
419
391
|
}, [onClose, handleScaleAnim, keyboardVisible]);
|
|
420
392
|
|
|
421
393
|
return (
|
|
@@ -425,23 +397,6 @@ const OxyBottomSheet: React.FC<OxyProviderProps> = ({
|
|
|
425
397
|
snapPoints={snapPoints}
|
|
426
398
|
enablePanDownToClose
|
|
427
399
|
backdropComponent={renderBackdrop}
|
|
428
|
-
// Remove enableDynamicSizing as we're implementing our own solution
|
|
429
|
-
handleComponent={() => (
|
|
430
|
-
<Animated.View
|
|
431
|
-
style={{
|
|
432
|
-
alignItems: 'center',
|
|
433
|
-
paddingVertical: 8,
|
|
434
|
-
...(Platform.OS === 'ios' ? {
|
|
435
|
-
transform: [{ scale: handleScaleAnim }]
|
|
436
|
-
} : {})
|
|
437
|
-
}}
|
|
438
|
-
>
|
|
439
|
-
<View style={[
|
|
440
|
-
styles.indicator,
|
|
441
|
-
{ backgroundColor: customStyles.handleColor || (theme === 'light' ? '#CCCCCC' : '#444444') }
|
|
442
|
-
]} />
|
|
443
|
-
</Animated.View>
|
|
444
|
-
)}
|
|
445
400
|
backgroundStyle={[
|
|
446
401
|
getBackgroundStyle(),
|
|
447
402
|
{
|
|
@@ -455,6 +410,7 @@ const OxyBottomSheet: React.FC<OxyProviderProps> = ({
|
|
|
455
410
|
height: 4,
|
|
456
411
|
}}
|
|
457
412
|
onChange={handleSheetChanges}
|
|
413
|
+
style={styles.bottomSheetContainer}
|
|
458
414
|
// Adding additional props to improve layout behavior
|
|
459
415
|
keyboardBehavior="interactive"
|
|
460
416
|
keyboardBlurBehavior="restore"
|
|
@@ -477,38 +433,57 @@ const OxyBottomSheet: React.FC<OxyProviderProps> = ({
|
|
|
477
433
|
]}
|
|
478
434
|
onLayout={handleContentLayout}
|
|
479
435
|
>
|
|
480
|
-
<
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
436
|
+
<View style={styles.centeredContentWrapper}>
|
|
437
|
+
<Animated.View
|
|
438
|
+
style={[
|
|
439
|
+
styles.animatedContent,
|
|
440
|
+
// Apply animations - conditionally for Android
|
|
441
|
+
Platform.OS === 'android' ?
|
|
442
|
+
{
|
|
443
|
+
opacity: 1, // No fade animation on Android
|
|
444
|
+
} : {
|
|
445
|
+
opacity: fadeAnim,
|
|
446
|
+
transform: [{ translateY: slideAnim }]
|
|
447
|
+
}
|
|
448
|
+
]}
|
|
449
|
+
>
|
|
450
|
+
<OxyRouter
|
|
451
|
+
oxyServices={oxyServices}
|
|
452
|
+
initialScreen={initialScreen}
|
|
453
|
+
onClose={handleClose}
|
|
454
|
+
onAuthenticated={handleAuthenticated}
|
|
455
|
+
theme={theme}
|
|
456
|
+
adjustSnapPoints={adjustSnapPoints}
|
|
457
|
+
navigationRef={navigationRef}
|
|
458
|
+
containerWidth={containerWidth}
|
|
459
|
+
/>
|
|
460
|
+
</Animated.View>
|
|
461
|
+
</View>
|
|
503
462
|
</BottomSheetScrollView>
|
|
463
|
+
{/* Internal toaster - only show if showInternalToaster is true */}
|
|
464
|
+
{showInternalToaster && (
|
|
465
|
+
<View style={styles.toasterContainer}>
|
|
466
|
+
<Toaster position="top-center" swipeToDismissDirection="left" />
|
|
467
|
+
</View>
|
|
468
|
+
)}
|
|
504
469
|
</BottomSheetModal>
|
|
505
470
|
);
|
|
506
471
|
};
|
|
507
472
|
|
|
508
473
|
const styles = StyleSheet.create({
|
|
474
|
+
bottomSheetContainer: {
|
|
475
|
+
maxWidth: 800,
|
|
476
|
+
width: '100%',
|
|
477
|
+
marginHorizontal: 'auto',
|
|
478
|
+
},
|
|
509
479
|
contentContainer: {
|
|
510
480
|
width: '100%',
|
|
511
|
-
|
|
481
|
+
borderTopLeftRadius: 35,
|
|
482
|
+
borderTopRightRadius: 35,
|
|
483
|
+
},
|
|
484
|
+
centeredContentWrapper: {
|
|
485
|
+
width: '100%',
|
|
486
|
+
marginHorizontal: 'auto',
|
|
512
487
|
},
|
|
513
488
|
animatedContent: {
|
|
514
489
|
width: '100%',
|
|
@@ -516,7 +491,6 @@ const styles = StyleSheet.create({
|
|
|
516
491
|
indicator: {
|
|
517
492
|
width: 40,
|
|
518
493
|
height: 4,
|
|
519
|
-
alignSelf: 'center',
|
|
520
494
|
marginTop: 8,
|
|
521
495
|
marginBottom: 8,
|
|
522
496
|
borderRadius: 35,
|
|
@@ -531,6 +505,7 @@ const styles = StyleSheet.create({
|
|
|
531
505
|
position: 'relative',
|
|
532
506
|
backgroundColor: 'transparent',
|
|
533
507
|
...Platform.select({
|
|
508
|
+
|
|
534
509
|
android: {
|
|
535
510
|
height: '100%',
|
|
536
511
|
width: '100%',
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';
|
|
3
|
+
import { Ionicons } from '@expo/vector-icons';
|
|
4
|
+
import Avatar from './Avatar';
|
|
5
|
+
import { fontFamilies } from '../styles/fonts';
|
|
6
|
+
|
|
7
|
+
interface ProfileCardProps {
|
|
8
|
+
user: {
|
|
9
|
+
username: string;
|
|
10
|
+
email?: string;
|
|
11
|
+
name?: {
|
|
12
|
+
full?: string;
|
|
13
|
+
};
|
|
14
|
+
avatar?: {
|
|
15
|
+
url?: string;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
theme: 'light' | 'dark';
|
|
19
|
+
onEditPress?: () => void;
|
|
20
|
+
onClosePress?: () => void;
|
|
21
|
+
showCloseButton?: boolean;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const ProfileCard: React.FC<ProfileCardProps> = ({
|
|
25
|
+
user,
|
|
26
|
+
theme,
|
|
27
|
+
onEditPress,
|
|
28
|
+
onClosePress,
|
|
29
|
+
showCloseButton = false,
|
|
30
|
+
}) => {
|
|
31
|
+
const isDarkTheme = theme === 'dark';
|
|
32
|
+
const textColor = isDarkTheme ? '#FFFFFF' : '#000000';
|
|
33
|
+
const secondaryBackgroundColor = isDarkTheme ? '#222222' : '#FFFFFF';
|
|
34
|
+
const primaryColor = '#0066CC';
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<View style={styles.headerSection}>
|
|
38
|
+
<View style={[
|
|
39
|
+
styles.profileCard,
|
|
40
|
+
styles.firstGroupedItem,
|
|
41
|
+
styles.lastGroupedItem,
|
|
42
|
+
{ backgroundColor: secondaryBackgroundColor }
|
|
43
|
+
]}>
|
|
44
|
+
<View style={styles.userProfile}>
|
|
45
|
+
<Avatar
|
|
46
|
+
uri={user?.avatar?.url}
|
|
47
|
+
name={user?.name?.full || user?.username}
|
|
48
|
+
size={60}
|
|
49
|
+
theme={theme}
|
|
50
|
+
/>
|
|
51
|
+
<View style={styles.userInfo}>
|
|
52
|
+
<Text style={[styles.userName, { color: textColor }]}>{user.username}</Text>
|
|
53
|
+
{user.email && (
|
|
54
|
+
<Text style={[styles.userEmail, { color: isDarkTheme ? '#BBBBBB' : '#666666' }]}>
|
|
55
|
+
{user.email}
|
|
56
|
+
</Text>
|
|
57
|
+
)}
|
|
58
|
+
{onEditPress && (
|
|
59
|
+
<TouchableOpacity
|
|
60
|
+
style={styles.editProfileButton}
|
|
61
|
+
onPress={onEditPress}
|
|
62
|
+
>
|
|
63
|
+
<Text style={[styles.editProfileText, { color: primaryColor }]}>Edit Profile</Text>
|
|
64
|
+
</TouchableOpacity>
|
|
65
|
+
)}
|
|
66
|
+
</View>
|
|
67
|
+
</View>
|
|
68
|
+
{showCloseButton && onClosePress && (
|
|
69
|
+
<TouchableOpacity style={styles.closeButton} onPress={onClosePress}>
|
|
70
|
+
<Ionicons name="close" size={24} color={textColor} />
|
|
71
|
+
</TouchableOpacity>
|
|
72
|
+
)}
|
|
73
|
+
</View>
|
|
74
|
+
</View>
|
|
75
|
+
);
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const styles = StyleSheet.create({
|
|
79
|
+
headerSection: {
|
|
80
|
+
padding: 16,
|
|
81
|
+
paddingTop: 20,
|
|
82
|
+
},
|
|
83
|
+
profileCard: {
|
|
84
|
+
padding: 20,
|
|
85
|
+
flexDirection: 'row',
|
|
86
|
+
alignItems: 'center',
|
|
87
|
+
justifyContent: 'space-between',
|
|
88
|
+
},
|
|
89
|
+
firstGroupedItem: {
|
|
90
|
+
borderTopLeftRadius: 24,
|
|
91
|
+
borderTopRightRadius: 24,
|
|
92
|
+
},
|
|
93
|
+
lastGroupedItem: {
|
|
94
|
+
borderBottomLeftRadius: 24,
|
|
95
|
+
borderBottomRightRadius: 24,
|
|
96
|
+
marginBottom: 8,
|
|
97
|
+
},
|
|
98
|
+
userProfile: {
|
|
99
|
+
flexDirection: 'row',
|
|
100
|
+
alignItems: 'center',
|
|
101
|
+
flex: 1,
|
|
102
|
+
},
|
|
103
|
+
userInfo: {
|
|
104
|
+
marginLeft: 16,
|
|
105
|
+
flex: 1,
|
|
106
|
+
},
|
|
107
|
+
userName: {
|
|
108
|
+
fontSize: 22,
|
|
109
|
+
fontWeight: 'bold',
|
|
110
|
+
fontFamily: fontFamilies.phuduBold,
|
|
111
|
+
marginBottom: 4,
|
|
112
|
+
},
|
|
113
|
+
userEmail: {
|
|
114
|
+
fontSize: 14,
|
|
115
|
+
marginBottom: 8,
|
|
116
|
+
},
|
|
117
|
+
editProfileButton: {
|
|
118
|
+
alignSelf: 'flex-start',
|
|
119
|
+
},
|
|
120
|
+
editProfileText: {
|
|
121
|
+
fontSize: 14,
|
|
122
|
+
fontWeight: '600',
|
|
123
|
+
},
|
|
124
|
+
closeButton: {
|
|
125
|
+
padding: 8,
|
|
126
|
+
},
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
export default ProfileCard;
|