@heycar-uikit/core
Version:
The React UI library from HeyCar
106 lines (102 loc) • 6.27 kB
JavaScript
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 };