Skip to content

Commit

Permalink
Create a CellProps configuration component
Browse files Browse the repository at this point in the history
  • Loading branch information
chandlerprall committed Jan 26, 2022
1 parent f58e3a5 commit fc51609
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 78 deletions.
42 changes: 24 additions & 18 deletions src-docs/src/views/datagrid/datagrid.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import React, {
Fragment,
useCallback,
useEffect,
useMemo,
useState,
createContext,
Expand Down Expand Up @@ -366,33 +365,40 @@ 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
? data[rowIndex][columnId].formatted
: 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 = (
<CellProps
props={{
style: {
backgroundColor: `rgba(0, 255, 0, ${numeric * 0.0002})`,
},
}}
/>
);
}

return (
<>
{content}
{cellProps}
</>
);
};
}, []);

Expand Down
Original file line number Diff line number Diff line change
@@ -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 [
<div
data-test-subj="popover-test"
>
<div>
<button
data-datagrid-interactable="true"
>
hello
</button>
<button
data-datagrid-interactable="true"
>
world
</button>
</div>
</div>,
<div
class="euiPopoverFooter"
>
<div
class="euiFlexGroup euiFlexGroup--gutterSmall euiFlexGroup--directionRow euiFlexGroup--responsive"
>
<div
class="euiFlexItem"
>
<button />
</div>
</div>
</div>,
]
`;

exports[`EuiDataGridCell renders 1`] = `
<EuiDataGridCell
colIndex={0}
Expand Down Expand Up @@ -83,6 +117,7 @@ exports[`EuiDataGridCell renders 1`] = `
className="euiDataGridRowCell__expandContent"
>
<Memo()
CellProps={[Function]}
colIndex={0}
columnId="someColumn"
isDefinedHeight={false}
Expand Down Expand Up @@ -131,6 +166,7 @@ exports[`EuiDataGridCell renders 1`] = `
style={Object {}}
>
<renderCellValue
CellProps={[Function]}
columnId="someColumn"
data-test-subj="cell-content"
isDetails={false}
Expand Down Expand Up @@ -167,37 +203,3 @@ exports[`EuiDataGridCell renders 1`] = `
</div>
</EuiDataGridCell>
`;

exports[`EuiDataGridCell componentDidUpdate handles the cell popover by forwarding the cell's DOM node and contents to the parent popover context 1`] = `
Array [
<div
data-test-subj="popover-test"
>
<div>
<button
data-datagrid-interactable="true"
>
hello
</button>
<button
data-datagrid-interactable="true"
>
world
</button>
</div>
</div>,
<div
class="euiPopoverFooter"
>
<div
class="euiFlexGroup euiFlexGroup--gutterSmall euiFlexGroup--directionRow euiFlexGroup--responsive"
>
<div
class="euiFlexItem"
>
<button />
</div>
</div>
</div>,
]
`;
76 changes: 50 additions & 26 deletions src/components/datagrid/body/data_grid_cell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import classNames from 'classnames';
import React, {
Component,
createContext,
createRef,
FocusEvent,
FunctionComponent,
Expand All @@ -17,6 +18,8 @@ import React, {
KeyboardEvent,
memo,
MutableRefObject,
useContext,
useEffect,
} from 'react';
import { createPortal } from 'react-dom';
import tabbable from 'tabbable';
Expand All @@ -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;
Expand Down Expand Up @@ -99,6 +103,22 @@ const EuiDataGridCellContent: FunctionComponent<
}
);

const CellPropsContext = createContext<{
setCellProps: (props: HTMLAttributes<HTMLDivElement>) => void;
}>({
setCellProps: () => {},
});

export const CellProps: FunctionComponent<{
props: HTMLAttributes<HTMLDivElement>;
}> = ({ props }) => {
const { setCellProps } = useContext(CellPropsContext);
useEffect(() => {
setCellProps(props);
}, [setCellProps, props]);
return null;
};

export class EuiDataGridCell extends Component<
EuiDataGridCellProps,
EuiDataGridCellState
Expand Down Expand Up @@ -469,6 +489,7 @@ export class EuiDataGridCell extends Component<
isExpandable={true}
isExpanded={true}
setCellProps={this.setCellProps}
CellProps={CellProps}
isDetails={true}
/>
</PopoverContent>
Expand Down Expand Up @@ -599,6 +620,7 @@ export class EuiDataGridCell extends Component<
const cellContentProps = {
...rest,
setCellProps: this.setCellProps,
CellProps,
column,
columnType: columnType,
isExpandable,
Expand Down Expand Up @@ -668,32 +690,34 @@ export class EuiDataGridCell extends Component<
}

