v3/src/components/form/collection_picker.tsx

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>
);
}