"use client" import { useMemo, useRef, useState } from "react" import { X } from "lucide-react" import { Input } from "@/components/ui/input" import { Label } from "@/components/ui/label" import { Popover, PopoverContent, PopoverTrigger, } from "@/components/ui/popover" import type { AiModelCatalogEntry } from "@/lib/admin-settings/org-settings-types" import { cn } from "@/lib/utils" const VISIBLE_SUGGESTIONS = 5 const SUGGESTION_ROW_HEIGHT_REM = 2.25 function modelKey(entry: AiModelCatalogEntry) { return entry.model_id } function chipLabel(entry: AiModelCatalogEntry) { const label = entry.label.trim() return label && label !== entry.model_id ? label : entry.model_id } export function AiAuthorizedModelPicker({ models, onChange, availableModelIds, disabled, emptyHint, }: { models: AiModelCatalogEntry[] onChange: (models: AiModelCatalogEntry[]) => void availableModelIds: string[] disabled?: boolean emptyHint?: string }) { const [query, setQuery] = useState("") const [focused, setFocused] = useState(false) const [activeIndex, setActiveIndex] = useState(0) const blurTimer = useRef(null) const taken = useMemo(() => new Set(models.map((m) => m.model_id)), [models]) const suggestions = useMemo(() => { const q = query.trim().toLowerCase() const pool = availableModelIds.filter((id) => !taken.has(id)) const matches = q ? pool.filter((id) => id.toLowerCase().includes(q)) : pool return matches.sort((a, b) => a.localeCompare(b)) }, [availableModelIds, query, taken]) const showSuggestions = focused && !disabled && suggestions.length > 0 function addModel(modelId: string) { const id = modelId.trim() if (!id || taken.has(id)) return onChange([...models, { model_id: id, label: id, enabled: true }]) setQuery("") setActiveIndex(0) } function removeModel(modelId: string) { onChange(models.filter((entry) => entry.model_id !== modelId)) } function updateLabel(modelId: string, label: string) { onChange( models.map((entry) => entry.model_id === modelId ? { ...entry, label } : entry, ), ) } function tryAddFromQuery() { const id = query.trim() if (!id) return false if (suggestions[activeIndex]) { addModel(suggestions[activeIndex]!) return true } if (!taken.has(id)) { addModel(id) return true } return false } return (
{ setQuery(e.target.value) setActiveIndex(0) }} onFocus={() => { if (blurTimer.current) window.clearTimeout(blurTimer.current) setFocused(true) }} onBlur={() => { blurTimer.current = window.setTimeout(() => setFocused(false), 120) }} onKeyDown={(e) => { if (e.key === "Enter") { e.preventDefault() tryAddFromQuery() return } if (!showSuggestions || suggestions.length === 0) return if (e.key === "ArrowDown") { e.preventDefault() setActiveIndex((i) => (i + 1) % suggestions.length) } else if (e.key === "ArrowUp") { e.preventDefault() setActiveIndex((i) => (i - 1 + suggestions.length) % suggestions.length) } else if (e.key === "Escape") { setFocused(false) } }} /> {showSuggestions ? (
    {suggestions.map((modelId, index) => (
  • ))}
) : null}
{models.length > 0 ? (
{models.map((entry) => (

{entry.model_id}

updateLabel(entry.model_id, e.target.value)} placeholder={entry.model_id} />
))}
) : emptyHint ? (

{emptyHint}

) : null}
) }