@oxyhq/services 5.7.5 → 5.8.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.
Files changed (239) hide show
  1. package/README.md +76 -76
  2. package/lib/commonjs/core/index.js +177 -102
  3. package/lib/commonjs/core/index.js.map +1 -1
  4. package/lib/commonjs/index.js +88 -29
  5. package/lib/commonjs/index.js.map +1 -1
  6. package/lib/commonjs/node/createAuth.js +585 -7
  7. package/lib/commonjs/node/createAuth.js.map +1 -1
  8. package/lib/commonjs/node/index.js +38 -1
  9. package/lib/commonjs/node/index.js.map +1 -1
  10. package/lib/commonjs/ui/components/Avatar.js +15 -6
  11. package/lib/commonjs/ui/components/Avatar.js.map +1 -1
  12. package/lib/commonjs/ui/components/GroupedItem.js +58 -13
  13. package/lib/commonjs/ui/components/GroupedItem.js.map +1 -1
  14. package/lib/commonjs/ui/components/GroupedSection.js +7 -1
  15. package/lib/commonjs/ui/components/GroupedSection.js.map +1 -1
  16. package/lib/commonjs/ui/components/Header.js +322 -0
  17. package/lib/commonjs/ui/components/Header.js.map +1 -0
  18. package/lib/commonjs/ui/components/OxyProvider.js +23 -7
  19. package/lib/commonjs/ui/components/OxyProvider.js.map +1 -1
  20. package/lib/commonjs/ui/components/index.js +7 -0
  21. package/lib/commonjs/ui/components/index.js.map +1 -1
  22. package/lib/commonjs/ui/components/internal/GroupedPillButtons.js +1 -1
  23. package/lib/commonjs/ui/components/internal/GroupedPillButtons.js.map +1 -1
  24. package/lib/commonjs/ui/components/internal/TextField.js +606 -546
  25. package/lib/commonjs/ui/components/internal/TextField.js.map +1 -1
  26. package/lib/commonjs/ui/components/internal/TextField.md +436 -0
  27. package/lib/commonjs/ui/context/OxyContext.js +122 -78
  28. package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
  29. package/lib/commonjs/ui/hooks/useSessionSocket.js +5 -2
  30. package/lib/commonjs/ui/hooks/useSessionSocket.js.map +1 -1
  31. package/lib/commonjs/ui/navigation/OxyRouter.js +1 -1
  32. package/lib/commonjs/ui/navigation/OxyRouter.js.map +1 -1
  33. package/lib/commonjs/ui/screens/AccountCenterScreen.js +6 -6
  34. package/lib/commonjs/ui/screens/AccountCenterScreen.js.map +1 -1
  35. package/lib/commonjs/ui/screens/AccountManagementDemo.js +3 -3
  36. package/lib/commonjs/ui/screens/AccountManagementDemo.js.map +1 -1
  37. package/lib/commonjs/ui/screens/AccountOverviewScreen.js +241 -598
  38. package/lib/commonjs/ui/screens/AccountOverviewScreen.js.map +1 -1
  39. package/lib/commonjs/ui/screens/AccountSettingsScreen.js +1151 -406
  40. package/lib/commonjs/ui/screens/AccountSettingsScreen.js.map +1 -1
  41. package/lib/commonjs/ui/screens/AccountSwitcherScreen.js +135 -237
  42. package/lib/commonjs/ui/screens/AccountSwitcherScreen.js.map +1 -1
  43. package/lib/commonjs/ui/screens/AppInfoScreen.js +246 -463
  44. package/lib/commonjs/ui/screens/AppInfoScreen.js.map +1 -1
  45. package/lib/commonjs/ui/screens/FeedbackScreen.js +3 -3
  46. package/lib/commonjs/ui/screens/FeedbackScreen.js.map +1 -1
  47. package/lib/commonjs/ui/screens/PaymentGatewayScreen.js +808 -650
  48. package/lib/commonjs/ui/screens/PaymentGatewayScreen.js.map +1 -1
  49. package/lib/commonjs/ui/screens/RecoverAccountScreen.js +51 -72
  50. package/lib/commonjs/ui/screens/RecoverAccountScreen.js.map +1 -1
  51. package/lib/commonjs/ui/screens/SessionManagementScreen.js +11 -29
  52. package/lib/commonjs/ui/screens/SessionManagementScreen.js.map +1 -1
  53. package/lib/commonjs/ui/screens/SignInScreen.js +30 -303
  54. package/lib/commonjs/ui/screens/SignInScreen.js.map +1 -1
  55. package/lib/commonjs/ui/screens/SignUpScreen.js +4 -4
  56. package/lib/commonjs/ui/screens/SignUpScreen.js.map +1 -1
  57. package/lib/commonjs/ui/screens/internal/SignInPasswordStep.js +19 -31
  58. package/lib/commonjs/ui/screens/internal/SignInPasswordStep.js.map +1 -1
  59. package/lib/commonjs/ui/screens/internal/SignInUsernameStep.js +7 -10
  60. package/lib/commonjs/ui/screens/internal/SignInUsernameStep.js.map +1 -1
  61. package/lib/commonjs/ui/screens/internal/SignUpIdentityStep.js +11 -5
  62. package/lib/commonjs/ui/screens/internal/SignUpIdentityStep.js.map +1 -1
  63. package/lib/commonjs/ui/screens/internal/SignUpSecurityStep.js +11 -4
  64. package/lib/commonjs/ui/screens/internal/SignUpSecurityStep.js.map +1 -1
  65. package/lib/commonjs/ui/stores/authStore.js +12 -0
  66. package/lib/commonjs/ui/stores/authStore.js.map +1 -1
  67. package/lib/commonjs/ui/styles/authStyles.js +337 -0
  68. package/lib/commonjs/ui/styles/authStyles.js.map +1 -0
  69. package/lib/commonjs/ui/styles/index.js +11 -0
  70. package/lib/commonjs/ui/styles/index.js.map +1 -1
  71. package/lib/module/core/index.js +177 -41
  72. package/lib/module/core/index.js.map +1 -1
  73. package/lib/module/index.js +26 -4
  74. package/lib/module/index.js.map +1 -1
  75. package/lib/module/node/createAuth.js +584 -7
  76. package/lib/module/node/createAuth.js.map +1 -1
  77. package/lib/module/node/index.js +7 -1
  78. package/lib/module/node/index.js.map +1 -1
  79. package/lib/module/ui/components/Avatar.js +15 -6
  80. package/lib/module/ui/components/Avatar.js.map +1 -1
  81. package/lib/module/ui/components/GroupedItem.js +59 -14
  82. package/lib/module/ui/components/GroupedItem.js.map +1 -1
  83. package/lib/module/ui/components/GroupedSection.js +7 -1
  84. package/lib/module/ui/components/GroupedSection.js.map +1 -1
  85. package/lib/module/ui/components/Header.js +317 -0
  86. package/lib/module/ui/components/Header.js.map +1 -0
  87. package/lib/module/ui/components/OxyProvider.js +25 -9
  88. package/lib/module/ui/components/OxyProvider.js.map +1 -1
  89. package/lib/module/ui/components/index.js +1 -0
  90. package/lib/module/ui/components/index.js.map +1 -1
  91. package/lib/module/ui/components/internal/GroupedPillButtons.js +1 -1
  92. package/lib/module/ui/components/internal/GroupedPillButtons.js.map +1 -1
  93. package/lib/module/ui/components/internal/TextField.js +607 -547
  94. package/lib/module/ui/components/internal/TextField.js.map +1 -1
  95. package/lib/module/ui/components/internal/TextField.md +436 -0
  96. package/lib/module/ui/context/OxyContext.js +121 -77
  97. package/lib/module/ui/context/OxyContext.js.map +1 -1
  98. package/lib/module/ui/hooks/useSessionSocket.js +5 -2
  99. package/lib/module/ui/hooks/useSessionSocket.js.map +1 -1
  100. package/lib/module/ui/navigation/OxyRouter.js +1 -1
  101. package/lib/module/ui/navigation/OxyRouter.js.map +1 -1
  102. package/lib/module/ui/screens/AccountCenterScreen.js +6 -6
  103. package/lib/module/ui/screens/AccountCenterScreen.js.map +1 -1
  104. package/lib/module/ui/screens/AccountManagementDemo.js +3 -3
  105. package/lib/module/ui/screens/AccountManagementDemo.js.map +1 -1
  106. package/lib/module/ui/screens/AccountOverviewScreen.js +242 -597
  107. package/lib/module/ui/screens/AccountOverviewScreen.js.map +1 -1
  108. package/lib/module/ui/screens/AccountSettingsScreen.js +1152 -407
  109. package/lib/module/ui/screens/AccountSettingsScreen.js.map +1 -1
  110. package/lib/module/ui/screens/AccountSwitcherScreen.js +135 -237
  111. package/lib/module/ui/screens/AccountSwitcherScreen.js.map +1 -1
  112. package/lib/module/ui/screens/AppInfoScreen.js +248 -465
  113. package/lib/module/ui/screens/AppInfoScreen.js.map +1 -1
  114. package/lib/module/ui/screens/FeedbackScreen.js +3 -3
  115. package/lib/module/ui/screens/FeedbackScreen.js.map +1 -1
  116. package/lib/module/ui/screens/PaymentGatewayScreen.js +809 -651
  117. package/lib/module/ui/screens/PaymentGatewayScreen.js.map +1 -1
  118. package/lib/module/ui/screens/RecoverAccountScreen.js +53 -74
  119. package/lib/module/ui/screens/RecoverAccountScreen.js.map +1 -1
  120. package/lib/module/ui/screens/SessionManagementScreen.js +11 -29
  121. package/lib/module/ui/screens/SessionManagementScreen.js.map +1 -1
  122. package/lib/module/ui/screens/SignInScreen.js +32 -305
  123. package/lib/module/ui/screens/SignInScreen.js.map +1 -1
  124. package/lib/module/ui/screens/SignUpScreen.js +5 -5
  125. package/lib/module/ui/screens/SignUpScreen.js.map +1 -1
  126. package/lib/module/ui/screens/internal/SignInPasswordStep.js +19 -31
  127. package/lib/module/ui/screens/internal/SignInPasswordStep.js.map +1 -1
  128. package/lib/module/ui/screens/internal/SignInUsernameStep.js +7 -10
  129. package/lib/module/ui/screens/internal/SignInUsernameStep.js.map +1 -1
  130. package/lib/module/ui/screens/internal/SignUpIdentityStep.js +11 -5
  131. package/lib/module/ui/screens/internal/SignUpIdentityStep.js.map +1 -1
  132. package/lib/module/ui/screens/internal/SignUpSecurityStep.js +11 -4
  133. package/lib/module/ui/screens/internal/SignUpSecurityStep.js.map +1 -1
  134. package/lib/module/ui/stores/authStore.js +12 -0
  135. package/lib/module/ui/stores/authStore.js.map +1 -1
  136. package/lib/module/ui/styles/authStyles.js +332 -0
  137. package/lib/module/ui/styles/authStyles.js.map +1 -0
  138. package/lib/module/ui/styles/index.js +1 -0
  139. package/lib/module/ui/styles/index.js.map +1 -1
  140. package/lib/typescript/core/index.d.ts +68 -24
  141. package/lib/typescript/core/index.d.ts.map +1 -1
  142. package/lib/typescript/index.d.ts +13 -3
  143. package/lib/typescript/index.d.ts.map +1 -1
  144. package/lib/typescript/node/createAuth.d.ts +112 -0
  145. package/lib/typescript/node/createAuth.d.ts.map +1 -1
  146. package/lib/typescript/node/index.d.ts +2 -0
  147. package/lib/typescript/node/index.d.ts.map +1 -1
  148. package/lib/typescript/ui/components/Avatar.d.ts.map +1 -1
  149. package/lib/typescript/ui/components/GroupedItem.d.ts +6 -0
  150. package/lib/typescript/ui/components/GroupedItem.d.ts.map +1 -1
  151. package/lib/typescript/ui/components/GroupedSection.d.ts +6 -0
  152. package/lib/typescript/ui/components/GroupedSection.d.ts.map +1 -1
  153. package/lib/typescript/ui/components/Header.d.ts +22 -0
  154. package/lib/typescript/ui/components/Header.d.ts.map +1 -0
  155. package/lib/typescript/ui/components/OxyProvider.d.ts.map +1 -1
  156. package/lib/typescript/ui/components/index.d.ts +1 -0
  157. package/lib/typescript/ui/components/index.d.ts.map +1 -1
  158. package/lib/typescript/ui/components/internal/TextField.d.ts +31 -16
  159. package/lib/typescript/ui/components/internal/TextField.d.ts.map +1 -1
  160. package/lib/typescript/ui/context/OxyContext.d.ts +5 -2
  161. package/lib/typescript/ui/context/OxyContext.d.ts.map +1 -1
  162. package/lib/typescript/ui/hooks/useSessionSocket.d.ts.map +1 -1
  163. package/lib/typescript/ui/navigation/types.d.ts +9 -2
  164. package/lib/typescript/ui/navigation/types.d.ts.map +1 -1
  165. package/lib/typescript/ui/screens/AccountOverviewScreen.d.ts.map +1 -1
  166. package/lib/typescript/ui/screens/AccountSettingsScreen.d.ts.map +1 -1
  167. package/lib/typescript/ui/screens/AccountSwitcherScreen.d.ts.map +1 -1
  168. package/lib/typescript/ui/screens/AppInfoScreen.d.ts.map +1 -1
  169. package/lib/typescript/ui/screens/PaymentGatewayScreen.d.ts.map +1 -1
  170. package/lib/typescript/ui/screens/RecoverAccountScreen.d.ts +5 -1
  171. package/lib/typescript/ui/screens/RecoverAccountScreen.d.ts.map +1 -1
  172. package/lib/typescript/ui/screens/SessionManagementScreen.d.ts.map +1 -1
  173. package/lib/typescript/ui/screens/SignInScreen.d.ts.map +1 -1
  174. package/lib/typescript/ui/screens/internal/SignInPasswordStep.d.ts +1 -1
  175. package/lib/typescript/ui/screens/internal/SignInPasswordStep.d.ts.map +1 -1
  176. package/lib/typescript/ui/screens/internal/SignInUsernameStep.d.ts +0 -1
  177. package/lib/typescript/ui/screens/internal/SignInUsernameStep.d.ts.map +1 -1
  178. package/lib/typescript/ui/screens/internal/SignUpIdentityStep.d.ts.map +1 -1
  179. package/lib/typescript/ui/screens/internal/SignUpSecurityStep.d.ts.map +1 -1
  180. package/lib/typescript/ui/stores/authStore.d.ts.map +1 -1
  181. package/lib/typescript/ui/styles/authStyles.d.ts +326 -0
  182. package/lib/typescript/ui/styles/authStyles.d.ts.map +1 -0
  183. package/lib/typescript/ui/styles/index.d.ts +1 -0
  184. package/lib/typescript/ui/styles/index.d.ts.map +1 -1
  185. package/package.json +1 -4
  186. package/src/core/index.ts +195 -41
  187. package/src/index.ts +72 -4
  188. package/src/node/createAuth.ts +623 -7
  189. package/src/node/index.ts +19 -1
  190. package/src/ui/components/Avatar.tsx +11 -5
  191. package/src/ui/components/GroupedItem.tsx +57 -9
  192. package/src/ui/components/GroupedSection.tsx +12 -0
  193. package/src/ui/components/Header.tsx +364 -0
  194. package/src/ui/components/OxyProvider.tsx +31 -15
  195. package/src/ui/components/index.ts +1 -0
  196. package/src/ui/components/internal/GroupedPillButtons.tsx +1 -1
  197. package/src/ui/components/internal/TextField.md +436 -0
  198. package/src/ui/components/internal/TextField.tsx +720 -620
  199. package/src/ui/context/OxyContext.tsx +150 -63
  200. package/src/ui/hooks/useSessionSocket.ts +5 -2
  201. package/src/ui/navigation/OxyRouter.tsx +1 -1
  202. package/src/ui/navigation/types.ts +10 -2
  203. package/src/ui/screens/AccountCenterScreen.tsx +5 -5
  204. package/src/ui/screens/AccountManagementDemo.tsx +9 -9
  205. package/src/ui/screens/AccountOverviewScreen.tsx +265 -414
  206. package/src/ui/screens/AccountSettingsScreen.tsx +1165 -403
  207. package/src/ui/screens/AccountSwitcherScreen.tsx +158 -202
  208. package/src/ui/screens/AppInfoScreen.tsx +270 -497
  209. package/src/ui/screens/FeedbackScreen.tsx +3 -3
  210. package/src/ui/screens/PaymentGatewayScreen.tsx +668 -365
  211. package/src/ui/screens/ProfileScreen.tsx +5 -5
  212. package/src/ui/screens/RecoverAccountScreen.tsx +46 -74
  213. package/src/ui/screens/SessionManagementScreen.tsx +14 -22
  214. package/src/ui/screens/SignInScreen.tsx +27 -294
  215. package/src/ui/screens/SignUpScreen.tsx +5 -5
  216. package/src/ui/screens/internal/SignInPasswordStep.tsx +11 -22
  217. package/src/ui/screens/internal/SignInUsernameStep.tsx +3 -10
  218. package/src/ui/screens/internal/SignUpIdentityStep.tsx +2 -5
  219. package/src/ui/screens/internal/SignUpSecurityStep.tsx +3 -4
  220. package/src/ui/stores/authStore.ts +12 -0
  221. package/src/ui/styles/authStyles.ts +352 -0
  222. package/src/ui/styles/index.ts +1 -0
  223. package/lib/commonjs/core/auth-manager.js +0 -440
  224. package/lib/commonjs/core/auth-manager.js.map +0 -1
  225. package/lib/commonjs/core/use-auth.js +0 -244
  226. package/lib/commonjs/core/use-auth.js.map +0 -1
  227. package/lib/module/core/auth-manager.js +0 -432
  228. package/lib/module/core/auth-manager.js.map +0 -1
  229. package/lib/module/core/use-auth.js +0 -235
  230. package/lib/module/core/use-auth.js.map +0 -1
  231. package/lib/typescript/core/auth-manager.d.ts +0 -136
  232. package/lib/typescript/core/auth-manager.d.ts.map +0 -1
  233. package/lib/typescript/core/use-auth.d.ts +0 -79
  234. package/lib/typescript/core/use-auth.d.ts.map +0 -1
  235. package/src/__tests__/middleware.test.ts +0 -105
  236. package/src/__tests__/setup.ts +0 -10
  237. package/src/__tests__/zero-config-auth.test.ts +0 -607
  238. package/src/core/auth-manager.ts +0 -500
  239. package/src/core/use-auth.tsx +0 -245
