Skip to content

Commit 41f2886

Browse files
committed
feat(clerk-js,react,nextjs): Export TaskResetPassword component and related functionality
1 parent 983070c commit 41f2886

File tree

10 files changed

+109
-2
lines changed

10 files changed

+109
-2
lines changed

packages/clerk-js/sandbox/app.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ const AVAILABLE_COMPONENTS = [
3737
'apiKeys',
3838
'oauthConsent',
3939
'taskChooseOrganization',
40+
'taskResetPassword',
4041
] as const;
4142

4243
const COMPONENT_PROPS_NAMESPACE = 'clerk-js-sandbox';
@@ -99,6 +100,7 @@ const componentControls: Record<(typeof AVAILABLE_COMPONENTS)[number], Component
99100
apiKeys: buildComponentControls('apiKeys'),
100101
oauthConsent: buildComponentControls('oauthConsent'),
101102
taskChooseOrganization: buildComponentControls('taskChooseOrganization'),
103+
taskResetPassword: buildComponentControls('taskResetPassword'),
102104
};
103105

104106
declare global {
@@ -352,6 +354,14 @@ void (async () => {
352354
},
353355
);
354356
},
357+
'/task-reset-password': () => {
358+
Clerk.mountTaskResetPassword(
359+
app,
360+
componentControls.taskResetPassword.getProps() ?? {
361+
redirectUrlComplete: '/user-profile',
362+
},
363+
);
364+
},
355365
'/open-sign-in': () => {
356366
mountOpenSignInButton(app, componentControls.signIn.getProps() ?? {});
357367
},

