You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
64 lines
1.6 KiB
64 lines
1.6 KiB
2 years ago
|
import {
|
||
|
Check as MUICheckIcon,
|
||
|
Close as MUICloseIcon,
|
||
|
} from '@mui/icons-material';
|
||
|
import { cloneElement, createElement, FC, ReactElement } from 'react';
|
||
|
|
||
|
import { BLUE, PURPLE } from '../lib/consts/DEFAULT_THEME';
|
||
|
|
||
|
import FlexBox from './FlexBox';
|
||
|
import { BodyText, SmallText } from './Text';
|
||
|
|
||
|
type StateTypeMap = Pick<MapToType, 'boolean'>;
|
||
|
|
||
|
type StateMap<TypeName extends keyof StateTypeMap> = Map<
|
||
|
StateTypeMap[TypeName],
|
||
|
ReactElement
|
||
|
>;
|
||
|
|
||
|
type LabelMap = Record<'small' | 'medium', FC>;
|
||
|
|
||
|
type StateOptionalProps<TypeName extends keyof StateTypeMap> = {
|
||
|
size?: keyof LabelMap;
|
||
|
stateMap?: StateMap<TypeName>;
|
||
|
};
|
||
|
|
||
|
type StateProps<TypeName extends keyof StateTypeMap> =
|
||
|
StateOptionalProps<TypeName> & {
|
||
|
label: string;
|
||
|
state: StateTypeMap[TypeName];
|
||
|
};
|
||
|
|
||
|
const MAP_TO_TEXT_ELEMENT: LabelMap = {
|
||
|
small: SmallText,
|
||
|
medium: BodyText,
|
||
|
};
|
||
|
|
||
|
const STATE_DEFAULT_PROPS: Required<StateOptionalProps<'boolean'>> = {
|
||
|
size: 'small',
|
||
|
stateMap: new Map<boolean, ReactElement>([
|
||
|
[false, <MUICloseIcon key="state-false" sx={{ color: PURPLE }} />],
|
||
|
[true, <MUICheckIcon key="state-true" sx={{ color: BLUE }} />],
|
||
|
]),
|
||
|
};
|
||
|
|
||
|
const State = <TypeName extends keyof StateTypeMap>({
|
||
|
label,
|
||
|
size = STATE_DEFAULT_PROPS.size,
|
||
|
state,
|
||
|
stateMap = STATE_DEFAULT_PROPS.stateMap,
|
||
|
}: StateProps<TypeName>): ReturnType<FC<StateProps<TypeName>>> => {
|
||
|
const stateIcon = stateMap.get(state);
|
||
|
|
||
|
return (
|
||
|
<FlexBox row spacing=".3em">
|
||
|
{stateIcon && cloneElement(stateIcon, { fontSize: size })}
|
||
|
{createElement(MAP_TO_TEXT_ELEMENT[size], {}, label)}
|
||
|
</FlexBox>
|
||
|
);
|
||
|
};
|
||
|
|
||
|
State.defaultProps = STATE_DEFAULT_PROPS;
|
||
|
|
||
|
export default State;
|