Skip to content

Commit 83ec173

Browse files
authored
feat(elements): Visible Captcha (clerk#3235)
* feat(elements): Visible Captcha * chore(elements): Extend captcha types * chore(elements): Bump version
1 parent 414f935 commit 83ec173

6 files changed

Lines changed: 76 additions & 1 deletion

File tree

.changeset/silly-mice-perform.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
---
2+
---

packages/elements/examples/nextjs/app/sign-up/[[...sign-up]]/page.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,8 @@ export default function SignUpPage() {
147147
validatePassword
148148
/>
149149

150+
<SignUp.Captcha id='test' />
151+
150152
<CustomSubmit>Sign Up</CustomSubmit>
151153
</div>
152154
</div>

packages/elements/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@clerk/elements",
3-
"version": "0.1.44",
3+
"version": "0.1.45",
44
"description": "Clerk Elements",
55
"keywords": [
66
"clerk",

packages/elements/src/internals/constants/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,5 @@ export const SEARCH_PARAMS = {
2222
} as const;
2323

2424
export const RESENDABLE_COUNTDOWN_DEFAULT = 60;
25+
26+
export const CAPTCHA_ELEMENT_ID = 'clerk-captcha';
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import { Slot } from '@radix-ui/react-slot';
2+
import * as React from 'react';
3+
4+
import { CAPTCHA_ELEMENT_ID } from '~/internals/constants';
5+
import { ClerkElementsRuntimeError } from '~/internals/errors';
6+
7+
import { SignUpStartCtx } from './start';
8+
9+
export type SignUpCaptchaElement = React.ElementRef<'div'>;
10+
11+
type CaptchaElementProps = Omit<
12+
React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>,
13+
'id' | 'children'
14+
>;
15+
16+
export type SignUpCaptchaProps =
17+
| ({
18+
asChild: true;
19+
/* Must only be a self-closing element/component */
20+
children: React.ReactElement;
21+
} & CaptchaElementProps)
22+
| ({ asChild?: false; children?: undefined } & CaptchaElementProps);
23+
24+
/**
25+
* The `<SignUp.Captcha>` component is used to render the Cloudflare Turnstile widget. It must be used within the `<SignUp.Step name="start">` component.
26+
*
27+
* If utilizing the `asChild` prop, the component must be a self-closing element or component. Any children passed to the immediate child component of <SignUp.Captcha> will be ignored.
28+
*
29+
* @example
30+
* <SignUp.Root>
31+
* <SignUp.Step name="start">
32+
* <SignUp.Captcha />
33+
* <Clerk.Action submit>Sign Up</Clerk.Action>
34+
* </SignUp.Step>
35+
* </SignIn>
36+
*
37+
* @example
38+
* <SignUp.Root>
39+
* <SignUp.Step name="start">
40+
* <SignUp.Captcha asChild>
41+
* <aside/>
42+
* </SignUp.Captcha>
43+
* <Clerk.Action submit>Sign Up</Clerk.Action>
44+
* </SignUp.Step>
45+
* </SignIn>
46+
*/
47+
48+
export const SignUpCaptcha = React.forwardRef<SignUpCaptchaElement, SignUpCaptchaProps>(
49+
({ asChild, children, ...rest }, forwardedRef) => {
50+
const ref = SignUpStartCtx.useActorRef(true);
51+
52+
if (!ref) {
53+
throw new ClerkElementsRuntimeError(
54+
'<SignUp.Captcha> must be used within the <SignUp.Step name="start"> component.',
55+
);
56+
}
57+
58+
const Comp = asChild ? Slot : 'div';
59+
60+
return (
61+
<Comp
62+
id={CAPTCHA_ELEMENT_ID}
63+
{...rest}
64+
ref={forwardedRef}
65+
/>
66+
);
67+
},
68+
);

packages/elements/src/react/sign-up/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export { SignUpRoot as SignUp, SignUpRoot as Root } from './root';
77
export { SignUpStep as Step } from './step';
88
export { SignUpAction as Action } from './action';
99
export { SignUpStrategy as Strategy } from './verifications';
10+
export { SignUpCaptcha as Captcha } from './captcha';
1011

1112
/** @internal Internal use only */
1213
export const useSignUpActorRef_internal = SignUpRouterCtx.useActorRef;

0 commit comments

Comments
 (0)