UNPKG

@heycar-uikit/core

Version:
106 lines (102 loc) 6.27 kB
import { _ as __rest, a as __assign, D as DropdownOption } from './DropdownOption-144153e9.js'; import React, { useState, useRef, useCallback, useEffect } from 'react'; import cn from 'classnames'; import { ChevronTop, ChevronDown } from '../../icons'; import Input from '../../input'; var styles = {"container":"dropdown__container_5a833","disabled":"dropdown__disabled_5a833","value":"dropdown__value_5a833","options":"dropdown__options_5a833","show":"dropdown__show_5a833","option":"dropdown__option_5a833","selected":"dropdown__selected_5a833","highlighted":"dropdown__highlighted_5a833","fullWidth":"dropdown__fullWidth_5a833"}; function Dropdown(_a) { var _b = _a.Component, Component = _b === void 0 ? 'div' : _b, value = _a.value, onChange = _a.onChange, options = _a.options, disabled = _a.disabled, dataTestId = _a.dataTestId, onBlur = _a.onBlur, onClick = _a.onClick, label = _a.label, hint = _a.hint, inputRef = _a.inputRef, fullWidth = _a.fullWidth, placeholder = _a.placeholder, error = _a.error, onKeyDown = _a.onKeyDown, restProps = __rest(_a, ["Component", "value", "onChange", "options", "disabled", "dataTestId", "onBlur", "onClick", "label", "hint", "inputRef", "fullWidth", "placeholder", "error", "onKeyDown"]); var _c = useState(value), stateValue = _c[0], setStateValue = _c[1]; var _d = useState(false), isOpen = _d[0], setIsOpen = _d[1]; var _e = useState(0), highlightedIndex = _e[0], setHighlightedIndex = _e[1]; var containerRef = useRef(null); var isValueIncludedInOptions = useCallback(function (option) { return !!options.find(function (o) { return Object.entries(o).every(function (_a) { var key = _a[0], val = _a[1]; return val === option[key]; }); }); }, [options]); useEffect(function () { if (options.length === 0) setStateValue(undefined); if (value && !isValueIncludedInOptions(value)) setStateValue(undefined); if (stateValue && !isValueIncludedInOptions(stateValue)) setStateValue(undefined); if (!stateValue && value && isValueIncludedInOptions(value)) setStateValue(value); }, [value, options, stateValue, isValueIncludedInOptions]); var selectOption = useCallback(function (option) { if (onChange) { if (option !== stateValue) onChange(option); } setStateValue(option); }, [onChange, stateValue]); var onClickHandler = useCallback(function () { onClick === null || onClick === void 0 ? void 0 : onClick(); if (!disabled) setIsOpen(function (nextState) { return !nextState; }); }, [onClick, disabled, setIsOpen]); useEffect(function () { if (isOpen) setHighlightedIndex(0); }, [isOpen]); useEffect(function () { var _a; var handler = function (e) { if (e.target != containerRef.current) return; switch (e.code) { case 'Enter': case 'Space': setIsOpen(function (prev) { return !prev; }); if (isOpen) selectOption(options[highlightedIndex]); break; case 'ArrowUp': case 'ArrowDown': { if (!isOpen) { setIsOpen(true); break; } var newValue = highlightedIndex + (e.code === 'ArrowDown' ? 1 : -1); if (newValue >= 0 && newValue < options.length) { setHighlightedIndex(newValue); } break; } case 'Escape': setIsOpen(false); break; } }; (_a = containerRef.current) === null || _a === void 0 ? void 0 : _a.addEventListener('keydown', handler); return function () { var _a; // eslint-disable-next-line react-hooks/exhaustive-deps (_a = containerRef.current) === null || _a === void 0 ? void 0 : _a.removeEventListener('keydown', handler); }; // eslint-disable-next-line react-hooks/exhaustive-deps }, [highlightedIndex, options, selectOption]); var isOptionSelection = function (option) { return (option === null || option === void 0 ? void 0 : option.value) === (stateValue === null || stateValue === void 0 ? void 0 : stateValue.value); }; var onBlurHandler = useCallback(function () { onBlur === null || onBlur === void 0 ? void 0 : onBlur(); setIsOpen(false); }, [onBlur, setIsOpen]); var classNames = cn(styles.container, disabled && styles.disabled, fullWidth && styles.fullWidth); var valueClassNames = cn(disabled && 'disabled', styles.value); return (React.createElement(Component, { className: classNames, onBlur: onBlurHandler, onClick: onClickHandler, ref: containerRef, tabIndex: 0 }, React.createElement(Input, __assign({ "aria-disabled": true, className: valueClassNames, disabled: disabled, error: error, fullWidth: true, hint: hint, label: label, onChange: function () { setStateValue(options[highlightedIndex]); }, onKeyDown: onKeyDown, placeholder: placeholder, ref: inputRef, rightIcon: isOpen ? React.createElement(ChevronTop, null) : React.createElement(ChevronDown, null), value: stateValue === null || stateValue === void 0 ? void 0 : stateValue.label }, restProps)), React.createElement("ul", { className: styles.options + " " + (isOpen ? styles.show : ''), "data-test-id": dataTestId }, options.map(function (option, index) { return (React.createElement("li", { className: styles.option + " " + (isOptionSelection(option) ? styles.selected : '') + " " + (index === highlightedIndex ? styles.highlighted : ''), key: option.value, onMouseDown: function (e) { selectOption(option); e.stopPropagation(); setIsOpen(false); }, onMouseEnter: function () { return setHighlightedIndex(index); } }, React.createElement(DropdownOption, __assign({}, option)))); })))); } export { Dropdown as default };