@erikey/react 0.4.32 → 0.4.34
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/package.json
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
"use client"
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
type ReactNode,
|
|
5
|
+
type MouseEvent,
|
|
6
|
+
useCallback,
|
|
7
|
+
useMemo,
|
|
8
|
+
useState
|
|
9
|
+
} from "react"
|
|
4
10
|
|
|
5
11
|
import { AuthUIContext, AuthUIProvider } from "../../lib/auth-ui-provider"
|
|
6
12
|
import type { AuthUIProviderProps } from "../../lib/auth-ui-provider"
|
|
@@ -80,7 +86,9 @@ const flowViewToPathKey: Record<AuthFlowView, keyof AuthViewPaths> = {
|
|
|
80
86
|
TWO_FACTOR: "TWO_FACTOR",
|
|
81
87
|
FORGOT_PASSWORD: "FORGOT_PASSWORD",
|
|
82
88
|
RESET_PASSWORD: "RESET_PASSWORD",
|
|
83
|
-
MAGIC_LINK: "MAGIC_LINK"
|
|
89
|
+
MAGIC_LINK: "MAGIC_LINK",
|
|
90
|
+
EMAIL_OTP: "EMAIL_OTP",
|
|
91
|
+
RECOVER_ACCOUNT: "RECOVER_ACCOUNT"
|
|
84
92
|
}
|
|
85
93
|
|
|
86
94
|
/**
|
|
@@ -109,6 +117,12 @@ function parsePathToView(path: string): { view: AuthFlowView; email?: string } {
|
|
|
109
117
|
if (pathname.includes("magic-link")) {
|
|
110
118
|
return { view: "MAGIC_LINK", email }
|
|
111
119
|
}
|
|
120
|
+
if (pathname.includes("email-otp")) {
|
|
121
|
+
return { view: "SIGN_IN", email } // EMAIL_OTP is a sign-in variant
|
|
122
|
+
}
|
|
123
|
+
if (pathname.includes("recover-account")) {
|
|
124
|
+
return { view: "TWO_FACTOR", email } // Recover account is part of 2FA flow
|
|
125
|
+
}
|
|
112
126
|
return { view: "SIGN_IN", email }
|
|
113
127
|
}
|
|
114
128
|
|
|
@@ -144,6 +158,24 @@ function parsePathToView(path: string): { view: AuthFlowView; email?: string } {
|
|
|
144
158
|
* basePath="/auth"
|
|
145
159
|
* />
|
|
146
160
|
*/
|
|
161
|
+
/**
|
|
162
|
+
* Check if a path is an auth-related path that should be intercepted
|
|
163
|
+
* These match the viewPaths defined in view-paths.ts
|
|
164
|
+
*/
|
|
165
|
+
function isAuthPath(href: string): boolean {
|
|
166
|
+
return (
|
|
167
|
+
href.includes("sign-in") ||
|
|
168
|
+
href.includes("sign-up") ||
|
|
169
|
+
href.includes("email-verification") ||
|
|
170
|
+
href.includes("two-factor") ||
|
|
171
|
+
href.includes("forgot-password") ||
|
|
172
|
+
href.includes("reset-password") ||
|
|
173
|
+
href.includes("magic-link") ||
|
|
174
|
+
href.includes("email-otp") ||
|
|
175
|
+
href.includes("recover-account")
|
|
176
|
+
)
|
|
177
|
+
}
|
|
178
|
+
|
|
147
179
|
export function AuthFlow({
|
|
148
180
|
mode = "internal",
|
|
149
181
|
onEvent,
|
|
@@ -159,6 +191,7 @@ export function AuthFlow({
|
|
|
159
191
|
// AuthUIProvider props
|
|
160
192
|
authClient,
|
|
161
193
|
basePath = "/auth",
|
|
194
|
+
Link: ExternalLink,
|
|
162
195
|
...providerProps
|
|
163
196
|
}: AuthFlowProps) {
|
|
164
197
|
// Internal state for "internal" mode
|
|
@@ -192,6 +225,56 @@ export function AuthFlow({
|
|
|
192
225
|
[mode, externalNavigate, onEvent]
|
|
193
226
|
)
|
|
194
227
|
|
|
228
|
+
// Custom Link component for internal mode that intercepts auth paths
|
|
229
|
+
const InternalLink = useCallback(
|
|
230
|
+
({
|
|
231
|
+
href,
|
|
232
|
+
children,
|
|
233
|
+
className: linkClassName,
|
|
234
|
+
...rest
|
|
235
|
+
}: {
|
|
236
|
+
href: string
|
|
237
|
+
children: ReactNode
|
|
238
|
+
className?: string
|
|
239
|
+
}) => {
|
|
240
|
+
const handleClick = (e: MouseEvent<HTMLAnchorElement>) => {
|
|
241
|
+
// In internal mode, intercept auth-related links
|
|
242
|
+
if (mode === "internal" && isAuthPath(href)) {
|
|
243
|
+
e.preventDefault()
|
|
244
|
+
handleNavigate(href)
|
|
245
|
+
}
|
|
246
|
+
// In route mode, or for non-auth paths, let the link work normally
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// If external Link provided (e.g., react-router), use it
|
|
250
|
+
if (ExternalLink) {
|
|
251
|
+
return (
|
|
252
|
+
<ExternalLink
|
|
253
|
+
href={href}
|
|
254
|
+
className={linkClassName}
|
|
255
|
+
onClick={handleClick}
|
|
256
|
+
{...rest}
|
|
257
|
+
>
|
|
258
|
+
{children}
|
|
259
|
+
</ExternalLink>
|
|
260
|
+
)
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// Default to anchor tag
|
|
264
|
+
return (
|
|
265
|
+
<a
|
|
266
|
+
href={href}
|
|
267
|
+
className={linkClassName}
|
|
268
|
+
onClick={handleClick}
|
|
269
|
+
{...rest}
|
|
270
|
+
>
|
|
271
|
+
{children}
|
|
272
|
+
</a>
|
|
273
|
+
)
|
|
274
|
+
},
|
|
275
|
+
[mode, handleNavigate, ExternalLink]
|
|
276
|
+
)
|
|
277
|
+
|
|
195
278
|
// Combined event handler that wraps user's onEvent
|
|
196
279
|
const handleAuthEvent = useCallback(
|
|
197
280
|
(event: AuthFlowEvent) => {
|
|
@@ -225,6 +308,7 @@ export function AuthFlow({
|
|
|
225
308
|
navigate={handleNavigate}
|
|
226
309
|
onAuthEvent={handleAuthEvent}
|
|
227
310
|
redirectTo={redirectTo}
|
|
311
|
+
Link={InternalLink}
|
|
228
312
|
{...providerProps}
|
|
229
313
|
>
|
|
230
314
|
<AuthViewComponent
|