packages/clerk-js/src/core/clerk.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ import type {
8585
SignUpRedirectOptions,
8686
SignUpResource,
8787
TaskChooseOrganizationProps,
88+
TaskResetPasswordProps,
8889
TasksRedirectOptions,
8990
UnsubscribeCallback,
9091
UserAvatarProps,
@@ -1424,6 +1425,26 @@ export class Clerk implements ClerkInterface {
14241425
void this.#componentControls.ensureMounted().then(controls => controls.unmountComponent({ node }));
14251426
};
14261427

1428+
public mountTaskResetPassword = (node: HTMLDivElement, props?: TaskResetPasswordProps) => {
1429+
this.assertComponentsReady(this.#componentControls);
1430+
1431+
void this.#componentControls.ensureMounted({ preloadHint: 'TaskResetPassword' }).then(controls =>
1432+
controls.mountComponent({
1433+
name: 'TaskResetPassword',
1434+
appearanceKey: 'taskResetPassword',
1435+
node,
1436+
props,
1437+
}),
1438+
);
1439+
1440+
this.telemetry?.record(eventPrebuiltComponentMounted('TaskResetPassword', props));
1441+
};
1442+
1443+
public unmountTaskResetPassword = (node: HTMLDivElement) => {
1444+
this.assertComponentsReady(this.#componentControls);
1445+
void this.#componentControls.ensureMounted().then(controls => controls.unmountComponent({ node }));
1446+
};
1447+
14271448
/**
14281449
* `setActive` can be used to set the active session and/or organization.
14291450
*/

packages/clerk-js/src/ui/lazyModules/components.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ const componentImportPaths = {
2323
SessionTasks: () => import(/* webpackChunkName: "sessionTasks" */ '../components/SessionTasks'),
2424
TaskChooseOrganization: () =>
2525
import(/* webpackChunkName: "taskChooseOrganization" */ '../components/SessionTasks/tasks/TaskChooseOrganization'),
26+
TaskResetPassword: () =>
27+
import(/* webpackChunkName: "taskResetPassword" */ '../components/SessionTasks/tasks/TaskResetPassword'),
2628
PlanDetails: () => import(/* webpackChunkName: "planDetails" */ '../components/Plans/PlanDetails'),
2729
SubscriptionDetails: () => import(/* webpackChunkName: "subscriptionDetails" */ '../components/SubscriptionDetails'),
2830
APIKeys: () => import(/* webpackChunkName: "apiKeys" */ '../components/APIKeys/APIKeys'),
@@ -123,6 +125,10 @@ export const TaskChooseOrganization = lazy(() =>
123125
componentImportPaths.TaskChooseOrganization().then(module => ({ default: module.TaskChooseOrganization })),
124126
);
125127

128+
export const TaskResetPassword = lazy(() =>
129+
componentImportPaths.TaskResetPassword().then(module => ({ default: module.TaskResetPassword })),
130+
);
131+
126132
export const PlanDetails = lazy(() =>
127133
componentImportPaths.PlanDetails().then(module => ({ default: module.PlanDetails })),
128134
);
@@ -172,6 +178,7 @@ export const ClerkComponents = {
172178
OAuthConsent,
173179
SubscriptionDetails,
174180
TaskChooseOrganization,
181+
TaskResetPassword,
175182
};
176183

177184
export type ClerkComponentName = keyof typeof ClerkComponents;

packages/clerk-js/src/ui/types.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ export type AvailableComponentProps =
5959
| __internal_SubscriptionDetailsProps
6060
| __internal_PlanDetailsProps
6161
| APIKeysProps
62-
| TaskChooseOrganizationProps;
62+
| TaskChooseOrganizationProps
63+
| TaskResetPasswordProps;
6364

6465
type ComponentMode = 'modal' | 'mounted';
6566
type SignInMode = 'modal' | 'redirect';

packages/nextjs/src/client-boundary/uiComponents.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export {
2323
SignOutButton,
2424
SignUpButton,
2525
TaskChooseOrganization,
26+
TaskResetPassword,
2627
UserAvatar,
2728
UserButton,
2829
Waitlist,

packages/react/src/components/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export {
99
SignIn,
1010
SignUp,
1111
TaskChooseOrganization,
12+
TaskResetPassword,
1213
UserAvatar,
1314
UserButton,
1415
UserProfile,

packages/react/src/components/uiComponents.tsx

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import type {
99
SignInProps,
1010
SignUpProps,
1111
TaskChooseOrganizationProps,
12+
TaskResetPasswordProps,
1213
UserAvatarProps,
1314
UserButtonProps,
1415
UserProfileProps,
@@ -696,3 +697,31 @@ export const TaskChooseOrganization = withClerk(
696697
},
697698
{ component: 'TaskChooseOrganization', renderWhileLoading: true },
698699
);
700+
701+
export const TaskResetPassword = withClerk(
702+
({ clerk, component, fallback, ...props }: WithClerkProp<TaskResetPasswordProps & FallbackProp>) => {
703+
const mountingStatus = useWaitForComponentMount(component);
704+
const shouldShowFallback = mountingStatus === 'rendering' || !clerk.loaded;
705+
706+
const rendererRootProps = {
707+
...(shouldShowFallback && fallback && { style: { display: 'none' } }),
708+
};
709+
710+
return (
711+
<>
712+
{shouldShowFallback && fallback}
713+
{clerk.loaded && (
714+
<ClerkHostRenderer
715+
component={component}
716+
mount={clerk.mountTaskResetPassword}
717+
unmount={clerk.unmountTaskResetPassword}
718+
updateProps={(clerk as any).__unstable__updateProps}
719+
props={props}
720+
rootProps={rendererRootProps}
721+
/>
722+
)}
723+
</>
724+
);
725+
},
726+
{ component: 'TaskResetPassword', renderWhileLoading: true },
727+
);

packages/react/src/isomorphicClerk.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ import type {
4848
SignUpResource,
4949
State,
5050
TaskChooseOrganizationProps,
51+
TaskResetPasswordProps,
5152
TasksRedirectOptions,
5253
UnsubscribeCallback,
5354
UserAvatarProps,
@@ -150,7 +151,7 @@ export class IsomorphicClerk implements IsomorphicLoadedClerk {
150151
private premountAPIKeysNodes = new Map<HTMLDivElement, APIKeysProps | undefined>();
151152
private premountOAuthConsentNodes = new Map<HTMLDivElement, __internal_OAuthConsentProps | undefined>();
152153
private premountTaskChooseOrganizationNodes = new Map<HTMLDivElement, TaskChooseOrganizationProps | undefined>();
153-
154+
private premountTaskResetPasswordNodes = new Map<HTMLDivElement, TaskResetPasswordProps | undefined>();
154155
// A separate Map of `addListener` method calls to handle multiple listeners.
155156
private premountAddListenerCalls = new Map<
156157
ListenerCallback,
@@ -1218,6 +1219,22 @@ export class IsomorphicClerk implements IsomorphicLoadedClerk {
12181219
}
12191220
};
12201221

1222+
mountTaskResetPassword = (node: HTMLDivElement, props?: TaskResetPasswordProps): void => {
1223+
if (this.clerkjs && this.loaded) {
1224+
this.clerkjs.mountTaskResetPassword(node, props);
1225+
} else {
1226+
this.premountTaskResetPasswordNodes.set(node, props);
1227+
}
1228+
};
1229+
1230+
unmountTaskResetPassword = (node: HTMLDivElement): void => {
1231+
if (this.clerkjs && this.loaded) {
1232+
this.clerkjs.unmountTaskResetPassword(node);
1233+
} else {
1234+
this.premountTaskResetPasswordNodes.delete(node);
1235+
}
1236+
};
1237+
12211238
addListener = (listener: ListenerCallback): UnsubscribeCallback => {
12221239
if (this.clerkjs) {
12231240
return this.clerkjs.addListener(listener);

packages/shared/src/types/appearance.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1125,6 +1125,10 @@ export type Appearance<T = Theme> = T &
11251125
* Theme overrides that only apply to the `<TaskChooseOrganization />` component
11261126
*/
11271127
taskChooseOrganization?: T;
1128+
/**
1129+
* Theme overrides that only apply to the `<TaskResetPassword />` component
1130+
*/
1131+
taskResetPassword?: T;
11281132
/**
11291133
* Theme overrides that only apply to the `<EnableOrganizations/>` component
11301134
*/

packages/shared/src/types/clerk.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,22 @@ export interface Clerk {
646646
*/
647647
unmountTaskChooseOrganization: (targetNode: HTMLDivElement) => void;
648648

649+
/**
650+
* Mounts a TaskResetPassword component at the target element.
651+
*
652+
* @param targetNode - Target node to mount the TaskChooseOrganization component.
653+
* @param props - configuration parameters.
654+
*/
655+
mountTaskResetPassword: (targetNode: HTMLDivElement, props?: TaskResetPasswordProps) => void;
656+
657+
/**
658+
* Unmount a TaskResetPassword component from the target element.
659+
* If there is no component mounted at the target node, results in a noop.
660+
*
661+
* @param targetNode - Target node to unmount the TaskChooseOrganization component from.
662+
*/
663+
unmountTaskResetPassword: (targetNode: HTMLDivElement) => void;
664+
649665
/**
650666
* @internal
651667
* Loads Stripe libraries for commerce functionality

0 commit comments

Comments
 (0)