import React, { cloneElement, isValidElement, useEffect, useId, useState, type ReactNode } from 'react'; import { FloatingFocusManager, FloatingOverlay, FloatingPortal, useClick, useDismiss, useFloating, useInteractions, useRole, } from '@floating-ui/react'; interface Props { render: (data: { close: () => void; labelId: string; descriptionId: string }) => ReactNode; children?: ReactNode; } function useMediaQuery({ query }: { query: string }) { const [matches, setMatches] = useState(false); useEffect(() => { const mediaQuery = window.matchMedia(query); const listener = () => setMatches(mediaQuery.matches); listener(); mediaQuery.addEventListener('change', listener); return () => mediaQuery.removeEventListener('change', listener); }, [query]); return matches; } export function Drawer({ children, render }: Props) { const [open, setOpen] = useState(false); const isLargeScreen = useMediaQuery({ query: '(min-width: 1400px)' }); const { refs, context } = useFloating({ open, onOpenChange: setOpen }); const id = useId(); const labelId = `${id}-label`; const descriptionId = `${id}-description`; const modal = !isLargeScreen; const { getReferenceProps, getFloatingProps } = useInteractions([ useClick(context), useRole(context), useDismiss(context, { outsidePress: modal, outsidePressEvent: 'mousedown', }), ]); const content = (
{render({ labelId, descriptionId, close: () => setOpen(false), })}
); return ( <> {isValidElement(children) && cloneElement(children, getReferenceProps({ ref: refs.setReference }))} {/* eslint-disable-next-line react/jsx-no-undef */} {open && (modal ? ( {content} ) : ( content ))} ); }