DrMint dd3beff508
Added meilisearch (#89)
* Added search on most pages

* Changed material icons to symbols and added wikipage search

* Updated deps

* Changed color of the play button on previewcard overlay

* Updated search params

* Updated deps

* Audit fix

* Removed unused graphql files
2023-01-07 01:59:54 +01:00

102 lines
3.5 KiB
TypeScript

import { Fragment, useCallback, useRef } from "react";
import { useBoolean, useOnClickOutside } from "usehooks-ts";
import { Ico } from "components/Ico";
import { cIf, cJoin } from "helpers/className";
/*
* ╭─────────────╮
* ───────────────────────────────────────╯ COMPONENT ╰───────────────────────────────────────────
*/
interface Props {
value: number;
options: string[];
selected?: number;
allowEmpty?: boolean;
className?: string;
onChange: (value: number) => void;
disabled?: boolean;
}
// ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
export const Select = ({
className,
value,
options,
allowEmpty,
disabled = false,
onChange,
}: Props): JSX.Element => {
const { value: isOpened, setFalse: setClosed, toggle: toggleOpened } = useBoolean(false);
const tryToggling = useCallback(() => {
if (disabled) return;
const optionCount = options.length + (value === -1 ? 1 : 0);
if (optionCount > 1) toggleOpened();
}, [disabled, options.length, value, toggleOpened]);
const onSelectionChanged = useCallback(
(newIndex: number) => {
setClosed();
onChange(newIndex);
},
[onChange, setClosed]
);
const ref = useRef<HTMLDivElement>(null);
useOnClickOutside(ref, setClosed);
return (
<div
ref={ref}
className={cJoin(
"relative text-center transition-filter",
cIf(isOpened, "z-10 drop-shadow-lg shadow-shade"),
className
)}>
<div
className={cJoin(
`grid cursor-pointer select-none grid-flow-col grid-cols-[1fr_auto_auto]
place-items-center rounded-3xl p-1 outline outline-1 -outline-offset-1
outline-mid`,
cIf(isOpened, "rounded-b-none bg-highlight outline-transparent"),
cIf(
disabled,
"cursor-not-allowed text-dark opacity-50 outline-dark/60 grayscale",
"transition-all hover:bg-mid hover:outline-transparent"
)
)}>
<p onClick={tryToggling} className="w-full px-4 py-1">
{value === -1 ? "—" : options[value]}
</p>
{value >= 0 && allowEmpty && (
<Ico
icon="close"
className="!text-xs"
onClick={() => !disabled && onSelectionChanged(-1)}
/>
)}
<Ico onClick={tryToggling} icon={isOpened ? "arrow_drop_up" : "arrow_drop_down"} />
</div>
<div className={cJoin("left-0 right-0 rounded-b-[1em]", cIf(isOpened, "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(isOpened, "bg-highlight", "bg-light")
)}
id={option}
onClick={() => onSelectionChanged(index)}>
{option}
</div>
)}
</Fragment>
))}
</div>
</div>
);
};