'use client'; import classnames from 'classnames'; import React, { useEffect, useId, useRef, useState } from 'react'; import MdInputChip from '../chips/MdInputChip'; import MdHelpButton from '../help/MdHelpButton'; import MdHelpText from '../help/MdHelpText'; import useDropdown from '../hooks/useDropdown'; import MdIconKeyboardArrowDown from '../icons-material/MdIconKeyboardArrowDown'; import MdClickOutsideWrapper from '../utils/MdClickOutsideWrapper'; import MdCheckbox from './MdCheckbox'; interface Labels { helpTextFor?: string; } export interface MdMultiAutocompleteOption { text: string; value: string; } export interface MdMultiAutocompleteProps extends React.InputHTMLAttributes { label?: string | null; labels?: Labels; options: MdMultiAutocompleteOption[]; defaultOptions?: MdMultiAutocompleteOption[]; mode?: 'large' | 'medium' | 'small'; helpText?: string; error?: boolean; selectedOptions?: MdMultiAutocompleteOption[]; errorText?: string; showChips?: boolean; closeOnSelect?: boolean; prefixIcon?: React.ReactNode; noResultsText?: string; dropdownHeight?: number; numberOfElementsShown?: number; onSelectOption(_e: MdMultiAutocompleteOption): void; } export const MdMultiAutocomplete = React.forwardRef( ( { label, labels = {}, options, defaultOptions, id, showChips, placeholder = 'Søk', disabled = false, mode = 'large', helpText, selectedOptions = [], error = false, errorText, prefixIcon = null, closeOnSelect, dropdownHeight, numberOfElementsShown = null, className, noResultsText = 'Ingen resultater funnet', onSelectOption, ...otherProps }, ref, ) => { // eslint-disable-next-line no-console console.warn( 'MdAutocomplete is deprecated and will be removed in a future release. Use MdCombobox with multiple options instead.', ); const [open, setOpen] = useState(false); const [helpOpen, setHelpOpen] = useState(false); const [autocompleteValue, setAutocompleteValue] = useState(''); const [results, setResults] = useState([]); const dropdownRef = useRef(null); useDropdown(dropdownRef, open, setOpen, 'autocomplete'); const uuid = useId(); const multiAutocompleteId = id && id !== '' ? id : uuid; let hasMultipleSelected = false; const defaultLabels: Required = { helpTextFor: 'Hjelpetekst for', }; const mergedLabels: Required = { ...defaultLabels, ...labels }; const classNames = classnames('md-multiautocomplete', { 'md-multiautocomplete--open': !!open, 'md-multiautocomplete--error': !!error, 'md-multiautocomplete--disabled': !!disabled, 'md-multiautocomplete--medium': mode === 'medium', 'md-multiautocomplete--small': mode === 'small', }); const inputClassNames = classnames('md-multiautocomplete__input', { 'md-multiautocomplete__input--open': !!open, 'md-multiautocomplete__input--error': !!error, 'md-multiautocomplete__input--has-prefix': prefixIcon !== null && prefixIcon !== '', 'md-multiautocomplete--small': mode === 'small', className, }); useEffect(() => { // eslint-disable-next-line no-console console.warn( 'Notice: MdAutocomplete and MdMultiAutocomplete are deprecated and will be removed in a future version. use MdCombobox instead.', ); }, []); const optionClass = (option: MdMultiAutocompleteOption) => { return classnames('md-multiautocomplete__dropdown-item', { 'md-multiautocomplete__dropdown-item--selected': optionIsChecked(option), }); }; const optionIsChecked = (option: MdMultiAutocompleteOption) => { const isChecked = selectedOptions && selectedOptions.length && selectedOptions.find(item => { return item.value === option.value; }); return isChecked && isChecked !== undefined; }; let displayValue = placeholder; const selectedOptionsFull: MdMultiAutocompleteOption[] = []; if (!open && selectedOptions && selectedOptions.length > 0) { const findFirstOption = options.find(option => { return option.value === selectedOptions[0].value; }); if (findFirstOption) { displayValue = findFirstOption.text; } if (selectedOptions.length > 1) { hasMultipleSelected = true; } if (open) { displayValue = ''; } selectedOptions.forEach(item => { const opt = options.find(option => { return option.value === item.value; }); if (opt) { selectedOptionsFull.push(opt); } }); } const handleOptionClick = (option: MdMultiAutocompleteOption) => { onSelectOption(option); if (closeOnSelect) { setOpen(false); setAutocompleteValue(''); } }; const handleChipClick = (option: MdMultiAutocompleteOption) => { handleOptionClick(option); }; const displayedOptions = autocompleteValue ? results : defaultOptions && defaultOptions.length ? defaultOptions : options ? options : []; const displayedOptionsSliced = numberOfElementsShown == null ? displayedOptions : displayedOptions.slice(0, numberOfElementsShown); let ariaDescribedBy = helpText && helpText !== '' ? `md-multiautocomplete_help-text_${multiAutocompleteId}` : undefined; ariaDescribedBy = error && errorText && errorText !== '' ? `md-multiautocomplete_error_${multiAutocompleteId}` : ariaDescribedBy; return (
{label && label !== '' && (
{helpText && helpText !== '' && (
{ return setHelpOpen(!helpOpen); }} expanded={helpOpen} />
)}
)} {helpText && helpText !== '' && (
{helpText}
)} { return setOpen(false); }} className={`md-multiautocomplete__container ${mode === 'small' ? 'md-multiautocomplete--small' : ''}`} > {prefixIcon && ( )} { setAutocompleteValue(e.target.value); if (e.target.value && e.target.value !== '') { const results = options?.filter(o => { return o.text?.toLowerCase().includes(e.target.value.toLowerCase() || ''); }); setResults(results || []); } else { setResults([]); } }} onFocus={() => { if (!disabled) { setOpen(true); } }} type="text" placeholder={placeholder} disabled={!!disabled} ref={ref} {...otherProps} /> {hasMultipleSelected && !open && (
+{selectedOptions.length - 1}
)} {options && options.length > 0 && (
{displayedOptionsSliced.map(option => { return (
{ if (e.key === 'Enter') { return handleOptionClick(option); } }} onChange={() => { handleOptionClick(option); }} />
); })} {displayedOptionsSliced.length === 0 && (
{noResultsText}
)}
)}
{error && errorText && errorText !== '' && (
{errorText}
)} {!open && showChips && selectedOptionsFull.length > 0 && (
{selectedOptionsFull.map(chip => { return ( { return handleChipClick(chip); }} /> ); })}
)}
); }, ); MdMultiAutocomplete.displayName = 'MdMultiAutocomplete'; export default MdMultiAutocomplete;