import type { ReactNode } from 'react' import { Box, Collapse, Typography } from '@mui/material' import { ExpandMore as ExpandMoreIcon } from '@mui/icons-material' import { SortableContext, verticalListSortingStrategy } from '@dnd-kit/sortable' import { SmartTooltip } from '../../../components/smart-tooltip/smart-tooltip' import { selectGroupVisibility, selectLayersByGroup, useLegendId, useLegendShallow, useLegendStore, } from '../../stores' import { accordionKeyDown } from '../a11y' import { LegendGroupContext } from '../contexts' import { partitionLegendChildren } from '../legend-actions/legend-actions' import { useLegendSortable } from '../legend-sortable/contexts' import { SortableEntity, type SortableEntityRenderProps, } from '../legend-sortable/sortable-entity' import { toSortableId } from '../legend-sortable/sortable-ids' import { styles } from './styles' export interface LegendGroupProps { groupId: string /** `` in the sticky header; member ``s in the body. */ children?: ReactNode } /** * Store-connected group wrapper. Draggable inside ``. * * @experimental This API is new and may change in a future release. */ export function LegendGroup({ groupId, children }: LegendGroupProps) { const id = useLegendId() const group = useLegendShallow(id, (s) => s.groups[groupId]) const setGroupCollapsed = useLegendShallow(id, (s) => s.setGroupCollapsed) const hidden = useLegendStore( id, (s) => selectGroupVisibility(s, groupId) === 'hidden', ) const sortable = useLegendSortable() // Member ids only — useShallow ignores opacity/visibility noise on siblings. const memberSortableIds = useLegendShallow(id, (s) => selectLayersByGroup(s, groupId).map((l) => toSortableId('layer', l.id)), ) if (!group) return null const { actions, body } = partitionLegendChildren(children) const toggle = () => setGroupCollapsed(groupId, !group.collapsed) const renderGroup = (sortableProps?: SortableEntityRenderProps) => ( {sortableProps?.handle} {/* Whole title area toggles collapse (accordion header); the actions box is a sibling outside the click target. */} {group.icon != null && ( {group.icon} )} {({ ref }) => ( {group.label} )} {/* Informative only (the row is the button); hidden on touch. */} {actions} {sortable ? ( {body} ) : ( body )} ) return sortable ? ( ) : ( renderGroup() ) }