2022-07-13 03:46:58 +02:00

100 lines
3.2 KiB
TypeScript

import { Fragment, useCallback, useState } from "react";
import { Ico, Icon } from "components/Ico";
import { cIf, cJoin } from "helpers/className";
import { useToggle } from "hooks/useToggle";
/*
* ╭─────────────╮
* ───────────────────────────────────────╯ COMPONENT ╰───────────────────────────────────────────
*/
interface Props {
value: number;
options: string[];
selected?: number;
allowEmpty?: boolean;
className?: string;
onChange: (value: number) => void;
}
// ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
export const Select = ({
className,
value,
options,
allowEmpty,
onChange,
}: Props): JSX.Element => {
const [opened, setOpened] = useState(false);
const toggleOpened = useToggle(setOpened);
const tryToggling = useCallback(() => {
const optionCount = options.length + (value === -1 ? 1 : 0);
if (optionCount > 1) toggleOpened();
}, [options.length, value, toggleOpened]);
return (
<div
className={cJoin(
"relative text-center transition-[filter]",
cIf(opened, "z-10 drop-shadow-shade-lg"),
className
)}
>
<div
className={cJoin(
`grid cursor-pointer grid-flow-col grid-cols-[1fr_auto_auto] place-items-center
rounded-[1em] bg-light p-1 outline outline-2 outline-offset-[-2px] outline-mid
transition-all hover:bg-mid hover:outline-[transparent]`,
cIf(opened, "rounded-b-none bg-highlight outline-[transparent]")
)}
>
<p onClick={tryToggling} className="w-full">
{value === -1 ? "—" : options[value]}
</p>
{value >= 0 && allowEmpty && (
<Ico
icon={Icon.Close}
className="!text-xs"
onClick={() => {
onChange(-1);
setOpened(false);
}}
/>
)}
<Ico
onClick={tryToggling}
icon={opened ? Icon.ArrowDropUp : Icon.ArrowDropDown}
/>
</div>
<div
className={cJoin(
"left-0 right-0 rounded-b-[1em]",
cIf(opened, "absolute", "hidden")
)}
>
{options.map((option, index) => (
<Fragment key={index}>
{index !== value && (
<div
className={cJoin(
"cursor-pointer p-1 transition-colors last-of-type:rounded-b-[1em] hover:bg-mid",
cIf(opened, "bg-highlight", "bg-light")
)}
id={option}
onClick={() => {
setOpened(false);
onChange(index);
}}
>
{option}
</div>
)}
</Fragment>
))}
</div>
</div>
);
};