import React from 'react' import { useGridContext, useGridSelector } from '../context/grid-context' import type { MenuCloseReason } from '@planview/pv-uikit' import { ListGroup, ListItem, Menu } from '@planview/pv-uikit' import { defineMessages, useIntl } from 'react-intl' import { buildHeaderHierarchy } from '../state/reducer/column-utils' import type { ColumnState } from '../state' const messages = defineMessages({ labelColumnMenu: { id: 'pvds.grid.rows.columnMenuLabel', defaultMessage: 'Show or hide columns', description: 'Screen reader label for the column context menu to control the visibility of columns', }, }) const EMPTY_ARRAY: never[] = [] const getColumnLabel = (column: ColumnState) => column.data.accessibleLabel ?? column.data.label const isColumnGroup = ( column: ColumnState | { label: string; children: ColumnState[] } ): column is { label: string; children: ColumnState[] } => typeof column === 'object' && 'label' in column export const GridColumnMenu = () => { const grid = useGridContext() const { formatMessage } = useIntl() const { visible, coordinates } = useGridSelector( grid.selectors.selectColumnMenuDetails ) const handleClose = React.useCallback( (reason: MenuCloseReason) => { if (reason !== 'confirm' && reason !== 'confirm_with_focus') { grid.api.column.hideMenu() } if (reason === 'key_escape' || reason === 'key_tab') { grid.events.emit('onReturnFocus') } }, [grid.api.column, grid.events] ) const { selectColumnIdsWithoutInternal, selectColumnEntities, selectHiddenIds, } = grid.selectors const hiddenIds = useGridSelector(selectHiddenIds) const columnsToRender = useGridSelector((state) => { if (!visible) { return EMPTY_ARRAY } const sortedIds = selectColumnIdsWithoutInternal(state) const entities = selectColumnEntities(state) const { groups } = buildHeaderHierarchy(entities, []) return sortedIds .map((id) => entities[id]) .filter( (column) => column.id !== '__actions' && getColumnLabel(column).trim().length > 0 && column.data.hideable !== false ) .reduce( (acc, column) => { const parent = groups.find((group) => group.childIds.includes(column.id) ) if (parent) { const parentEntity = entities[parent.id] const foundGroup = acc.find( (col) => col.id === parent.id ) if (foundGroup && isColumnGroup(foundGroup)) { foundGroup.children.push(column) } else { const group = { label: parentEntity.data.label, id: parentEntity.id, children: [column], } acc.push(group) } } else { acc.push(column) } return acc }, [] as ( | ColumnState | { label: string; children: ColumnState[]; id: string } )[] ) }) if (!visible || !coordinates) { return null } const { top, left } = coordinates return (
) }