2024-07-29 11:48:55 +02:00

79 lines
2.4 KiB
TypeScript

import useOpenable from "@Front/Hooks/useOpenable";
import { ChevronDownIcon } from "@heroicons/react/24/outline";
import classNames from "classnames";
import { useCallback, useEffect, useState } from "react";
import Typography, { ETypo, ETypoColor } from "../Typography";
import classes from "./classes.module.scss";
import DropdownMenu from "./DropdownMenu";
import { IOption } from "./DropdownMenu/DropdownOption";
type IProps = {
options: IOption[];
label?: string;
placeholder?: string;
disabled?: boolean;
onSelect?: (option: IOption) => void;
selectedOption?: IOption | null;
};
export default function Dropdown(props: IProps) {
const { options, placeholder, disabled, onSelect, selectedOption: selectedOptionProps, label } = props;
const [selectedOption, setSelectedOption] = useState<IOption | null>(selectedOptionProps ?? null);
const openable = useOpenable({ defaultOpen: false });
useEffect(() => {
setSelectedOption(selectedOptionProps ?? null);
}, [selectedOptionProps]);
const handleOnSelect = useCallback(
(newOption: IOption, _options: IOption[]) => {
setSelectedOption(newOption);
onSelect?.(newOption);
},
[onSelect],
);
return (
<DropdownMenu
options={options}
openable={openable}
onSelect={handleOnSelect}
selectedOptions={selectedOption ? [selectedOption] : []}>
<div className={classes["root"]}>
{label && (
<Typography className={classes["label"]} typo={ETypo.TEXT_MD_REGULAR} color={ETypoColor.CONTRAST_DEFAULT}>
{label}
</Typography>
)}
<div
className={classNames([
classes["container"],
openable.isOpen && classes["open"],
disabled && classes["disabled"],
!!selectedOption && classes["active"],
])}
onClick={openable.toggle}>
<div className={classes["content"]}>
<Typography
className={classes["value"]}
typo={!!selectedOption ? ETypo.TEXT_MD_SEMIBOLD : ETypo.TEXT_MD_REGULAR}
color={!!selectedOption ? ETypoColor.DROPDOWN_CONTRAST_ACTIVE : ETypoColor.DROPDOWN_CONTRAST_DEFAULT}>
{getLabel(selectedOption) ?? placeholder}
</Typography>
<ChevronDownIcon />
</div>
</div>
</div>
</DropdownMenu>
);
}
export function getLabel(option: IOption | null): string | null {
if (!option) return null;
if (typeof option.label === "string") {
return option.label;
}
return `${option.label.text} ${option.label.subtext}`;
}