85 lines
3.7 KiB
TypeScript
85 lines
3.7 KiB
TypeScript
import Icon from "@mdi/react";
|
|
import { ChevronsUpDown } from "lucide-react";
|
|
import { useState } from "react";
|
|
import { Button } from "~/components/ui/button";
|
|
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from "~/components/ui/command";
|
|
import { Popover, PopoverContent, PopoverTrigger } from "~/components/ui/popover";
|
|
import { useCollection, useCollections } from "~/hooks/use-metadata";
|
|
import { colors } from "~/lib/color";
|
|
import { icons } from "~/lib/icon";
|
|
import { type CollectionId } from "~/lib/metadata";
|
|
import { cn } from "~/lib/utils";
|
|
|
|
type CollectionPickerProps = {
|
|
onChange?: (collectionId?: CollectionId) => void;
|
|
className?: string;
|
|
}
|
|
|
|
export function CollectionPicker(props: CollectionPickerProps) {
|
|
const [open, setOpen] = useState(false);
|
|
const [value, setValue] = useState<CollectionId | undefined>();
|
|
|
|
const collections = useCollections();
|
|
|
|
return (
|
|
<Popover open={open} onOpenChange={setOpen}>
|
|
<PopoverTrigger asChild>
|
|
<Button
|
|
variant="outline"
|
|
role="combobox"
|
|
aria-expanded={open}
|
|
className={cn("w-[200px] justify-between", props.className)}
|
|
>
|
|
<Entry collectionId={value} />
|
|
<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
|
</Button>
|
|
</PopoverTrigger>
|
|
<PopoverContent className="w-[200px] p-0">
|
|
<Command>
|
|
<CommandInput placeholder="Search collections..." />
|
|
<CommandList>
|
|
<CommandEmpty>No collection found.</CommandEmpty>
|
|
<CommandGroup>
|
|
<CommandItem
|
|
value="none"
|
|
onSelect={() => {
|
|
setValue(undefined);
|
|
setOpen(false);
|
|
props.onChange && props.onChange(undefined);
|
|
}}
|
|
>
|
|
<Entry collectionId={undefined} />
|
|
</CommandItem>
|
|
{collections.map((collection) => (
|
|
<CommandItem
|
|
key={collection.get("id")}
|
|
value={collection.get("name")}
|
|
onSelect={() => {
|
|
setValue(collection.get("id"));
|
|
setOpen(false);
|
|
props.onChange && props.onChange(collection.get("id"));
|
|
}}
|
|
>
|
|
<Entry collectionId={collection.get("id")} />
|
|
</CommandItem>
|
|
))}
|
|
</CommandGroup>
|
|
</CommandList>
|
|
</Command>
|
|
</PopoverContent>
|
|
</Popover>
|
|
);
|
|
}
|
|
|
|
function Entry(props: { collectionId?: CollectionId }) {
|
|
const collection = useCollection(props.collectionId)
|
|
|
|
return (
|
|
<div className="flex flex-row w-full gap-3 items-center">
|
|
<div className="h-4 w-4 flex items-center justify-center">
|
|
{collection?.get("icon") && <Icon color={colors[collection.get("color")].base} path={icons[collection.get("icon")]!.path} size={1} />}
|
|
</div>
|
|
<span style={{ color: collection ? colors[collection.get("color")].hover : undefined }}>{collection?.get("name") ?? "None"}</span>
|
|
</div>
|
|
);
|
|
}
|