@erikey/react 0.4.33 → 0.4.35
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,70 @@ 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
|
+
// In internal mode for auth paths, ALWAYS use plain <a> that we control
|
|
250
|
+
// This avoids relying on external Link components forwarding onClick
|
|
251
|
+
if (mode === "internal" && isAuthPath(href)) {
|
|
252
|
+
return (
|
|
253
|
+
<a
|
|
254
|
+
href={href}
|
|
255
|
+
className={linkClassName}
|
|
256
|
+
onClick={handleClick}
|
|
257
|
+
{...rest}
|
|
258
|
+
>
|
|
259
|
+
{children}
|
|
260
|
+
</a>
|
|
261
|
+
)
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// For non-auth paths or route mode, use external Link if provided
|
|
265
|
+
if (ExternalLink) {
|
|
266
|
+
return (
|
|
267
|
+
<ExternalLink
|
|
268
|
+
href={href}
|
|
269
|
+
className={linkClassName}
|
|
270
|
+
{...rest}
|
|
271
|
+
>
|
|
272
|
+
{children}
|
|
273
|
+
</ExternalLink>
|
|
274
|
+
)
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// Default to anchor tag
|
|
278
|
+
return (
|
|
279
|
+
<a
|
|
280
|
+
href={href}
|
|
281
|
+
className={linkClassName}
|
|
282
|
+
onClick={handleClick}
|
|
283
|
+
{...rest}
|
|
284
|
+
>
|
|
285
|
+
{children}
|
|
286
|
+
</a>
|
|
287
|
+
)
|
|
288
|
+
},
|
|
289
|
+
[mode, handleNavigate, ExternalLink]
|
|
290
|
+
)
|
|
291
|
+
|
|
195
292
|
// Combined event handler that wraps user's onEvent
|
|
196
293
|
const handleAuthEvent = useCallback(
|
|
197
294
|
(event: AuthFlowEvent) => {
|
|
@@ -225,6 +322,7 @@ export function AuthFlow({
|
|
|
225
322
|
navigate={handleNavigate}
|
|
226
323
|
onAuthEvent={handleAuthEvent}
|
|
227
324
|
redirectTo={redirectTo}
|
|
325
|
+
Link={InternalLink}
|
|
228
326
|
{...providerProps}
|
|
229
327
|
>
|
|
230
328
|
<AuthViewComponent
|