From 64d64793b18a8154fd058d1f687de03fcda92721 Mon Sep 17 00:00:00 2001 From: Jacek Date: Wed, 9 Apr 2025 15:28:46 -0500 Subject: [PATCH 1/4] feat(elements): Upgrade xstate and @xstate/react --- packages/elements/package.json | 4 ++-- pnpm-lock.yaml | 32 ++++++++++++++++---------------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/packages/elements/package.json b/packages/elements/package.json index b9f37cb34d7..099e68c3b75 100644 --- a/packages/elements/package.json +++ b/packages/elements/package.json @@ -76,10 +76,10 @@ "@radix-ui/primitive": "^1.1.0", "@radix-ui/react-form": "^0.1.0", "@radix-ui/react-slot": "^1.1.0", - "@xstate/react": "^4.1.1", + "@xstate/react": "^5.0.3", "client-only": "^0.0.1", "tslib": "catalog:repo", - "xstate": "^5.15.0" + "xstate": "^5.19.2" }, "devDependencies": { "@statelyai/inspect": "^0.4.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6f181591512..05f81c8da47 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -556,8 +556,8 @@ importers: specifier: ^1.1.0 version: 1.1.2(@types/react@18.3.20)(react@18.3.1) '@xstate/react': - specifier: ^4.1.1 - version: 4.1.1(@types/react@18.3.20)(react@18.3.1)(xstate@5.15.0) + specifier: ^5.0.3 + version: 5.0.3(@types/react@18.3.20)(react@18.3.1)(xstate@5.19.2) client-only: specifier: ^0.0.1 version: 0.0.1 @@ -571,12 +571,12 @@ importers: specifier: catalog:repo version: 2.8.1 xstate: - specifier: ^5.15.0 - version: 5.15.0 + specifier: ^5.19.2 + version: 5.19.2 devDependencies: '@statelyai/inspect': specifier: ^0.4.0 - version: 0.4.0(ws@8.18.1)(xstate@5.15.0) + version: 0.4.0(ws@8.18.1)(xstate@5.19.2) concurrently: specifier: ^8.2.2 version: 8.2.2 @@ -5632,11 +5632,11 @@ packages: resolution: {integrity: sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==} engines: {node: '>=10.0.0'} - '@xstate/react@4.1.1': - resolution: {integrity: sha512-pFp/Y+bnczfaZ0V8B4LOhx3d6Gd71YKAPbzerGqydC2nsYN/mp7RZu3q/w6/kvI2hwR/jeDeetM7xc3JFZH2NA==} + '@xstate/react@5.0.3': + resolution: {integrity: sha512-Zdnn0VTPcVdoaAiW0OX6Nkvdoe7SNGjfaZqM61NKhjt2aNULqiicmDu2tOd1ChzlRWYDxGTdbzVqqVyMLpoHJw==} peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - xstate: ^5.11.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + xstate: ^5.19.2 peerDependenciesMeta: xstate: optional: true @@ -14451,8 +14451,8 @@ packages: xmlchars@2.2.0: resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} - xstate@5.15.0: - resolution: {integrity: sha512-0DGArbj+ych7PcCqHzhEvXH1qVG41lhenwdbEPBRJyxQP9TLooUsR7oiR4YWYHblLOVWvz/esiw8HUtHXp/kZA==} + xstate@5.19.2: + resolution: {integrity: sha512-B8fL2aP0ogn5aviAXFzI5oZseAMqN00fg/TeDa3ZtatyDcViYLIfuQl4y8qmHCiKZgGEzmnTyNtNQL9oeJE2gw==} xtend@4.0.2: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} @@ -18952,7 +18952,7 @@ snapshots: '@stablelib/base64@1.0.1': {} - '@statelyai/inspect@0.4.0(ws@8.18.1)(xstate@5.15.0)': + '@statelyai/inspect@0.4.0(ws@8.18.1)(xstate@5.19.2)': dependencies: fast-safe-stringify: 2.1.1 isomorphic-ws: 5.0.0(ws@8.18.1) @@ -18960,7 +18960,7 @@ snapshots: safe-stable-stringify: 2.4.3 superjson: 1.13.3 uuid: 9.0.1 - xstate: 5.15.0 + xstate: 5.19.2 transitivePeerDependencies: - ws @@ -20707,13 +20707,13 @@ snapshots: '@xmldom/xmldom@0.8.10': {} - '@xstate/react@4.1.1(@types/react@18.3.20)(react@18.3.1)(xstate@5.15.0)': + '@xstate/react@5.0.3(@types/react@18.3.20)(react@18.3.1)(xstate@5.19.2)': dependencies: react: 18.3.1 use-isomorphic-layout-effect: 1.1.2(@types/react@18.3.20)(react@18.3.1) use-sync-external-store: 1.4.0(react@18.3.1) optionalDependencies: - xstate: 5.15.0 + xstate: 5.19.2 transitivePeerDependencies: - '@types/react' @@ -31482,7 +31482,7 @@ snapshots: xmlchars@2.2.0: {} - xstate@5.15.0: {} + xstate@5.19.2: {} xtend@4.0.2: {} From 86460de8d205682dc728ddda15110d06135f6fc3 Mon Sep 17 00:00:00 2001 From: Jacek Date: Wed, 9 Apr 2025 20:04:23 -0500 Subject: [PATCH 2/4] changeset --- .changeset/fine-ducks-love.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/fine-ducks-love.md diff --git a/.changeset/fine-ducks-love.md b/.changeset/fine-ducks-love.md new file mode 100644 index 00000000000..936c5f69fa0 --- /dev/null +++ b/.changeset/fine-ducks-love.md @@ -0,0 +1,5 @@ +--- +'@clerk/elements': patch +--- + +Upgrading xstate and @xstate/react to add react@19 as a transitive peerDependency From 7cf18fffc573bd1e2db4c98e5f0253fa50fc5f2f Mon Sep 17 00:00:00 2001 From: Jacek Date: Wed, 9 Apr 2025 20:16:35 -0500 Subject: [PATCH 3/4] Typescript fixes --- .../internals/machines/sign-in/router.types.ts | 6 ++++-- .../machines/sign-in/verification.machine.ts | 17 ++++++++++++----- .../machines/sign-up/continue.machine.ts | 3 +-- .../internals/machines/sign-up/router.types.ts | 3 ++- .../machines/sign-up/verification.machine.ts | 6 +++--- .../src/react/sign-in/context/router.context.ts | 3 ++- .../src/react/sign-up/context/router.context.ts | 3 ++- 7 files changed, 26 insertions(+), 15 deletions(-) diff --git a/packages/elements/src/internals/machines/sign-in/router.types.ts b/packages/elements/src/internals/machines/sign-in/router.types.ts index dd1823deb71..d084c173f18 100644 --- a/packages/elements/src/internals/machines/sign-in/router.types.ts +++ b/packages/elements/src/internals/machines/sign-in/router.types.ts @@ -140,7 +140,8 @@ export type SignInRouterSnapshot = MachineSnapshot< SignInRouterStateValue, SignInRouterTags, SignInRouterOuptut, - any // TMeta - Introduced in XState 5.12.x + any, // TMeta - Introduced in XState 5.12.x + any // TConfig - Required in newer XState versions >; // ---------------------------------- Machine Type ---------------------------------- // @@ -158,7 +159,8 @@ export type TSignInRouterParentMachine = StateMachine< any, // input SignInRouterOuptut, // output any, // emitted - any // meta + any, // meta + any // config >; // ---------------------------------- Machine Actor Ref ---------------------------------- // diff --git a/packages/elements/src/internals/machines/sign-in/verification.machine.ts b/packages/elements/src/internals/machines/sign-in/verification.machine.ts index bb04445e562..56263c596f4 100644 --- a/packages/elements/src/internals/machines/sign-in/verification.machine.ts +++ b/packages/elements/src/internals/machines/sign-in/verification.machine.ts @@ -109,11 +109,13 @@ const SignInVerificationMachine = setup({ if (process.env.NODE_ENV === 'development') { if ( clerk.client.signIn.supportedFirstFactors && - !clerk.client.signIn.supportedFirstFactors.every(factor => context.registeredStrategies.has(factor.strategy)) + !clerk.client.signIn.supportedFirstFactors.every((factor: SignInFirstFactor) => + context.registeredStrategies.has(factor.strategy), + ) ) { console.warn( `Clerk: Your instance is configured to support these strategies: ${clerk.client.signIn.supportedFirstFactors - .map(factor => factor.strategy) + .map((factor: SignInFirstFactor) => factor.strategy) .join(', ')}, but the rendered strategies are: ${Array.from(context.registeredStrategies).join( ', ', )}. Make sure to render a component for each supported strategy. More information: https://clerk.com/docs/elements/reference/sign-in#strategy`, @@ -122,11 +124,13 @@ const SignInVerificationMachine = setup({ if ( clerk.client.signIn.supportedSecondFactors && - !clerk.client.signIn.supportedSecondFactors.every(factor => context.registeredStrategies.has(factor.strategy)) + !clerk.client.signIn.supportedSecondFactors.every((factor: SignInSecondFactor) => + context.registeredStrategies.has(factor.strategy), + ) ) { console.warn( `Clerk: Your instance is configured to support these 2FA strategies: ${clerk.client.signIn.supportedSecondFactors - .map(f => f.strategy) + .map((f: SignInSecondFactor) => f.strategy) .join(', ')}, but the rendered strategies are: ${Array.from(context.registeredStrategies).join( ', ', )}. Make sure to render a component for each supported strategy. More information: https://clerk.com/docs/elements/reference/sign-in#strategy`, @@ -134,7 +138,10 @@ const SignInVerificationMachine = setup({ } const strategiesUsedButNotActivated = Array.from(context.registeredStrategies).filter( - strategy => !clerk.client.signIn.supportedFirstFactors?.some(supported => supported.strategy === strategy), + strategy => + !clerk.client.signIn.supportedFirstFactors?.some( + (supported: SignInFirstFactor) => supported.strategy === strategy, + ), ); if (strategiesUsedButNotActivated.length > 0) { diff --git a/packages/elements/src/internals/machines/sign-up/continue.machine.ts b/packages/elements/src/internals/machines/sign-up/continue.machine.ts index 62cdeb3eea4..dee44be5f61 100644 --- a/packages/elements/src/internals/machines/sign-up/continue.machine.ts +++ b/packages/elements/src/internals/machines/sign-up/continue.machine.ts @@ -44,8 +44,7 @@ export const SignUpContinueMachine = setup({ for (const key of required.concat(optional) as (keyof SignUpResource)[]) { if (key in signUp) { - // @ts-expect-error - TS doesn't understand that key is a valid key of SignUpResource - progressiveFieldValues.set(key, signUp[key]); + progressiveFieldValues.set(key, signUp[key] as string | number | readonly string[] | undefined); } } diff --git a/packages/elements/src/internals/machines/sign-up/router.types.ts b/packages/elements/src/internals/machines/sign-up/router.types.ts index 77fa4648dd2..217ef7265d9 100644 --- a/packages/elements/src/internals/machines/sign-up/router.types.ts +++ b/packages/elements/src/internals/machines/sign-up/router.types.ts @@ -124,7 +124,8 @@ export type TSignUpRouterParentMachine = StateMachine< any, // input SignUpRouterOuptut, // output any, // emitted - any // meta - Introduced in XState 5.12.x + any, // meta - Introduced in XState 5.12.x + any // config - Required in newer XState versions >; // ---------------------------------- Machine Actor Ref ---------------------------------- // diff --git a/packages/elements/src/internals/machines/sign-up/verification.machine.ts b/packages/elements/src/internals/machines/sign-up/verification.machine.ts index 27b3418d03c..63e27144200 100644 --- a/packages/elements/src/internals/machines/sign-up/verification.machine.ts +++ b/packages/elements/src/internals/machines/sign-up/verification.machine.ts @@ -93,7 +93,7 @@ export const SignUpVerificationMachine = setup({ void run(async () => clerk.client.signUp .reload() - .then(resource => { + .then((resource: SignUpResource) => { const signInStatus = resource.status; const verificationStatus = resource.verifications.emailAddress.status; @@ -124,9 +124,9 @@ export const SignUpVerificationMachine = setup({ stop(); }) - .catch(error => { + .catch((error: Error) => { stop(); - new ClerkElementsRuntimeError(error); + new ClerkElementsRuntimeError(error.message); }), ); diff --git a/packages/elements/src/react/sign-in/context/router.context.ts b/packages/elements/src/react/sign-in/context/router.context.ts index 409c7d09c0e..aec7e1a0917 100644 --- a/packages/elements/src/react/sign-in/context/router.context.ts +++ b/packages/elements/src/react/sign-in/context/router.context.ts @@ -11,7 +11,8 @@ import { createContextFromActorRef } from '~/react/utils/create-context-from-act export type SnapshotState = SnapshotFrom; -export const SignInRouterCtx = createContextFromActorRef('SignInRouterCtx'); +export const SignInRouterCtx: ReturnType> = + createContextFromActorRef('SignInRouterCtx'); function useSignInStep>(name: string) { return SignInRouterCtx.useSelector(state => state.children[name] as AnyActorRef) as T; diff --git a/packages/elements/src/react/sign-up/context/router.context.ts b/packages/elements/src/react/sign-up/context/router.context.ts index 0f347d98c84..d865dbf0ff3 100644 --- a/packages/elements/src/react/sign-up/context/router.context.ts +++ b/packages/elements/src/react/sign-up/context/router.context.ts @@ -10,7 +10,8 @@ import { createContextFromActorRef } from '~/react/utils/create-context-from-act export type SnapshotState = SnapshotFrom; -export const SignUpRouterCtx = createContextFromActorRef('SignUpRouterCtx'); +export const SignUpRouterCtx: ReturnType> = + createContextFromActorRef('SignUpRouterCtx'); function useSignUpStep>(name: string) { return SignUpRouterCtx.useSelector(state => state.children[name] as AnyActorRef) as T; From 2eec4f7d21c304242913aa4f040475a40c732944 Mon Sep 17 00:00:00 2001 From: Jacek Date: Wed, 9 Apr 2025 20:33:16 -0500 Subject: [PATCH 4/4] TS fixes --- .../src/internals/utils/inspector/console/console.ts | 9 ++++++--- .../elements/src/react/hooks/use-active-states.hook.ts | 4 +++- .../elements/src/react/hooks/use-active-tags.hook.ts | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/elements/src/internals/utils/inspector/console/console.ts b/packages/elements/src/internals/utils/inspector/console/console.ts index 7276a5fd355..0f2f6fa2f57 100644 --- a/packages/elements/src/internals/utils/inspector/console/console.ts +++ b/packages/elements/src/internals/utils/inspector/console/console.ts @@ -1,4 +1,4 @@ -import type { AnyActorRef, AnyEventObject, InspectionEvent, Observer } from 'xstate'; +import type { ActorRefLike, AnyEventObject, InspectionEvent, Observer } from 'xstate'; let consoleInspector: Observer | undefined; @@ -24,17 +24,19 @@ export function createConsoleInspector({ return undefined; } - const parseRefId = (ref: AnyActorRef | undefined, includeSystemId?: false): string | undefined => { + const parseRefId = (ref: ActorRefLike | undefined, includeSystemId?: false): string | undefined => { if (!ref) { return undefined; } // @ts-expect-error - Exists on the ref.src - const id = ref.src.id; + const id = ref.src?.id; + // @ts-expect-error - id exists on ActorRefLike let output = id || ref.id; if (includeSystemId) { + // @ts-expect-error - id exists on ActorRefLike output += `(${ref.id})`; } @@ -152,6 +154,7 @@ export function createConsoleInspector({ }, () => { logEvent('Type', inspectionEvent.event.type); + // @ts-expect-error - _parent exists on ActorRefLike logEvent('Parent', parseRefId(inspectionEvent.actorRef._parent)); logEvent('Actor', inspectionEvent.actorRef); logEvent('Event', inspectionEvent.event); diff --git a/packages/elements/src/react/hooks/use-active-states.hook.ts b/packages/elements/src/react/hooks/use-active-states.hook.ts index 923ddae82fb..94057579267 100644 --- a/packages/elements/src/react/hooks/use-active-states.hook.ts +++ b/packages/elements/src/react/hooks/use-active-states.hook.ts @@ -2,7 +2,9 @@ import { useSelector } from '@xstate/react'; import type { ActorRef, AnyActorRef, AnyMachineSnapshot, MachineSnapshot } from 'xstate'; type StatefulActor = - TActor extends ActorRef, any> ? TStateValue : never; + TActor extends ActorRef, any> + ? TStateValue + : never; /** * Generic hook to check if a state is active. diff --git a/packages/elements/src/react/hooks/use-active-tags.hook.ts b/packages/elements/src/react/hooks/use-active-tags.hook.ts index ff99fa14bf7..b42c9001f46 100644 --- a/packages/elements/src/react/hooks/use-active-tags.hook.ts +++ b/packages/elements/src/react/hooks/use-active-tags.hook.ts @@ -2,7 +2,7 @@ import { useSelector } from '@xstate/react'; import type { ActorRef, AnyActorRef, AnyMachineSnapshot, MachineSnapshot } from 'xstate'; type TaggedActor = - TActor extends ActorRef, any> ? TTags : never; + TActor extends ActorRef, any> ? TTags : never; export const ActiveTagsMode = { any: 'any',