Skip to content

Commit

Permalink
feat(elements): Visible Captcha (#3235)
Browse files Browse the repository at this point in the history
* feat(elements): Visible Captcha

* chore(elements): Extend captcha types

* chore(elements): Bump version
  • Loading branch information
tmilewski committed Apr 19, 2024
1 parent 414f935 commit 83ec173
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 1 deletion.
2 changes: 2 additions & 0 deletions .changeset/silly-mice-perform.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
---
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,8 @@ export default function SignUpPage() {
validatePassword
/>

<SignUp.Captcha id='test' />

<CustomSubmit>Sign Up</CustomSubmit>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion packages/elements/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@clerk/elements",
"version": "0.1.44",
"version": "0.1.45",
"description": "Clerk Elements",
"keywords": [
"clerk",
Expand Down
2 changes: 2 additions & 0 deletions packages/elements/src/internals/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,5 @@ export const SEARCH_PARAMS = {
} as const;

export const RESENDABLE_COUNTDOWN_DEFAULT = 60;

export const CAPTCHA_ELEMENT_ID = 'clerk-captcha';
68 changes: 68 additions & 0 deletions packages/elements/src/react/sign-up/captcha.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { Slot } from '@radix-ui/react-slot';
import * as React from 'react';

import { CAPTCHA_ELEMENT_ID } from '~/internals/constants';
import { ClerkElementsRuntimeError } from '~/internals/errors';

import { SignUpStartCtx } from './start';

export type SignUpCaptchaElement = React.ElementRef<'div'>;

type CaptchaElementProps = Omit<
React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>,
'id' | 'children'
>;

export type SignUpCaptchaProps =
| ({
asChild: true;
/* Must only be a self-closing element/component */
children: React.ReactElement;
} & CaptchaElementProps)
| ({ asChild?: false; children?: undefined } & CaptchaElementProps);

/**
* The `<SignUp.Captcha>` component is used to render the Cloudflare Turnstile widget. It must be used within the `<SignUp.Step name="start">` component.
*
* 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.
*
* @example
* <SignUp.Root>
* <SignUp.Step name="start">
* <SignUp.Captcha />
* <Clerk.Action submit>Sign Up</Clerk.Action>
* </SignUp.Step>
* </SignIn>
*
* @example
* <SignUp.Root>
* <SignUp.Step name="start">
* <SignUp.Captcha asChild>
* <aside/>
* </SignUp.Captcha>
* <Clerk.Action submit>Sign Up</Clerk.Action>
* </SignUp.Step>
* </SignIn>
*/

export const SignUpCaptcha = React.forwardRef<SignUpCaptchaElement, SignUpCaptchaProps>(
({ asChild, children, ...rest }, forwardedRef) => {
const ref = SignUpStartCtx.useActorRef(true);

if (!ref) {
throw new ClerkElementsRuntimeError(
'<SignUp.Captcha> must be used within the <SignUp.Step name="start"> component.',
);
}

const Comp = asChild ? Slot : 'div';

return (
<Comp
id={CAPTCHA_ELEMENT_ID}
{...rest}
ref={forwardedRef}
/>
);
},
);
1 change: 1 addition & 0 deletions packages/elements/src/react/sign-up/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export { SignUpRoot as SignUp, SignUpRoot as Root } from './root';
export { SignUpStep as Step } from './step';
export { SignUpAction as Action } from './action';
export { SignUpStrategy as Strategy } from './verifications';
export { SignUpCaptcha as Captcha } from './captcha';

/** @internal Internal use only */
export const useSignUpActorRef_internal = SignUpRouterCtx.useActorRef;
Expand Down

0 comments on commit 83ec173

Please sign in to comment.