Skip to content

Commit fce6eba

Browse files
committed
feat: add as prop
1 parent 317ad17 commit fce6eba

File tree

4 files changed

+46
-7
lines changed

4 files changed

+46
-7
lines changed

docs/props.mdx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ These are the props you can pass to the `Turnstile` component.
1414
| onSuccess | `function` | Callback that is invoked upon success of the challenge. The callback is passed a token that can be validated. | |
1515
| 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. | |
1616
| onError | `function` | Callback that is invoked when there is a network error. | |
17+
| as | `string` | Define the HTML tag of the widget container. Default to `'div'`. | |
18+
19+
<Info>
20+
You can pass any valid HTML prop such as `className`, `id`, or `style`, based on the `as` prop.
21+
</Info>
1722

1823
### `options` prop
1924

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

4345
### `scriptOptions` prop
4446

packages/lib/src/container.tsx

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import type { ComponentPropsWithoutRef, ElementType, ForwardedRef } from 'react'
2+
import { forwardRef } from 'react'
3+
4+
type Props<Tag extends ElementType> = {
5+
as?: Tag
6+
} & ComponentPropsWithoutRef<Tag>
7+
8+
type ComponentProps<Tag extends ElementType = 'div'> = Tag extends keyof JSX.IntrinsicElements
9+
? Props<Tag>
10+
: // eslint-disable-next-line @typescript-eslint/no-explicit-any
11+
Props<any>
12+
13+
const Component = <Tag extends ElementType = 'div'>(
14+
{ as: Element = 'div', ...props }: ComponentProps<Tag>,
15+
ref: ForwardedRef<Element>
16+
) => {
17+
return <Element {...props} ref={ref} />
18+
}
19+
20+
export default forwardRef(Component)

packages/lib/src/lib.tsx

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,21 @@ import {
77
injectTurnstileScript
88
} from './utils'
99
import { RenderOptions, TurnstileInstance, TurnstileProps } from './types'
10+
import Container from './container'
1011

1112
export const Turnstile = forwardRef<TurnstileInstance | undefined, TurnstileProps>((props, ref) => {
12-
const { scriptOptions, options, siteKey, onSuccess, onExpire, onError, id, style, ...divProps } =
13-
props
13+
const {
14+
scriptOptions,
15+
options,
16+
siteKey,
17+
onSuccess,
18+
onExpire,
19+
onError,
20+
id,
21+
style,
22+
as = 'div',
23+
...divProps
24+
} = props
1425
const config = options ?? {}
1526
const widgetSize = config.size ?? 'normal'
1627

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

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

207218
return (
208-
<div
219+
<Container
209220
ref={containerRef}
221+
as={as}
210222
id={containerId}
211223
style={{ ...containerStyle, ...style }}
212224
{...divProps}

packages/lib/src/types.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,11 @@ interface TurnstileProps extends React.HTMLAttributes<HTMLDivElement> {
285285
* Custom injected script options.
286286
*/
287287
scriptOptions?: ScriptOptions
288+
289+
/**
290+
* Define the HTML tag of the widget container. Default to `'div'`.
291+
*/
292+
as?: React.ElementType
288293
}
289294

290295
interface InjectTurnstileScriptParams {

0 commit comments

Comments
 (0)