import React, { type FC, type ReactNode } from "react"; export interface IfProps { condition: boolean; children?: React.ReactNode; } export interface ThenProps { children?: React.ReactNode; } export interface ElseProps { children?: React.ReactNode; } export interface ElseIfProps { condition: boolean; children?: React.ReactNode; } const Then: FC = (props) => { return <>{props.children}; }; const Else: FC = ({ children }) => { return <>{children}; }; const ElseIf: FC = (props) => { return <>{props.children}; }; Then.displayName = "If_Then"; Else.displayName = "If_Else"; ElseIf.displayName = "If_ElseIf"; export const If = ({ condition, children, }: IfProps): React.ReactElement | null => { let thenChild: React.ReactElement | null = null as React.ReactElement | null; let elseChild: React.ReactElement | null = null; const elseIfChildren: React.ReactElement[] = []; React.Children.forEach(children, (child) => { if (!React.isValidElement(child)) { throw new Error("If component only accepts valid React elements"); } const type = child.type as any; if (type.displayName === Then.displayName) { if (thenChild) { throw new Error("If component can only have one Then child"); } thenChild = child as React.ReactElement; } else if (type.displayName === ElseIf.displayName) { elseIfChildren.push(child as React.ReactElement); } else if (type.displayName === Else.displayName) { if (elseChild) { throw new Error("If component can only have one Else child"); } elseChild = child as React.ReactElement; } else { throw new Error( `If component only accepts 'Then', 'ElseIf', or 'Else' elements as children, found: ${String( type.displayName || type.name || type, )}`, ); } }); if (condition) { return thenChild ? <>{thenChild.props.children} : null; } for (const elseIf of elseIfChildren) { if (elseIf.props.condition) { return <>{elseIf.props.children}; } } if (elseChild) { return <>{(elseChild as React.ReactElement).props.children}; } return null; }; If.displayName = "If"; If.Then = Then; If.ElseIf = ElseIf; If.Else = Else; If.createTyped = () => { return { If, Then, ElseIf, Else, } as { If: (props: IfProps) => React.ReactElement | null; Then: (props: ThenProps) => React.ReactElement; ElseIf: (props: ElseIfProps) => React.ReactElement; Else: (props: ElseProps) => React.ReactElement; }; }; export interface TrueProps { condition: boolean; children?: ReactNode; } export const True: FC = ({ condition, children }) => { return condition ? <>{children} : null; }; export interface FalseProps { condition: boolean; children?: ReactNode; } export const False: FC = ({ condition, children }) => { return condition === false ? <>{children} : null; };