@dr.pogodin/react-utils
Version:
Collection of generic ReactJS components and utils
82 lines (79 loc) • 2.95 kB
JavaScript
// Implements dropdown based on the native HTML <select> element.
import themed from '@dr.pogodin/react-themes';
import { optionValueName } from "../common";
import defaultTheme from "./theme.scss";
/**
* Implements a themeable dropdown list. Internally it is rendered with help of
* the standard HTML `<select>` element, thus the styling support is somewhat
* limited.
* @param [props] Component properties.
* @param [props.filter] Options filter function. If provided, only
* those elements of `options` list will be used by the dropdown, for which this
* filter returns `true`.
* @param [props.label] Dropdown label.
* @param [props.onChange] Selection event handler.
* @param [props.options=[]] Array of dropdown
* options. For string elements the option value and name will be the same.
* It is allowed to mix DropdownOption and string elements in the same option
* list.
* @param [props.theme] _Ad hoc_ theme.
* @param [props.value] Currently selected value.
* @param [props....]
* [Other theming properties](https://www.npmjs.com/package/@dr.pogodin/react-themes#themed-component-properties)
*/
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
const Dropdown = ({
filter,
label,
onChange,
options,
testId,
theme,
value
}) => {
let isValidValue = false;
const optionElements = [];
for (const option of options) {
if (!filter || filter(option)) {
const [iValue, iName] = optionValueName(option);
isValidValue ||= iValue === value;
optionElements.push(/*#__PURE__*/_jsx("option", {
className: theme.option,
value: iValue,
children: iName
}, iValue));
}
}
// NOTE: This element represents the current `value` when it does not match
// any valid option. In Chrome, and some other browsers, we are able to hide
// it from the opened dropdown; in others, e.g. Safari, the best we can do is
// to show it as disabled.
const hiddenOption = isValidValue ? null : /*#__PURE__*/_jsx("option", {
className: theme.hiddenOption,
disabled: true,
value: value,
children: value
}, "__reactUtilsHiddenOption");
let selectClassName = theme.select;
if (!isValidValue) selectClassName += ` ${theme.invalid}`;
return /*#__PURE__*/_jsxs("div", {
className: theme.container,
children: [label === undefined ? null : /*#__PURE__*/_jsx("div", {
className: theme.label,
children: label
}), /*#__PURE__*/_jsxs("div", {
className: theme.dropdown,
children: [/*#__PURE__*/_jsxs("select", {
className: selectClassName,
"data-testid": process.env.NODE_ENV === 'production' ? undefined : testId,
onChange: onChange,
value: value,
children: [hiddenOption, optionElements]
}), /*#__PURE__*/_jsx("div", {
className: theme.arrow
})]
})]
});
};
export default themed(Dropdown, 'Dropdown', defaultTheme);
//# sourceMappingURL=index.js.map