@entropy-softworks/ui 2026.9.8 → 2026.9.10

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.
@@ -1,31 +1,27 @@
1
1
  import React, { useCallback, useEffect, useRef, useState } from "react";
2
- import { Platform, ScrollView, View } from "react-native";
3
- import { SafeAreaView } from "react-native-safe-area-context";
2
+ import { Platform } from "react-native";
4
3
  import { useLocalSearchParams } from "expo-router";
5
4
  import { useNavigation } from "../../context/NavigationContext";
6
- import { StatusBar } from "expo-status-bar";
7
5
  import { Ionicons } from "@expo/vector-icons";
8
6
  import { useColorScheme } from "nativewind";
9
7
  import * as Haptics from "expo-haptics";
10
8
  import Toast from "react-native-toast-message";
11
9
  import { MutedText, Text } from "../../components/text";
12
10
  import { Button, IconButton } from "../../components/button";
13
- import {
14
- Card,
15
- CardContent,
16
- CardDescription,
17
- CardFooter,
18
- CardHeader,
19
- CardTitle,
20
- } from "../../components/card";
21
11
  import { withClickTracking } from "../../services/telemetry";
22
12
  import { Input } from "../../components/input";
23
13
  import AuthService from "../../services/auth.service";
24
14
  import { useAuth } from "../../hooks/useAuth";
25
15
  import { useAppConfig } from "../../context/AppConfigContext";
26
16
  import { getErrorMessage } from "../../utils/error";
17
+ import { AuthPage, type AuthPageLayout } from "./AuthPage";
27
18
 
