mirror of
https://github.com/CompassConnections/Compass.git
synced 2026-01-04 11:58:21 -05:00
58 lines
1.6 KiB
TypeScript
58 lines
1.6 KiB
TypeScript
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
|
|
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)
|
|
}
|