@@ -24,6 +24,9 @@ import {
2424 type DOMAttributes ,
2525 type EventHandler ,
2626 type JSX as ReactJSX ,
27+ type LazyExoticComponent ,
28+ type MemoExoticComponent ,
29+ type ForwardRefExoticComponent ,
2730 type PropsWithChildren ,
2831 type ReactElement ,
2932 type ReactNode ,
@@ -35,6 +38,13 @@ export type ReactJsxComponent<Props = Record<string, unknown>> = ComponentType<
3538 PropsWithChildren < Props >
3639>
3740
41+ type ReactJsxExoticComponent =
42+ | MemoExoticComponent < ReactJsxComponent >
43+ | ForwardRefExoticComponent < Record < string , unknown > >
44+ | LazyExoticComponent < ReactJsxComponent >
45+
46+ type ReactJsxTagComponent = ReactJsxComponent | ReactJsxExoticComponent
47+
3848export type ReactJsxRenderable = ReactNode
3949export type ReactJsxChildren = ReactJsxRenderable | ReactJsxRenderable [ ]
4050export type ReactJsxRef < T > = Ref < T >
@@ -44,7 +54,7 @@ export type ReactJsxIntrinsicElements = ReactJSX.IntrinsicElements
4454export type ReactJsxIntrinsicElement < Tag extends keyof ReactJsxIntrinsicElements > =
4555 ReactJsxIntrinsicElements [ Tag ]
4656
47- type ReactJsxContext = TemplateContext < ReactJsxComponent >
57+ type ReactJsxContext = TemplateContext < ReactJsxTagComponent >
4858
4959const isIterable = ( value : unknown ) : value is Iterable < unknown > => {
5060 if ( ! value || typeof value === 'string' ) {
@@ -172,13 +182,34 @@ const evaluateReactJsxChildren = (children: JSXChild[], ctx: ReactJsxContext) =>
172182}
173183
174184const createReactElement = (
175- type : string | ReactJsxComponent ,
185+ type : string | ReactJsxTagComponent ,
176186 props : Record < string , unknown > ,
177187 children : ReactNode [ ] ,
178188) => {
179189 return createElement ( type as never , props , ...children )
180190}
181191
192+ const reactMemoSymbol = Symbol . for ( 'react.memo' )
193+ const reactForwardRefSymbol = Symbol . for ( 'react.forward_ref' )
194+ const reactLazySymbol = Symbol . for ( 'react.lazy' )
195+
196+ const isReactTagBindingValue = ( value : unknown ) : value is ReactJsxTagComponent => {
197+ if ( typeof value === 'function' ) {
198+ return true
199+ }
200+
201+ if ( typeof value !== 'object' || value === null ) {
202+ return false
203+ }
204+
205+ const candidate = value as { $$typeof ?: unknown }
206+ return (
207+ candidate . $$typeof === reactMemoSymbol ||
208+ candidate . $$typeof === reactForwardRefSymbol ||
209+ candidate . $$typeof === reactLazySymbol
210+ )
211+ }
212+
182213const evaluateReactJsxElement = (
183214 element : JSXElement ,
184215 ctx : ReactJsxContext ,
@@ -218,7 +249,9 @@ export const reactJsx = (
218249 templates : TemplateStringsArray ,
219250 ...values : unknown [ ]
220251) : ReactElement => {
221- const build = buildTemplate < ReactJsxComponent > ( templates , values )
252+ const build = buildTemplate < ReactJsxTagComponent > ( templates , values , {
253+ isTagNameBindingValue : isReactTagBindingValue ,
254+ } )
222255 const result = parseSync ( 'inline.jsx' , build . source , parserOptions )
223256
224257 if ( result . errors . length > 0 ) {
0 commit comments