28
- export function VerifyEmailScreen() {
19
+ export interface VerifyEmailScreenProps {
20
+ /** See `AuthPageLayout`. Defaults to the card, as it always was. */
21
+ layout?: AuthPageLayout;
22
+ }
23
+
24
+ export function VerifyEmailScreen({ layout }: VerifyEmailScreenProps = {}) {
29
25
  const { refreshUser, logout, user } = useAuth();
30
26
  const { routes } = useAppConfig();
31
27
  const router = useNavigation();
@@ -214,100 +210,87 @@ export function VerifyEmailScreen() {
214
210
  };
215
211
 
216
212
  return (
217
- <SafeAreaView className="flex-1 bg-background dark:bg-black">
218
- <StatusBar style={isDark ? "light" : "dark"} />
219
- <ScrollView
220
- className="flex-1"
221
- contentContainerClassName="flex-1 items-center justify-center p-6"
222
- keyboardShouldPersistTaps="handled"
223
- >
224
- <View className="mt-4 self-start absolute top-4 left-6">
225
- <IconButton
213
+ <AuthPage
214
+ layout={layout}
215
+ title="Verify your email"
216
+ subtitle={`Enter the verification code sent to ${params.email || "your email"}`}
217
+ corner={
218
+ <IconButton
219
+ variant="ghost"
220
+ telemetryId="auth.verify_email.logout"
221
+ onPress={() => logout()}
222
+ accessibilityLabel="Sign out"
223
+ accessibilityRole="button"
224
+ >
225
+ <Ionicons name="log-out-outline" size={24} color={isDark ? "#FFFFFF" : "#000000"} />
226
+ </IconButton>
227
+ }
228
+ footer={
229
+ <>
230
+ <Button
231
+ className="h-14 w-full"
232
+ telemetryId="auth.verify_email.verify"
233
+ onPress={handleVerify}
234
+ isLoading={isLoading}
235
+ accessibilityLabel="Continue"
236
+ accessibilityRole="button"
237
+ accessibilityHint="Double tap to verify your email"
238
+ testID="verify-submit"
239
+ >
240
+ Continue
241
+ </Button>
242
+
243
+ <Button
226
244
  variant="ghost"
227
- telemetryId="auth.verify_email.logout"
228
- onPress={() => logout()}
245
+ className="w-full"
246
+ telemetryId="auth.verify_email.logout_2"
247
+ onPress={() => logout()}
229
248
  accessibilityLabel="Sign out"
230
249
  accessibilityRole="button"
231
250
  >
232
- <Ionicons name="log-out-outline" size={24} color={isDark ? "#FFFFFF" : "#000000"} />
233
- </IconButton>
234
- </View>
235
-
236
- <Card className="w-full max-w-[440px]">
237
- <CardHeader className="items-center">
238
- <CardTitle className="text-center text-2xl">Verify your email</CardTitle>
239
- <CardDescription className="text-center text-base">
240
- {`Enter the verification code sent to\n${params.email || "your email"}`}
241
- </CardDescription>
242
- </CardHeader>
243
-
244
- <CardContent className="gap-4 pb-3">
245
- <Input
246
- label="Verification Code"
247
- labelClassName="text-base"
248
- className="h-14"
249
- value={code}
250
- onChangeText={(text) => {
251
- setCode(text);
252
- if (error) {
253
- setError("");
254
- }
255
- }}
256
- error={error}
257
- placeholder="Paste your verification code"
258
- autoCapitalize="none"
259
- autoFocus
260
- returnKeyType="done"
261
- onSubmitEditing={handleVerify}
262
- accessibilityLabel="Verification code"
263
- testID="verify-code-input"
264
- />
265
-
266
- <MutedText className="text-center text-base">
267
- Didn&apos;t receive the code?{" "}
268
- {resendCooldown > 0 ? (
269
- <Text className="text-base text-foreground">Resend ({resendCooldown})</Text>
270
- ) : (
271
- <Text
272
- className="text-base text-foreground underline"
273
- onPress={withClickTracking("auth.verify_email.resend", handleResend)}
274
- accessibilityRole="button"
275
- accessibilityLabel="Resend verification code"
276
- >
277
- Resend
278
- </Text>
279
- )}
280
- </MutedText>
281
- </CardContent>
282
-
283
- <CardFooter className="flex-col items-center gap-1 border-t-0 pt-0">
284
- <Button
285
- className="h-14 w-full"
286
- telemetryId="auth.verify_email.verify"
287
- onPress={handleVerify}
288
- isLoading={isLoading}
289
- accessibilityLabel="Continue"
290
- accessibilityRole="button"
291
- accessibilityHint="Double tap to verify your email"
292
- testID="verify-submit"
293
- >
294
- Continue
295
- </Button>
251
+ Sign Out
252
+ </Button>
253
+ </>
254
+ }
255
+ >
256
+ <Input
257
+ label="Verification Code"
258
+ labelClassName="text-base"
259
+ className="h-14"
260
+ value={code}
261
+ onChangeText={(text) => {
262
+ setCode(text);
263
+ if (error) {
264
+ setError("");
265
+ }
266
+ }}
267
+ error={error}
268
+ placeholder="Enter the 6-digit code"
269
+ autoCapitalize="none"
270
+ keyboardType="number-pad"
271
+ autoFocus
272
+ returnKeyType="done"
273
+ onSubmitEditing={handleVerify}
274
+ accessibilityLabel="Verification code"
275
+ testID="verify-code-input"
276
+ />
296
277
 
297
- <Button
298
- variant="ghost"
299
- className="w-full"
300
- telemetryId="auth.verify_email.logout_2"
301
- onPress={() => logout()}
302
- accessibilityLabel="Sign out"
303
- accessibilityRole="button"
304
- >
305
- Sign Out
306
- </Button>
307
- </CardFooter>
308
- </Card>
309
- </ScrollView>
310
- </SafeAreaView>
278
+ <MutedText className="text-center text-base">
279
+ Didn&apos;t receive the code?{" "}
280
+ {resendCooldown > 0 ? (
281
+ <Text className="text-base text-foreground">Resend ({resendCooldown})</Text>
282
+ ) : (
283
+ <Text
284
+ className="text-base text-foreground underline"
285
+ onPress={withClickTracking("auth.verify_email.resend", handleResend)}
286
+ accessibilityRole="button"
287
+ accessibilityLabel="Resend verification code"
288
+ >
289
+ Resend
290
+ </Text>
291
+ )}
292
+ </MutedText>
293
+ </AuthPage>
311
294
  );
312
295
  }
313
296
 
@@ -1,3 +1,4 @@
1
+ export { AuthPage, type AuthPageProps, type AuthPageLayout } from "./AuthPage";
1
2
  export { WelcomeScreen, type WelcomeScreenProps } from "./WelcomeScreen";
2
3
  export { ForgotPasswordScreen } from "./ForgotPasswordScreen";
3
4
  export { MfaChallengeScreen } from "./MfaChallengeScreen";
@@ -6,7 +7,7 @@ export {
6
7
  type TermsOfServiceScreenProps,
7
8
  type LegalSection,
8
9
  } from "./TermsOfServiceScreen";
9
- export { VerifyEmailScreen } from "./VerifyEmailScreen";
10
+ export { VerifyEmailScreen, type VerifyEmailScreenProps } from "./VerifyEmailScreen";
10
11
  export { PrivacyPolicyScreen, type PrivacyPolicyScreenProps } from "./PrivacyPolicyScreen";
11
12
  export { ResetPasswordScreen, type ResetPasswordScreenProps } from "./ResetPasswordScreen";
12
13
  export { LoginScreen, type LoginScreenProps } from "./LoginScreen";
@@ -15,22 +16,12 @@ export { MfaEnrollScreen, type MfaEnrollScreenProps } from "./MfaEnrollScreen";
15
16
  export { RegisterScreen, type RegisterScreenProps } from "./RegisterScreen";
16
17
  export { ServerConfigScreen, type ServerConfigScreenProps } from "./ServerConfigScreen";
17
18
  export { ImportDataScreen, type ImportDataScreenProps } from "./ImportDataScreen";
18
- export {
19
- ConsentScreen,
20
- type ConsentScreenProps,
21
- type ConsentScope,
22
- } from "./ConsentScreen";
19
+ export { ConsentScreen, type ConsentScreenProps, type ConsentScope } from "./ConsentScreen";
23
20
  export {
24
21
  AccountPickerScreen,
25
22
  type AccountPickerScreenProps,
26
23
  type PickableAccount,
27
24
  } from "./AccountPickerScreen";
28
- export {
29
- PasskeyEnrollScreen,
30
- type PasskeyEnrollScreenProps,
31
- } from "./PasskeyEnrollScreen";
25
+ export { PasskeyEnrollScreen, type PasskeyEnrollScreenProps } from "./PasskeyEnrollScreen";
32
26
  export { ErrorScreen, type ErrorScreenProps } from "./ErrorScreen";
33
- export {
34
- ExpiredLinkScreen,
35
- type ExpiredLinkScreenProps,
36
- } from "./ExpiredLinkScreen";
27
+ export { ExpiredLinkScreen, type ExpiredLinkScreenProps } from "./ExpiredLinkScreen";