Skip to content

Commit

Permalink
refactor(elements): Use nested states (#2471)
Browse files Browse the repository at this point in the history
* refactor(elements): Use nested states

* chore(elements): Change ClerkHostRouter to ClerkRouter

* chore(elements): Update contexts
  • Loading branch information
tmilewski authored Jan 3, 2024
1 parent 7b17bf2 commit 124d9f3
Show file tree
Hide file tree
Showing 5 changed files with 217 additions and 157 deletions.
2 changes: 2 additions & 0 deletions .changeset/fast-hornets-report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
---
7 changes: 5 additions & 2 deletions packages/elements/src/internals/machines/sign-in.actors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type {
AttemptFirstFactorParams,
AttemptSecondFactorParams,
AuthenticateWithRedirectParams,
EnvironmentResource,
HandleOAuthCallbackParams,
HandleSamlCallbackParams,
PrepareFirstFactorParams,
Expand Down Expand Up @@ -37,14 +38,16 @@ export const createSignIn = fromPromise<SignInResource, WithClient<{ fields: Sig
export const authenticateWithRedirect = fromPromise<
void,
WithClerk<{
environment: EnvironmentResource | undefined;
strategy: AuthenticateWithRedirectParams['strategy'] | undefined;
}>
>(async ({ input: { clerk, strategy } }) => {
>(async ({ input: { clerk, environment, strategy } }) => {
assertIsDefined(environment);
assertIsDefined(strategy);

return clerk.client.signIn.authenticateWithRedirect({
strategy,
redirectUrl: `${clerk.__unstable__environment.displayConfig.signInUrl}/sso-callback`,
redirectUrl: `${environment.displayConfig.signInUrl}/sso-callback`,
redirectUrlComplete: clerk.buildAfterSignInUrl(),
});
});
Expand Down
29 changes: 15 additions & 14 deletions packages/elements/src/internals/machines/sign-in.context.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import type { OAuthStrategy, Web3Strategy } from '@clerk/types';
import { createActorContext } from '@xstate/react';
import { useCallback, useEffect } from 'react';
import { useCallback, useEffect, useMemo } from 'react';
import type { SnapshotFrom } from 'xstate';

import { isAuthenticatableOauthStrategy, isWeb3Strategy } from '../../utils/third-party-strategies';
import {
getEnabledThirdPartyProviders,
isAuthenticatableOauthStrategy,
isWeb3Strategy,
} from '../../utils/third-party-strategies';
import { SignInMachine } from './sign-in.machine';
import type { FieldDetails } from './sign-in.types';

Expand All @@ -29,23 +33,17 @@ const fieldHasValueSelector = (type: string | undefined) => (state: SnapshotStat
* Selects a field-specific error, if it exists
*/
const fieldErrorSelector = (type: string | undefined) => (state: SnapshotState) =>
type ? Boolean(state.context.fields.get(type)?.error) : undefined;
type ? state.context.fields.get(type)?.error : undefined;

/**
* Selects a global error, if it exists
*/
const globalErrorSelector = (state: SnapshotState) => state.context.error;

/**
* Selects if the environment is loaded
* Selects the clerk environment
*/
const hasEnvironmentSelector = (state: SnapshotState) => Boolean(state.context.clerk.__unstable__environment);

/**
* Selects third-party providers details
*/
const thirdPartyStrategiesSelector = (state: SnapshotState) =>
state.context.enabledThirdPartyProviders ? state.context.enabledThirdPartyProviders : undefined;
const clerkEnvironmentSelector = (state: SnapshotState) => state.context.environment;

// ================= HOOKS ================= //

Expand Down Expand Up @@ -80,7 +78,8 @@ export const useForm = () => {
*/
export const useThirdPartyProviders = () => {
const ref = useSignInFlow();
const providers = useSignInFlowSelector(thirdPartyStrategiesSelector);
const env = useSignInFlowSelector(clerkEnvironmentSelector);
const providers = useMemo(() => env && getEnabledThirdPartyProviders(env), [env]);

// Register the onSubmit handler for button click
const createOnClick = useCallback(
Expand Down Expand Up @@ -122,13 +121,15 @@ export const useField = ({ type }: Partial<Pick<FieldDetails, 'type'>>) => {
const error = useSignInFlowSelector(fieldErrorSelector(type));

const shouldBeHidden = false; // TODO: Implement clerk-js utils
const validity = error ? 'invalid' : 'valid';
const hasError = Boolean(error);
const validity = hasError ? 'invalid' : 'valid';

return {
hasValue,
props: {
[`data-${validity}`]: true,
'data-hidden': shouldBeHidden ? true : undefined,
serverInvalid: hasError,
tabIndex: shouldBeHidden ? -1 : 0,
},
};
Expand Down Expand Up @@ -179,7 +180,7 @@ export const useInput = ({ type, value: initialValue }: Partial<Pick<FieldDetail
*/
export const useSSOCallbackHandler = () => {
const ref = useSignInFlow();
const hasEnv = useSignInFlowSelector(hasEnvironmentSelector);
const hasEnv = useSignInFlowSelector(clerkEnvironmentSelector);

// TODO: Wholesale move this to the machine ?
// Wait for the environment to be loaded before sending the callback event
Expand Down
Loading

0 comments on commit 124d9f3

Please sign in to comment.