@oxyhq/services 6.9.24 → 6.9.26

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 (104) hide show
  1. package/lib/commonjs/ui/components/BottomSheet.js +15 -19
  2. package/lib/commonjs/ui/components/BottomSheet.js.map +1 -1
  3. package/lib/commonjs/ui/components/BottomSheetRouter.js +6 -9
  4. package/lib/commonjs/ui/components/BottomSheetRouter.js.map +1 -1
  5. package/lib/commonjs/ui/components/Header.js +9 -12
  6. package/lib/commonjs/ui/components/Header.js.map +1 -1
  7. package/lib/commonjs/ui/components/SignInModal.js +24 -53
  8. package/lib/commonjs/ui/components/SignInModal.js.map +1 -1
  9. package/lib/commonjs/ui/components/StepBasedScreen.js +20 -7
  10. package/lib/commonjs/ui/components/StepBasedScreen.js.map +1 -1
  11. package/lib/commonjs/ui/components/feedback/feedbackStyles.js +2 -2
  12. package/lib/commonjs/ui/components/feedback/feedbackStyles.js.map +1 -1
  13. package/lib/commonjs/ui/components/modals/DeleteAccountModal.js +32 -29
  14. package/lib/commonjs/ui/components/modals/DeleteAccountModal.js.map +1 -1
  15. package/lib/commonjs/ui/components/payment/paymentStyles.js +6 -6
  16. package/lib/commonjs/ui/components/payment/paymentStyles.js.map +1 -1
  17. package/lib/commonjs/ui/constants/theme.js +3 -2
  18. package/lib/commonjs/ui/constants/theme.js.map +1 -1
  19. package/lib/commonjs/ui/hooks/useAuth.js +6 -1
  20. package/lib/commonjs/ui/hooks/useAuth.js.map +1 -1
  21. package/lib/commonjs/ui/hooks/useWebSSO.js +6 -1
  22. package/lib/commonjs/ui/hooks/useWebSSO.js.map +1 -1
  23. package/lib/commonjs/ui/screens/AccountOverviewScreen.js +0 -8
  24. package/lib/commonjs/ui/screens/AccountOverviewScreen.js.map +1 -1
  25. package/lib/commonjs/ui/styles/authStyles.js +3 -3
  26. package/lib/commonjs/ui/styles/authStyles.js.map +1 -1
  27. package/lib/commonjs/ui/styles/theme.js +45 -9
  28. package/lib/commonjs/ui/styles/theme.js.map +1 -1
  29. package/lib/module/ui/components/BottomSheet.js +15 -19
  30. package/lib/module/ui/components/BottomSheet.js.map +1 -1
  31. package/lib/module/ui/components/BottomSheetRouter.js +6 -9
  32. package/lib/module/ui/components/BottomSheetRouter.js.map +1 -1
  33. package/lib/module/ui/components/Header.js +9 -12
  34. package/lib/module/ui/components/Header.js.map +1 -1
  35. package/lib/module/ui/components/SignInModal.js +25 -54
  36. package/lib/module/ui/components/SignInModal.js.map +1 -1
  37. package/lib/module/ui/components/StepBasedScreen.js +21 -8
  38. package/lib/module/ui/components/StepBasedScreen.js.map +1 -1
  39. package/lib/module/ui/components/feedback/feedbackStyles.js +2 -2
  40. package/lib/module/ui/components/feedback/feedbackStyles.js.map +1 -1
  41. package/lib/module/ui/components/modals/DeleteAccountModal.js +33 -30
  42. package/lib/module/ui/components/modals/DeleteAccountModal.js.map +1 -1
  43. package/lib/module/ui/components/payment/paymentStyles.js +6 -6
  44. package/lib/module/ui/components/payment/paymentStyles.js.map +1 -1
  45. package/lib/module/ui/constants/theme.js +3 -2
  46. package/lib/module/ui/constants/theme.js.map +1 -1
  47. package/lib/module/ui/hooks/useAuth.js +6 -1
  48. package/lib/module/ui/hooks/useAuth.js.map +1 -1
  49. package/lib/module/ui/hooks/useWebSSO.js +6 -1
  50. package/lib/module/ui/hooks/useWebSSO.js.map +1 -1
  51. package/lib/module/ui/screens/AccountOverviewScreen.js +0 -8
  52. package/lib/module/ui/screens/AccountOverviewScreen.js.map +1 -1
  53. package/lib/module/ui/styles/authStyles.js +3 -3
  54. package/lib/module/ui/styles/authStyles.js.map +1 -1
  55. package/lib/module/ui/styles/theme.js +46 -9
  56. package/lib/module/ui/styles/theme.js.map +1 -1
  57. package/lib/typescript/commonjs/ui/components/BottomSheet.d.ts.map +1 -1
  58. package/lib/typescript/commonjs/ui/components/BottomSheetRouter.d.ts.map +1 -1
  59. package/lib/typescript/commonjs/ui/components/Header.d.ts.map +1 -1
  60. package/lib/typescript/commonjs/ui/components/SignInModal.d.ts.map +1 -1
  61. package/lib/typescript/commonjs/ui/components/StepBasedScreen.d.ts.map +1 -1
  62. package/lib/typescript/commonjs/ui/components/modals/DeleteAccountModal.d.ts +0 -8
  63. package/lib/typescript/commonjs/ui/components/modals/DeleteAccountModal.d.ts.map +1 -1
  64. package/lib/typescript/commonjs/ui/components/payment/types.d.ts +2 -0
  65. package/lib/typescript/commonjs/ui/components/payment/types.d.ts.map +1 -1
  66. package/lib/typescript/commonjs/ui/constants/theme.d.ts +3 -2
  67. package/lib/typescript/commonjs/ui/constants/theme.d.ts.map +1 -1
  68. package/lib/typescript/commonjs/ui/hooks/useAuth.d.ts.map +1 -1
  69. package/lib/typescript/commonjs/ui/hooks/useWebSSO.d.ts.map +1 -1
  70. package/lib/typescript/commonjs/ui/screens/AccountOverviewScreen.d.ts.map +1 -1
  71. package/lib/typescript/commonjs/ui/styles/theme.d.ts +8 -0
  72. package/lib/typescript/commonjs/ui/styles/theme.d.ts.map +1 -1
  73. package/lib/typescript/module/ui/components/BottomSheet.d.ts.map +1 -1
  74. package/lib/typescript/module/ui/components/BottomSheetRouter.d.ts.map +1 -1
  75. package/lib/typescript/module/ui/components/Header.d.ts.map +1 -1
  76. package/lib/typescript/module/ui/components/SignInModal.d.ts.map +1 -1
  77. package/lib/typescript/module/ui/components/StepBasedScreen.d.ts.map +1 -1
  78. package/lib/typescript/module/ui/components/modals/DeleteAccountModal.d.ts +0 -8
  79. package/lib/typescript/module/ui/components/modals/DeleteAccountModal.d.ts.map +1 -1
  80. package/lib/typescript/module/ui/components/payment/types.d.ts +2 -0
  81. package/lib/typescript/module/ui/components/payment/types.d.ts.map +1 -1
  82. package/lib/typescript/module/ui/constants/theme.d.ts +3 -2
  83. package/lib/typescript/module/ui/constants/theme.d.ts.map +1 -1
  84. package/lib/typescript/module/ui/hooks/useAuth.d.ts.map +1 -1
  85. package/lib/typescript/module/ui/hooks/useWebSSO.d.ts.map +1 -1
  86. package/lib/typescript/module/ui/screens/AccountOverviewScreen.d.ts.map +1 -1
  87. package/lib/typescript/module/ui/styles/theme.d.ts +8 -0
  88. package/lib/typescript/module/ui/styles/theme.d.ts.map +1 -1
  89. package/package.json +2 -2
  90. package/src/ui/components/BottomSheet.tsx +12 -18
  91. package/src/ui/components/BottomSheetRouter.tsx +7 -9
  92. package/src/ui/components/Header.tsx +9 -12
  93. package/src/ui/components/SignInModal.tsx +17 -40
  94. package/src/ui/components/StepBasedScreen.tsx +22 -9
  95. package/src/ui/components/feedback/feedbackStyles.ts +2 -2
  96. package/src/ui/components/modals/DeleteAccountModal.tsx +25 -34
  97. package/src/ui/components/payment/paymentStyles.ts +6 -6
  98. package/src/ui/components/payment/types.ts +2 -0
  99. package/src/ui/constants/theme.ts +3 -2
  100. package/src/ui/hooks/useAuth.ts +4 -1
  101. package/src/ui/hooks/useWebSSO.ts +4 -1
  102. package/src/ui/screens/AccountOverviewScreen.tsx +0 -8
  103. package/src/ui/styles/authStyles.ts +3 -3
  104. package/src/ui/styles/theme.ts +44 -10
