From fce6ebaf2eecf653d5e907037949c85a57d3ff3b Mon Sep 17 00:00:00 2001 From: Luis Marsiglia Date: Sat, 1 Apr 2023 20:13:38 -0400 Subject: [PATCH] feat: add `as` prop --- docs/props.mdx | 8 +++++--- packages/lib/src/container.tsx | 20 ++++++++++++++++++++ packages/lib/src/lib.tsx | 20 ++++++++++++++++---- packages/lib/src/types.d.ts | 5 +++++ 4 files changed, 46 insertions(+), 7 deletions(-) create mode 100644 packages/lib/src/container.tsx diff --git a/docs/props.mdx b/docs/props.mdx index b270022..ea1da5f 100644 --- a/docs/props.mdx +++ b/docs/props.mdx @@ -14,6 +14,11 @@ These are the props you can pass to the `Turnstile` component. | onSuccess | `function` | Callback that is invoked upon success of the challenge. The callback is passed a token that can be validated. | | | onExpire | `function` | Callback that is invoked when a challenge expires. Read the [Cloudflare docs](https://developers.cloudflare.com/turnstile/get-started/client-side-rendering/#refreshing-a-widget) for more info about handling expired widgets. | | | onError | `function` | Callback that is invoked when there is a network error. | | +| as | `string` | Define the HTML tag of the widget container. Default to `'div'`. | | + + + You can pass any valid HTML prop such as `className`, `id`, or `style`, based on the `as` prop. + ### `options` prop @@ -36,9 +41,6 @@ These are the props you can pass to the `Turnstile` component. Read the [Cloudflare docs](https://developers.cloudflare.com/turnstile/get-started/client-side-rendering/#configurations) to get more info about this options. - - The widget is wrapped in a `div`, so you can also pass any valid `div` prop such as `className`, `id`, or `style`. - ### `scriptOptions` prop diff --git a/packages/lib/src/container.tsx b/packages/lib/src/container.tsx new file mode 100644 index 0000000..c5af607 --- /dev/null +++ b/packages/lib/src/container.tsx @@ -0,0 +1,20 @@ +import type { ComponentPropsWithoutRef, ElementType, ForwardedRef } from 'react' +import { forwardRef } from 'react' + +type Props = { + as?: Tag +} & ComponentPropsWithoutRef + +type ComponentProps = Tag extends keyof JSX.IntrinsicElements + ? Props + : // eslint-disable-next-line @typescript-eslint/no-explicit-any + Props + +const Component = ( + { as: Element = 'div', ...props }: ComponentProps, + ref: ForwardedRef +) => { + return +} + +export default forwardRef(Component) diff --git a/packages/lib/src/lib.tsx b/packages/lib/src/lib.tsx index d7ade5d..984a926 100644 --- a/packages/lib/src/lib.tsx +++ b/packages/lib/src/lib.tsx @@ -7,10 +7,21 @@ import { injectTurnstileScript } from './utils' import { RenderOptions, TurnstileInstance, TurnstileProps } from './types' +import Container from './container' export const Turnstile = forwardRef((props, ref) => { - const { scriptOptions, options, siteKey, onSuccess, onExpire, onError, id, style, ...divProps } = - props + const { + scriptOptions, + options, + siteKey, + onSuccess, + onExpire, + onError, + id, + style, + as = 'div', + ...divProps + } = props const config = options ?? {} const widgetSize = config.size ?? 'normal' @@ -19,7 +30,7 @@ export const Turnstile = forwardRef(null) + const containerRef = useRef(null) const firstRendered = useRef(false) const containerId = id ?? DEFAULT_CONTAINER_ID @@ -205,8 +216,9 @@ export const Turnstile = forwardRef { * Custom injected script options. */ scriptOptions?: ScriptOptions + + /** + * Define the HTML tag of the widget container. Default to `'div'`. + */ + as?: React.ElementType } interface InjectTurnstileScriptParams {