wip:milestone 0 fixes
Some checks failed
CI/CD Pipeline / unit-tests (push) Failing after 1m16s
CI/CD Pipeline / integration-tests (push) Failing after 2m32s
CI/CD Pipeline / lint (push) Successful in 5m22s
CI/CD Pipeline / e2e-tests (push) Has been skipped
CI/CD Pipeline / build (push) Has been skipped

This commit is contained in:
2026-03-15 12:35:42 +02:00
parent 6708cf28a7
commit cffdf8af86
61266 changed files with 4511646 additions and 1938 deletions

View File

@@ -0,0 +1,47 @@
import * as React from 'react';
export interface GridColumnMenuState {
open: boolean;
field?: string;
}
export interface GridColumnMenuSlotProps {
/**
* Every item has a `displayOrder` based which it will be placed before or after other
* items in the column menu, `array.prototype.sort` is applied to sort the items.
* Note: If same `displayOrder` is applied to two or more items they will be sorted
* based on the definition order
* @default 100
*/
displayOrder?: number;
[key: string]: any;
}
export interface GridColumnMenuRootProps {
/**
* Initial `slots` - it is internal, to be overrriden by Pro or Premium packages
* @ignore - do not document.
*/
defaultSlots: {
[key: string]: React.JSXElementConstructor<any>;
};
/**
* Initial `slotProps` - it is internal, to be overrriden by Pro or Premium packages
* @ignore - do not document.
*/
defaultSlotProps: {
[key: string]: GridColumnMenuSlotProps;
};
/**
* `slots` could be used to add new and (or) override default column menu items
* If you register a nee component you must pass it's `displayOrder` in `slotProps`
* or it will be placed in the end of the list
*/
slots?: {
[key: string]: React.JSXElementConstructor<any> | null;
};
/**
* Could be used to pass new props or override props specific to a column menu component
* e.g. `displayOrder`
*/
slotProps?: {
[key: string]: GridColumnMenuSlotProps;
};
}

View File

@@ -0,0 +1 @@
export {};

View File

@@ -0,0 +1,2 @@
import { GridStateCommunity } from '../../../models/gridStateCommunity';
export declare const gridColumnMenuSelector: (state: GridStateCommunity) => import("./columnMenuInterfaces").GridColumnMenuState;

View File

@@ -0,0 +1 @@
export const gridColumnMenuSelector = state => state.columnMenu;

View File

@@ -0,0 +1,2 @@
export * from './columnMenuInterfaces';
export * from './columnMenuSelector';

View File

@@ -0,0 +1,2 @@
export * from './columnMenuInterfaces';
export * from './columnMenuSelector';

View File

@@ -0,0 +1,9 @@
import * as React from 'react';
import { GridPrivateApiCommunity } from '../../../models/api/gridApiCommunity';
import { GridStateInitializer } from '../../utils/useGridInitializeState';
export declare const columnMenuStateInitializer: GridStateInitializer;
/**
* @requires useGridColumnResize (event)
* @requires useGridInfiniteLoader (event)
*/
export declare const useGridColumnMenu: (apiRef: React.MutableRefObject<GridPrivateApiCommunity>) => void;

View File

@@ -0,0 +1,101 @@
import _extends from "@babel/runtime/helpers/esm/extends";
import * as React from 'react';
import { useGridLogger, useGridApiMethod, useGridApiEventHandler } from '../../utils';
import { gridColumnMenuSelector } from './columnMenuSelector';
import { gridColumnLookupSelector, gridColumnVisibilityModelSelector, gridColumnFieldsSelector } from '../columns/gridColumnsSelector';
export const columnMenuStateInitializer = state => _extends({}, state, {
columnMenu: {
open: false
}
});
/**
* @requires useGridColumnResize (event)
* @requires useGridInfiniteLoader (event)
*/
export const useGridColumnMenu = apiRef => {
const logger = useGridLogger(apiRef, 'useGridColumnMenu');
/**
* API METHODS
*/
const showColumnMenu = React.useCallback(field => {
const shouldUpdate = apiRef.current.setState(state => {
if (state.columnMenu.open && state.columnMenu.field === field) {
return state;
}
logger.debug('Opening Column Menu');
return _extends({}, state, {
columnMenu: {
open: true,
field
}
});
});
if (shouldUpdate) {
apiRef.current.hidePreferences();
apiRef.current.forceUpdate();
}
}, [apiRef, logger]);
const hideColumnMenu = React.useCallback(() => {
const columnMenuState = gridColumnMenuSelector(apiRef.current.state);
if (columnMenuState.field) {
const columnLookup = gridColumnLookupSelector(apiRef);
const columnVisibilityModel = gridColumnVisibilityModelSelector(apiRef);
const orderedFields = gridColumnFieldsSelector(apiRef);
let fieldToFocus = columnMenuState.field;
// If the column was removed from the grid, we need to find the closest visible field
if (!columnLookup[fieldToFocus]) {
fieldToFocus = orderedFields[0];
}
// If the field to focus is hidden, we need to find the closest visible field
if (columnVisibilityModel[fieldToFocus] === false) {
// contains visible column fields + the field that was just hidden
const visibleOrderedFields = orderedFields.filter(field => {
if (field === fieldToFocus) {
return true;
}
return columnVisibilityModel[field] !== false;
});
const fieldIndex = visibleOrderedFields.indexOf(fieldToFocus);
fieldToFocus = visibleOrderedFields[fieldIndex + 1] || visibleOrderedFields[fieldIndex - 1];
}
apiRef.current.setColumnHeaderFocus(fieldToFocus);
}
const shouldUpdate = apiRef.current.setState(state => {
if (!state.columnMenu.open && state.columnMenu.field === undefined) {
return state;
}
logger.debug('Hiding Column Menu');
return _extends({}, state, {
columnMenu: _extends({}, state.columnMenu, {
open: false,
field: undefined
})
});
});
if (shouldUpdate) {
apiRef.current.forceUpdate();
}
}, [apiRef, logger]);
const toggleColumnMenu = React.useCallback(field => {
logger.debug('Toggle Column Menu');
const columnMenu = gridColumnMenuSelector(apiRef.current.state);
if (!columnMenu.open || columnMenu.field !== field) {
showColumnMenu(field);
} else {
hideColumnMenu();
}
}, [apiRef, logger, showColumnMenu, hideColumnMenu]);
const columnMenuApi = {
showColumnMenu,
hideColumnMenu,
toggleColumnMenu
};
useGridApiMethod(apiRef, columnMenuApi, 'public');
useGridApiEventHandler(apiRef, 'columnResizeStart', hideColumnMenu);
useGridApiEventHandler(apiRef, 'virtualScrollerWheel', apiRef.current.hideColumnMenu);
useGridApiEventHandler(apiRef, 'virtualScrollerTouchMove', apiRef.current.hideColumnMenu);
};

