"use client"; /* eslint-disable @next/next/no-img-element */ import type { MediaKind } from "@prisma/client"; import { Check, ImageIcon, Search, Trash2 } from "lucide-react"; import { useEffect, useMemo, useRef, useState } from "react"; import { AppCard } from "@/components/ui/app-card"; import { Button } from "@/components/ui/button"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import type { MediaOption } from "@/lib/media"; import { cn } from "@/lib/utils"; export type MediaFieldState = { mode: "upload" | "external" | "library"; assetId: string; url: string; label: string; kind: MediaKind; isCleared?: boolean; }; type MediaFieldPickerProps = { title: string; value: MediaFieldState; onChange: (nextValue: MediaFieldState) => void; options: MediaOption[]; hasInitialValue?: boolean; inputName: string; fileFieldName: string; allowClear?: boolean; clearLabel?: string; emptyValue?: Partial; }; export function MediaFieldPicker({ title, value, onChange, options, hasInitialValue = false, inputName, allowClear = false, clearLabel = "Remove", emptyValue, }: MediaFieldPickerProps) { const hiddenInputRef = useRef(null); const [open, setOpen] = useState(false); const [query, setQuery] = useState(""); const filteredOptions = options.filter((option) => option.kind === value.kind); const selectedOption = filteredOptions.find((option) => option.id === value.assetId) ?? null; const visibleOptions = useMemo(() => { const normalizedQuery = query.trim().toLowerCase(); if (!normalizedQuery) { return filteredOptions; } return filteredOptions.filter((option) => option.label.toLowerCase().includes(normalizedQuery)); }, [filteredOptions, query]); const serializedValue = JSON.stringify({ mode: value.mode, assetId: value.assetId, url: value.url, label: value.label, kind: value.kind, }); const canClear = allowClear && (Boolean(value.assetId) || (hasInitialValue && !value.isCleared)); useEffect(() => { const hiddenInput = hiddenInputRef.current; if (!hiddenInput) { return; } hiddenInput.dispatchEvent(new Event("input", { bubbles: true })); hiddenInput.dispatchEvent(new Event("change", { bubbles: true })); }, [serializedValue]); return (

Media must be selected from the {" "} Media Library .

{canClear ? ( ) : null}
{selectedOption ? (
{selectedOption.label}

{selectedOption.label}

{selectedOption.source}

) : (
No media selected.
)}
{title} Select an existing item from the media library.
setQuery(event.target.value)} placeholder="Search media" className="pl-9" />
{visibleOptions.map((option) => { const isActive = option.id === value.assetId; return ( ); })}
); }