import { IconButton, Paper, useMediaQuery, useTheme } from '@mui/material' import type { BasemapsUIProps } from './types' import { useEffect, useRef, useState, type JSX } from 'react' import { styles } from './styles' import deepmerge from 'deepmerge' import { DEFAULT_BASEMAPS_LABELS } from './const' import { Header } from './header' import { GroupWrapper } from './group-wrapper' import { Group } from './group' import { ResponsiveDrawer } from '../responsive-drawer/responsive-drawer' import { Tooltip } from '../tooltip/tooltip' const EMPTY_OPTIONS: BasemapsUIProps['options'] = [] /** * Provides an interactive basemap selector with responsive drawer, grouping support, and customizable positioning. * * @remarks * This is an uncontrolled component focused on UI presentation. Typically used with the `BasemapsControls` HOC from `@carto/ps-react-maps` for automatic state management. * * @example * ```tsx * * {({ basemap, setBasemap }) => ( * * )} * * ``` */ export function BasemapsUI({ options = EMPTY_OPTIONS, labels: _labels, position = 'bottom-right', selected = null, onChange, TooltipProps, }: BasemapsUIProps): JSX.Element { const [toggleRef, setToggleRef] = useState(null) const [isOpen, setIsOpen] = useState(false) const timeoutRef = useRef(null) const [timer, setTimer] = useState(null) const theme = useTheme() const isMobile = useMediaQuery(theme.breakpoints.down('sm')) const labels = deepmerge(DEFAULT_BASEMAPS_LABELS, _labels ?? {}) const optionSelected = options.find((option) => option.id === selected) const groups = Object.groupBy(options, (option) => option.group ?? 'default') const groupCount = Object.keys(groups).length const handleClose = () => { setToggleRef(null) setIsOpen(false) } useEffect(() => { if (timeoutRef.current) { clearTimeout(timeoutRef.current) } if (!timer) { return } timeoutRef.current = setTimeout(() => { handleClose() return }, timer) return () => { if (timeoutRef.current) { clearTimeout(timeoutRef.current) } } }, [timer]) const handleMouseOver = () => { setTimer(null) } const handleMouseLeave = () => { setTimer(400) } return ( { setToggleRef(e.currentTarget as HTMLButtonElement) setIsOpen(true) }} > {optionSelected?.label handleClose()} >
handleClose()} /> {Object.entries(groups).map(([group, values]) => ( { handleClose() onChange(e) }} /> ))} ) }