View File

@@ -0,0 +1,16 @@
import * as React from 'react';
import { GridColumnMenuRootProps } from './columnMenuInterfaces';
import { GridColDef } from '../../../models/colDef/gridColDef';
interface UseGridColumnMenuSlotsProps extends GridColumnMenuRootProps {
colDef: GridColDef;
hideMenu: (event: React.SyntheticEvent) => void;
addDividers?: boolean;
}
type UseGridColumnMenuSlotsResponse = Array<[
React.JSXElementConstructor<any>,
{
[key: string]: any;
}
]>;
declare const useGridColumnMenuSlots: (props: UseGridColumnMenuSlotsProps) => UseGridColumnMenuSlotsResponse;
export { useGridColumnMenuSlots };

View File

@@ -0,0 +1,58 @@
import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
import _extends from "@babel/runtime/helpers/esm/extends";
const _excluded = ["displayOrder"];
import * as React from 'react';
import Divider from '@mui/material/Divider';
import { useGridPrivateApiContext } from '../../utils/useGridPrivateApiContext';
const useGridColumnMenuSlots = props => {
const apiRef = useGridPrivateApiContext();
const {
defaultSlots,
defaultSlotProps,
slots = {},
slotProps = {},
hideMenu,
colDef,
addDividers = true
} = props;
const processedComponents = React.useMemo(() => _extends({}, defaultSlots, slots), [defaultSlots, slots]);
const processedSlotProps = React.useMemo(() => {
if (!slotProps || Object.keys(slotProps).length === 0) {
return defaultSlotProps;
}
const mergedProps = _extends({}, slotProps);
Object.entries(defaultSlotProps).forEach(([key, currentSlotProps]) => {
mergedProps[key] = _extends({}, currentSlotProps, slotProps[key] || {});
});
return mergedProps;
}, [defaultSlotProps, slotProps]);
const defaultItems = apiRef.current.unstable_applyPipeProcessors('columnMenu', [], props.colDef);
const userItems = React.useMemo(() => {
const defaultComponentKeys = Object.keys(defaultSlots);
return Object.keys(slots).filter(key => !defaultComponentKeys.includes(key));
}, [slots, defaultSlots]);
return React.useMemo(() => {
const uniqueItems = Array.from(new Set([...defaultItems, ...userItems]));
const cleansedItems = uniqueItems.filter(key => processedComponents[key] != null);
const sorted = cleansedItems.sort((a, b) => {
const leftItemProps = processedSlotProps[a];
const rightItemProps = processedSlotProps[b];
const leftDisplayOrder = Number.isFinite(leftItemProps == null ? void 0 : leftItemProps.displayOrder) ? leftItemProps.displayOrder : 100;
const rightDisplayOrder = Number.isFinite(rightItemProps == null ? void 0 : rightItemProps.displayOrder) ? rightItemProps.displayOrder : 100;
return leftDisplayOrder - rightDisplayOrder;
});
return sorted.reduce((acc, key, index) => {
let itemProps = {
colDef,
onClick: hideMenu
};
const processedComponentProps = processedSlotProps[key];
if (processedComponentProps) {
const customProps = _objectWithoutPropertiesLoose(processedComponentProps, _excluded);
itemProps = _extends({}, itemProps, customProps);
}
return addDividers && index !== sorted.length - 1 ? [...acc, [processedComponents[key], itemProps], [Divider, {}]] : [...acc, [processedComponents[key], itemProps]];
}, []);
}, [addDividers, colDef, defaultItems, hideMenu, processedComponents, processedSlotProps, userItems]);
};
export { useGridColumnMenuSlots };