mirror of https://github.com/coder/coder.git
49 lines
1.9 KiB
TypeScript
49 lines
1.9 KiB
TypeScript
import { Children, PropsWithChildren } from "react";
|
|
|
|
export interface CondProps {
|
|
condition?: boolean;
|
|
}
|
|
|
|
/**
|
|
* Wrapper component that attaches a condition to a child component so that ChooseOne can
|
|
* determine which child to render. The last Cond in a ChooseOne is the fallback case and
|
|
* should not have a condition.
|
|
* @param condition boolean expression indicating whether the child should be rendered, or undefined
|
|
* @returns child. Note that Cond alone does not enforce the condition; it should be used inside ChooseOne.
|
|
*/
|
|
export const Cond = ({
|
|
children,
|
|
}: PropsWithChildren<CondProps>): JSX.Element => {
|
|
return <>{children}</>;
|
|
};
|
|
|
|
/**
|
|
* Wrapper component for rendering exactly one of its children. Wrap each child in Cond to associate it
|
|
* with a condition under which it should be rendered. If no conditions are met, the final child
|
|
* will be rendered.
|
|
* @returns one of its children, or null if there are no children
|
|
* @throws an error if its last child has a condition prop, or any non-final children do not have a condition prop
|
|
*/
|
|
export const ChooseOne = ({
|
|
children,
|
|
}: PropsWithChildren): JSX.Element | null => {
|
|
const childArray = Children.toArray(children) as JSX.Element[];
|
|
if (childArray.length === 0) {
|
|
return null;
|
|
}
|
|
const conditionedOptions = childArray.slice(0, childArray.length - 1);
|
|
const defaultCase = childArray[childArray.length - 1];
|
|
if (defaultCase.props.condition !== undefined) {
|
|
throw new Error(
|
|
"The last Cond in a ChooseOne was given a condition prop, but it is the default case.",
|
|
);
|
|
}
|
|
if (conditionedOptions.some((cond) => cond.props.condition === undefined)) {
|
|
throw new Error(
|
|
"A non-final Cond in a ChooseOne does not have a condition prop or the prop is undefined.",
|
|
);
|
|
}
|
|
const chosen = conditionedOptions.find((child) => child.props.condition);
|
|
return chosen ?? defaultCase;
|
|
};
|