in superset-frontend/plugins/plugin-chart-table/src/TableChart.tsx [765:951]
id: String(i), // to allow duplicate column keys
// must use custom accessor to allow `.` in column names
// typing is incorrect in current version of `@types/react-table`
// so we ask TS not to check.
accessor: ((datum: D) => datum[key]) as never,
Cell: ({ value, row }: { value: DataRecordValue; row: Row<D> }) => {
const [isHtml, text] = formatColumnValue(column, value);
const html = isHtml && allowRenderHtml ? { __html: text } : undefined;
let backgroundColor;
let arrow = '';
const originKey = column.key.substring(column.label.length).trim();
if (!hasColumnColorFormatters && hasBasicColorFormatters) {
backgroundColor =
basicColorFormatters[row.index][originKey]?.backgroundColor;
arrow =
column.label === comparisonLabels[0]
? basicColorFormatters[row.index][originKey]?.mainArrow
: '';
}
if (hasColumnColorFormatters) {
columnColorFormatters!
.filter(formatter => formatter.column === column.key)
.forEach(formatter => {
const formatterResult =
value || value === 0
? formatter.getColorFromValue(value as number)
: false;
if (formatterResult) {
backgroundColor = formatterResult;
}
});
}
if (
basicColorColumnFormatters &&
basicColorColumnFormatters?.length > 0
) {
backgroundColor =
basicColorColumnFormatters[row.index][column.key]
?.backgroundColor || backgroundColor;
arrow =
column.label === comparisonLabels[0]
? basicColorColumnFormatters[row.index][column.key]?.mainArrow
: '';
}
const StyledCell = styled.td`
text-align: ${sharedStyle.textAlign};
white-space: ${value instanceof Date ? 'nowrap' : undefined};
position: relative;
background: ${backgroundColor || undefined};
padding-left: ${column.isChildColumn
? `${theme.gridUnit * 5}px`
: `${theme.gridUnit}px`};
`;
const cellBarStyles = css`
position: absolute;
height: 100%;
display: block;
top: 0;
${valueRange &&
`
width: ${`${cellWidth({
value: value as number,
valueRange,
alignPositiveNegative,
})}%`};
left: ${`${cellOffset({
value: value as number,
valueRange,
alignPositiveNegative,
})}%`};
background-color: ${cellBackground({
value: value as number,
colorPositiveNegative,
})};
`}
`;
let arrowStyles = css`
color: ${basicColorFormatters &&
basicColorFormatters[row.index][originKey]?.arrowColor ===
ColorSchemeEnum.Green
? theme.colors.success.base
: theme.colors.error.base};
margin-right: ${theme.gridUnit}px;
`;
if (
basicColorColumnFormatters &&
basicColorColumnFormatters?.length > 0
) {
arrowStyles = css`
color: ${basicColorColumnFormatters[row.index][column.key]
?.arrowColor === ColorSchemeEnum.Green
? theme.colors.success.base
: theme.colors.error.base};
margin-right: ${theme.gridUnit}px;
`;
}
const cellProps = {
'aria-labelledby': `header-${column.key}`,
role: 'cell',
// show raw number in title in case of numeric values
title: typeof value === 'number' ? String(value) : undefined,
onClick:
emitCrossFilters && !valueRange && !isMetric
? () => {
// allow selecting text in a cell
if (!getSelectedText()) {
toggleFilter(key, value);
}
}
: undefined,
onContextMenu: (e: MouseEvent) => {
if (handleContextMenu) {
e.preventDefault();
e.stopPropagation();
handleContextMenu(
row.original,
{ key, value, isMetric },
e.nativeEvent.clientX,
e.nativeEvent.clientY,
);
}
},
className: [
className,
value == null ? 'dt-is-null' : '',
isActiveFilterValue(key, value) ? ' dt-is-active-filter' : '',
].join(' '),
tabIndex: 0,
};
if (html) {
if (truncateLongCells) {
// eslint-disable-next-line react/no-danger
return (
<StyledCell {...cellProps}>
<div
className="dt-truncate-cell"
style={columnWidth ? { width: columnWidth } : undefined}
dangerouslySetInnerHTML={html}
/>
</StyledCell>
);
}
// eslint-disable-next-line react/no-danger
return <StyledCell {...cellProps} dangerouslySetInnerHTML={html} />;
}
// If cellProps renders textContent already, then we don't have to
// render `Cell`. This saves some time for large tables.
return (
<StyledCell {...cellProps}>
{valueRange && (
<div
/* The following classes are added to support custom CSS styling */
className={cx(
'cell-bar',
typeof value === 'number' && value < 0
? 'negative'
: 'positive',
)}
css={cellBarStyles}
role="presentation"
/>
)}
{truncateLongCells ? (
<div
className="dt-truncate-cell"
style={columnWidth ? { width: columnWidth } : undefined}
>
{arrow && <span css={arrowStyles}>{arrow}</span>}
{text}
</div>
) : (
<>
{arrow && <span css={arrowStyles}>{arrow}</span>}
{text}
</>
)}
</StyledCell>
);
},