@@ -7,25 +7,18 @@ import {
7
7
  TouchableOpacity,
8
8
  StyleSheet,
9
9
  Modal,
10
- ActivityIndicator,
11
10
  KeyboardAvoidingView,
12
11
  Platform,
13
12
  } from 'react-native';
14
13
  import OxyIcon from '../icon/OxyIcon';
14
+ import { useTheme } from '@oxyhq/bloom/theme';
15
+ import { Loading } from '@oxyhq/bloom/loading';
15
16
 
16
17
  interface DeleteAccountModalProps {
17
18
  visible: boolean;
18
19
  username: string;
19
20
  onClose: () => void;
20
21
  onDelete: (password: string) => Promise<void>;
21
- colors: {
22
- background: string;
23
- text: string;
24
- secondaryText: string;
25
- border: string;
26
- danger: string;
27
- inputBackground: string;
28
- };
29
22
  t: (key: string, params?: Record<string, string>) => string | undefined;
30
23
  }
31
24
 
@@ -34,9 +27,9 @@ const DeleteAccountModal: React.FC<DeleteAccountModalProps> = ({
34
27
  username,
35
28
  onClose,
36
29
  onDelete,
37
- colors,
38
30
  t,
39
31
  }) => {
32
+ const theme = useTheme();
40
33
  const [password, setPassword] = useState('');
41
34
  const [confirmUsername, setConfirmUsername] = useState('');
42
35
  const [isDeleting, setIsDeleting] = useState(false);
@@ -81,41 +74,41 @@ const DeleteAccountModal: React.FC<DeleteAccountModalProps> = ({
81
74
  style={styles.overlay}
82
75
  >
83
76
  <TouchableOpacity
84
- style={styles.backdrop}
77
+ style={[styles.backdrop, { backgroundColor: theme.colors.overlay }]}
85
78
  activeOpacity={1}
86
79
  onPress={handleClose}
87
80
  />
88
- <View style={[styles.modal, { backgroundColor: colors.background }]}>
81
+ <View style={[styles.modal, { backgroundColor: theme.colors.background }]}>
89
82
  <View style={styles.header}>
90
- <OxyIcon name="alert" size={32} color={colors.danger} />
91
- <Text style={[styles.title, { color: colors.danger }]}>
83
+ <OxyIcon name="alert" size={32} color={theme.colors.error} />
84
+ <Text style={[styles.title, { color: theme.colors.error }]}>
92
85
  {t('deleteAccount.title') || 'Delete Account'}
93
86
  </Text>
94
87
  </View>
95
88
 
96
- <Text style={[styles.warning, { color: colors.text }]}>
89
+ <Text style={[styles.warning, { color: theme.colors.text }]}>
97
90
  {t('deleteAccount.warning') || 'This action cannot be undone. Your account and all associated data will be permanently deleted.'}
98
91
  </Text>
99
92
 
100
93
  {error && (
101
- <View style={[styles.errorContainer, { backgroundColor: `${colors.danger}20` }]}>
102
- <Text style={[styles.errorText, { color: colors.danger }]}>
94
+ <View style={[styles.errorContainer, { backgroundColor: `${theme.colors.error}20` }]}>
95
+ <Text style={[styles.errorText, { color: theme.colors.error }]}>
103
96
  {error}
104
97
  </Text>
105
98
  </View>
106
99
  )}
107
100
 
108
101
  <View style={styles.inputGroup}>
109
- <Text style={[styles.label, { color: colors.secondaryText }]}>
102
+ <Text style={[styles.label, { color: theme.colors.textSecondary }]}>
110
103
  {t('deleteAccount.passwordLabel') || 'Enter your password'}
111
104
  </Text>
112
- <View style={[styles.inputContainer, { borderColor: colors.border, backgroundColor: colors.inputBackground }]}>
105
+ <View style={[styles.inputContainer, { borderColor: theme.colors.border, backgroundColor: theme.colors.background }]}>
113
106
  <TextInput
114
- style={[styles.input, { color: colors.text }]}
107
+ style={[styles.input, { color: theme.colors.text }]}
115
108
  value={password}
116
109
  onChangeText={setPassword}
117
110
  placeholder={t('deleteAccount.passwordPlaceholder') || 'Password'}
118
- placeholderTextColor={colors.secondaryText}
111
+ placeholderTextColor={theme.colors.textSecondary}
119
112
  secureTextEntry={!showPassword}
120
113
  autoCapitalize="none"
121
114
  editable={!isDeleting}
@@ -127,14 +120,14 @@ const DeleteAccountModal: React.FC<DeleteAccountModalProps> = ({
127
120
  <OxyIcon
128
121
  name={showPassword ? 'eye-off' : 'eye'}
129
122
  size={20}
130
- color={colors.secondaryText}
123
+ color={theme.colors.textSecondary}
131
124
  />
132
125
  </TouchableOpacity>
133
126
  </View>
134
127
  </View>
135
128
 
136
129
  <View style={styles.inputGroup}>
137
- <Text style={[styles.label, { color: colors.secondaryText }]}>
130
+ <Text style={[styles.label, { color: theme.colors.textSecondary }]}>
138
131
  {t('deleteAccount.confirmLabel', { username }) || `Type "${username}" to confirm`}
139
132
  </Text>
140
133
  <TextInput
@@ -142,15 +135,15 @@ const DeleteAccountModal: React.FC<DeleteAccountModalProps> = ({
142
135
  styles.input,
143
136
  styles.confirmInput,
144
137
  {
145
- borderColor: confirmUsername === username ? '#34C759' : colors.border,
146
- backgroundColor: colors.inputBackground,
147
- color: colors.text,
138
+ borderColor: confirmUsername === username ? theme.colors.success : theme.colors.border,
139
+ backgroundColor: theme.colors.background,
140
+ color: theme.colors.text,
148
141
  },
149
142
  ]}
150
143
  value={confirmUsername}
151
144
  onChangeText={setConfirmUsername}
152
145
  placeholder={username}
153
- placeholderTextColor={colors.secondaryText}
146
+ placeholderTextColor={theme.colors.textSecondary}
154
147
  autoCapitalize="none"
155
148
  autoCorrect={false}
156
149
  editable={!isDeleting}
@@ -159,11 +152,11 @@ const DeleteAccountModal: React.FC<DeleteAccountModalProps> = ({
159
152
 
160
153
  <View style={styles.buttons}>
161
154
  <TouchableOpacity
162
- style={[styles.button, styles.cancelButton, { borderColor: colors.border }]}
155
+ style={[styles.button, styles.cancelButton, { borderColor: theme.colors.border }]}
163
156
  onPress={handleClose}
164
157
  disabled={isDeleting}
165
158
  >
166
- <Text style={[styles.buttonText, { color: colors.text }]}>
159
+ <Text style={[styles.buttonText, { color: theme.colors.text }]}>
167
160
  {t('common.cancel') || 'Cancel'}
168
161
  </Text>
169
162
  </TouchableOpacity>
@@ -172,15 +165,15 @@ const DeleteAccountModal: React.FC<DeleteAccountModalProps> = ({
172
165
  style={[
173
166
  styles.button,
174
167
  styles.deleteButton,
175
- { backgroundColor: isValid ? colors.danger : `${colors.danger}50` },
168
+ { backgroundColor: isValid ? theme.colors.error : `${theme.colors.error}50` },
176
169
  ]}
177
170
  onPress={handleDelete}
178
171
  disabled={!isValid || isDeleting}
179
172
  >
180
173
  {isDeleting ? (
181
- <ActivityIndicator color="#fff" size="small" />
174
+ <Loading size="small" />
182
175
  ) : (
183
- <Text style={styles.deleteButtonText}>
176
+ <Text style={[styles.deleteButtonText, { color: theme.colors.card }]}>
184
177
  {t('deleteAccount.confirm') || 'Delete Forever'}
185
178
  </Text>
186
179
  )}
@@ -200,7 +193,6 @@ const styles = StyleSheet.create({
200
193
  },
201
194
  backdrop: {
202
195
  ...StyleSheet.absoluteFillObject,
203
- backgroundColor: 'rgba(0, 0, 0, 0.5)',
204
196
  },
205
197
  modal: {
206
198
  width: '90%',
@@ -288,7 +280,6 @@ const styles = StyleSheet.create({
288
280
  deleteButtonText: {
289
281
  fontSize: 16,
290
282
  fontWeight: '600',
291
- color: '#fff',
292
283
  },
293
284
  });
294
285
 
@@ -34,12 +34,12 @@ export const createPaymentStyles = (colors: PaymentColors) => StyleSheet.create(
34
34
  },
35
35
  errorText: {
36
36
  fontSize: 18,
37
- color: 'red',
37
+ color: colors.error ?? '#EF4444',
38
38
  marginBottom: 24,
39
39
  },
40
40
  // Summary card styles
41
41
  summaryCard: {
42
- backgroundColor: '#fff',
42
+ backgroundColor: colors.card ?? colors.background ?? '#fff',
43
43
  borderRadius: 16,
44
44
  padding: 24,
45
45
  marginBottom: 24,
@@ -131,7 +131,7 @@ export const createPaymentStyles = (colors: PaymentColors) => StyleSheet.create(
131
131
  },
132
132
  // Card payment styles
133
133
  cardPaymentCard: {
134
- backgroundColor: '#fff',
134
+ backgroundColor: colors.card ?? colors.background ?? '#fff',
135
135
  borderRadius: 16,
136
136
  padding: 24,
137
137
  marginBottom: 24,
@@ -200,7 +200,7 @@ export const createPaymentStyles = (colors: PaymentColors) => StyleSheet.create(
200
200
  },
201
201
  // Oxy Pay styles
202
202
  oxyPayCard: {
203
- backgroundColor: '#fff',
203
+ backgroundColor: colors.card ?? colors.background ?? '#fff',
204
204
  borderRadius: 16,
205
205
  padding: 24,
206
206
  marginBottom: 24,
@@ -247,7 +247,7 @@ export const createPaymentStyles = (colors: PaymentColors) => StyleSheet.create(
247
247
  },
248
248
  // FairCoin styles
249
249
  faircoinCard: {
250
- backgroundColor: '#fff',
250
+ backgroundColor: colors.card ?? colors.background ?? '#fff',
251
251
  borderRadius: 16,
252
252
  padding: 24,
253
253
  marginBottom: 24,
@@ -358,7 +358,7 @@ export const createPaymentStyles = (colors: PaymentColors) => StyleSheet.create(
358
358
  },
359
359
  // Success styles
360
360
  successCard: {
361
- backgroundColor: '#fff',
361
+ backgroundColor: colors.card ?? colors.background ?? '#fff',
362
362
  borderRadius: 16,
363
363
  padding: 24,
364
364
  marginBottom: 24,
@@ -41,5 +41,7 @@ export interface PaymentColors {
41
41
  secondaryText: string;
42
42
  border: string;
43
43
  success?: string;
44
+ error?: string;
44
45
  background?: string;
46
+ card?: string;
45
47
  }
@@ -1,6 +1,7 @@
1
1
  /**
2
- * Below are the colors that are used in the app. The colors are defined in the light and dark mode.
3
- * There are many other ways to style your app. For example, [Nativewind](https://www.nativewind.dev/), [Tamagui](https://tamagui.dev/), [unistyles](https://reactnativeunistyles.vercel.app), etc.
2
+ * Below are the colors that are used in the app.
3
+ * These are kept as a compatibility layer prefer using bloom's useTheme() / useThemeColor()
4
+ * directly in new code. Existing screens still reference Colors.light / Colors.dark.
4
5
  */
5
6
 
6
7
  import { Platform } from 'react-native';
@@ -110,7 +110,10 @@ export function useAuth(): UseAuthReturn {
110
110
  // Check if we're on the identity provider itself
111
111
  // Only the IdP has local login forms - other apps are client apps
112
112
  const authWebUrl = oxyServices.config?.authWebUrl;
113
- const idpHostname = authWebUrl ? new URL(authWebUrl).hostname : 'auth.oxy.so';
113
+ let idpHostname = 'auth.oxy.so';
114
+ if (authWebUrl) {
115
+ try { idpHostname = new URL(authWebUrl).hostname; } catch { /* malformed URL, use default */ }
116
+ }
114
117
  const isIdentityProvider = isWebBrowser() &&
115
118
  window.location.hostname === idpHostname;
116
119
 
@@ -54,7 +54,10 @@ function isWebBrowser(): boolean {
54
54
  function isIdentityProvider(authWebUrl?: string): boolean {
55
55
  if (!isWebBrowser()) return false;
56
56
  const hostname = window.location.hostname;
57
- const idpHostname = authWebUrl ? new URL(authWebUrl).hostname : 'auth.oxy.so';
57
+ let idpHostname = 'auth.oxy.so';
58
+ if (authWebUrl) {
59
+ try { idpHostname = new URL(authWebUrl).hostname; } catch { /* malformed URL, use default */ }
60
+ }
58
61
  return hostname === idpHostname;
59
62
  }
60
63
 
@@ -698,14 +698,6 @@ const AccountOverviewScreen: React.FC<BaseScreenProps> = ({
698
698
  username={user.username || ''}
699
699
  onClose={() => setShowDeleteModal(false)}
700
700
  onDelete={handleConfirmDelete}
701
- colors={{
702
- background: themeStyles.backgroundColor,
703
- text: themeStyles.textColor,
704
- secondaryText: themeStyles.isDarkTheme ? '#888888' : '#666666',
705
- border: themeStyles.borderColor,
706
- danger: '#FF3B30',
707
- inputBackground: themeStyles.isDarkTheme ? '#333333' : '#F5F5F5',
708
- }}
709
701
  t={t}
710
702
  />
711
703
  )}
@@ -203,7 +203,7 @@ export const createAuthStyles = (colors: AuthThemeColors, theme: string) => Styl
203
203
  width: '100%',
204
204
  },
205
205
  modernButtonText: {
206
- color: '#FFFFFF',
206
+ color: colors.background,
207
207
  fontSize: 16,
208
208
  fontWeight: '600',
209
209
  letterSpacing: 0.5,
@@ -244,7 +244,7 @@ export const createAuthStyles = (colors: AuthThemeColors, theme: string) => Styl
244
244
  },
245
245
  modernUserAvatar: {
246
246
  borderWidth: 4,
247
- borderColor: 'rgba(209, 105, 229, 0.2)',
247
+ borderColor: `${colors.primary}33`,
248
248
  },
249
249
  statusIndicator: {
250
250
  position: 'absolute',
@@ -254,7 +254,7 @@ export const createAuthStyles = (colors: AuthThemeColors, theme: string) => Styl
254
254
  height: 20,
255
255
  borderRadius: 10,
256
256
  borderWidth: 3,
257
- borderColor: '#FFFFFF',
257
+ borderColor: colors.background,
258
258
  },
259
259
  modernUserDisplayName: {
260
260
  fontFamily: fontFamilies.interBold,
@@ -1,6 +1,11 @@
1
1
  import { Platform, StyleSheet, type TextStyle } from 'react-native';
2
+ import { useTheme as useBloomThemeHook, type ThemeColors as BloomThemeColors } from '@oxyhq/bloom';
2
3
  import { fontFamilies } from './fonts';
3
4
 
5
+ /**
6
+ * ThemeColors used by services style files.
7
+ * Maps to bloom's ThemeColors, with a few convenience aliases.
8
+ */
4
9
  export interface ThemeColors {
5
10
  text: string;
6
11
  background: string;
@@ -24,7 +29,26 @@ export interface Theme {
24
29
  };
25
30
  }
26
31
 
27
- const lightColors: ThemeColors = {
32
+ /**
33
+ * Adapts bloom's ThemeColors into the services ThemeColors shape.
34
+ */
35
+ function bloomColorsToThemeColors(bloomColors: BloomThemeColors): ThemeColors {
36
+ return {
37
+ text: bloomColors.text,
38
+ background: bloomColors.background,
39
+ inputBackground: bloomColors.backgroundSecondary,
40
+ placeholder: bloomColors.textTertiary,
41
+ primary: bloomColors.primary,
42
+ border: bloomColors.border,
43
+ error: bloomColors.error,
44
+ success: bloomColors.success,
45
+ warning: bloomColors.warning,
46
+ secondaryText: bloomColors.textSecondary,
47
+ };
48
+ }
49
+
50
+ /** Fallback colors when bloom context is not available */
51
+ const fallbackLight: ThemeColors = {
28
52
  text: '#000000',
29
53
  background: '#FFFFFF',
30
54
  inputBackground: '#F5F5F5',
@@ -37,7 +61,7 @@ const lightColors: ThemeColors = {
37
61
  secondaryText: '#666666',
38
62
  };
39
63
 
40
- const darkColors: ThemeColors = {
64
+ const fallbackDark: ThemeColors = {
41
65
  text: '#FFFFFF',
42
66
  background: '#000000',
43
67
  inputBackground: '#333333',
@@ -50,11 +74,11 @@ const darkColors: ThemeColors = {
50
74
  secondaryText: '#BBBBBB',
51
75
  };
52
76
 
53
- const createTheme = (isDark: boolean): Theme => {
54
- const colors = isDark ? darkColors : lightColors;
55
-
77
+ const createTheme = (isDark: boolean, colors?: ThemeColors): Theme => {
78
+ const themeColors = colors ?? (isDark ? fallbackDark : fallbackLight);
79
+
56
80
  return {
57
- colors,
81
+ colors: themeColors,
58
82
  fonts: {
59
83
  title: {
60
84
  fontFamily: fontFamilies.interBold,
@@ -69,7 +93,7 @@ const createTheme = (isDark: boolean): Theme => {
69
93
  fontFamily: fontFamilies.interSemiBold,
70
94
  fontSize: 16,
71
95
  fontWeight: '600',
72
- color: '#FFFFFF',
96
+ color: themeColors.background,
73
97
  },
74
98
  label: {
75
99
  fontSize: 14,
@@ -84,8 +108,18 @@ export const getTheme = (theme: 'light' | 'dark'): Theme => {
84
108
  return createTheme(theme === 'dark');
85
109
  };
86
110
 
111
+ /**
112
+ * Returns theme colors from bloom when available, with fallback to local colors.
113
+ * Prefer this hook for new code — it reads from bloom's ThemeProvider.
114
+ */
87
115
  export const useThemeColors = (theme: 'light' | 'dark'): ThemeColors => {
88
- return getTheme(theme).colors;
116
+ try {
117
+ const bloomTheme = useBloomThemeHook();
118
+ return bloomColorsToThemeColors(bloomTheme.colors);
119
+ } catch {
120
+ // Bloom provider not available, fall back to local colors
121
+ return getTheme(theme).colors;
122
+ }
89
123
  };
90
124
 
91
125
  // Common styles that can be reused across components
@@ -122,10 +156,10 @@ export const createCommonStyles = (theme: 'light' | 'dark') => {
122
156
  fontFamily: fontFamilies.interSemiBold,
123
157
  fontSize: 16,
124
158
  fontWeight: '600',
125
- color: '#FFFFFF',
159
+ color: colors.background,
126
160
  },
127
161
  errorContainer: {
128
- backgroundColor: '#FFEBEE',
162
+ backgroundColor: `${colors.error}18`,
129
163
  padding: 12,
130
164
  borderRadius: 35,
131
165
  marginBottom: 16,