import { ReactNode, useRef, useState } from "react"; import clsx from "~/utils/shared/ClassesUtils"; import HintTooltip from "../tooltips/HintTooltip"; import ColorBadge from "../badges/ColorBadge"; import { useTranslation } from "react-i18next"; import { Input } from "../input"; import { Select } from "~/ui/components/Select"; interface Props { name?: string; title?: string; withLabel?: boolean; options: { name: string | ReactNode; value: string | number | undefined; disabled?: boolean; component?: ReactNode; color?: number; }[]; value?: string | number | undefined; setValue?: React.Dispatch>; defaultValue?: string | number | undefined; className?: string; required?: boolean; disabled?: boolean; help?: string; hint?: ReactNode; borderless?: boolean; autoFocus?: boolean; placeholder?: string; withColors?: boolean; withSearch?: boolean; selectClassName?: string; canClear?: boolean; dirty?: boolean; size?: "sm" | "default"; style?: React.CSSProperties; hideIcon?: boolean; icon?: React.ReactNode; } export default function InputSelect({ name, title, withLabel = true, value, defaultValue, options, setValue, className, required, disabled, help, hint, borderless, // autoFocus, placeholder, withColors, withSearch = false, selectClassName, canClear = true, size = "default", style, icon, hideIcon = false, }: Props) { const { t } = useTranslation(); const refSearch = useRef(null); const [inputSearch, setInputSearch] = useState(""); const filteredOptions = () => { let filteredItems = options.filter((f) => f.value); if (inputSearch.trim()) { filteredItems = options.filter((item) => { return ( item.name?.toString().toLowerCase().includes(inputSearch.toLowerCase()) || item.value?.toString().toLowerCase().includes(inputSearch.toLowerCase()) ); }); } if (canClear) { return [ { name: getPlaceholder(), value: "{null}", disabled: false, }, ...filteredItems, ]; } return filteredItems; }; const getPlaceholder = () => { return withLabel ? placeholder || `${t("shared.select")}...` : title || `${t("shared.select")}...`; }; const showLabel = Boolean(withLabel && title); // Rich label content rendered into Subframe's label slot (spans only → inline-safe). const labelContent: ReactNode = showLabel ? ( {title} {required && title && *} {help && } {hint} ) : null; return (
setInputSearch(e.target.value)} onKeyDown={(e) => e.stopPropagation()} onKeyDownCapture={(e) => e.stopPropagation()} onKeyUp={(e) => e.stopPropagation()} /> )} {filteredOptions().length === 0 && (
{t("shared.noRecords")}
)} {filteredOptions().map((item, idx) => { return ( {("component" in item && item.component) || (
{withColors && "color" in item && }
{item.name}
)}
); })}
); }