phx-react
Version:
PHX REACT
130 lines • 5.98 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.DropDownItem = DropDownItem;
exports.default = DropDown;
const tslib_1 = require("tslib");
const React = tslib_1.__importStar(require("react"));
const react_1 = require("react");
const react_dom_1 = require("react-dom");
const DropDownContext = React.createContext(null);
const dropDownPadding = 4;
function DropDownItem({ children, className, onClick, title, }) {
const ref = (0, react_1.useRef)(null);
const dropDownContext = React.useContext(DropDownContext);
if (dropDownContext === null) {
throw new Error('DropDownItem must be used within a DropDown');
}
const { registerItem } = dropDownContext;
(0, react_1.useEffect)(() => {
if (ref && ref.current) {
registerItem(ref);
}
}, [ref, registerItem]);
return (React.createElement("button", { ref: ref, className: className, onClick: onClick, title: title, type: 'button' }, children));
}
function DropDownItems({ children, dropDownRef, onClose, }) {
const [items, setItems] = (0, react_1.useState)();
const [highlightedItem, setHighlightedItem] = (0, react_1.useState)();
const registerItem = (0, react_1.useCallback)((itemRef) => {
setItems((prev) => (prev ? [...prev, itemRef] : [itemRef]));
}, [setItems]);
const handleKeyDown = (event) => {
if (!items)
return;
const key = event.key;
if (['Escape', 'ArrowUp', 'ArrowDown', 'Tab'].includes(key)) {
event.preventDefault();
}
if (key === 'Escape' || key === 'Tab') {
onClose();
}
else if (key === 'ArrowUp') {
setHighlightedItem((prev) => {
if (!prev)
return items[0];
const index = items.indexOf(prev) - 1;
return items[index === -1 ? items.length - 1 : index];
});
}
else if (key === 'ArrowDown') {
setHighlightedItem((prev) => {
if (!prev)
return items[0];
return items[items.indexOf(prev) + 1];
});
}
};
const contextValue = (0, react_1.useMemo)(() => ({
registerItem,
}), [registerItem]);
(0, react_1.useEffect)(() => {
if (items && !highlightedItem) {
setHighlightedItem(items[0]);
}
if (highlightedItem && highlightedItem.current) {
highlightedItem.current.focus();
}
}, [items, highlightedItem]);
return (React.createElement(DropDownContext.Provider, { value: contextValue },
React.createElement("div", { ref: dropDownRef, className: 'dropdown', onKeyDown: handleKeyDown }, children)));
}
function DropDown({ buttonAriaLabel, buttonClassName, buttonIconClassName, buttonLabel, children, disabled = false, stopCloseOnClickSelf, }) {
console.log(stopCloseOnClickSelf, 'stopCloseOnClickSelf');
const dropDownRef = (0, react_1.useRef)(null);
const buttonRef = (0, react_1.useRef)(null);
const [showDropDown, setShowDropDown] = (0, react_1.useState)(false);
const handleClose = () => {
setShowDropDown(false);
if (buttonRef && buttonRef.current) {
buttonRef.current.focus();
}
};
(0, react_1.useEffect)(() => {
const button = buttonRef.current;
const dropDown = dropDownRef.current;
if (showDropDown && button !== null && dropDown !== null) {
const { left, top } = button.getBoundingClientRect();
dropDown.style.top = `${top + button.offsetHeight + dropDownPadding}px`;
dropDown.style.left = `${Math.min(left, window.innerWidth - dropDown.offsetWidth - 20)}px`;
}
}, [dropDownRef, buttonRef, showDropDown]);
(0, react_1.useEffect)(() => {
const handleButtonPositionUpdate = () => {
if (showDropDown) {
const button = buttonRef.current;
const dropDown = dropDownRef.current;
if (button !== null && dropDown !== null) {
const { top } = button.getBoundingClientRect();
const newPosition = top + button.offsetHeight + dropDownPadding;
if (newPosition !== dropDown.getBoundingClientRect().top) {
dropDown.style.top = `${newPosition}px`;
}
}
}
};
document.addEventListener('scroll', handleButtonPositionUpdate);
return () => {
document.removeEventListener('scroll', handleButtonPositionUpdate);
};
}, [buttonRef, dropDownRef, showDropDown]);
(0, react_1.useEffect)(() => {
const handleClickOutside = (event) => {
var _a;
if (dropDownRef.current && !((_a = dropDownRef.current) === null || _a === void 0 ? void 0 : _a.contains(event.target))) {
setShowDropDown(false);
}
};
document.addEventListener('mousedown', handleClickOutside);
return () => {
document.removeEventListener('mousedown', handleClickOutside);
};
}, [dropDownRef]);
return (React.createElement("div", { className: 'z-10' },
React.createElement("button", { ref: buttonRef, "aria-label": buttonAriaLabel || buttonLabel, className: buttonClassName, disabled: disabled, onClick: () => setShowDropDown(!showDropDown), type: 'button' },
buttonIconClassName && React.createElement("span", { className: buttonIconClassName }),
buttonLabel && React.createElement("span", { className: 'text dropdown-button-text' }, buttonLabel),
React.createElement("i", { className: 'chevron-down' })),
showDropDown &&
(0, react_dom_1.createPortal)(React.createElement(DropDownItems, { dropDownRef: dropDownRef, onClose: handleClose }, children), document.body)));
}
//# sourceMappingURL=DropDown.js.map