terriajs
Version:
Geospatial data visualization platform.
59 lines • 3.31 kB
JavaScript
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
import { useState, useRef, useEffect, useCallback } from "react";
import classNames from "classnames";
import Styles from "./dropdown.scss";
import { OutsideClickHandler } from "./OutsideClickHandler";
const Dropdown = ({ theme = {}, options = [], selected, selectOption, textProperty = "name", disabled = false, children }) => {
const [isOpen, setIsOpen] = useState(false);
const buttonRef = useRef(null);
const scrollListeners = useRef([]);
const hideList = useCallback(() => {
setIsOpen(false);
}, []);
const showList = useCallback(() => {
setIsOpen(true);
}, []);
const select = useCallback((option, index) => {
selectOption?.(option, index);
hideList();
}, [selectOption, hideList]);
const addScrollListeners = useCallback((element, listeningToSoFar) => {
if (!element)
return listeningToSoFar;
if (element.scrollHeight > element.clientHeight) {
element.addEventListener("scroll", hideList);
listeningToSoFar.push(element);
}
if (element !== document.body) {
return addScrollListeners(element.parentElement, listeningToSoFar);
}
return listeningToSoFar;
}, [hideList]);
const clearListeners = useCallback(() => {
scrollListeners.current.forEach((element) => element?.removeEventListener("scroll", hideList));
scrollListeners.current = [];
}, [hideList]);
useEffect(() => {
if (isOpen) {
scrollListeners.current = addScrollListeners(buttonRef.current, []);
}
else {
clearListeners();
}
return clearListeners;
}, [addScrollListeners, clearListeners, hideList, isOpen]);
const selectedText = selected?.[textProperty];
return (_jsx("div", { className: classNames(Styles.dropdown, theme.dropdown), children: _jsxs(OutsideClickHandler, { disabled: !isOpen, onOutsideClick: hideList, children: [_jsxs("button", { type: "button", onClick: isOpen ? hideList : showList, className: classNames(theme.button, Styles.btnDropdown), ref: buttonRef, disabled: disabled, children: [selectedText || children, theme.icon] }), _jsx("ul", { className: classNames(Styles.list, theme.list, {
[Styles.isOpen]: isOpen,
[theme.isOpen ?? ""]: isOpen
}), children: options.map((option, i) => {
const optionText = option[textProperty];
return (_jsx("li", { children: option.href ? (_jsx("a", { href: option.href, target: "_blank", rel: "noopener noreferrer", className: classNames(Styles.btnOption, theme.btnOption || "", {
[Styles.isSelected]: option === selected
}), download: option.download, children: optionText })) : (_jsx("button", { type: "button", className: classNames(Styles.btnOption, theme.btnOption || "", {
[Styles.isSelected]: option === selected
}), onClick: () => select(option, i), children: optionText })) }, optionText));
}) })] }) }));
};
export default Dropdown;
//# sourceMappingURL=Dropdown.js.map