import type { MouseEvent } from 'react'
import { CircularProgress, MenuItem } from '@mui/material'
import {
getLegendStore,
selectAllGroupsCollapsed,
selectGroupVisibility,
selectHasGroups,
selectLayersByGroup,
selectOrderedGroups,
useLegendId,
useLegendStore,
} from '../../stores'
import { useLegendConfig } from '../../provider'
import { useLegendGroupId, useLegendMenu } from '../contexts'
import { runAsyncMenuAction } from '../run-async-menu-action'
/**
* Show only this group (hide all other layers).
*
* @experimental This API is new and may change in a future release.
*/
export function LegendShowOnlyGroup() {
const id = useLegendId()
const groupId = useLegendGroupId()
const { labels } = useLegendConfig()
if (groupId === null) return null
const showOnly = () => {
const state = getLegendStore(id).getState()
for (const group of selectOrderedGroups(state)) {
state.setGroupVisibility(group.id, group.id === groupId)
}
// Exclusive: the ungrouped layers hide too.
for (const layer of selectLayersByGroup(state, undefined)) {
state.setVisibility(layer.id, false)
}
}
return
}
/**
* Show every layer (panel-level `Legend.PanelMenu` only).
*
* @experimental This API is new and may change in a future release.
*/
export function LegendShowAllGroups() {
const id = useLegendId()
const hasGroups = useLegendStore(id, selectHasGroups)
const { labels } = useLegendConfig()
if (!hasGroups) return null
const showAll = () => {
const state = getLegendStore(id).getState()
for (const group of selectOrderedGroups(state)) {
state.setGroupVisibility(group.id, true)
}
for (const layer of selectLayersByGroup(state, undefined)) {
state.setVisibility(layer.id, true)
}
}
return
}
/**
* Collapse / expand all groups (panel-level `Legend.PanelMenu` only).
*
* @experimental This API is new and may change in a future release.
*/
export function LegendCollapseAllGroups() {
const id = useLegendId()
const hasGroups = useLegendStore(id, selectHasGroups)
const allCollapsed = useLegendStore(id, selectAllGroupsCollapsed)
const { labels } = useLegendConfig()
if (!hasGroups) return null
const toggleAll = () => {
const state = getLegendStore(id).getState()
const collapsed = selectAllGroupsCollapsed(state)
for (const group of selectOrderedGroups(state)) {
state.setGroupCollapsed(group.id, !collapsed)
}
}
return (
)
}
export interface LegendZoomToGroupProps {
/** Fit viewport to the group; may return a Promise for async menu feedback. */
onZoomTo: (groupId: string) => void | Promise
}
/**
* Zoom-to-group menu item for `Legend.GroupMenu`. Self-hides when all members are hidden.
*
* @experimental This API is new and may change in a future release.
*/
export function LegendZoomToGroup({ onZoomTo }: LegendZoomToGroupProps) {
const id = useLegendId()
const groupId = useLegendGroupId()
const menu = useLegendMenu()
const hidden = useLegendStore(
id,
(s) => groupId !== null && selectGroupVisibility(s, groupId) === 'hidden',
)
const { labels } = useLegendConfig()
if (groupId === null || hidden) return null
const busy = menu?.busy ?? false
const handleClick = (e: MouseEvent) => {
e.stopPropagation()
if (!menu) return
void runAsyncMenuAction(menu, () => onZoomTo(groupId))
}
return (
)
}