diff --git a/src-docs/src/views/datagrid/datagrid.js b/src-docs/src/views/datagrid/datagrid.js index d2780c5d3b5..b3d4d3a83b2 100644 --- a/src-docs/src/views/datagrid/datagrid.js +++ b/src-docs/src/views/datagrid/datagrid.js @@ -1,7 +1,6 @@ import React, { Fragment, useCallback, - useEffect, useMemo, useState, createContext, @@ -366,23 +365,8 @@ export default () => { ); // initialize to the full set of columns const renderCellValue = useMemo(() => { - return ({ rowIndex, columnId, setCellProps }) => { + return ({ rowIndex, columnId, CellProps }) => { const data = useContext(DataContext); - useEffect(() => { - if (columnId === 'amount') { - if (data.hasOwnProperty(rowIndex)) { - const numeric = parseFloat( - data[rowIndex][columnId].match(/\d+\.\d+/)[0], - 10 - ); - setCellProps({ - style: { - backgroundColor: `rgba(0, 255, 0, ${numeric * 0.0002})`, - }, - }); - } - } - }, [rowIndex, columnId, setCellProps, data]); function getFormatted() { return data[rowIndex][columnId].formatted @@ -390,9 +374,31 @@ export default () => { : data[rowIndex][columnId]; } - return data.hasOwnProperty(rowIndex) + const content = data.hasOwnProperty(rowIndex) ? getFormatted(rowIndex, columnId) : null; + + // Apply custom background color to cells in the `amount` columns + let cellProps = undefined; + if (columnId === 'amount') { + const numeric = parseFloat(content.match(/\d+\.\d+/)[0], 10); + cellProps = ( + + ); + } + + return ( + <> + {content} + {cellProps} + + ); }; }, []); diff --git a/src/components/datagrid/body/__snapshots__/data_grid_cell.test.tsx.snap b/src/components/datagrid/body/__snapshots__/data_grid_cell.test.tsx.snap index 3f57f59cf0a..d2cd2c8d1c4 100644 --- a/src/components/datagrid/body/__snapshots__/data_grid_cell.test.tsx.snap +++ b/src/components/datagrid/body/__snapshots__/data_grid_cell.test.tsx.snap @@ -1,5 +1,39 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`EuiDataGridCell componentDidUpdate handles the cell popover by forwarding the cell's DOM node and contents to the parent popover context 1`] = ` +Array [ +
+
+ + +
+
, +
+
+
+
+
+
, +] +`; + exports[`EuiDataGridCell renders 1`] = ` `; - -exports[`EuiDataGridCell componentDidUpdate handles the cell popover by forwarding the cell's DOM node and contents to the parent popover context 1`] = ` -Array [ -
-
- - -
-
, -
-
-
-
-
-
, -] -`; diff --git a/src/components/datagrid/body/data_grid_cell.tsx b/src/components/datagrid/body/data_grid_cell.tsx index 4826891a3fa..812333d2f59 100644 --- a/src/components/datagrid/body/data_grid_cell.tsx +++ b/src/components/datagrid/body/data_grid_cell.tsx @@ -9,6 +9,7 @@ import classNames from 'classnames'; import React, { Component, + createContext, createRef, FocusEvent, FunctionComponent, @@ -17,6 +18,8 @@ import React, { KeyboardEvent, memo, MutableRefObject, + useContext, + useEffect, } from 'react'; import { createPortal } from 'react-dom'; import tabbable from 'tabbable'; @@ -41,6 +44,7 @@ import { IS_JEST_ENVIRONMENT } from '../../../test'; const EuiDataGridCellContent: FunctionComponent< EuiDataGridCellValueProps & { setCellProps: EuiDataGridCellValueElementProps['setCellProps']; + CellProps: typeof CellProps; setCellContentsRef: EuiDataGridCell['setCellContentsRef']; isExpanded: boolean; isDefinedHeight: boolean; @@ -99,6 +103,22 @@ const EuiDataGridCellContent: FunctionComponent< } ); +const CellPropsContext = createContext<{ + setCellProps: (props: HTMLAttributes) => void; +}>({ + setCellProps: () => {}, +}); + +export const CellProps: FunctionComponent<{ + props: HTMLAttributes; +}> = ({ props }) => { + const { setCellProps } = useContext(CellPropsContext); + useEffect(() => { + setCellProps(props); + }, [setCellProps, props]); + return null; +}; + export class EuiDataGridCell extends Component< EuiDataGridCellProps, EuiDataGridCellState @@ -469,6 +489,7 @@ export class EuiDataGridCell extends Component< isExpandable={true} isExpanded={true} setCellProps={this.setCellProps} + CellProps={CellProps} isDetails={true} /> @@ -599,6 +620,7 @@ export class EuiDataGridCell extends Component< const cellContentProps = { ...rest, setCellProps: this.setCellProps, + CellProps, column, columnType: columnType, isExpandable, @@ -668,32 +690,34 @@ export class EuiDataGridCell extends Component< } const content = ( -
{ - this.setState({ enableInteractions: true }); - }} - onMouseLeave={() => { - this.setState({ enableInteractions: false }); - }} - onBlur={this.onBlur} - > - {innerContent} -
+ +
{ + this.setState({ enableInteractions: true }); + }} + onMouseLeave={() => { + this.setState({ enableInteractions: false }); + }} + onBlur={this.onBlur} + > + {innerContent} +
+
); return rowManager && !IS_JEST_ENVIRONMENT diff --git a/src/components/datagrid/data_grid_types.ts b/src/components/datagrid/data_grid_types.ts index a84d03a0ead..eebf53eb94f 100644 --- a/src/components/datagrid/data_grid_types.ts +++ b/src/components/datagrid/data_grid_types.ts @@ -18,6 +18,7 @@ import { Dispatch, SetStateAction, MutableRefObject, + FunctionComponent, } from 'react'; import { VariableSizeGridProps, @@ -389,6 +390,10 @@ export interface EuiDataGridCellValueElementProps { * it's best to wrap calls to `setCellProps` in a `useEffect` hook */ setCellProps: (props: CommonProps & HTMLAttributes) => void; + /** + * React component that can be used to specific custom props & attributes on the cell's wrapping `div` element + */ + CellProps: FunctionComponent<{ props: HTMLAttributes }>; /** * whether or not the cell is expandable, comes from the #EuiDataGridColumn `isExpandable` which defaults to `true` */ diff --git a/src/components/datagrid/utils/in_memory.tsx b/src/components/datagrid/utils/in_memory.tsx index ef979fa2cb0..0522344cba6 100644 --- a/src/components/datagrid/utils/in_memory.tsx +++ b/src/components/datagrid/utils/in_memory.tsx @@ -24,6 +24,7 @@ import { EuiDataGridInMemoryRendererProps, EuiDataGridCellValueElementProps, } from '../data_grid_types'; +import { CellProps } from '../body/data_grid_cell'; /** * inMemory values hook @@ -124,6 +125,7 @@ export const EuiDataGridInMemoryRenderer: FunctionComponent