"use client"; import { Control, FieldValues, Path } from "react-hook-form"; import type { LucideIcon } from "lucide-react"; import { labelOrFallback } from "@/lib/api/labels"; import { NativeSelect } from "@/components/ui/native-select"; import { FormControl, FormField, FormItem, FormLabel, FormMessage, } from "@/components/ui/form"; export interface DiveVocabularyFieldProps< TFieldValues extends FieldValues, TValue extends string, > { control: Control; name: Path; label: string; icon: LucideIcon; /** * What the picker offers, in order: the API's vocabulary or part of it. A stored * value outside it is still offered while the field holds it, so a save never * drops it unasked. */ values: readonly TValue[]; labels: Record; } // One of the dive's closed vocabularies - the water, the dive type, the // conditions, the entry - as a select with "Not recorded" first. // // The three states behind "Not recorded" are DECISIONS.md's "A dive-level select // carries the same three states". export function DiveVocabularyField< TFieldValues extends FieldValues, TValue extends string, >({ control, name, label, icon: Icon, values, labels, }: DiveVocabularyFieldProps) { return ( ( {label}
field.onChange(e.target.value)} /> } > {(!field.value || values.includes(field.value) ? values : [...values, field.value as TValue] ).map((value) => ( ))}
)} /> ); }