Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(clerk-js): Add experimental combined flow #4607

Open
wants to merge 31 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
e53e4cf
wip
dstaley Nov 14, 2024
1196121
Merge branch 'main' into ds.feat/clerk-js-kitchen-sink
dstaley Nov 15, 2024
a5d7e4c
feat(clerk-js): Add JSDoc
dstaley Nov 15, 2024
b583b36
chore(repo): Add empty changeset
dstaley Nov 15, 2024
3dedf15
fix(clerk-js): Use shared team app
dstaley Nov 15, 2024
5f26fbd
feat(clerk-js): Use docs dark tailwind config
dstaley Nov 18, 2024
132233d
init
alexcarpenter Nov 18, 2024
ec88896
Merge branch 'main' into alexcarpenter/sign-in-up-flow-init
alexcarpenter Nov 19, 2024
aec24d4
wip
alexcarpenter Nov 19, 2024
4916296
wip
alexcarpenter Nov 19, 2024
75663b5
wip
alexcarpenter Nov 19, 2024
022c6ae
wip
alexcarpenter Nov 19, 2024
a78605a
wip
alexcarpenter Nov 19, 2024
1508e49
Merge branch 'main' into alexcarpenter/sign-in-up-flow-init
alexcarpenter Nov 19, 2024
9b58e3b
wip
alexcarpenter Nov 19, 2024
d82bb14
experimental prefix
alexcarpenter Nov 20, 2024
da880cc
move signUpProps to experimental
alexcarpenter Nov 20, 2024
555fd91
add changeset
alexcarpenter Nov 20, 2024
3f1e79f
Merge branch 'main' into alexcarpenter/sign-in-up-flow-init
alexcarpenter Nov 20, 2024
5e0c32a
Merge branch 'main' into alexcarpenter/sign-in-up-flow-init
alexcarpenter Nov 20, 2024
78c045c
feat(clerk-js,types): Move to waitlist with email address in combined…
alexcarpenter Nov 20, 2024
5e5f3f7
Merge branch 'main' into alexcarpenter/sign-in-up-flow-init
alexcarpenter Nov 20, 2024
11e7827
padding
alexcarpenter Nov 21, 2024
f06ae91
Merge branch 'main' into alexcarpenter/sign-in-up-flow-init
alexcarpenter Nov 21, 2024
274816b
Merge branch 'main' into alexcarpenter/sign-in-up-flow-init
alexcarpenter Nov 22, 2024
719dd8e
Merge branch 'main' into alexcarpenter/sign-in-up-flow-init
alexcarpenter Nov 22, 2024
0bf9516
feat(clerk-js): Add support for combined flow in `buildUrl` (#4626)
alexcarpenter Nov 25, 2024
f9db2df
Merge branch 'main' into alexcarpenter/sign-in-up-flow-init
alexcarpenter Nov 25, 2024
acee56f
feat(clerk-js): Combined flow transfer (#4637)
alexcarpenter Nov 27, 2024
ab07986
Merge branch 'main' into alexcarpenter/sign-in-up-flow-init
alexcarpenter Nov 27, 2024
0595202
remove signUpContext usage
alexcarpenter Nov 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 86 additions & 3 deletions packages/clerk-js/src/ui/components/SignIn/SignIn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,21 @@ import { useClerk } from '@clerk/shared/react';
import type { SignInModalProps, SignInProps } from '@clerk/types';
import React from 'react';

import { SignInEmailLinkFlowComplete } from '../../common/EmailLinkCompleteFlowCard';
import { SignInContext, useSignInContext, withCoreSessionSwitchGuard } from '../../contexts';
import { SignInEmailLinkFlowComplete, SignUpEmailLinkFlowComplete } from '../../common/EmailLinkCompleteFlowCard';
import {
SignInContext,
SignUpContext,
useSignInContext,
useSignUpContext,
withCoreSessionSwitchGuard,
} from '../../contexts';
import { Flow } from '../../customizables';
import { Route, Switch, VIRTUAL_ROUTER_BASE_PATH } from '../../router';
import { SignUpContinue } from '../SignUp/SignUpContinue';
import { SignUpSSOCallback } from '../SignUp/SignUpSSOCallback';
import { SignUpStart } from '../SignUp/SignUpStart';
import { SignUpVerifyEmail } from '../SignUp/SignUpVerifyEmail';
import { SignUpVerifyPhone } from '../SignUp/SignUpVerifyPhone';
import { ResetPassword } from './ResetPassword';
import { ResetPasswordSuccess } from './ResetPasswordSuccess';
import { SignInAccountSwitcher } from './SignInAccountSwitcher';
Expand All @@ -24,6 +35,7 @@ function RedirectToSignIn() {

function SignInRoutes(): JSX.Element {
const signInContext = useSignInContext();
const signUpContext = useSignUpContext();

return (
<Flow.Root flow='signIn'>
Expand Down Expand Up @@ -62,6 +74,61 @@ function SignInRoutes(): JSX.Element {
redirectUrl='../factor-two'
/>
</Route>
{signInContext.__experimental?.combinedFlow && (
<Route path='create'>
<Route
path='verify-email-address'
canActivate={clerk => !!clerk.client.signUp.emailAddress}
>
<SignUpVerifyEmail />
</Route>
<Route
path='verify-phone-number'
canActivate={clerk => !!clerk.client.signUp.phoneNumber}
>
<SignUpVerifyPhone />
</Route>
<Route path='sso-callback'>
<SignUpSSOCallback
signUpUrl={signUpContext.signUpUrl}
signInUrl={signUpContext.signInUrl}
signUpForceRedirectUrl={signUpContext.afterSignUpUrl}
signInForceRedirectUrl={signUpContext.afterSignInUrl}
secondFactorUrl={signUpContext.secondFactorUrl}
continueSignUpUrl='../continue'
verifyEmailAddressUrl='../verify-email-address'
verifyPhoneNumberUrl='../verify-phone-number'
/>
</Route>
<Route path='verify'>
<SignUpEmailLinkFlowComplete
redirectUrlComplete={signUpContext.afterSignUpUrl}
verifyEmailPath='../verify-email-address'
verifyPhonePath='../verify-phone-number'
/>
</Route>
<Route path='continue'>
<Route
path='verify-email-address'
canActivate={clerk => !!clerk.client.signUp.emailAddress}
>
<SignUpVerifyEmail />
</Route>
<Route
path='verify-phone-number'
canActivate={clerk => !!clerk.client.signUp.phoneNumber}
>
<SignUpVerifyPhone />
</Route>
<Route index>
<SignUpContinue />
</Route>
</Route>
<Route index>
<SignUpStart />
</Route>
</Route>
)}
<Route index>
<SignInStart />
</Route>
Expand All @@ -73,9 +140,25 @@ function SignInRoutes(): JSX.Element {
);
}

function SignInRoot() {
const signInContext = useSignInContext();

return (
<SignUpContext.Provider
value={{
componentName: 'SignUp',
...signInContext.signUpProps,
...(signInContext.__experimental?.combinedFlow ? { __experimental: { combinedFlow: true } } : {}),
}}
>
<SignInRoutes />
</SignUpContext.Provider>
);
}

SignInRoutes.displayName = 'SignIn';

export const SignIn: React.ComponentType<SignInProps> = withCoreSessionSwitchGuard(SignInRoutes);
export const SignIn: React.ComponentType<SignInProps> = withCoreSessionSwitchGuard(SignInRoot);

export const SignInModal = (props: SignInModalProps): JSX.Element => {
const signInProps = {
Expand Down
21 changes: 17 additions & 4 deletions packages/clerk-js/src/ui/components/SignIn/SignInStart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import type { FormControlState } from '../../utils';
import { buildRequest, handleError, isMobileDevice, useFormControl } from '../../utils';
import { useHandleAuthenticateWithPasskey } from './shared';
import { SignInSocialButtons } from './SignInSocialButtons';
import { getSignUpAttributeFromIdentifier } from './utils';

const useAutoFillPasskey = () => {
const [isSupported, setIsSupported] = useState(false);
Expand Down Expand Up @@ -65,7 +66,8 @@ export function _SignInStart(): JSX.Element {
const signIn = useCoreSignIn();
const { navigate } = useRouter();
const ctx = useSignInContext();
const { afterSignInUrl, signUpUrl, waitlistUrl } = ctx;
const { afterSignInUrl, signUpUrl, waitlistUrl, __experimental } = ctx;
const isCombinedFlow = __experimental?.combinedFlow || false;
const supportEmail = useSupportEmail();
const identifierAttributes = useMemo<SignInStartIdentifier[]>(
() => groupIdentifiers(userSettings.enabledFirstFactorIdentifiers),
Expand Down Expand Up @@ -335,6 +337,11 @@ export function _SignInStart(): JSX.Element {
const sid = alreadySignedInError.meta!.sessionId!;
await clerk.setActive({ session: sid, redirectUrl: afterSignInUrl });
} else {
if (isCombinedFlow) {
const attribute = getSignUpAttributeFromIdentifier(identifierField);
clerk.client.signUp[attribute] = identifierField.value;
return navigate('create');
}
handleError(e, [identifierField, instantPasswordField], card.setError);
}
};
Expand Down Expand Up @@ -366,8 +373,14 @@ export function _SignInStart(): JSX.Element {
<Card.Root>
<Card.Content>
<Header.Root showLogo>
<Header.Title localizationKey={localizationKeys('signIn.start.title')} />
<Header.Subtitle localizationKey={localizationKeys('signIn.start.subtitle')} />
{isCombinedFlow ? (
<Header.Title localizationKey={localizationKeys('signIn.start.titleCombined')} />
) : (
<>
<Header.Title localizationKey={localizationKeys('signIn.start.title')} />
<Header.Subtitle localizationKey={localizationKeys('signIn.start.subtitle')} />
</>
)}
</Header.Root>
<Card.Alert>{card.error}</Card.Alert>
{/*TODO: extract main in its own component */}
Expand Down Expand Up @@ -416,7 +429,7 @@ export function _SignInStart(): JSX.Element {
</Col>
</Card.Content>
<Card.Footer>
{userSettings.signUp.mode === SIGN_UP_MODES.PUBLIC && (
{userSettings.signUp.mode === SIGN_UP_MODES.PUBLIC && !isCombinedFlow && (
<Card.Action elementId='signIn'>
<Card.ActionText localizationKey={localizationKeys('signIn.start.actionText')} />
<Card.ActionLink
Expand Down
14 changes: 14 additions & 0 deletions packages/clerk-js/src/ui/components/SignIn/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { titleize } from '@clerk/shared/underscore';
import { isWebAuthnSupported } from '@clerk/shared/webauthn';
import type { PreferredSignInStrategy, SignInFactor, SignInResource, SignInStrategy } from '@clerk/types';
import type { FormControlState } from 'ui/utils';

import { PREFERRED_SIGN_IN_STRATEGIES } from '../../common/constants';
import { otpPrefFactorComparator, passwordPrefFactorComparator } from '../../utils/factorSorting';
Expand Down Expand Up @@ -108,3 +109,16 @@ export function determineStartingSignInSecondFactor(secondFactors: SignInFactor[
const resetPasswordStrategies: SignInStrategy[] = ['reset_password_phone_code', 'reset_password_email_code'];
export const isResetPasswordStrategy = (strategy: SignInStrategy | string | null | undefined) =>
!!strategy && resetPasswordStrategies.includes(strategy as SignInStrategy);

const isEmail = (str: string) => /^\S+@\S+\.\S+$/.test(str);
export function getSignUpAttributeFromIdentifier(identifier: FormControlState<'identifier'>) {
if (identifier.type === 'tel') {
return 'phoneNumber';
}

if (isEmail(identifier.value)) {
return 'emailAddress';
}

return 'username';
}
5 changes: 3 additions & 2 deletions packages/clerk-js/src/ui/components/SignUp/SignUpStart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ function _SignUpStart(): JSX.Element {
const { attributes } = userSettings;
const { setActive } = useClerk();
const ctx = useSignUpContext();
const { afterSignUpUrl, signInUrl, unsafeMetadata } = ctx;
const { afterSignUpUrl, signInUrl, unsafeMetadata, __experimental } = ctx;
const isCombinedFlow = __experimental?.combinedFlow;
const [activeCommIdentifierType, setActiveCommIdentifierType] = React.useState<ActiveIdentifier>(
getInitialActiveIdentifier(attributes, userSettings.signUp.progressive),
);
Expand Down Expand Up @@ -315,7 +316,7 @@ function _SignUpStart(): JSX.Element {
<Card.ActionText localizationKey={localizationKeys('signUp.start.actionText')} />
<Card.ActionLink
localizationKey={localizationKeys('signUp.start.actionLink')}
to={clerk.buildUrlWithAuth(signInUrl)}
to={isCombinedFlow ? '../' : clerk.buildUrlWithAuth(signInUrl)}
/>
</Card.Action>
</Card.Footer>
Expand Down
1 change: 1 addition & 0 deletions packages/localizations/src/ar-SA.ts
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,7 @@ export const arSA: LocalizationResource = {
actionText__join_waitlist: undefined,
subtitle: 'للمتابعة إلى {{applicationName}}',
title: 'تسجيل الدخول',
titleCombined: undefined,
},
totpMfa: {
formTitle: 'رمز التحقق',
Expand Down
1 change: 1 addition & 0 deletions packages/localizations/src/be-BY.ts
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,7 @@ export const beBY: LocalizationResource = {
actionText__join_waitlist: undefined,
subtitle: 'каб працягнуць працу ў "{{applicationName}}"',
title: 'Увайсці',
titleCombined: undefined,
},
totpMfa: {
formTitle: 'Код верыфікацыі',
Expand Down
1 change: 1 addition & 0 deletions packages/localizations/src/bg-BG.ts
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,7 @@ export const bgBG: LocalizationResource = {
actionText__join_waitlist: undefined,
subtitle: 'Добре дошли обратно! Моля, влезте, за да продължите',
title: 'Влезте в {{applicationName}}',
titleCombined: undefined,
},
totpMfa: {
formTitle: 'Код за потвърждение',
Expand Down
1 change: 1 addition & 0 deletions packages/localizations/src/cs-CZ.ts
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,7 @@ export const csCZ: LocalizationResource = {
actionText__join_waitlist: undefined,
subtitle: 'pro pokračování do {{applicationName}}',
title: 'Přihlásit se',
titleCombined: undefined,
},
totpMfa: {
formTitle: 'Ověřovací kód',
Expand Down
1 change: 1 addition & 0 deletions packages/localizations/src/da-DK.ts
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,7 @@ export const daDK: LocalizationResource = {
actionText__join_waitlist: undefined,
subtitle: 'Forsæt til {{applicationName}}',
title: 'Log ind',
titleCombined: undefined,
},
totpMfa: {
formTitle: 'Bekræftelseskode',
Expand Down
1 change: 1 addition & 0 deletions packages/localizations/src/de-DE.ts
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,7 @@ export const deDE: LocalizationResource = {
actionText__join_waitlist: undefined,
subtitle: 'weiter zu {{applicationName}}',
title: 'Einloggen',
titleCombined: undefined,
},
totpMfa: {
formTitle: 'Bestätigungscode',
Expand Down
1 change: 1 addition & 0 deletions packages/localizations/src/el-GR.ts
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,7 @@ export const elGR: LocalizationResource = {
actionText__join_waitlist: undefined,
subtitle: 'για να συνεχίσετε στο {{applicationName}}',
title: 'Σύνδεση',
titleCombined: undefined,
},
totpMfa: {
formTitle: 'Κωδικός επαλήθευσης',
Expand Down
1 change: 1 addition & 0 deletions packages/localizations/src/en-US.ts
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,7 @@ export const enUS: LocalizationResource = {
actionText__join_waitlist: 'Want early access?',
subtitle: 'Welcome back! Please sign in to continue',
title: 'Sign in to {{applicationName}}',
titleCombined: 'Continue to {{applicationName}}',
},
totpMfa: {
formTitle: 'Verification code',
Expand Down
1 change: 1 addition & 0 deletions packages/localizations/src/es-ES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,7 @@ export const esES: LocalizationResource = {
actionText__join_waitlist: undefined,
subtitle: 'para continuar a {{applicationName}}',
title: 'Entrar',
titleCombined: undefined,
},
totpMfa: {
formTitle: 'Código de verificación',
Expand Down
1 change: 1 addition & 0 deletions packages/localizations/src/es-MX.ts
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,7 @@ export const esMX: LocalizationResource = {
actionText__join_waitlist: undefined,
subtitle: 'para continuar con {{applicationName}}',
title: 'Iniciar sesión',
titleCombined: undefined,
},
totpMfa: {
formTitle: 'Código de verificación',
Expand Down
1 change: 1 addition & 0 deletions packages/localizations/src/fi-FI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,7 @@ export const fiFI: LocalizationResource = {
actionText__join_waitlist: undefined,
subtitle: 'jatkaaksesi kohteeseen {{applicationName}}',
title: 'Kirjaudu sisään',
titleCombined: undefined,
},
totpMfa: {
formTitle: 'Todennuskoodi',
Expand Down
1 change: 1 addition & 0 deletions packages/localizations/src/fr-FR.ts
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,7 @@ export const frFR: LocalizationResource = {
actionText__join_waitlist: undefined,
subtitle: 'pour continuer vers {{applicationName}}',
title: "S'identifier",
titleCombined: undefined,
},
totpMfa: {
formTitle: 'Le code de vérification',
Expand Down
1 change: 1 addition & 0 deletions packages/localizations/src/he-IL.ts
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,7 @@ export const heIL: LocalizationResource = {
actionText__join_waitlist: undefined,
subtitle: 'להמשיך אל {{applicationName}}',
title: 'התחבר',
titleCombined: undefined,
},
totpMfa: {
formTitle: 'קוד אימות',
Expand Down
1 change: 1 addition & 0 deletions packages/localizations/src/hu-HU.ts
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,7 @@ export const huHU: LocalizationResource = {
actionText__join_waitlist: undefined,
subtitle: 'Üdv újra! A folytatáshoz kérlek jelentkezz be.',
title: 'Bejelentkezés a(z) {{applicationName}} fiókba',
titleCombined: undefined,
},
totpMfa: {
formTitle: 'Visszaigazoló kód',
Expand Down
1 change: 1 addition & 0 deletions packages/localizations/src/is-IS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,7 @@ export const isIS: LocalizationResource = {
actionText__join_waitlist: undefined,
subtitle: 'Velkomin aftur! Vinsamlegast skráðu þig inn til að halda áfram',
title: 'Skrá inn í {{applicationName}}',
titleCombined: undefined,
},
totpMfa: {
formTitle: 'Staðfestingarkóði',
Expand Down
1 change: 1 addition & 0 deletions packages/localizations/src/it-IT.ts
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,7 @@ export const itIT: LocalizationResource = {
actionText__join_waitlist: undefined,
subtitle: 'per continuare su {{applicationName}}',
title: 'Accedi',
titleCombined: undefined,
},
totpMfa: {
formTitle: 'Codice di verifica',
Expand Down
1 change: 1 addition & 0 deletions packages/localizations/src/ja-JP.ts
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,7 @@ export const jaJP: LocalizationResource = {
actionText__join_waitlist: undefined,
subtitle: '{{applicationName}}へのアクセスを続ける',
title: 'サインイン',
titleCombined: undefined,
},
totpMfa: {
formTitle: '検証コード',
Expand Down
1 change: 1 addition & 0 deletions packages/localizations/src/ko-KR.ts
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,7 @@ export const koKR: LocalizationResource = {
actionText__join_waitlist: undefined,
subtitle: '환영합니다! 계속하려면 로그인해 주세요',
title: '{{applicationName}}에 로그인',
titleCombined: undefined,
},
totpMfa: {
formTitle: '인증 코드',
Expand Down
1 change: 1 addition & 0 deletions packages/localizations/src/mn-MN.ts
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,7 @@ export const mnMN: LocalizationResource = {
actionText__join_waitlist: undefined,
subtitle: 'Тавтай морил! Үргэлжлүүлэхийн тулд нэвтэрнэ үү',
title: '{{applicationName}} руу нэвтрэх',
titleCombined: undefined,
},
totpMfa: {
formTitle: 'Баталгаажуулах код',
Expand Down
1 change: 1 addition & 0 deletions packages/localizations/src/nb-NO.ts
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,7 @@ export const nbNO: LocalizationResource = {
actionText__join_waitlist: undefined,
subtitle: 'for å fortsette til {{applicationName}}',
title: 'Logg inn',
titleCombined: undefined,
},
totpMfa: {
formTitle: 'Verifiseringskode',
Expand Down
1 change: 1 addition & 0 deletions packages/localizations/src/nl-NL.ts
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,7 @@ export const nlNL: LocalizationResource = {
actionText__join_waitlist: undefined,
subtitle: 'om door te gaan naar {{applicationName}}',
title: 'Inloggen',
titleCombined: undefined,
},
totpMfa: {
formTitle: 'Verificatiecode',
Expand Down
1 change: 1 addition & 0 deletions packages/localizations/src/pl-PL.ts
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,7 @@ export const plPL: LocalizationResource = {
actionText__join_waitlist: undefined,
subtitle: 'aby przejść do {{applicationName}}',
title: 'Zaloguj się',
titleCombined: undefined,
},
totpMfa: {
formTitle: 'Kod weryfikacyjny',
Expand Down
Loading
Loading