UNPKG

@hitachivantara/uikit-react-core

Version:

Core React components for the NEXT Design System.

170 lines (169 loc) 5.3 kB
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 };