import {createElement, ReactElement, ReactNode} from 'react' // new function for type reasons export function classToTw(element: ReactElement) { return replaceTw(element) as ReactElement } /** Traverse react element's tree, replacing className prop with tw for satori engine */ function replaceTw(element: ReactNode): ReactNode { // base case if (!element || typeof element !== 'object') { if (typeof element === 'string') return element return element } // fragment if (!('type' in element)) { // Convert to array safely const children = Array.isArray(element) ? element : [element] return <>{children.map(replaceTw)} } // component if (typeof element.type === 'function') { if (element.type.prototype?.isReactComponent) { throw Error( 'React class component not supported in classname to tw middleware because Sinclair is lazy.', ) } // functional component const component = element.type as (props: any) => ReactElement const newType = (props: any) => replaceTw(component(props)) as ReactElement return createElement(newType, element.props) } // pure element // Replace `className` with `tw` for this element const props = element.props as {className?: string; children?: ReactNode; tw?: string} const newProps = {...props} if (props.className) { newProps.tw = props.className delete newProps.className } // Recursively replace children, whether we have many, one, or no children const {children} = props const newChildren = children ? Array.isArray(children) ? children.map(replaceTw) : [replaceTw(children)] : [] return createElement(element.type, newProps, newChildren) }