'use client' import type { ReactNode } from 'react' import { Controller, type Control } from 'react-hook-form' import { Autocomplete, AutocompleteItem } from '@/components/heroui/Autocomplete' import { Checkbox, Radio, RadioGroup, Switch } from '@/components/heroui/SelectionControls' import { InputOtp } from '@/components/heroui/InputOtp' import { Select, SelectItem } from '@/components/heroui/Select' import { cn } from '@/lib/cn' import { texts } from '@/texts' import { buildOutsideLabel, getOptionValue, type SelectOptionItem } from '@/components/formElements/input/inputUtils' import { coerceToString } from '@/helpers' import { useDialogPortalContainer } from '@/components/formElements/input/useDialogPortalContainer' type Kind = 'otp' | 'combobox' | 'select' | 'radio' | 'checkbox' | 'switch' interface Props { ariaLabel?: string autoFocus?: boolean className?: string control: Control description?: ReactNode disabled?: boolean finalInputWrapper: string getValues: (name: string) => unknown iconEnd?: ReactNode iconStart?: ReactNode inputType?: 'text' | 'email' | 'number' | 'password' | 'tel' kind: Kind label?: string loading: boolean multiple?: boolean name: string options: SelectOptionItem[] orientation: 'horizontal' | 'vertical' otpLength: number placeholder?: string radius: 'none' | 'sm' | 'md' | 'lg' | 'full' readonly?: boolean required?: boolean searchOptions: SelectOptionItem[] selectKey: string selectValue: string size?: 'sm' | 'md' | 'lg' variant: 'flat' | 'bordered' | 'faded' | 'underlined' onSearch: (value: string) => void } function OutsideLabel({ invalid, label, required }: { invalid: boolean; label?: string; required?: boolean }) { if (!label) return null return {buildOutsideLabel(label, null, required)} } export default function ChoiceFieldControl(props: Props) { const { portalContainer, setHostEl } = useDialogPortalContainer() return ( { const invalid = !!error const ariaLabel = props.ariaLabel ?? props.label ?? props.name if (props.kind === 'otp') { return ( {buildOutsideLabel(props.label, null, props.required)} ) } if (props.kind === 'combobox') { return ( { if (props.multiple) { const current = props.getValues(field.name) field.onChange([...(Array.isArray(current) ? current : []), value]) } else field.onChange(value) }} > {(item) => ( {coerceToString(getOptionValue(item, props.selectValue))} )} ) } if (props.kind === 'select') { const selectedKeys = props.multiple ? field.value : field.value !== undefined && field.value !== null && field.value !== '' ? [String(field.value)] : [] return ( { if (props.multiple) field.onChange(keys) else if (keys === 'all') field.onChange('') else field.onChange(String(Array.from(keys as Set)[0] ?? '')) }} > {props.options.map((item, index) => { const optionKey = coerceToString(getOptionValue(item, props.selectKey)) || `select-item-${index}` const optionLabel = coerceToString(getOptionValue(item, props.selectValue)) const depth = Number(getOptionValue(item, 'depth') ?? 0) return ( {depth > 0 ? ( – {optionLabel} ) : ( optionLabel )} ) })} ) } if (props.kind === 'radio') { return ( {props.options.map((item) => ( {coerceToString(getOptionValue(item, 'name'))} ))} ) } if (props.kind === 'checkbox') { return ( {props.label} ) } return ( {props.label} ) }} /> ) }