import { useInstanceId } from '@wordpress/compose'; import { Fragment, useEffect, useRef, useState } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; import classnames from 'classnames'; import React from 'react'; import useClickOutside from '../../hooks/useClickOutside'; import { useDeviceType } from '../../hooks/useDeviceType'; import DeviceSelector from '../device-selector'; import Icon from '../icon'; import './editor.scss'; interface PropsType { value: any; // eslint-disable-next-line no-unused-vars onChange: (value: any) => void; label: string; options: { label: string; value: any; }[]; inline: boolean; placeholder?: string; responsive?: boolean; search?: boolean; } const Select: React.FC = (props) => { const [isOpen, setIsOpen] = useState(false); const [focus, setFocus] = useState(0); const [searchTerm, setSearchTerm] = useState(''); const { value, onChange, label, options, inline = true, placeholder = __('Select', 'learning-management-system'), responsive = false, search = false, } = props; const selectRef = useRef(); const inputRef = useRef(); const id = useInstanceId(Select); const devices = { desktop: 'Desktop', tablet: 'Tablet', mobile: 'Mobile', }; const [deviceType] = useDeviceType(); useEffect(() => { const ref = inputRef.current; if (isOpen && ref) { ref.focus(); } return () => { if (ref) { ref.blur(); } }; }, [isOpen]); useClickOutside(selectRef, () => setIsOpen(false)); const getValue = () => { if (responsive) { return value && value[deviceType] ? options.filter((option) => option.value === value[deviceType])[0] .label : placeholder; } // eslint-disable-next-line no-nested-ternary return value ? options.some((option) => value === option.value) ? options.filter((option) => option.value === value)[0].label : options[0].label : placeholder; }; const setSettings = (type: any, val: any) => { const data = { [type]: val }; onChange(Object.assign({}, value, data)); setIsOpen(false); setSearchTerm(''); }; const finalOptions = () => { const selected = options.filter((option) => getValue() === option.label) || []; if (selected.length > 0) { options.forEach((option, index) => { if (option.value === selected[0].value) { options.splice(index, 1); options.unshift(option); } }); } if (search) { const temp = options .filter( (option) => getValue().toLowerCase() !== option.label.toLowerCase(), ) .filter((option) => option.label.toLowerCase().includes(searchTerm)); if (selected.length > 0) { temp.unshift(selected[0]); } return temp; } return options; }; const onKeydownHandler = (e: any, device: string | undefined = undefined) => { switch (e.keyCode) { case 13: if (device) { setSettings(device, finalOptions()[focus].value); } else { onChange(finalOptions()[focus].value); } setIsOpen(false); break; case 38: if (focus === 0) { setFocus(finalOptions().length - 1); return; } setFocus(focus - 1); break; case 40: if (focus === finalOptions().length - 1) { setFocus(0); return; } setFocus(focus + 1); break; case 27: setIsOpen(false); } }; return (
{label && ( )} {responsive && }
{responsive ? ( Object.keys(devices).map( (deviceKey) => deviceKey === deviceType && (
    {isOpen && ( {search && (
  • onKeydownHandler(e, deviceKey)} onChange={(e) => setSearchTerm(e.target.value)} />
  • )} {finalOptions().map((option, idx) => (
  • setSettings(deviceKey, option.value)} role="option" onMouseOver={() => setFocus(idx)} onFocus={() => setFocus(idx)} aria-selected={idx === focus} tabIndex={-1} onKeyDown={() => null} > {option.label}
  • ))}
    )}
), ) ) : (
    {isOpen && ( {search && (
  • onKeydownHandler(e)} onChange={(e) => setSearchTerm(e.target.value)} />
  • )} {finalOptions().map((option, idx) => (
  • { onChange(option.value); setIsOpen(false); }} role="option" onKeyDown={() => null} onMouseOver={() => setFocus(idx)} onFocus={() => setFocus(idx)} aria-selected={idx === focus} tabIndex={-1} > {option.label}
  • ))}
    )}
)}
); }; export default Select;