Skip to content

Commit

Permalink
feat: add as prop
Browse files Browse the repository at this point in the history
  • Loading branch information
marsidev committed Apr 2, 2023
1 parent 317ad17 commit fce6eba
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 7 deletions.
8 changes: 5 additions & 3 deletions docs/props.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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'`. | |

<Info>
You can pass any valid HTML prop such as `className`, `id`, or `style`, based on the `as` prop.
</Info>

### `options` prop

Expand All @@ -36,9 +41,6 @@ These are the props you can pass to the `Turnstile` component.
<Info>
Read the [Cloudflare docs](https://developers.cloudflare.com/turnstile/get-started/client-side-rendering/#configurations) to get more info about this options.
</Info>
<Info>
The widget is wrapped in a `div`, so you can also pass any valid `div` prop such as `className`, `id`, or `style`.
</Info>

### `scriptOptions` prop

Expand Down
20 changes: 20 additions & 0 deletions packages/lib/src/container.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import type { ComponentPropsWithoutRef, ElementType, ForwardedRef } from 'react'
import { forwardRef } from 'react'

type Props<Tag extends ElementType> = {
as?: Tag
} & ComponentPropsWithoutRef<Tag>

type ComponentProps<Tag extends ElementType = 'div'> = Tag extends keyof JSX.IntrinsicElements
? Props<Tag>
: // eslint-disable-next-line @typescript-eslint/no-explicit-any
Props<any>

const Component = <Tag extends ElementType = 'div'>(
{ as: Element = 'div', ...props }: ComponentProps<Tag>,
ref: ForwardedRef<Element>
) => {
return <Element {...props} ref={ref} />
}

export default forwardRef(Component)
20 changes: 16 additions & 4 deletions packages/lib/src/lib.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,21 @@ import {
injectTurnstileScript
} from './utils'
import { RenderOptions, TurnstileInstance, TurnstileProps } from './types'
import Container from './container'

export const Turnstile = forwardRef<TurnstileInstance | undefined, TurnstileProps>((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'

Expand All @@ -19,7 +30,7 @@ export const Turnstile = forwardRef<TurnstileInstance | undefined, TurnstileProp
config.execution === 'execute' ? CONTAINER_STYLE_SET.invisible : CONTAINER_STYLE_SET[widgetSize]
)
const [scriptLoaded, setScriptLoaded] = useState(false)
const containerRef = useRef<HTMLDivElement | null>(null)
const containerRef = useRef<HTMLElement | null>(null)
const firstRendered = useRef(false)

const containerId = id ?? DEFAULT_CONTAINER_ID
Expand Down Expand Up @@ -205,8 +216,9 @@ export const Turnstile = forwardRef<TurnstileInstance | undefined, TurnstileProp
}, [widgetSize, config.execution])

return (
<div
<Container
ref={containerRef}
as={as}
id={containerId}
style={{ ...containerStyle, ...style }}
{...divProps}
Expand Down
5 changes: 5 additions & 0 deletions packages/lib/src/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,11 @@ interface TurnstileProps extends React.HTMLAttributes<HTMLDivElement> {
* Custom injected script options.
*/
scriptOptions?: ScriptOptions

/**
* Define the HTML tag of the widget container. Default to `'div'`.
*/
as?: React.ElementType
}

interface InjectTurnstileScriptParams {
Expand Down

1 comment on commit fce6eba

@vercel
Copy link

@vercel vercel bot commented on fce6eba Apr 2, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

react-turnstile – ./

react-turnstile.vercel.app
react-turnstile-marsi.vercel.app
react-turnstile-git-main-marsi.vercel.app

Please sign in to comment.