@hitachivantara/uikit-react-core
Version:
Core React components for the NEXT Design System.
170 lines (169 loc) • 5.3 kB
JavaScript
import { useGetLatest, makePropGetter } from "react-table";
import { theme } from "@hitachivantara/uikit-styles";
const isSticky = (value) => /left|right/i.test(value);
const getStickyValue = ({ sticky, parent }) => {
if (isSticky(sticky)) {
return sticky;
}
if (parent != null) {
sticky = getStickyValue(parent);
if (isSticky(sticky)) {
return sticky;
}
const { columns } = parent;
if (columns?.length > 0) {
sticky = columns?.find((col) => col.sticky != null)?.sticky;
if (isSticky(sticky)) {
return sticky;
}
}
}
return void 0;
};
const updateColumnAndParent = (column, props) => {
Object.assign(column, props);
if (column.parent != null) {
updateColumnAndParent(column.parent, props);
}
};
const visibleColumnsHook = (columns, { instance }) => {
const toTheLeft = [];
const toTheRight = [];
const others = [];
columns.forEach((column) => {
const sticky = getStickyValue(column)?.toLowerCase();
updateColumnAndParent(column, { sticky });
if (sticky === "left") {
toTheLeft.push(column);
} else if (sticky === "right") {
toTheRight.push(column);
} else {
others.push(column);
}
});
if (others.length > 0) {
const [firstNotSticky] = others;
updateColumnAndParent(firstNotSticky, { isFirstNotSticky: true });
const lastNotSticky = others[others.length - 1];
updateColumnAndParent(lastNotSticky, { isLastNotSticky: true });
}
const hasLeftSticky = toTheLeft.length > 0;
if (hasLeftSticky) {
const lastLeftSticky = toTheLeft[toTheLeft.length - 1];
updateColumnAndParent(lastLeftSticky, { isLastLeftSticky: true });
}
const hasRightSticky = toTheRight.length > 0;
if (hasRightSticky) {
const [firstRightSticky] = toTheRight;
updateColumnAndParent(firstRightSticky, { isFirstRightSticky: true });
}
instance.hasStickyColumns = hasLeftSticky || hasRightSticky;
return [...toTheLeft, ...others, ...toTheRight];
};
const calculateHeaderWidthsToTheRight = (headers, right = 0) => {
if (!headers?.length) {
return;
}
for (let i = headers.length - 1; i !== -1; i -= 1) {
const header = headers[i];
header.totalRight = right;
const { headers: subHeaders } = header;
if (subHeaders?.length > 0) {
calculateHeaderWidthsToTheRight(subHeaders, right);
}
if (header.isVisible) {
right += header.totalWidth;
}
}
};
const useInstanceHook = (instance) => {
calculateHeaderWidthsToTheRight(instance.headers);
const getInstance = useGetLatest(instance);
instance.getTableHeadProps = makePropGetter(
instance.getHooks().getTableHeadProps,
{
instance: getInstance()
}
);
};
const getRowProps = () => ({
style: {
display: "flex",
flex: "1 0 auto"
}
});
const getCellProps = (header, isHeaderCell) => {
const props = {
style: {
display: "inline-flex",
flex: `${header.totalWidth} ${header.totalMinWidth} auto`,
alignItems: isHeaderCell ? "start" : "center",
justifyContent: header.align,
width: `${header.totalWidth}px`,
minWidth: `${header.totalMinWidth}px`,
...isHeaderCell && { backgroundColor: theme.colors.bgPage }
}
};
if (header.sticky != null) {
props.stickyColumn = true;
const margin = header.sticky === "left" ? header.totalLeft : header.totalRight;
props.style[header.sticky] = `${margin}px`;
if (header.isLastLeftSticky) {
props.stickyColumnMostLeft = true;
}
if (header.isFirstRightSticky) {
props.stickyColumnLeastRight = true;
}
} else {
if (header.isFirstNotSticky) {
props.style.borderLeft = 0;
}
if (header.isLastNotSticky) {
props.style.borderRight = 0;
}
}
return props;
};
const getTablePropsHook = (props, { instance }) => {
const nextProps = {
stickyHeader: instance.stickyHeader,
stickyColumns: instance.hasStickyColumns
};
return [props, nextProps];
};
const getTableHeadPropsHook = (props, { instance }) => {
const nextProps = {
stickyHeader: instance.stickyHeader
};
return [props, nextProps];
};
const getHeaderGroupPropsHook = (props, { instance }) => {
const nextProps = instance.hasStickyColumns ? getRowProps() : {};
return [props, nextProps];
};
const getHeaderPropsHook = (props, { instance, column }) => {
const nextProps = instance.hasStickyColumns ? getCellProps(column, true) : {};
return [props, nextProps];
};
const getRowPropsHook = (props, { instance }) => {
const nextProps = instance.hasStickyColumns ? getRowProps() : {};
return [props, nextProps];
};
const getCellPropsHook = (props, { instance, cell }) => {
const nextProps = instance.hasStickyColumns ? getCellProps(cell.column, false) : {};
return [props, nextProps];
};
const useHvTableSticky = (hooks) => {
hooks.visibleColumns.push(visibleColumnsHook);
hooks.useInstance.push(useInstanceHook);
hooks.getTableProps.push(getTablePropsHook);
hooks.getTableHeadProps = [getTableHeadPropsHook];
hooks.getHeaderGroupProps.push(getHeaderGroupPropsHook);
hooks.getHeaderProps.push(getHeaderPropsHook);
hooks.getRowProps.push(getRowPropsHook);
hooks.getCellProps.push(getCellPropsHook);
};
useHvTableSticky.pluginName = "useHvTableSticky";
export {
useHvTableSticky
};