package/src/node/index.ts CHANGED
@@ -7,10 +7,28 @@ import { OxyServices, OXY_CLOUD_URL } from '../core'; // Adjusted path
7
7
  import { createAuth } from './createAuth';
8
8
  import * as Models from '../models/interfaces'; // Adjusted path
9
9
 
10
+ // ------------- Enhanced Authentication Imports -------------
11
+ import {
12
+ OxyAuth,
13
+ AuthRequest,
14
+ AuthOptions,
15
+ AuthMiddlewareOptions,
16
+ TokenValidationResult
17
+ } from './createAuth';
18
+
10
19
  // ------------- Core Exports -------------
11
20
  export { OxyServices, OXY_CLOUD_URL };
12
21
 
13
- // Zero-config auth and session router
22
+ // ------------- Enhanced Authentication Exports -------------
23
+ export {
24
+ OxyAuth,
25
+ AuthRequest,
26
+ AuthOptions,
27
+ AuthMiddlewareOptions,
28
+ TokenValidationResult
29
+ };
30
+
31
+ // Zero-config auth and session router (legacy)
14
32
  export { createAuth };
15
33
 
16
34
  // ------------- Model Exports -------------
@@ -112,13 +112,15 @@ const Avatar: React.FC<AvatarProps> = ({
112
112
  );
113
113
  }
