@guettonenrique/passwordless-auth 0.0.0-stage → 0.1.2

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.
@@ -0,0 +1,606 @@
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined") return require.apply(this, arguments);
5
+ throw Error('Dynamic require of "' + x + '" is not supported');
6
+ });
7
+
8
+ // src/react-native/api.ts
9
+ import { getFunctions, httpsCallable } from "@react-native-firebase/functions";
10
+ import { getAuth, signInWithCustomToken } from "@react-native-firebase/auth";
11
+ async function requestEmailOtp(email) {
12
+ const functions = getFunctions();
13
+ const callable = httpsCallable(
14
+ functions,
15
+ "requestEmailOtp"
16
+ );
17
+ const result = await callable({ email: email.trim().toLowerCase() });
18
+ return result.data;
19
+ }
20
+ async function verifyEmailOtp(email, code) {
21
+ const functions = getFunctions();
22
+ const callable = httpsCallable(
23
+ functions,
24
+ "verifyEmailOtp"
25
+ );
26
+ const result = await callable({
27
+ email: email.trim().toLowerCase(),
28
+ code: code.trim()
29
+ });
30
+ return result.data.customToken;
31
+ }
32
+ async function signInWithEmailOtp(email, code) {
33
+ const customToken = await verifyEmailOtp(email, code);
34
+ await signInWithCustomToken(getAuth(), customToken);
35
+ }
36
+
37
+ // src/react-native/OtpInput.tsx
38
+ import { useEffect, useRef, useState } from "react";
39
+ import {
40
+ Platform,
41
+ Text,
42
+ TextInput,
43
+ TouchableOpacity,
44
+ View
45
+ } from "react-native";
46
+
47
+ // src/shared/constants.ts
48
+ var CODE_LENGTH = 6;
49
+ var RESEND_COOLDOWN_MS = 60 * 1e3;
50
+ var OTP_EXPIRY_MS = 10 * 60 * 1e3;
51
+
52
+ // src/shared/utils.ts
53
+ var EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
54
+ function normalizeEmail(raw) {
55
+ return raw.trim().toLowerCase();
56
+ }
57
+ function isValidEmail(raw) {
58
+ return EMAIL_REGEX.test(normalizeEmail(raw));
59
+ }
60
+
61
+ // src/react-native/OtpInput.tsx
62
+ import { jsx, jsxs } from "react/jsx-runtime";
63
+ var Haptics = null;
64
+ try {
65
+ Haptics = __require("expo-haptics");
66
+ } catch {
67
+ Haptics = null;
68
+ }
69
+ var impact = (style) => {
70
+ try {
71
+ if (style === "light") {
72
+ Haptics?.impactAsync?.("light").catch(() => null);
73
+ } else {
74
+ Haptics?.notificationAsync?.("success").catch(() => null);
75
+ }
76
+ } catch {
77
+ }
78
+ };
79
+ function OtpInput({
80
+ length = CODE_LENGTH,
81
+ value,
82
+ onChange,
83
+ onComplete,
84
+ disabled = false,
85
+ error = false,
86
+ autoFocus = true
87
+ }) {
88
+ const inputRef = useRef(null);
89
+ const [isFocused, setIsFocused] = useState(false);
90
+ const [cursorVisible, setCursorVisible] = useState(true);
91
+ useEffect(() => {
92
+ if (!isFocused) return;
93
+ const interval = setInterval(() => {
94
+ setCursorVisible((prev) => !prev);
95
+ }, 550);
96
+ return () => clearInterval(interval);
97
+ }, [isFocused]);
98
+ const handleChangeText = (text) => {
99
+ const cleaned = text.replace(/[^0-9]/g, "").slice(0, length);
100
+ onChange(cleaned);
101
+ if (cleaned.length > value.length) impact("light");
102
+ if (cleaned.length === length) {
103
+ impact("success");
104
+ onComplete?.(cleaned);
105
+ }
106
+ };
107
+ const slots = Array.from({ length }, (_, i) => i);
108
+ return /* @__PURE__ */ jsxs(
109
+ TouchableOpacity,
110
+ {
111
+ style: { width: "100%" },
112
+ activeOpacity: 1,
113
+ onPress: () => {
114
+ if (!disabled) inputRef.current?.focus();
115
+ },
116
+ children: [
117
+ /* @__PURE__ */ jsx(
118
+ View,
119
+ {
120
+ style: {
121
+ flexDirection: "row",
122
+ width: "100%",
123
+ justifyContent: "space-between",
124
+ alignItems: "center",
125
+ marginVertical: 12
126
+ },
127
+ children: slots.map((index) => {
128
+ const char = value[index] ?? "";
129
+ const isSlotActive = isFocused && index === value.length && !disabled;
130
+ const isFilled = char !== "";
131
+ let borderColor = "#e5e7eb";
132
+ let backgroundColor = "#f8fafc";
133
+ if (error) {
134
+ borderColor = "#f43f5e";
135
+ backgroundColor = "#fff1f2";
136
+ } else if (isSlotActive) {
137
+ borderColor = "#3b82f6";
138
+ backgroundColor = "#ffffff";
139
+ } else if (isFilled) {
140
+ borderColor = "#94a3b8";
141
+ backgroundColor = "#ffffff";
142
+ }
143
+ return /* @__PURE__ */ jsx(
144
+ View,
145
+ {
146
+ style: {
147
+ flex: 1,
148
+ maxWidth: 48,
149
+ height: 56,
150
+ borderRadius: 8,
151
+ alignItems: "center",
152
+ justifyContent: "center",
153
+ marginHorizontal: 4,
154
+ borderWidth: isSlotActive ? 2 : 1,
155
+ borderColor,
156
+ backgroundColor
157
+ },
158
+ children: char ? /* @__PURE__ */ jsx(
159
+ Text,
160
+ {
161
+ style: {
162
+ fontSize: 24,
163
+ fontWeight: "700",
164
+ color: error ? "#e11d48" : "#1e293b"
165
+ },
166
+ children: char
167
+ }
168
+ ) : isSlotActive && cursorVisible ? /* @__PURE__ */ jsx(
169
+ View,
170
+ {
171
+ style: {
172
+ width: 2,
173
+ height: 24,
174
+ backgroundColor: "#3b82f6",
175
+ borderRadius: 2
176
+ }
177
+ }
178
+ ) : null
179
+ },
180
+ index
181
+ );
182
+ })
183
+ }
184
+ ),
185
+ /* @__PURE__ */ jsx(
186
+ TextInput,
187
+ {
188
+ ref: inputRef,
189
+ value,
190
+ onChangeText: handleChangeText,
191
+ keyboardType: "number-pad",
192
+ textContentType: "oneTimeCode",
193
+ autoComplete: Platform.OS === "android" ? "one-time-code" : void 0,
194
+ maxLength: length,
195
+ editable: !disabled,
196
+ autoFocus,
197
+ onFocus: () => setIsFocused(true),
198
+ onBlur: () => setIsFocused(false),
199
+ caretHidden: true,
200
+ style: {
201
+ position: "absolute",
202
+ top: 0,
203
+ bottom: 0,
204
+ left: 0,
205
+ right: 0,
206
+ opacity: 0
207
+ },
208
+ accessibilityLabel: `${length}-digit verification code`
209
+ }
210
+ )
211
+ ]
212
+ }
213
+ );
214
+ }
215
+
216
+ // src/react-native/EmailOtpModal.tsx
217
+ import { useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
218
+ import {
219
+ ActivityIndicator,
220
+ Modal,
221
+ Text as Text2,
222
+ TextInput as TextInput2,
223
+ TouchableOpacity as TouchableOpacity2,
224
+ View as View2
225
+ } from "react-native";
226
+ import { KeyboardAwareScrollView } from "react-native-keyboard-controller";
227
+ import { AlertCircle, ArrowLeft, Mail, X } from "lucide-react-native";
228
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
229
+ function EmailOtpModal({
230
+ visible,
231
+ onClose,
232
+ initialEmail = "",
233
+ appName,
234
+ cooldownSeconds = Math.round(RESEND_COOLDOWN_MS / 1e3)
235
+ }) {
236
+ const [step, setStep] = useState2("email");
237
+ const [email, setEmail] = useState2(initialEmail);
238
+ const [otp, setOtp] = useState2("");
239
+ const [loading, setLoading] = useState2(false);
240
+ const [resending, setResending] = useState2(false);
241
+ const [error, setError] = useState2(null);
242
+ const [cooldown, setCooldown] = useState2(0);
243
+ const [prevVisible, setPrevVisible] = useState2(false);
244
+ const isVerifyingRef = useRef2(false);
245
+ const emailRef = useRef2(null);
246
+ if (visible !== prevVisible) {
247
+ setPrevVisible(visible);
248
+ if (visible) {
249
+ setStep("email");
250
+ setEmail(initialEmail);
251
+ setOtp("");
252
+ setError(null);
253
+ setLoading(false);
254
+ setResending(false);
255
+ setCooldown(0);
256
+ isVerifyingRef.current = false;
257
+ }
258
+ }
259
+ useEffect2(() => {
260
+ if (cooldown <= 0) return;
261
+ const timer = setInterval(() => {
262
+ setCooldown((prev) => prev > 0 ? prev - 1 : 0);
263
+ }, 1e3);
264
+ return () => clearInterval(timer);
265
+ }, [cooldown]);
266
+ const cleanErrorMessage = (err, fallback) => {
267
+ const raw = err instanceof Error ? err.message : typeof err === "string" ? err : "";
268
+ if (raw.length > 0) {
269
+ return raw.replace(/^\[.*?\]\s*/, "").trim();
270
+ }
271
+ return fallback;
272
+ };
273
+ const handleSendCode = async () => {
274
+ const trimmedEmail = email.trim().toLowerCase();
275
+ if (!trimmedEmail) {
276
+ setError("Please enter your email address.");
277
+ return;
278
+ }
279
+ if (!isValidEmail(trimmedEmail)) {
280
+ setError("Please enter a valid email address.");
281
+ return;
282
+ }
283
+ setLoading(true);
284
+ setError(null);
285
+ emailRef.current?.blur();
286
+ try {
287
+ await requestEmailOtp(trimmedEmail);
288
+ setStep("otp");
289
+ setCooldown(cooldownSeconds);
290
+ setOtp("");
291
+ } catch (err) {
292
+ console.error("[passwordless-auth] requestEmailOtp failed:", err);
293
+ setError(cleanErrorMessage(err, "Failed to send verification code. Please try again."));
294
+ } finally {
295
+ setLoading(false);
296
+ }
297
+ };
298
+ const handleResendCode = async () => {
299
+ if (cooldown > 0 || resending || loading) return;
300
+ setResending(true);
301
+ setError(null);
302
+ try {
303
+ await requestEmailOtp(email.trim().toLowerCase());
304
+ setCooldown(cooldownSeconds);
305
+ setOtp("");
306
+ } catch (err) {
307
+ console.error("[passwordless-auth] resend failed:", err);
308
+ setError(cleanErrorMessage(err, "Failed to resend verification code."));
309
+ } finally {
310
+ setResending(false);
311
+ }
312
+ };
313
+ const handleClose = () => {
314
+ setError(null);
315
+ setLoading(false);
316
+ setResending(false);
317
+ onClose();
318
+ };
319
+ const handleVerifyOtp = async (codeToVerify) => {
320
+ const code = (codeToVerify ?? otp).trim();
321
+ if (code.length < CODE_LENGTH || isVerifyingRef.current) return;
322
+ isVerifyingRef.current = true;
323
+ setLoading(true);
324
+ setError(null);
325
+ try {
326
+ await signInWithEmailOtp(email.trim().toLowerCase(), code);
327
+ handleClose();
328
+ } catch (err) {
329
+ console.error("[passwordless-auth] verifyEmailOtp failed:", err);
330
+ setError(
331
+ cleanErrorMessage(err, "Invalid or expired verification code. Please try again.")
332
+ );
333
+ setOtp("");
334
+ } finally {
335
+ setLoading(false);
336
+ isVerifyingRef.current = false;
337
+ }
338
+ };
339
+ const handleBackToEmail = () => {
340
+ if (loading) return;
341
+ setStep("email");
342
+ setOtp("");
343
+ setError(null);
344
+ };
345
+ const buttonBase = {
346
+ flex: 1,
347
+ paddingVertical: 14,
348
+ borderRadius: 12,
349
+ alignItems: "center",
350
+ flexDirection: "row",
351
+ justifyContent: "center",
352
+ gap: 8
353
+ };
354
+ return /* @__PURE__ */ jsx2(Modal, { visible, transparent: true, animationType: "fade", onRequestClose: handleClose, children: /* @__PURE__ */ jsx2(
355
+ KeyboardAwareScrollView,
356
+ {
357
+ contentContainerStyle: { flexGrow: 1 },
358
+ keyboardShouldPersistTaps: "handled",
359
+ bottomOffset: 24,
360
+ showsVerticalScrollIndicator: false,
361
+ children: /* @__PURE__ */ jsx2(
362
+ TouchableOpacity2,
363
+ {
364
+ style: {
365
+ flex: 1,
366
+ backgroundColor: "rgba(0,0,0,0.5)",
367
+ justifyContent: "center",
368
+ alignItems: "center",
369
+ padding: 16
370
+ },
371
+ activeOpacity: 1,
372
+ onPress: handleClose,
373
+ children: /* @__PURE__ */ jsxs2(
374
+ TouchableOpacity2,
375
+ {
376
+ activeOpacity: 1,
377
+ style: {
378
+ backgroundColor: "#fff",
379
+ width: "100%",
380
+ maxWidth: 420,
381
+ borderRadius: 16,
382
+ overflow: "hidden",
383
+ shadowColor: "#000",
384
+ shadowOpacity: 0.2,
385
+ shadowRadius: 12,
386
+ elevation: 10
387
+ },
388
+ children: [
389
+ /* @__PURE__ */ jsxs2(
390
+ View2,
391
+ {
392
+ style: {
393
+ flexDirection: "row",
394
+ alignItems: "center",
395
+ justifyContent: "space-between",
396
+ paddingHorizontal: 24,
397
+ paddingVertical: 16,
398
+ borderBottomWidth: 1,
399
+ borderBottomColor: "#f3f4f6"
400
+ },
401
+ children: [
402
+ /* @__PURE__ */ jsxs2(View2, { style: { flexDirection: "row", alignItems: "center", gap: 12 }, children: [
403
+ step === "otp" && /* @__PURE__ */ jsx2(TouchableOpacity2, { onPress: handleBackToEmail, disabled: loading, activeOpacity: 0.7, children: /* @__PURE__ */ jsx2(ArrowLeft, { size: 20, color: "#64748b" }) }),
404
+ /* @__PURE__ */ jsxs2(View2, { children: [
405
+ /* @__PURE__ */ jsx2(Text2, { style: { fontSize: 12, color: "#94a3b8", marginBottom: 2 }, children: step === "email" ? "Instant Sign In" : "Verification" }),
406
+ /* @__PURE__ */ jsx2(Text2, { style: { fontSize: 18, fontWeight: "700", color: "#1e293b" }, children: step === "email" ? appName ? `${appName} \u2014 email code` : "Sign in with email code" : "Enter verification code" })
407
+ ] })
408
+ ] }),
409
+ /* @__PURE__ */ jsx2(TouchableOpacity2, { onPress: handleClose, activeOpacity: 0.7, children: /* @__PURE__ */ jsx2(X, { size: 20, color: "#94a3b8" }) })
410
+ ]
411
+ }
412
+ ),
413
+ /* @__PURE__ */ jsxs2(View2, { style: { padding: 24 }, children: [
414
+ error ? /* @__PURE__ */ jsxs2(
415
+ View2,
416
+ {
417
+ style: {
418
+ flexDirection: "row",
419
+ alignItems: "center",
420
+ gap: 8,
421
+ padding: 12,
422
+ marginBottom: 16,
423
+ borderRadius: 12,
424
+ backgroundColor: "#fef2f2",
425
+ borderWidth: 1,
426
+ borderColor: "#fecaca"
427
+ },
428
+ children: [
429
+ /* @__PURE__ */ jsx2(AlertCircle, { size: 16, color: "#dc2626" }),
430
+ /* @__PURE__ */ jsx2(Text2, { style: { fontSize: 12, color: "#dc2626", flex: 1, fontWeight: "500" }, children: error })
431
+ ]
432
+ }
433
+ ) : null,
434
+ step === "email" ? (
435
+ /* ---------- Step 1: Email ---------- */
436
+ /* @__PURE__ */ jsxs2(View2, { children: [
437
+ /* @__PURE__ */ jsx2(Text2, { style: { fontSize: 13, color: "#64748b", marginBottom: 16, lineHeight: 18 }, children: "We'll send a 6-digit verification code to your email. No password needed." }),
438
+ /* @__PURE__ */ jsxs2(View2, { style: { marginBottom: 24 }, children: [
439
+ /* @__PURE__ */ jsx2(Text2, { style: { fontSize: 12, fontWeight: "600", color: "#334155", marginBottom: 8 }, children: "Email" }),
440
+ /* @__PURE__ */ jsxs2(
441
+ View2,
442
+ {
443
+ style: {
444
+ flexDirection: "row",
445
+ alignItems: "center",
446
+ paddingHorizontal: 16,
447
+ backgroundColor: "#f8fafc",
448
+ borderRadius: 12,
449
+ borderWidth: 1,
450
+ borderColor: "#e5e7eb",
451
+ height: 56
452
+ },
453
+ children: [
454
+ /* @__PURE__ */ jsx2(
455
+ TextInput2,
456
+ {
457
+ ref: emailRef,
458
+ style: { flex: 1, fontSize: 14, fontWeight: "600", color: "#1e293b" },
459
+ placeholder: "name@email.com",
460
+ placeholderTextColor: "#94a3b8",
461
+ value: email,
462
+ onChangeText: (val) => {
463
+ setEmail(val);
464
+ if (error) setError(null);
465
+ },
466
+ keyboardType: "email-address",
467
+ autoCapitalize: "none",
468
+ autoCorrect: false,
469
+ returnKeyType: "send",
470
+ onSubmitEditing: handleSendCode,
471
+ autoFocus: true,
472
+ editable: !loading
473
+ }
474
+ ),
475
+ /* @__PURE__ */ jsx2(Mail, { size: 20, color: "#cbd5e1" })
476
+ ]
477
+ }
478
+ )
479
+ ] }),
480
+ /* @__PURE__ */ jsxs2(View2, { style: { flexDirection: "row", gap: 12 }, children: [
481
+ /* @__PURE__ */ jsx2(
482
+ TouchableOpacity2,
483
+ {
484
+ onPress: handleClose,
485
+ style: { ...buttonBase, borderWidth: 1, borderColor: "#e5e7eb", backgroundColor: "transparent" },
486
+ activeOpacity: 0.7,
487
+ children: /* @__PURE__ */ jsx2(Text2, { style: { color: "#64748b", fontWeight: "600", fontSize: 12, textTransform: "uppercase", letterSpacing: 1 }, children: "Cancel" })
488
+ }
489
+ ),
490
+ /* @__PURE__ */ jsxs2(
491
+ TouchableOpacity2,
492
+ {
493
+ onPress: handleSendCode,
494
+ disabled: loading,
495
+ style: { ...buttonBase, backgroundColor: loading ? "#93c5fd" : "#3b82f6" },
496
+ activeOpacity: 0.7,
497
+ children: [
498
+ loading ? /* @__PURE__ */ jsx2(ActivityIndicator, { size: "small", color: "#fff" }) : null,
499
+ /* @__PURE__ */ jsx2(Text2, { style: { color: "#fff", fontWeight: "600", fontSize: 12, textTransform: "uppercase", letterSpacing: 1 }, children: loading ? "Sending\u2026" : "Send Code" })
500
+ ]
501
+ }
502
+ )
503
+ ] })
504
+ ] })
505
+ ) : (
506
+ /* ---------- Step 2: Code ---------- */
507
+ /* @__PURE__ */ jsxs2(View2, { children: [
508
+ /* @__PURE__ */ jsxs2(Text2, { style: { fontSize: 13, color: "#64748b", marginBottom: 16, lineHeight: 18 }, children: [
509
+ "We sent a 6-digit code to",
510
+ " ",
511
+ /* @__PURE__ */ jsx2(Text2, { style: { fontWeight: "600", color: "#1e293b" }, children: email.trim() }),
512
+ " ",
513
+ ". Enter it below to sign in."
514
+ ] }),
515
+ /* @__PURE__ */ jsx2(View2, { style: { alignItems: "center", marginBottom: 16 }, children: /* @__PURE__ */ jsx2(
516
+ OtpInput,
517
+ {
518
+ value: otp,
519
+ onChange: (val) => {
520
+ setOtp(val);
521
+ if (error) setError(null);
522
+ },
523
+ onComplete: (code) => handleVerifyOtp(code),
524
+ disabled: loading,
525
+ error: !!error,
526
+ autoFocus: true
527
+ }
528
+ ) }),
529
+ /* @__PURE__ */ jsxs2(
530
+ View2,
531
+ {
532
+ style: {
533
+ flexDirection: "row",
534
+ alignItems: "center",
535
+ justifyContent: "space-between",
536
+ marginBottom: 24,
537
+ paddingHorizontal: 4
538
+ },
539
+ children: [
540
+ /* @__PURE__ */ jsx2(TouchableOpacity2, { onPress: handleBackToEmail, disabled: loading, activeOpacity: 0.7, children: /* @__PURE__ */ jsx2(Text2, { style: { fontSize: 12, fontWeight: "600", color: "#64748b" }, children: "Change email" }) }),
541
+ cooldown > 0 ? /* @__PURE__ */ jsxs2(Text2, { style: { fontSize: 12, color: "#94a3b8", fontWeight: "500" }, children: [
542
+ "Resend in ",
543
+ cooldown,
544
+ "s"
545
+ ] }) : /* @__PURE__ */ jsxs2(
546
+ TouchableOpacity2,
547
+ {
548
+ onPress: handleResendCode,
549
+ disabled: resending || loading,
550
+ style: { flexDirection: "row", alignItems: "center", gap: 6 },
551
+ activeOpacity: 0.7,
552
+ children: [
553
+ resending ? /* @__PURE__ */ jsx2(ActivityIndicator, { size: "small", color: "#2563eb" }) : null,
554
+ /* @__PURE__ */ jsx2(Text2, { style: { fontSize: 12, fontWeight: "600", color: "#2563eb" }, children: "Resend Code" })
555
+ ]
556
+ }
557
+ )
558
+ ]
559
+ }
560
+ ),
561
+ /* @__PURE__ */ jsxs2(View2, { style: { flexDirection: "row", gap: 12 }, children: [
562
+ /* @__PURE__ */ jsx2(
563
+ TouchableOpacity2,
564
+ {
565
+ onPress: handleClose,
566
+ style: { ...buttonBase, borderWidth: 1, borderColor: "#e5e7eb", backgroundColor: "transparent" },
567
+ activeOpacity: 0.7,
568
+ children: /* @__PURE__ */ jsx2(Text2, { style: { color: "#64748b", fontWeight: "600", fontSize: 12, textTransform: "uppercase", letterSpacing: 1 }, children: "Cancel" })
569
+ }
570
+ ),
571
+ /* @__PURE__ */ jsxs2(
572
+ TouchableOpacity2,
573
+ {
574
+ onPress: () => handleVerifyOtp(),
575
+ disabled: loading || otp.length < CODE_LENGTH,
576
+ style: {
577
+ ...buttonBase,
578
+ backgroundColor: loading || otp.length < CODE_LENGTH ? "#93c5fd" : "#3b82f6"
579
+ },
580
+ activeOpacity: 0.7,
581
+ children: [
582
+ loading ? /* @__PURE__ */ jsx2(ActivityIndicator, { size: "small", color: "#fff" }) : null,
583
+ /* @__PURE__ */ jsx2(Text2, { style: { color: "#fff", fontWeight: "600", fontSize: 12, textTransform: "uppercase", letterSpacing: 1 }, children: loading ? "Verifying\u2026" : "Verify & Sign In" })
584
+ ]
585
+ }
586
+ )
587
+ ] })
588
+ ] })
589
+ )
590
+ ] })
591
+ ]
592
+ }
593
+ )
594
+ }
595
+ )
596
+ }
597
+ ) });
598
+ }
599
+ export {
600
+ EmailOtpModal,
601
+ OtpInput,
602
+ requestEmailOtp,
603
+ signInWithEmailOtp,
604
+ verifyEmailOtp
605
+ };
606
+ //# sourceMappingURL=index.js.map