UNPKG

@mui/x-data-grid-premium

Version:

The Premium plan edition of the MUI X Data Grid Components.

374 lines (371 loc) 16.2 kB
'use client'; import _extends from "@babel/runtime/helpers/esm/extends"; import * as React from 'react'; import { styled } from '@mui/material/styles'; import { gridPivotActiveSelector, vars } from '@mui/x-data-grid-pro/internals'; import { getDataGridUtilityClass, GridShadowScrollArea, useGridSelector } from '@mui/x-data-grid-pro'; import composeClasses from '@mui/utils/composeClasses'; import { useGridRootProps } from "../../../hooks/utils/useGridRootProps.mjs"; import { Collapsible, CollapsiblePanel, CollapsibleTrigger } from "../../collapsible/index.mjs"; import { ResizablePanel, ResizablePanelHandle } from "../../resizablePanel/index.mjs"; import { GridChartsPanelDataField } from "./GridChartsPanelDataField.mjs"; import { gridChartableColumnsSelector, gridChartsDimensionsSelector, gridChartsIntegrationActiveChartIdSelector, gridChartsValuesSelector } from "../../../hooks/features/chartsIntegration/gridChartsIntegrationSelectors.mjs"; import { useGridPrivateApiContext } from "../../../hooks/utils/useGridPrivateApiContext.mjs"; import { useGridChartsIntegrationContext } from "../../../hooks/utils/useGridChartIntegration.mjs"; import { getBlockedSections } from "../../../hooks/features/chartsIntegration/utils.mjs"; import { gridRowGroupingSanitizedModelSelector } from "../../../hooks/features/rowGrouping/gridRowGroupingSelector.mjs"; import { gridPivotModelSelector } from "../../../hooks/features/pivoting/gridPivotingSelectors.mjs"; import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; const useUtilityClasses = ownerState => { const { classes } = ownerState; const slots = { root: ['chartsPanelDataBody'], availableFields: ['chartsPanelDataAvailableFields'], sections: ['chartsPanelDataSections'], scrollArea: ['chartsPanelDataScrollArea'], section: ['chartsPanelDataSection'], sectionTitle: ['chartsPanelDataSectionTitle'], fieldList: ['chartsPanelDataFieldList'], placeholder: ['chartsPanelDataPlaceholder'] }; return composeClasses(slots, getDataGridUtilityClass, classes); }; const GridChartsPanelDataBodyRoot = styled('div', { name: 'MuiDataGrid', slot: 'ChartsPanelDataBody' })({ flex: 1, display: 'flex', flexDirection: 'column', overflow: 'hidden' }); const GridChartsPanelDataAvailableFields = styled(GridShadowScrollArea, { name: 'MuiDataGrid', slot: 'ChartsPanelDataAvailableFields' })({ flex: 1, minHeight: 84, transition: vars.transition(['background-color'], { duration: vars.transitions.duration.short, easing: vars.transitions.easing.easeInOut }), '&[data-drag-over="true"]': { backgroundColor: vars.colors.interactive.hover } }); const GridChartsPanelDataSections = styled(ResizablePanel, { name: 'MuiDataGrid', slot: 'ChartsPanelDataSections' })({ position: 'relative', minHeight: 158, overflow: 'hidden', display: 'flex', flexDirection: 'column' }); const GridChartsPanelDataScrollArea = styled(GridShadowScrollArea, { name: 'MuiDataGrid', slot: 'ChartsPanelDataScrollArea' })({ height: '100%' }); const GridChartsPanelDataSection = styled(Collapsible, { name: 'MuiDataGrid', slot: 'ChartsPanelDataSection', shouldForwardProp: prop => prop !== 'disabled' })(({ disabled }) => ({ opacity: disabled ? 0.5 : 1, margin: vars.spacing(0.5, 1), transition: vars.transition(['border-color', 'background-color'], { duration: vars.transitions.duration.short, easing: vars.transitions.easing.easeInOut }), '&[data-drag-over="true"]': { backgroundColor: vars.colors.interactive.hover, outline: `2px solid ${vars.colors.interactive.selected}` } })); const GridChartsPanelDataSectionTitle = styled('div', { name: 'MuiDataGrid', slot: 'ChartsPanelDataSectionTitle' })({ flex: 1, marginRight: vars.spacing(1.75), display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: vars.spacing(1), font: vars.typography.font.body, fontWeight: vars.typography.fontWeight.medium }); const GridChartsPanelDataFieldList = styled('div', { name: 'MuiDataGrid', slot: 'ChartsPanelDataFieldList' })({ flex: 1, display: 'flex', flexDirection: 'column', padding: vars.spacing(0.5, 0) }); const GridChartsPanelDataPlaceholder = styled('div', { name: 'MuiDataGrid', slot: 'ChartsPanelDataPlaceholder' })({ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center', textWrap: 'balance', textAlign: 'center', minHeight: 38, height: '100%', padding: vars.spacing(0, 1), color: vars.colors.foreground.muted, font: vars.typography.font.body }); const INITIAL_DRAG_STATE = { active: false, field: null, dropSection: null, initialSection: null }; // dimensions and values const SECTION_COUNT = 2; function GridChartsPanelDataBody(props) { const { searchValue } = props; const apiRef = useGridPrivateApiContext(); const rootProps = useGridRootProps(); const rowGroupingModel = useGridSelector(apiRef, gridRowGroupingSanitizedModelSelector); const pivotActive = useGridSelector(apiRef, gridPivotActiveSelector); const pivotModel = useGridSelector(apiRef, gridPivotModelSelector); const activeChartId = useGridSelector(apiRef, gridChartsIntegrationActiveChartIdSelector); const { chartStateLookup } = useGridChartsIntegrationContext(); const dimensions = useGridSelector(apiRef, gridChartsDimensionsSelector, activeChartId); const values = useGridSelector(apiRef, gridChartsValuesSelector, activeChartId); const classes = useUtilityClasses(rootProps); const chartableColumns = useGridSelector(apiRef, gridChartableColumnsSelector); const dimensionsLabel = React.useMemo(() => chartStateLookup[activeChartId]?.dimensionsLabel || apiRef.current.getLocaleText('chartsCategories'), [chartStateLookup, activeChartId, apiRef]); const valuesLabel = React.useMemo(() => chartStateLookup[activeChartId]?.valuesLabel || apiRef.current.getLocaleText('chartsSeries'), [chartStateLookup, activeChartId, apiRef]); const fullSections = React.useMemo(() => { const sections = []; if (chartStateLookup[activeChartId]?.maxDimensions && dimensions.length >= chartStateLookup[activeChartId]?.maxDimensions) { sections.push('dimensions'); } if (chartStateLookup[activeChartId]?.maxValues && values.length >= chartStateLookup[activeChartId]?.maxValues) { sections.push('values'); } return sections; }, [dimensions, values, chartStateLookup, activeChartId]); const blockedSectionsLookup = React.useMemo(() => new Map(Object.values(chartableColumns).map(column => [column.field, Array.from(new Set([...getBlockedSections(column, rowGroupingModel, pivotActive ? pivotModel : undefined), ...fullSections]))])), [rowGroupingModel, chartableColumns, pivotActive, pivotModel, fullSections]); const availableFields = React.useMemo(() => { const notUsedFields = Object.keys(chartableColumns).filter(field => !dimensions.some(dimension => dimension.field === field) && !values.some(value => value.field === field)); if (searchValue) { return notUsedFields.filter(field => { const fieldName = apiRef.current.chartsIntegration.getColumnName(field); return fieldName.toLowerCase().includes(searchValue.toLowerCase()); }); } // Fields with all sections blocked should be at the end return notUsedFields.sort((a, b) => { const aBlockedSections = blockedSectionsLookup.get(a).length; const bBlockedSections = blockedSectionsLookup.get(b).length; return (aBlockedSections >= SECTION_COUNT ? 1 : 0) - (bBlockedSections >= SECTION_COUNT ? 1 : 0); }); }, [apiRef, searchValue, chartableColumns, dimensions, values, blockedSectionsLookup]); const [drag, setDrag] = React.useState(INITIAL_DRAG_STATE); const disabledSections = React.useMemo(() => { if (!drag.field) { return new Set(); } return new Set(blockedSectionsLookup.get(drag.field)); }, [blockedSectionsLookup, drag.field]); const handleDragStart = (field, section) => { setDrag({ active: true, field, initialSection: section, dropSection: null }); }; const handleDragEnd = () => { setDrag(INITIAL_DRAG_STATE); }; const handleDrop = event => { setDrag(INITIAL_DRAG_STATE); // The drop event was already handled by a child if (event.defaultPrevented) { return; } event.preventDefault(); const { field, section: originSection } = JSON.parse(event.dataTransfer.getData('text/plain')); const targetSection = event.currentTarget.getAttribute('data-section'); if (originSection === targetSection) { return; } apiRef.current.chartsIntegration.updateDataReference(field, originSection, targetSection); }; const handleDragOver = React.useCallback(event => { event.preventDefault(); event.dataTransfer.dropEffect = 'move'; }, []); const handleDragEnter = React.useCallback(event => { if (!event.currentTarget.contains(event.relatedTarget)) { const dropSection = event.currentTarget.getAttribute('data-section'); setDrag(v => _extends({}, v, { active: true, dropSection })); } }, []); const handleDragLeave = React.useCallback(event => { if (!event.currentTarget.contains(event.relatedTarget)) { setDrag(v => _extends({}, v, { active: true, dropSection: v.initialSection })); } }, []); const handleChange = React.useCallback((field, section) => { const apiMethod = section === 'dimensions' ? apiRef.current.updateChartDimensionsData : apiRef.current.updateChartValuesData; apiMethod(activeChartId, currentItems => currentItems.map(item => item.field === field ? _extends({}, item, { hidden: item.hidden !== true }) : item)); }, [apiRef, activeChartId]); return /*#__PURE__*/_jsxs(GridChartsPanelDataBodyRoot, { ownerState: rootProps, className: classes.root, "data-dragging": drag.active, onDragLeave: handleDragLeave, children: [/*#__PURE__*/_jsxs(GridChartsPanelDataAvailableFields, { ownerState: rootProps, className: classes.availableFields, onDrop: handleDrop, onDragEnter: handleDragEnter, onDragOver: handleDragOver, "data-section": null, "data-drag-over": drag.active && drag.dropSection === null, children: [availableFields.length === 0 && /*#__PURE__*/_jsx(GridChartsPanelDataPlaceholder, { ownerState: rootProps, className: classes.placeholder, children: apiRef.current.getLocaleText('chartsNoFields') }), availableFields.length > 0 && /*#__PURE__*/_jsx(GridChartsPanelDataFieldList, { ownerState: rootProps, className: classes.fieldList, children: availableFields.map(field => /*#__PURE__*/_jsx(GridChartsPanelDataField, { field: field, section: null, disabled: blockedSectionsLookup.get(field).length >= SECTION_COUNT, blockedSections: blockedSectionsLookup.get(field), dimensionsLabel: dimensionsLabel, valuesLabel: valuesLabel, onDragStart: handleDragStart, onDragEnd: handleDragEnd, children: apiRef.current.chartsIntegration.getColumnName(field) }, field)) })] }), /*#__PURE__*/_jsxs(GridChartsPanelDataSections, { ownerState: rootProps, className: classes.sections, direction: "vertical", children: [/*#__PURE__*/_jsx(ResizablePanelHandle, {}), /*#__PURE__*/_jsxs(GridChartsPanelDataScrollArea, { ownerState: rootProps, className: classes.scrollArea, children: [/*#__PURE__*/_jsxs(GridChartsPanelDataSection, { ownerState: rootProps, className: classes.section, onDrop: handleDrop, onDragEnter: handleDragEnter, onDragOver: handleDragOver, disabled: disabledSections.has('dimensions'), "data-section": "dimensions", "data-drag-over": !disabledSections.has('dimensions') && drag.dropSection === 'dimensions', children: [/*#__PURE__*/_jsx(CollapsibleTrigger, { "aria-label": dimensionsLabel, children: /*#__PURE__*/_jsxs(GridChartsPanelDataSectionTitle, { ownerState: rootProps, className: classes.sectionTitle, children: [dimensionsLabel, (chartStateLookup[activeChartId]?.maxDimensions || dimensions.length > 0) && /*#__PURE__*/_jsx(rootProps.slots.baseBadge, { badgeContent: chartStateLookup[activeChartId]?.maxDimensions ? `${dimensions.length}/${chartStateLookup[activeChartId]?.maxDimensions}` : dimensions.length })] }) }), /*#__PURE__*/_jsxs(CollapsiblePanel, { children: [dimensions.length === 0 && /*#__PURE__*/_jsx(GridChartsPanelDataPlaceholder, { ownerState: rootProps, className: classes.placeholder, children: apiRef.current.getLocaleText('chartsDragToDimensions')(dimensionsLabel) }), dimensions.length > 0 && /*#__PURE__*/_jsx(GridChartsPanelDataFieldList, { ownerState: rootProps, className: classes.fieldList, children: dimensions.map(dimension => /*#__PURE__*/_jsx(GridChartsPanelDataField, { field: dimension.field, selected: dimension.hidden !== true, onChange: handleChange, section: "dimensions", blockedSections: blockedSectionsLookup.get(dimension.field), dimensionsLabel: dimensionsLabel, valuesLabel: valuesLabel, disabled: disabledSections.has('dimensions'), onDragStart: handleDragStart, onDragEnd: handleDragEnd, children: apiRef.current.chartsIntegration.getColumnName(dimension.field) }, dimension.field)) })] })] }), /*#__PURE__*/_jsxs(GridChartsPanelDataSection, { ownerState: rootProps, className: classes.section, onDrop: handleDrop, onDragEnter: handleDragEnter, onDragOver: handleDragOver, disabled: disabledSections.has('values'), "data-section": "values", "data-drag-over": !disabledSections.has('values') && drag.dropSection === 'values', children: [/*#__PURE__*/_jsx(CollapsibleTrigger, { "aria-label": valuesLabel, children: /*#__PURE__*/_jsxs(GridChartsPanelDataSectionTitle, { ownerState: rootProps, className: classes.sectionTitle, children: [valuesLabel, (chartStateLookup[activeChartId]?.maxValues || values.length > 0) && /*#__PURE__*/_jsx(rootProps.slots.baseBadge, { badgeContent: chartStateLookup[activeChartId]?.maxValues ? `${values.length}/${chartStateLookup[activeChartId]?.maxValues}` : values.length })] }) }), /*#__PURE__*/_jsxs(CollapsiblePanel, { children: [values.length === 0 && /*#__PURE__*/_jsx(GridChartsPanelDataPlaceholder, { ownerState: rootProps, className: classes.placeholder, children: apiRef.current.getLocaleText('chartsDragToValues')(valuesLabel) }), values.length > 0 && /*#__PURE__*/_jsx(GridChartsPanelDataFieldList, { ownerState: rootProps, className: classes.fieldList, children: values.map(value => /*#__PURE__*/_jsx(GridChartsPanelDataField, { field: value.field, selected: value.hidden !== true, onChange: handleChange, section: "values", blockedSections: blockedSectionsLookup.get(value.field), dimensionsLabel: dimensionsLabel, valuesLabel: valuesLabel, disabled: disabledSections.has('values'), onDragStart: handleDragStart, onDragEnd: handleDragEnd, children: apiRef.current.chartsIntegration.getColumnName(value.field) }, value.field)) })] })] })] })] })] }); } export { GridChartsPanelDataBody };