import { HTMLAttributes, ReactNode, RefObject, useEffect, useRef } from "react"; import { selectedOnChange } from "./selectorItem"; import { createPortal } from "react-dom"; export type selectionType = string | number | boolean; interface PickerPropsChildrenStyle extends HTMLAttributes { selected: selectionType; selectionOnChange: selectedOnChange; displayContent: string; children: ReactNode; } interface PickerPropsParamStyle extends HTMLAttributes { selected: selectionType; selectionOnChange: selectedOnChange; displayContent: string; selectionItems: PickedItem; } interface PickedItem { [key: string]: selectionType; } export default function Picker(props: PickerPropsChildrenStyle | PickerPropsParamStyle) { const itemListRef: RefObject = useRef(null); const buttonRef: RefObject = useRef(null); const updatePosition = () => { if (itemListRef.current == null || buttonRef.current == null) { return; } const buttonRect = buttonRef.current.getBoundingClientRect(); const listWidth = itemListRef.current.getBoundingClientRect().width; // Align to center itemListRef.current.style.left = buttonRect.x + buttonRect.width / 2 - listWidth / 2 + "px"; itemListRef.current.style.top = buttonRect.y + buttonRect.height + 16 + "px"; }; useEffect(() => { updatePosition(); const handleResize = () => { updatePosition(); }; window.addEventListener('resize', handleResize); // Cleanup event listener on component unmount return () => { window.removeEventListener('resize', handleResize); }; }, [itemListRef, buttonRef]); if ("selectionItems" in props) { const { selectionItems, displayContent, selectionOnChange, ...rest } = props; return ( {displayContent} {createPortal( {Object.keys(selectionItems).map((key: string, index) => { return {selectionItems[key]}; })} , document.body )} ); } else { return ( {props.displayContent} {createPortal({props.children}, document.body)} ); } }