const content = (
<div
role="gridcell"
tabIndex={
this.state.isFocused && !this.state.disableCellTabIndex ? 0 : -1
}
ref={this.cellRef}
{...cellProps}
data-test-subj="dataGridRowCell"
// Data attributes to help target specific cells by either data or current cell location
data-gridcell-column-id={this.props.columnId} // Static column ID name, not affected by column order
data-gridcell-column-index={this.props.colIndex} // Affected by column reordering
data-gridcell-row-index={this.props.rowIndex} // Index from data, not affected by sorting or pagination
data-gridcell-visible-row-index={this.props.visibleRowIndex} // Affected by sorting & pagination
data-gridcell-id={`${this.props.colIndex},${this.props.rowIndex}`} // TODO: Deprecate in favor of the above 4 data attrs
onKeyDown={handleCellKeyDown}
onFocus={this.onFocus}
onMouseEnter={() => {
this.setState({ enableInteractions: true });
}}
onMouseLeave={() => {
this.setState({ enableInteractions: false });
}}
onBlur={this.onBlur}
>
{innerContent}
</div>
<CellPropsContext.Provider value={{ setCellProps: this.setCellProps }}>
<div
role="gridcell"
tabIndex={
this.state.isFocused && !this.state.disableCellTabIndex ? 0 : -1
}
ref={this.cellRef}
{...cellProps}
data-test-subj="dataGridRowCell"
// Data attributes to help target specific cells by either data or current cell location
data-gridcell-column-id={this.props.columnId} // Static column ID name, not affected by column order
data-gridcell-column-index={this.props.colIndex} // Affected by column reordering
data-gridcell-row-index={this.props.rowIndex} // Index from data, not affected by sorting or pagination
data-gridcell-visible-row-index={this.props.visibleRowIndex} // Affected by sorting & pagination
data-gridcell-id={`${this.props.colIndex},${this.props.rowIndex}`} // TODO: Deprecate in favor of the above 4 data attrs
onKeyDown={handleCellKeyDown}
onFocus={this.onFocus}
onMouseEnter={() => {
this.setState({ enableInteractions: true });
}}
onMouseLeave={() => {
this.setState({ enableInteractions: false });
}}
onBlur={this.onBlur}
>
{innerContent}
</div>
</CellPropsContext.Provider>
);

return rowManager && !IS_JEST_ENVIRONMENT
Expand Down
5 changes: 5 additions & 0 deletions src/components/datagrid/data_grid_types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
Dispatch,
SetStateAction,
MutableRefObject,
FunctionComponent,
} from 'react';
import {
VariableSizeGridProps,
Expand Down Expand Up @@ -389,6 +390,10 @@ export interface EuiDataGridCellValueElementProps {
* it's best to wrap calls to `setCellProps` in a `useEffect` hook
*/
setCellProps: (props: CommonProps & HTMLAttributes<HTMLDivElement>) => void;
/**
* React component that can be used to specific custom props & attributes on the cell's wrapping `div` element
*/
CellProps: FunctionComponent<{ props: HTMLAttributes<HTMLDivElement> }>;
/**
* whether or not the cell is expandable, comes from the #EuiDataGridColumn `isExpandable` which defaults to `true`
*/
Expand Down
2 changes: 2 additions & 0 deletions src/components/datagrid/utils/in_memory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
EuiDataGridInMemoryRendererProps,
EuiDataGridCellValueElementProps,
} from '../data_grid_types';
import { CellProps } from '../body/data_grid_cell';

/**
* inMemory values hook
Expand Down Expand Up @@ -124,6 +125,7 @@ export const EuiDataGridInMemoryRenderer: FunctionComponent<EuiDataGridInMemoryR
rowIndex={i}
columnId={column.id}
setCellProps={noop}
CellProps={CellProps}
isExpandable={isExpandable}
isExpanded={false}
isDetails={false}
Expand Down

0 comments on commit fc51609

Please sign in to comment.