|
| 1 | +import React, { Suspense } from 'react'; |
| 2 | + |
| 3 | +import { jsxToString, useData } from '../render/jsx-to-string'; |
| 4 | +import type { JsxEmailComponent } from '../types'; |
| 5 | + |
| 6 | +export interface ConditionalProps { |
| 7 | + children?: React.ReactNode; |
| 8 | + expression?: string; |
| 9 | + mso?: boolean; |
| 10 | +} |
| 11 | + |
| 12 | +const notMso = (html: string) => `<!--[if !mso]><!-->${html}<!--<![endif]-->`; |
| 13 | + |
| 14 | +const comment = (expression: string, html: string) => `<!--[if ${expression}]>${html}<![endif]-->`; |
| 15 | + |
| 16 | +const Renderer = (props: ConditionalProps) => { |
| 17 | + const { children, mso } = props; |
| 18 | + let { expression } = props; |
| 19 | + const html = useData(props, () => jsxToString(<>{children}</>)); |
| 20 | + let innerHtml = ''; |
| 21 | + |
| 22 | + if (mso === false) innerHtml = notMso(html); |
| 23 | + else if (mso === true && !expression) expression = 'mso'; |
| 24 | + if (expression) innerHtml = comment(expression, html); |
| 25 | + |
| 26 | + // @ts-ignore |
| 27 | + // Note: This is perfectly valid. TS just expects lowercase tag names to match a specific type |
| 28 | + return <jsx-email-cond dangerouslySetInnerHTML={{ __html: innerHtml }} />; |
| 29 | +}; |
| 30 | + |
| 31 | +export const Conditional: JsxEmailComponent<ConditionalProps> = (props) => { |
| 32 | + const { children, expression, mso } = props; |
| 33 | + |
| 34 | + if (typeof expression === 'undefined' && typeof mso === 'undefined') |
| 35 | + throw new RangeError( |
| 36 | + 'jsx-email: Conditional expects the `expression` or `mso` prop to be defined' |
| 37 | + ); |
| 38 | + |
| 39 | + if (typeof expression !== 'undefined' && typeof mso !== 'undefined') |
| 40 | + throw new RangeError( |
| 41 | + 'jsx-email: Conditional expects the `expression` or `mso` prop to be defined, not both' |
| 42 | + ); |
| 43 | + |
| 44 | + return ( |
| 45 | + <> |
| 46 | + <Suspense fallback={<div>waiting</div>}> |
| 47 | + <Renderer {...props}>{children}</Renderer> |
| 48 | + </Suspense> |
| 49 | + </> |
| 50 | + ); |
| 51 | +}; |
| 52 | + |
| 53 | +Conditional.displayName = 'Conditional'; |
0 commit comments