114
114
 
115
- // If an image URL is provided, use Image component
115
+ // If an image URL is provided, use Image component with optional background
116
116
  if (uri) {
117
117
  return (
118
- <Image
119
- source={{ uri: uri }}
120
- style={[styles.container, containerStyle, imageStyle]}
121
- />
118
+ <View style={[styles.container, containerStyle, { backgroundColor: bgColor }, style]}>
119
+ <Image
120
+ source={{ uri: uri }}
121
+ style={[styles.image, containerStyle, imageStyle]}
122
+ />
123
+ </View>
122
124
  );
123
125
  }
124
126
 
@@ -146,6 +148,10 @@ const styles = StyleSheet.create({
146
148
  justifyContent: 'center',
147
149
  alignItems: 'center',
148
150
  },
151
+ image: {
152
+ width: '100%',
153
+ height: '100%',
154
+ },
149
155
  text: {
150
156
  // Font family is applied directly in the component to use the constants
151
157
  fontWeight: Platform.OS === 'web' ? 'bold' : undefined, // Only apply fontWeight on web
@@ -1,10 +1,12 @@
1
1
  import React from 'react';
2
- import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';
2
+ import { View, Text, TouchableOpacity, StyleSheet, Image } from 'react-native';
3
3
  import { Ionicons } from '@expo/vector-icons';
4
4
 
5
5
  interface GroupedItemProps {
6
6
  icon?: string;
7
7
  iconColor?: string;
8
+ image?: string;
9
+ imageSize?: number;
8
10
  title: string;
9
11
  subtitle?: string;
10
12
  theme: 'light' | 'dark';
@@ -13,12 +15,18 @@ interface GroupedItemProps {
13
15
  isLast?: boolean;
14
16
  showChevron?: boolean;
15
17
  disabled?: boolean;
18
+ selected?: boolean;
16
19
  customContent?: React.ReactNode;
20
+ customIcon?: React.ReactNode;
21
+ multiRow?: boolean;
22
+ customContentBelow?: React.ReactNode;
17
23
  }
18
24
 
19
25
  const GroupedItem: React.FC<GroupedItemProps> = ({
20
26
  icon,
21
27
  iconColor = '#007AFF',
28
+ image,
29
+ imageSize = 20,
22
30
  title,
23
31
  subtitle,
24
32
  theme,
@@ -27,36 +35,57 @@ const GroupedItem: React.FC<GroupedItemProps> = ({
27
35
  isLast = false,
28
36
  showChevron = true,
29
37
  disabled = false,
38
+ selected = false,
30
39
  customContent,
40
+ customIcon,
41
+ multiRow = false,
42
+ customContentBelow,
31
43
  }) => {
32
44
  const isDarkTheme = theme === 'dark';
33
45
  const textColor = isDarkTheme ? '#FFFFFF' : '#000000';
34
46
  const secondaryBackgroundColor = isDarkTheme ? '#222222' : '#FFFFFF';
47
+ const selectedBackgroundColor = selected ? `${iconColor}15` : secondaryBackgroundColor;
35
48
 
36
49
  const itemStyles = [
37
50
  styles.groupedItem,
38
51
  isFirst && styles.firstGroupedItem,
39
52
  isLast && styles.lastGroupedItem,
40
- { backgroundColor: secondaryBackgroundColor },
53
+ {
54
+ backgroundColor: selected ? selectedBackgroundColor : secondaryBackgroundColor,
55
+ },
41
56
  ];
42
57
 
43
58
  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}>
59
+ <View style={[styles.groupedItemContent, multiRow && styles.groupedItemContentMultiRow]}>
60
+ {customIcon ? (
61
+ <View style={styles.actionIcon}>
62
+ {customIcon}
63
+ </View>
64
+ ) : image ? (
65
+ <Image
66
+ source={{ uri: image }}
67
+ style={[styles.actionImage, { width: imageSize, height: imageSize }]}
68
+ />
69
+ ) : icon ? (
70
+ <View style={[styles.iconContainer, { backgroundColor: `${iconColor}20` }]}>
71
+ <Ionicons name={icon as any} size={20} color={iconColor} />
72
+ </View>
73
+ ) : null}
74
+ <View style={[styles.actionTextContainer, multiRow && styles.actionTextContainerMultiRow]}>
49
75
  <Text style={[styles.actionButtonText, { color: textColor }]}>{title}</Text>
50
76
  {subtitle && (
51
77
  <Text style={[styles.actionButtonSubtext, { color: isDarkTheme ? '#BBBBBB' : '#666666' }]}>
52
78
  {subtitle}
53
79
  </Text>
54
80
  )}
81
+ {customContentBelow}
55
82
  </View>
56
83
  {customContent}
57
- {showChevron && (
84
+ {selected ? (
85
+ <Ionicons name="checkmark-circle" size={20} color={iconColor || '#007AFF'} />
86
+ ) : showChevron ? (
58
87
  <Ionicons name="chevron-forward" size={16} color={isDarkTheme ? '#666666' : '#999999'} />
59
- )}
88
+ ) : null}
60
89
  </View>
61
90
  );
62
91
 
@@ -101,6 +130,18 @@ const styles = StyleSheet.create({
101
130
  actionIcon: {
102
131
  marginRight: 12,
103
132
  },
133
+ iconContainer: {
134
+ width: 38,
135
+ height: 38,
136
+ borderRadius: 19,
137
+ alignItems: 'center',
138
+ justifyContent: 'center',
139
+ marginRight: 12,
140
+ },
141
+ actionImage: {
142
+ marginRight: 12,
143
+ borderRadius: 16,
144
+ },
104
145
  actionTextContainer: {
105
146
  flex: 1,
106
147
  },
@@ -113,6 +154,13 @@ const styles = StyleSheet.create({
113
154
  fontSize: 13,
114
155
  lineHeight: 18,
115
156
  },
157
+ groupedItemContentMultiRow: {
158
+ alignItems: 'flex-start',
159
+ paddingVertical: 12,
160
+ },
161
+ actionTextContainerMultiRow: {
162
+ alignItems: 'flex-start',
163
+ },
116
164
  });
117
165
 
118
166
  export default GroupedItem;
@@ -6,12 +6,18 @@ interface GroupedSectionItem {
6
6
  id: string;
7
7
  icon?: string;
8
8
  iconColor?: string;
9
+ image?: string;
10
+ imageSize?: number;
9
11
  title: string;
10
12
  subtitle?: string;
11
13
  onPress?: () => void;
12
14
  showChevron?: boolean;
13
15
  disabled?: boolean;
16
+ selected?: boolean;
14
17
  customContent?: React.ReactNode;
18
+ customIcon?: React.ReactNode;
19
+ multiRow?: boolean;
20
+ customContentBelow?: React.ReactNode;
15
21
  }
16
22
 
17
23
  interface GroupedSectionProps {
@@ -27,6 +33,8 @@ const GroupedSection: React.FC<GroupedSectionProps> = ({ items, theme }) => {
27
33
  key={item.id}
28
34
  icon={item.icon}
29
35
  iconColor={item.iconColor}
36
+ image={item.image}
37
+ imageSize={item.imageSize}
30
38
  title={item.title}
31
39
  subtitle={item.subtitle}
32
40
  theme={theme}
@@ -35,7 +43,11 @@ const GroupedSection: React.FC<GroupedSectionProps> = ({ items, theme }) => {
35
43
  isLast={index === items.length - 1}
36
44
  showChevron={item.showChevron}
37
45
  disabled={item.disabled}
46
+ selected={item.selected}
38
47
  customContent={item.customContent}
48
+ customIcon={item.customIcon}
49
+ multiRow={item.multiRow}
50
+ customContentBelow={item.customContentBelow}
39
51
  />
40
52
  ))}
41
53
  </View>
@@ -0,0 +1,364 @@
1
+ import React from 'react';
2
+ import {
3
+ View,
4
+ Text,
5
+ TouchableOpacity,
6
+ StyleSheet,
7
+ Platform,
8
+ Animated,
9
+ } from 'react-native';
10
+ import { Ionicons } from '@expo/vector-icons';
11
+ import OxyIcon from './icon/OxyIcon';
12
+ import { fontFamilies } from '../styles/fonts';
13
+
14
+ export interface HeaderProps {
15
+ title: string;
16
+ subtitle?: string;
17
+ onBack?: () => void;
18
+ onClose?: () => void;
19
+ rightAction?: {
20
+ icon?: string;
21
+ onPress: () => void;
22
+ loading?: boolean;
23
+ disabled?: boolean;
24
+ text?: string;
25
+ };
26
+ theme: 'light' | 'dark';
27
+ showBackButton?: boolean;
28
+ showCloseButton?: boolean;
29
+ variant?: 'default' | 'large' | 'minimal' | 'gradient';
30
+ elevation?: 'none' | 'subtle' | 'prominent';
31
+ }
32
+
33
+ const Header: React.FC<HeaderProps> = ({
34
+ title,
35
+ subtitle,
36
+ onBack,
37
+ onClose,
38
+ rightAction,
39
+ theme,
40
+ showBackButton = true,
41
+ showCloseButton = false,
42
+ variant = 'default',
43
+ elevation = 'subtle',
44
+ }) => {
45
+ const isDarkTheme = theme === 'dark';
46
+
47
+ // Modern color palette
48
+ const colors = {
49
+ background: isDarkTheme ? '#1C1C1E' : '#FFFFFF',
50
+ surface: isDarkTheme ? '#2C2C2E' : '#F8F9FA',
51
+ primary: '#007AFF',
52
+ secondary: isDarkTheme ? '#8E8E93' : '#6C757D',
53
+ text: {
54
+ primary: isDarkTheme ? '#FFFFFF' : '#1A1A1A',
55
+ secondary: isDarkTheme ? '#8E8E93' : '#6C757D',
56
+ tertiary: isDarkTheme ? '#636366' : '#ADB5BD',
57
+ },
58
+ border: isDarkTheme ? '#38383A' : '#E9ECEF',
59
+ accent: '#5856D6',
60
+ success: '#34C759',
61
+ warning: '#FF9500',
62
+ error: '#FF3B30',
63
+ };
64
+
65
+ const renderBackButton = () => {
66
+ if (!showBackButton || !onBack) return null;
67
+
68
+ return (
69
+ <TouchableOpacity
70
+ style={[
71
+ styles.backButton,
72
+ { backgroundColor: colors.surface }
73
+ ]}
74
+ onPress={onBack}
75
+ activeOpacity={0.7}
76
+ >
77
+ <OxyIcon name="chevron-back" size={18} color={colors.primary} />
78
+ </TouchableOpacity>
79
+ );
80
+ };
81
+
82
+ const renderCloseButton = () => {
83
+ if (!showCloseButton || !onClose) return null;
84
+
85
+ return (
86
+ <TouchableOpacity
87
+ style={[
88
+ styles.closeButton,
89
+ { backgroundColor: colors.surface }
90
+ ]}
91
+ onPress={onClose}
92
+ activeOpacity={0.7}
93
+ >
94
+ <Ionicons name="close" size={18} color={colors.text.primary} />
95
+ </TouchableOpacity>
96
+ );
97
+ };
98
+
99
+ const renderRightAction = () => {
100
+ if (!rightAction) return null;
101
+
102
+ const isTextAction = rightAction.text;
103
+
104
+ return (
105
+ <TouchableOpacity
106
+ style={[
107
+ styles.rightActionButton,
108
+ isTextAction ? styles.textActionButton : styles.iconActionButton,
109
+ {
110
+ backgroundColor: isTextAction ? colors.primary : colors.surface,
111
+ opacity: rightAction.disabled ? 0.5 : 1
112
+ }
113
+ ]}
114
+ onPress={rightAction.onPress}
115
+ disabled={rightAction.disabled || rightAction.loading}
116
+ activeOpacity={0.7}
117
+ >
118
+ {rightAction.loading ? (
119
+ <View style={styles.loadingContainer}>
120
+ <View style={[styles.loadingDot, { backgroundColor: isTextAction ? '#FFFFFF' : colors.primary }]} />
121
+ <View style={[styles.loadingDot, { backgroundColor: isTextAction ? '#FFFFFF' : colors.primary }]} />
122
+ <View style={[styles.loadingDot, { backgroundColor: isTextAction ? '#FFFFFF' : colors.primary }]} />
123
+ </View>
124
+ ) : isTextAction ? (
125
+ <Text style={[styles.actionText, { color: '#FFFFFF' }]}>
126
+ {rightAction.text}
127
+ </Text>
128
+ ) : (
129
+ <Ionicons name={rightAction.icon as any} size={18} color={colors.primary} />
130
+ )}
131
+ </TouchableOpacity>
132
+ );
133
+ };
134
+
135
+ const renderTitle = () => {
136
+ const titleStyle = variant === 'large' ? styles.titleLarge :
137
+ variant === 'minimal' ? styles.titleMinimal :
138
+ styles.titleDefault;
139
+
140
+ const subtitleStyle = variant === 'large' ? styles.subtitleLarge :
141
+ variant === 'minimal' ? styles.subtitleMinimal :
142
+ styles.subtitleDefault;
143
+
144
+ return (
145
+ <View style={[
146
+ styles.titleContainer,
147
+ variant === 'minimal' && styles.titleContainerMinimal
148
+ ]}>
149
+ <Text style={[titleStyle, { color: colors.text.primary }]}>
150
+ {title}
151
+ </Text>
152
+ {subtitle && (
153
+ <Text style={[subtitleStyle, { color: colors.text.secondary }]}>
154
+ {subtitle}
155
+ </Text>
156
+ )}
157
+ </View>
158
+ );
159
+ };
160
+
161
+ const getElevationStyle = () => {
162
+ switch (elevation) {
163
+ case 'none':
164
+ return {};
165
+ case 'subtle':
166
+ return Platform.select({
167
+ web: {
168
+ boxShadow: isDarkTheme
169
+ ? '0 1px 3px rgba(0,0,0,0.3)'
170
+ : '0 1px 3px rgba(0,0,0,0.1)',
171
+ },
172
+ default: {
173
+ shadowColor: '#000000',
174
+ shadowOffset: { width: 0, height: 1 },
175
+ shadowOpacity: isDarkTheme ? 0.3 : 0.1,
176
+ shadowRadius: 3,
177
+ elevation: 2,
178
+ },
179
+ });
180
+ case 'prominent':
181
+ return Platform.select({
182
+ web: {
183
+ boxShadow: isDarkTheme
184
+ ? '0 4px 12px rgba(0,0,0,0.4)'
185
+ : '0 4px 12px rgba(0,0,0,0.15)',
186
+ },
187
+ default: {
188
+ shadowColor: '#000000',
189
+ shadowOffset: { width: 0, height: 4 },
190
+ shadowOpacity: isDarkTheme ? 0.4 : 0.15,
191
+ shadowRadius: 12,
192
+ elevation: 8,
193
+ },
194
+ });
195
+ default:
196
+ return {};
197
+ }
198
+ };
199
+
200
+ const getBackgroundStyle = () => {
201
+ if (variant === 'gradient') {
202
+ return {
203
+ backgroundColor: isDarkTheme ? '#1C1C1E' : '#FFFFFF',
204
+ // Add gradient overlay effect
205
+ borderBottomWidth: 1,
206
+ borderBottomColor: colors.border,
207
+ };
208
+ }
209
+
210
+ return {
211
+ backgroundColor: colors.background,
212
+ borderBottomWidth: elevation === 'none' ? 0 : 1,
213
+ borderBottomColor: colors.border,
214
+ };
215
+ };
216
+
217
+ return (
218
+ <View style={[
219
+ styles.container,
220
+ getBackgroundStyle(),
221
+ getElevationStyle(),
222
+ ]}>
223
+ <View style={[
224
+ styles.content,
225
+ variant === 'minimal' && styles.contentMinimal
226
+ ]}>
227
+ {renderBackButton()}
228
+ {renderTitle()}
229
+ {renderRightAction()}
230
+ {renderCloseButton()}
231
+ </View>
232
+ </View>
233
+ );
234
+ };
235
+
236
+ const styles = StyleSheet.create({
237
+ container: {
238
+ paddingTop: Platform.OS === 'ios' ? 50 : 16,
239
+ paddingBottom: 12,
240
+ position: 'absolute',
241
+ top: 0,
242
+ left: 0,
243
+ right: 0,
244
+ zIndex: 1000,
245
+ ...Platform.select({
246
+ web: {
247
+ position: 'sticky' as any,
248
+ },
249
+ default: {},
250
+ }),
251
+ },
252
+ content: {
253
+ flexDirection: 'row',
254
+ alignItems: 'center',
255
+ paddingHorizontal: 16,
256
+ position: 'relative',
257
+ minHeight: 40,
258
+ },
259
+ contentMinimal: {
260
+ paddingHorizontal: 12,
261
+ minHeight: 36,
262
+ },
263
+ backButton: {
264
+ width: 32,
265
+ height: 32,
266
+ borderRadius: 16,
267
+ alignItems: 'center',
268
+ justifyContent: 'center',
269
+ marginRight: 10,
270
+ },
271
+ closeButton: {
272
+ width: 32,
273
+ height: 32,
274
+ borderRadius: 16,
275
+ alignItems: 'center',
276
+ justifyContent: 'center',
277
+ marginLeft: 10,
278
+ },
279
+ titleContainer: {
280
+ flex: 1,
281
+ alignItems: 'flex-start',
282
+ justifyContent: 'center',
283
+ },
284
+ titleContainerMinimal: {
285
+ alignItems: 'center',
286
+ marginHorizontal: 16,
287
+ },
288
+ titleDefault: {
289
+ fontSize: 18,
290
+ fontWeight: '700',
291
+ fontFamily: fontFamilies.phuduBold,
292
+ letterSpacing: -0.5,
293
+ lineHeight: 22,
294
+ },
295
+ titleLarge: {
296
+ fontSize: 28,
297
+ fontWeight: '800',
298
+ fontFamily: fontFamilies.phuduExtraBold,
299
+ letterSpacing: -1,
300
+ lineHeight: 34,
301
+ marginBottom: 3,
302
+ },
303
+ titleMinimal: {
304
+ fontSize: 16,
305
+ fontWeight: '600',
306
+ fontFamily: fontFamilies.phuduSemiBold,
307
+ letterSpacing: -0.3,
308
+ lineHeight: 20,
309
+ },
310
+ subtitleDefault: {
311
+ fontSize: 14,
312
+ fontFamily: fontFamilies.phuduMedium,
313
+ lineHeight: 17,
314
+ marginTop: 1,
315
+ },
316
+ subtitleLarge: {
317
+ fontSize: 16,
318
+ fontFamily: fontFamilies.phuduMedium,
319
+ lineHeight: 19,
320
+ marginTop: 3,
321
+ },
322
+ subtitleMinimal: {
323
+ fontSize: 13,
324
+ fontFamily: fontFamilies.phuduMedium,
325
+ lineHeight: 15,
326
+ marginTop: 1,
327
+ },
328
+ rightActionButton: {
329
+ alignItems: 'center',
330
+ justifyContent: 'center',
331
+ marginLeft: 10,
332
+ },
333
+ iconActionButton: {
334
+ width: 32,
335
+ height: 32,
336
+ borderRadius: 16,
337
+ },
338
+ textActionButton: {
339
+ paddingHorizontal: 14,
340
+ paddingVertical: 6,
341
+ borderRadius: 18,
342
+ minWidth: 56,
343
+ },
344
+ actionText: {
345
+ fontSize: 14,
346
+ fontWeight: '600',
347
+ fontFamily: fontFamilies.phuduSemiBold,
348
+ letterSpacing: -0.2,
349
+ },
350
+ loadingContainer: {
351
+ flexDirection: 'row',
352
+ alignItems: 'center',
353
+ justifyContent: 'center',
354
+ gap: 2,
355
+ },
356
+ loadingDot: {
357
+ width: 4,
358
+ height: 4,
359
+ borderRadius: 2,
360
+ opacity: 0.6,
361
+ },
362
+ });
363
+
364
+ export default Header;