Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 5 additions & 0 deletions .changeset/forty-kings-roll.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@clerk/elements": patch
---

Refactors sign-up loading logic to be in-line with sign-in
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ export const SignUpRouterMachine = setup({
],
},
Start: {
tags: 'route:start',
tags: ['step:start'],
exit: 'clearFormErrors',
invoke: {
id: 'start',
Expand Down Expand Up @@ -322,7 +322,7 @@ export const SignUpRouterMachine = setup({
},
},
Continue: {
tags: 'route:continue',
tags: ['step:continue'],
invoke: {
id: 'continue',
src: 'continueMachine',
Expand Down Expand Up @@ -354,7 +354,7 @@ export const SignUpRouterMachine = setup({
},
},
Verification: {
tags: 'route:verification',
tags: ['step:verification'],
invoke: {
id: 'verification',
src: 'verificationMachine',
Expand Down Expand Up @@ -406,7 +406,7 @@ export const SignUpRouterMachine = setup({
},
},
Callback: {
tags: 'route:callback',
tags: ['step:callback'],
entry: sendTo(ThirdPartyMachineId, { type: 'CALLBACK' }),
on: {
NEXT: [
Expand Down Expand Up @@ -437,7 +437,7 @@ export const SignUpRouterMachine = setup({
},
},
Error: {
tags: 'route:error',
tags: ['step:error'],
on: {
NEXT: {
target: 'Start',
Expand Down
16 changes: 8 additions & 8 deletions packages/elements/src/internals/machines/sign-up/router.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,16 @@ import type {

// ---------------------------------- Tags ---------------------------------- //

export const SignUpRouterRoutes = {
start: 'route:start',
continue: 'route:continue',
verification: 'route:verification',
callback: 'route:callback',
error: 'route:error',
export const SignUpRouterSteps = {
start: 'step:start',
continue: 'step:continue',
verification: 'step:verification',
callback: 'step:callback',
error: 'step:error',
} as const;

export type SignUpRouterRoutes = keyof typeof SignUpRouterRoutes;
export type SignUpRouterTags = (typeof SignUpRouterRoutes)[keyof typeof SignUpRouterRoutes];
export type SignUpRouterSteps = keyof typeof SignUpRouterSteps;
export type SignUpRouterTags = (typeof SignUpRouterSteps)[keyof typeof SignUpRouterSteps];

// ---------------------------------- Children ---------------------------------- //

Expand Down
63 changes: 16 additions & 47 deletions packages/elements/src/react/common/loading.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,8 @@ import { SignInRouterCtx } from '~/react/sign-in/context';
import type { TSignInStep } from '~/react/sign-in/step';
import { SIGN_IN_STEPS } from '~/react/sign-in/step';
import { SignUpRouterCtx } from '~/react/sign-up/context';
import { SignUpContinueCtx } from '~/react/sign-up/continue';
import { SignUpStartCtx } from '~/react/sign-up/start';
import type { TSignUpStep } from '~/react/sign-up/step';
import { SIGN_UP_STEPS } from '~/react/sign-up/step';
import { SignUpVerificationCtx } from '~/react/sign-up/verifications';
import { isProviderStrategyScope, mapScopeToStrategy } from '~/react/utils/map-scope-to-strategy';

type Strategy = OAuthProvider | SamlStrategy | 'metamask';
Expand Down Expand Up @@ -175,54 +172,26 @@ type SignUpLoadingProps = {

function SignUpLoading({ children, scope, routerRef }: SignUpLoadingProps) {
const [isLoading, { step: loadingStep, strategy }] = useLoading(routerRef);
const tags = useSelector(routerRef, s => s.tags);

let computedScope: LoadingScope<TSignUpStep>;

// Figure out if the component is inside a `<Step>` component
const startCtx = SignUpStartCtx.useActorRef(true);
const continueCtx = SignUpContinueCtx.useActorRef(true);
const verificationsCtx = SignUpVerificationCtx.useActorRef(true);
const isStepLoading = (step: TSignUpStep) => isLoading && loadingStep === step;
const isInferredStepLoading = (step: TSignUpStep) => tags.has(`step:${step}`) && isStepLoading(step);

if (scope) {
computedScope = scope;
} else {
let inferredScope: LoadingScope<TSignUpStep>;

if (startCtx) {
inferredScope = `step:start`;
} else if (continueCtx) {
inferredScope = `step:continue`;
} else if (verificationsCtx) {
inferredScope = `step:verifications`;
} else {
inferredScope = `global`;
}

computedScope = inferredScope;
}
let loadingResult = false;

// Determine loading states based on the step
const isStartLoading = isLoading && loadingStep === 'start';
const isVerificationsLoading = isLoading && loadingStep === 'verifications';
const isContinueLoading = isLoading && loadingStep === 'continue';
const isStrategyLoading = isLoading && loadingStep === undefined && strategy !== undefined;

let returnValue: boolean;

if (computedScope === 'global') {
returnValue = isLoading;
} else if (computedScope === 'step:start') {
returnValue = isStartLoading;
} else if (computedScope === 'step:verifications') {
returnValue = isVerificationsLoading;
} else if (computedScope === 'step:continue') {
returnValue = isContinueLoading;
} else if (computedScope.startsWith('provider:')) {
const computedStrategy = mapScopeToStrategy(computedScope);
returnValue = isStrategyLoading && strategy === computedStrategy;
if (scope === 'global') {
// Global Loading Scope
loadingResult = isLoading;
} else if (scope && isProviderStrategyScope(scope)) {
// Provider-Specific Loading Scope
loadingResult = isLoading && loadingStep === undefined && strategy === mapScopeToStrategy(scope);
} else if (scope) {
loadingResult = isStepLoading(scope.replace('step:', '') as TSignUpStep);
} else {
throw new ClerkElementsRuntimeError(`Invalid scope "${computedScope}" used for <Loading>`);
// Inferred Loading Scope
loadingResult =
isInferredStepLoading('start') || isInferredStepLoading('continue') || isInferredStepLoading('verifications');
}

return children(returnValue);
return children(loadingResult);
}
2 changes: 1 addition & 1 deletion packages/elements/src/react/sign-up/continue.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const SignUpContinueCtx = createContextFromActorRef<TSignUpContinueMachin

export function SignUpContinue(props: SignUpContinueProps) {
const routerRef = SignUpRouterCtx.useActorRef();
const activeState = useActiveTags(routerRef, 'route:continue');
const activeState = useActiveTags(routerRef, 'step:continue');

return activeState ? <SignUpContinueInner {...props} /> : null;
}
Expand Down
2 changes: 1 addition & 1 deletion packages/elements/src/react/sign-up/start.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const SignUpStartCtx = createContextFromActorRef<TSignUpStartMachine>('Si

export function SignUpStart(props: SignUpStartProps) {
const routerRef = SignUpRouterCtx.useActorRef();
const activeState = useActiveTags(routerRef, 'route:start');
const activeState = useActiveTags(routerRef, 'step:start');

return activeState ? <SignUpStartInner {...props} /> : null;
}
Expand Down
2 changes: 1 addition & 1 deletion packages/elements/src/react/sign-up/verifications.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const SignUpVerificationCtx = createContextFromActorRef<TSignUpVerificati
*/
export function SignUpVerifications(props: SignUpVerificationsProps) {
const ref = SignUpRouterCtx.useActorRef();
const activeState = useActiveTags(ref, 'route:verification');
const activeState = useActiveTags(ref, 'step:verification');

return activeState ? <SignUpVerifyInner {...props} /> : null;
}
Expand Down