Skip to content

Commit

Permalink
fix(elements): Progressive sign up ticket flow (#4318)
Browse files Browse the repository at this point in the history
  • Loading branch information
brkalow authored Oct 14, 2024
1 parent c231cc7 commit 7cff9d8
Show file tree
Hide file tree
Showing 8 changed files with 46 additions and 13 deletions.
5 changes: 5 additions & 0 deletions .changeset/tender-badgers-rule.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@clerk/elements": patch
---

Fixes a bug during a ticket-based sign-up where the form could not be submitted if additional fields were needed.
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ export const FormMachine = setup({

if (field) {
field.checked = event.field.checked;
field.disabled = event.field.disabled || false;
field.disabled = event.field.disabled ?? field.disabled;
field.value = event.field.value;

context.fields.set(event.field.name, field);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import type {
SignUpContinueContext,
SignUpContinueEvents,
SignUpStartContext,
SignUpStartRedirectEvent,
SignUpStartEvents,
SignUpVerificationContext,
SignUpVerificationEvents,
} from '~/internals/machines/sign-up';
Expand All @@ -33,7 +33,7 @@ type SendToLoadingProps = {
| SignInVerificationEvents
| SignInResetPasswordEvents
| ThirdPartyMachineEvent
| SignUpStartRedirectEvent
| SignUpStartEvents
| SignUpContinueEvents
| SignUpVerificationEvents;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import type {
SignInStrategy,
} from '@clerk/types';
import type { SetRequired, Simplify } from 'type-fest';
import type { ActorRefFrom } from 'xstate';

import type { FormMachine } from '../form';

export type WithClerk<T = Record<string, unknown>> = { clerk: LoadedClerk } & T;
export type WithClient<T = Record<string, unknown>> = { client: LoadedClerk['client'] } & T;
Expand Down Expand Up @@ -33,3 +36,5 @@ export type AuthenticateWithRedirectSamlParams = Simplify<
// ================= Strategies ================= //

export type SignInStrategyName = SignInStrategy | 'oauth' | 'web3';

export type SetFormEvent = { type: 'SET_FORM'; formRef: ActorRefFrom<typeof FormMachine> };
Original file line number Diff line number Diff line change
Expand Up @@ -343,8 +343,10 @@ export const SignUpRouterMachine = setup({
},
on: {
'RESET.STEP': {
target: 'Start',
reenter: true,
actions: enqueueActions(({ enqueue, context }) => {
enqueue('clearFormErrors');
enqueue.sendTo('start', { type: 'SET_FORM', formRef: context.formRef });
}),
},
NEXT: [
{
Expand All @@ -355,6 +357,7 @@ export const SignUpRouterMachine = setup({
guard: and(['hasTicket', 'statusNeedsContinue']),
actions: { type: 'navigateInternal', params: { path: '/' } },
target: 'Start',
reenter: true,
},
{
guard: 'statusNeedsVerification',
Expand Down
23 changes: 21 additions & 2 deletions packages/elements/src/internals/machines/sign-up/start.machine.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import type { SignUpResource, Web3Strategy } from '@clerk/types';
import { assertEvent, enqueueActions, fromPromise, not, sendTo, setup } from 'xstate';
import type { DoneActorEvent } from 'xstate';
import { and, assertEvent, assign, enqueueActions, fromPromise, not, sendTo, setup } from 'xstate';

import { SIGN_UP_DEFAULT_BASE_PATH } from '~/internals/constants';
import { ClerkElementsRuntimeError } from '~/internals/errors';
import type { FormFields } from '~/internals/machines/form';
import type { SetFormEvent } from '~/internals/machines/shared';
import { sendToLoading } from '~/internals/machines/shared';
import { fieldsToSignUpParams } from '~/internals/machines/sign-up/utils';
import { ThirdPartyMachine } from '~/internals/machines/third-party';
Expand Down Expand Up @@ -48,8 +50,14 @@ export const SignUpStartMachine = setup({
thirdParty: ThirdPartyMachine,
},
actions: {
sendToNext: ({ context }) => context.parent.send({ type: 'NEXT' }),
sendToNext: ({ context, event }) =>
context.parent.send({ type: 'NEXT', resource: (event as unknown as DoneActorEvent<SignUpResource>).output }),
sendToLoading,
setFormRef: assign(({ event }) => {
return {
formRef: (event as unknown as SetFormEvent).formRef,
};
}),
setFormDisabledTicketFields: enqueueActions(({ context, enqueue }) => {
if (!context.ticket) {
return;
Expand Down Expand Up @@ -90,6 +98,8 @@ export const SignUpStartMachine = setup({
},
},
guards: {
isMissingRequirements: ({ context }) =>
context.parent.getSnapshot().context.clerk?.client?.signUp?.status === 'missing_requirements',
hasTicket: ({ context }) => Boolean(context.ticket),
isExampleMode: ({ context }) => Boolean(context.parent.getSnapshot().context.exampleMode),
},
Expand All @@ -105,11 +115,20 @@ export const SignUpStartMachine = setup({
}),
entry: 'setDefaultFormValues',
initial: 'Init',
on: {
SET_FORM: {
actions: 'setFormRef',
},
},
states: {
Init: {
description:
'Handle ticket, if present; Else, default to Pending state. Per tickets, `Attempting` makes a `signUp.create` request allowing for an incomplete sign up to contain progressively filled fields on the Start step.',
always: [
{
guard: and(['hasTicket', 'isMissingRequirements']),
target: 'Pending',
},
{
guard: 'hasTicket',
target: 'Attempting',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type { ActorRefFrom, ErrorActorEvent } from 'xstate';

import type { FormMachine } from '~/internals/machines/form';

import type { SetFormEvent } from '../shared';
import type { SignInRouterMachineActorRef } from './router.types';

// ---------------------------------- Tags ---------------------------------- //
Expand All @@ -24,7 +25,7 @@ export type SignUpStartRedirectEvent =
| SignUpStartRedirectSamlEvent
| SignUpStartRedirectWeb3Event;

export type SignUpStartEvents = ErrorActorEvent | SignUpStartSubmitEvent | SignUpStartRedirectEvent;
export type SignUpStartEvents = ErrorActorEvent | SignUpStartSubmitEvent | SignUpStartRedirectEvent | SetFormEvent;

// ---------------------------------- Input ---------------------------------- //

Expand Down
10 changes: 5 additions & 5 deletions packages/elements/src/react/sign-up/context/router.context.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import type { ActorRefFrom, AnyActorRef, AnyStateMachine, SnapshotFrom } from 'xstate';

import type {
TSignUpContinueMachine,
TSignUpRouterMachine,
TSignUpStartMachine,
TSignUpVerificationMachine,
import {
type TSignUpContinueMachine,
type TSignUpRouterMachine,
type TSignUpStartMachine,
type TSignUpVerificationMachine,
} from '~/internals/machines/sign-up';
import { createContextFromActorRef } from '~/react/utils/create-context-from-actor-ref';

Expand Down

0 comments on commit 7cff9d8

Please sign in to comment.