UNPKG

phx-react

Version:

PHX REACT

130 lines 5.98 kB
"use strict"; 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