@equinor/eds-data-grid-react
Version:
A feature-rich data-grid written in React, implementing the Equinor Design System
125 lines (122 loc) • 5.2 kB
JavaScript
import { flexRender } from '@tanstack/react-table';
import { useTableContext } from '../EdsDataGridContext.js';
import { useMemo } from 'react';
import { FilterWrapper } from './FilterWrapper.js';
import { SortIndicator } from './SortIndicator.js';
import { Resizer, ResizeInner } from './Resizer.js';
import { TableCell, FilterVisibility } from './TableCell.js';
import styled from 'styled-components';
import { useEds } from '@equinor/eds-core-react';
import { jsx, jsxs } from 'react/jsx-runtime';
const SortButton = styled.button.withConfig({
displayName: "TableHeaderCell__SortButton",
componentId: "sc-1n0j3v0-0"
})(["cursor:pointer;height:100%;width:calc(100% - 5px);display:flex;flex-direction:row;align-items:center;background:transparent;border:none;padding-left:var(--eds_table__cell__padding_x,16px);padding-right:var(--eds_table__cell__padding_x,16px);margin:0;outline:none;color:inherit;text-align:left;font:inherit;"]);
const TableHeaderCellLabel = styled.div.withConfig({
displayName: "TableHeaderCell__TableHeaderCellLabel",
componentId: "sc-1n0j3v0-1"
})(["display:flex;flex-direction:column;"]);
const getSortLabel = sorted => {
if (sorted) {
return `${sorted}ending`;
}
return 'none';
};
function TableHeaderCell({
header,
columnResizeMode
}) {
const ctx = useTableContext();
const table = ctx.table;
const pinned = header.column.getIsPinned();
const isFiltered = header.column.getIsFiltered();
const filterValue = header.column.getFilterValue();
const hasActiveFilters = useMemo(() => {
if (!isFiltered) return false;
if (Array.isArray(filterValue)) {
return filterValue.length > 0 && filterValue.some(v => !!v || v === 0); // avoid empty strings counting
}
return !!filterValue;
}, [isFiltered, filterValue]);
const canSort = header.column.getCanSort();
const canFilter = header.column.getCanFilter();
const offset = useMemo(() => {
if (!pinned) {
return null;
}
return pinned === 'left' ? header.getStart() : table.getTotalSize() - header.getStart() - header.getSize();
}, [pinned, header, table]);
const {
density
} = useEds();
// Future improvement: If we down the line end up granting the ability to customize row height, we should move this to the table-context
const rowHeight = density === 'compact' ? 32 : 48;
const vertOffset = ctx.stickyHeader ? (header.depth - 1) * rowHeight : undefined;
const tableCellPadding = useMemo(() => {
if (canSort && canFilter) {
return '0 var(--eds_table__cell__padding_x, 16px) 0 0';
}
if (canSort) {
return '0';
}
return '0 var(--eds_table__cell__padding_x, 16px) 0 var(--eds_table__cell__padding_x, 16px)';
}, [canSort, canFilter]);
return header.isPlaceholder ? /*#__PURE__*/jsx(TableCell, {
$sticky: ctx.stickyHeader,
$offset: offset,
$pinned: pinned,
className: ctx.headerClass ? ctx.headerClass(header.column) : '',
style: {
...(ctx.headerStyle ? ctx.headerStyle(header.column) : {}),
top: vertOffset
},
"aria-hidden": true
}) : /*#__PURE__*/jsxs(TableCell, {
$sticky: ctx.stickyHeader,
$offset: offset,
$pinned: pinned,
$activeFilter: hasActiveFilters,
className: ctx.headerClass ? ctx.headerClass(header.column) : '',
"aria-sort": getSortLabel(header.column.getIsSorted()),
colSpan: header.colSpan,
style: {
width: header.getSize(),
verticalAlign: ctx.enableColumnFiltering ? 'top' : 'middle',
...(ctx.headerStyle ? ctx.headerStyle(header.column) : {}),
padding: tableCellPadding,
top: vertOffset
},
children: [canSort ? /*#__PURE__*/jsxs(SortButton, {
tabIndex: -1,
onClick: header.column.getToggleSortingHandler(),
"data-testid": `sort-button-${header.id}`,
children: [/*#__PURE__*/jsx(TableHeaderCellLabel, {
className: "table-header-cell-label",
children: flexRender(header.column.columnDef.header, header.getContext())
}), !header.column.columnDef.meta?.customFilterInput && /*#__PURE__*/jsx(SortIndicator, {
column: header.column
})]
}) : /*#__PURE__*/jsx(TableHeaderCellLabel, {
className: "table-header-cell-label",
children: flexRender(header.column.columnDef.header, header.getContext())
}), canFilter && !header.column.columnDef.meta?.customFilterInput ?
/*#__PURE__*/
// Supressing this warning - div is not interactive, but prevents propagation of events to avoid unintended sorting
// eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions
jsx(FilterVisibility, {
onClick: e => e.stopPropagation(),
children: /*#__PURE__*/jsx(FilterWrapper, {
column: header.column
})
}) : null, columnResizeMode && /*#__PURE__*/jsx(Resizer, {
onMouseDown: header.getResizeHandler(),
onTouchStart: header.getResizeHandler(),
$isResizing: header.column.getIsResizing(),
$columnResizeMode: columnResizeMode,
className: 'resize-handle',
"data-testid": 'resize-handle',
children: /*#__PURE__*/jsx(ResizeInner, {})
})]
}, header.id);
}
export { TableHeaderCell };