react-table-sticky
Version:
Sticky components for react-table v7
111 lines (110 loc) • 4.77 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.checkErrors = (columns) => {
const hasGroups = !!columns.find((column) => column.parent);
const stickyColumnsWithoutGroup = columns.filter((column) => column.sticky && !column.parent).map(({ Header }) => `'${Header}'`);
if (hasGroups && stickyColumnsWithoutGroup.length) {
throw new Error(`WARNING react-table-sticky:
\nYour ReactTable has group and sticky columns outside groups, and that will break UI.
\nYou must place ${stickyColumnsWithoutGroup.join(' and ')} columns into a group (even a group with an empty Header label)\n`);
}
const bugWithUnderColumnsSticky = columns.find((parentCol) => !parentCol.sticky && parentCol.columns && parentCol.columns.find((col) => col.sticky));
if (!bugWithUnderColumnsSticky)
return;
// @ts-ignore
const childBugs = bugWithUnderColumnsSticky.columns.find(({ sticky }) => sticky);
if (!childBugs)
return;
throw new Error(`WARNING react-table-sticky:
\nYour ReactTable contain columns group with at least one child columns sticky.
\nWhen ReactTable has columns groups, only columns groups can be sticky
\nYou must set sticky: 'left' | 'right' for the '${bugWithUnderColumnsSticky.Header}'
column, or remove the sticky property of '${childBugs.Header}' column.`);
};
function getStickyValue(column) {
if (column.sticky === 'left' || column.sticky === 'right') {
return column.sticky;
}
if (column.parent) {
return getStickyValue(column.parent);
}
return null;
}
exports.getStickyValue = getStickyValue;
function columnIsLastLeftSticky(columnId, columns) {
const index = columns.findIndex(({ id }) => id === columnId);
const column = columns[index];
const nextColumn = columns[index + 1];
const columnIsLeftSticky = getStickyValue(column) === 'left';
const nextColumnIsLeftSticky = nextColumn && getStickyValue(nextColumn) === 'left';
return columnIsLeftSticky && !nextColumnIsLeftSticky;
}
exports.columnIsLastLeftSticky = columnIsLastLeftSticky;
function columnIsFirstRightSticky(columnId, columns) {
const index = columns.findIndex(({ id }) => id === columnId);
const column = columns[index];
const prevColumn = columns[index - 1];
const columnIsRightSticky = getStickyValue(column) === 'right';
const prevColumnIsRightSticky = prevColumn && getStickyValue(prevColumn) === 'right';
return columnIsRightSticky && !prevColumnIsRightSticky;
}
exports.columnIsFirstRightSticky = columnIsFirstRightSticky;
function getMarginRight(columnId, columns) {
const currentIndex = columns.findIndex(({ id }) => id === columnId);
let rightMargin = 0;
for (let i = currentIndex + 1; i < columns.length; i += 1) {
if (columns[i].isVisible !== false) {
rightMargin += columns[i].width;
}
}
return rightMargin;
}
exports.getMarginRight = getMarginRight;
const cellStylesSticky = {
// hard coded inline style will be remove in the next major release
position: 'sticky',
zIndex: 3,
};
function findHeadersSameLevel(header, headers) {
return headers.filter((flatHeaderItem) => {
return flatHeaderItem.depth === header.depth;
});
}
function getStickyProps(header, instance) {
let style = {};
const dataAttrs = {};
exports.checkErrors(instance.columns);
const sticky = getStickyValue(header);
if (sticky) {
style = Object.assign({}, cellStylesSticky);
// @ts-ignore
dataAttrs['data-sticky-td'] = true;
const headers = findHeadersSameLevel(header, instance.flatHeaders);
const margin = sticky === 'left'
? header.totalLeft
: getMarginRight(header.id, headers);
style = Object.assign(Object.assign({}, style), { [sticky]: `${margin}px` });
const isLastLeftSticky = columnIsLastLeftSticky(header.id, headers);
if (isLastLeftSticky) {
// @ts-ignore
dataAttrs['data-sticky-last-left-td'] = true;
}
const isFirstRightSticky = columnIsFirstRightSticky(header.id, headers);
if (isFirstRightSticky) {
// @ts-ignore
dataAttrs['data-sticky-first-right-td'] = true;
}
}
return Object.assign({ style }, dataAttrs);
}
exports.useSticky = (hooks) => {
hooks.getHeaderProps.push((props, { instance, column }) => {
const nextProps = getStickyProps(column, instance);
return [props, nextProps];
});
hooks.getCellProps.push((props, { instance, cell }) => {
const nextProps = getStickyProps(cell.column, instance);
return [props, nextProps];
});
};
exports.useSticky.pluginName = 'useSticky';
;