import { Ref, forwardRef, useImperativeHandle, useRef, ReactNode, useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { Link } from "react-router"; import { Colors } from "~/application/enums/shared/Colors"; import ColorBadge from "../badges/ColorBadge"; import HintTooltip from "../tooltips/HintTooltip"; import EntityIcon from "~/components/layouts/icons/EntityIcon"; import { Select } from "~/ui/components/Select"; import { PlusIcon } from "~/components/ui/icons/vendor"; export interface RefInputSelector { focus: () => void; } interface Props { name?: string; title?: string; value?: string | number | undefined; defaultValue?: string | number | undefined; disabled?: boolean; options: { name: string | ReactNode; value: string | number | undefined; color?: Colors; disabled?: boolean }[]; setValue?: React.Dispatch>; className?: string; withSearch?: boolean; withLabel?: boolean; withColors?: boolean; selectPlaceholder?: string; onNew?: () => void; onNewRoute?: string; required?: boolean; help?: string; hint?: ReactNode; icon?: string; borderless?: boolean; darkMode?: boolean; autoFocus?: boolean; readOnly?: boolean; isLoading?: boolean; } const InputSelector = ( { name, title, value, defaultValue, options, disabled, setValue, className, // withSearch — Subframe Select has built-in typeahead; legacy in-list search dropped. withLabel = true, withColors = false, selectPlaceholder, onNew, required, onNewRoute, help, hint, icon, borderless, // darkMode — handled by the global Subframe theme. autoFocus, readOnly, isLoading, }: Props, ref: Ref ) => { const { t } = useTranslation(); const container = useRef(null); const [selected, setSelected] = useState<{ name: string | ReactNode; value: string | number | undefined; color?: Colors }>(); useEffect(() => { const found = options?.find((f) => f.value === value); setSelected(found); }, [options, value]); useEffect(() => { if (selected && setValue && value !== selected?.value) { setValue(selected?.value); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [selected]); useImperativeHandle(ref, () => ({ focus })); function focus() { setTimeout(() => { const button = container.current?.querySelector("button"); button?.focus(); button?.click(); }, 1); } const showLabel = Boolean(withLabel && title); const newLabel = String(t("shared.new")); // Rich label content rendered into Subframe's label slot (spans only → inline-safe). const labelContent: ReactNode = showLabel ? ( {title} {required && *} {help && } {hint} ) : null; const placeholderText = isLoading ? `${t("shared.loading")}...` : `${selectPlaceholder ?? t("shared.select")}...`; return (
{onNew && ( )} {onNewRoute && (
); }; export default forwardRef(InputSelector);