import React, { useState, useRef, useEffect, KeyboardEvent, ReactNode, RefObject, Ref, forwardRef, useImperativeHandle } from "react"; import clsx from "clsx"; import HintTooltip from "../tooltips/HintTooltip"; import EntityIcon from "~/components/layouts/icons/EntityIcon"; import { useTranslation } from "react-i18next"; import { RowValueMultipleDto } from "~/application/dtos/entities/RowValueMultipleDto"; import { SeparatorFormatType } from "~/utils/shared/SeparatorUtils"; import { Input } from "../input"; export interface RefInputMultiText { input: RefObject; } interface Props { name?: string; title?: string; withLabel?: boolean; value?: RowValueMultipleDto[]; className?: string; classNameBg?: string; minLength?: number; maxLength?: number; readOnly?: boolean; disabled?: boolean; required?: boolean; autoComplete?: string; translationParams?: string[]; placeholder?: string; pattern?: string; rows?: number; button?: ReactNode; lowercase?: boolean; uppercase?: boolean; darkMode?: boolean; hint?: ReactNode; help?: string; icon?: string; onBlur?: () => void; borderless?: boolean; autoFocus?: boolean; separator?: SeparatorFormatType; } const InputMultiText = ( { name, title, withLabel = true, value, className, classNameBg, help, disabled = false, readOnly = false, required = false, minLength, maxLength, autoComplete, placeholder, pattern, hint, rows, button, lowercase, uppercase, darkMode, icon, onBlur, borderless, autoFocus, separator = ",", }: Props, ref: Ref ) => { const { t } = useTranslation(); useImperativeHandle(ref, () => ({ input })); const input = useRef(null); const [inputValue, setInputValue] = useState(""); const [actualValue, setActualValue] = useState<(string | number)[]>([]); useEffect(() => { const selection = value?.map((f) => f.value) ?? []; if (selection.sort().join(",") !== actualValue.sort().join(",")) { setActualValue(selection); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [value]); const handleKeyDown = (e: KeyboardEvent) => { if (separator === e.key) { e.preventDefault(); if (inputValue.trim() !== "") { setActualValue?.((prevTags) => [...prevTags, inputValue.trim()]); setInputValue(""); } } if (e.key === "Backspace" && inputValue === "") { setActualValue?.((prevTags) => prevTags.slice(0, prevTags.length - 1)); } }; const removeTag = (index: number) => { setActualValue?.((prevTags) => prevTags.filter((_, i) => i !== index)); }; return (
{withLabel && ( )} {actualValue.map((item, idx) => { return ( ); })}
{icon && (
)}
{actualValue?.map((tag, index) => (
{tag} {!disabled && !readOnly && ( )}
))} {!disabled && !readOnly && ( { if (lowercase) { setInputValue(e.target.value.toLowerCase()); } else if (uppercase) { setInputValue(e.target.value.toUpperCase()); } else { setInputValue(e.target.value); } }} onKeyDown={handleKeyDown} placeholder={placeholder ?? t("shared.typeAndPressTo", { 0: separator, 1: t("shared.add").toLowerCase() })} id={name} autoComplete={autoComplete} // required={required} minLength={minLength} maxLength={maxLength} // defaultValue={value} onBlur={() => { if (inputValue.trim() !== "") { setActualValue?.((prevTags) => [...prevTags, inputValue.trim()]); setInputValue(""); } if (onBlur) { onBlur(); } }} disabled={disabled} readOnly={readOnly} pattern={pattern !== "" && pattern !== undefined ? pattern : undefined} autoFocus={autoFocus} className={clsx( "m-0.5 min-w-0 flex-1", icon && "rounded-md pl-10" // "focus:border-border focus:ring-ring block w-full min-w-0 flex-1 rounded-md border-border sm:text-sm", // className, // classNameBg, // disabled || readOnly ? "cursor-not-allowed bg-secondary/90" : "hover:bg-secondary focus:bg-secondary", // borderless && "border-transparent" )} /> )}
{button}
); }; export default forwardRef(InputMultiText);