'use client'; import classnames from 'classnames'; import React, { 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 MdIconChevronForward from '../icons-material/MdIconChevronForward'; import MdClickOutsideWrapper from '../utils/MdClickOutsideWrapper'; import MdCheckbox from './MdCheckbox'; interface Labels { helpTextFor?: string; } export interface MdMultiSelectOption { text: string; value: string; } export interface MdMultiSelectProps { label?: string | null; labels?: Labels; options?: MdMultiSelectOption[]; selectedOptions?: MdMultiSelectOption[]; placeholder?: string; disabled?: boolean; mode?: 'large' | 'medium' | 'small'; helpText?: string; error?: boolean; errorText?: string; showChips?: boolean; closeOnSelect?: boolean; id?: string; dropdownHeight?: number; onSelectOption?(_option: MdMultiSelectOption): void; } export const MdMultiSelect = React.forwardRef( ( { label, labels = {}, options = [], selectedOptions = [], placeholder = 'Vennligst velg', disabled = false, mode = 'large', helpText, error, errorText, showChips = false, closeOnSelect = false, id, onSelectOption, dropdownHeight, ...otherProps }, ref, ) => { // eslint-disable-next-line no-console console.warn( 'MdMultiSelect is deprecated and will be removed in a future release. Use MdSelect multiple options instead.', ); const uuid = useId(); const multiSelectId = id || uuid; const [open, setOpen] = useState(false); const [helpOpen, setHelpOpen] = useState(false); const dropdownRef = useRef(null); useDropdown(dropdownRef, open, setOpen); const defaultLabels: Required = { helpTextFor: 'Hjelpetekst for', }; const mergedLabels: Required = { ...defaultLabels, ...labels }; let hasMultipleSelected = false; const classNames = classnames('md-select', { 'md-multiselect--open': !!open, 'md-multiselect--disabled': !!disabled, 'md-multiselect--error': !!error, 'md-multiselect--medium': mode === 'medium', 'md-multiselect--small': mode === 'small', }); const buttonClassNames = classnames('md-multiselect__button', { 'md-multiselect__button--open': !!open, 'md-multiselect--small': mode === 'small', }); const dropDownClassNames = classnames('md-multiselect__dropdown', { 'md-multiselect__dropdown--open': !!open, }); const optionClass = (option: MdMultiSelectOption) => { return classnames('md-multiselect__dropdown-item', { 'md-multiselect__dropdown-item--selected': optionIsChecked(option), }); }; const optionIsChecked = (option: MdMultiSelectOption) => { const isChecked = selectedOptions && selectedOptions.length && selectedOptions.find(item => { return item.value === option.value; }); return isChecked && isChecked !== undefined; }; let displayValue = placeholder; const selectedOptionsFull: MdMultiSelectOption[] = []; 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; } selectedOptions.forEach(item => { const opt = options.find(option => { return option.value === item.value; }); if (opt) { selectedOptionsFull.push(opt); } }); } const handleOptionClick = (option: MdMultiSelectOption) => { if (onSelectOption) { onSelectOption(option); } if (closeOnSelect) { setOpen(false); } }; let ariaDescribedBy = helpText && helpText !== '' ? `md-multiselect_help-text_${multiSelectId}` : undefined; ariaDescribedBy = error && errorText && errorText !== '' ? `md-multiselect_error_${multiSelectId}` : ariaDescribedBy; const showLabel = (label && label !== '') || (helpText && helpText !== ''); return (
{showLabel && (
{label && label !== '' &&
{label}
} {helpText && helpText !== '' && (
{ return setHelpOpen(!helpOpen); }} expanded={helpOpen} />
)}
{helpText && helpText !== '' && (
{helpText}
)}
)} { return setOpen(false); }} className="md-multiselect__dropdown-wrapper" > {options && options.length > 0 && (
{options.map(option => { return (
) => { if (e.key === 'Enter') { return handleOptionClick(option); } }} onChange={() => { return handleOptionClick(option); }} />
); })}
)}
{error && errorText && errorText !== '' && (
{errorText}
)} {!open && showChips && selectedOptionsFull.length > 0 && (
{selectedOptionsFull.map(chip => { return ( { return handleOptionClick(chip); }} /> ); })}
)}
); }, ); MdMultiSelect.displayName = 'MdMultiSelect'; export default MdMultiSelect;