Created
August 18, 2020 11:36
-
-
Save adamscybot/65df3ce2b155c20c8b867786ef612e72 to your computer and use it in GitHub Desktop.
Reac table v6 percentage column width plugin hook
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* This plugin hook for React table provides the ability for percentage | |
* widths to be provided in the column definitions, whilst maintaining the | |
* ability to resize those columns. | |
*/ | |
export const usePercentageColumns = hooks => { | |
hooks.useInstance.push(useInstance) | |
hooks.getRowProps.push(getRowStyles) | |
hooks.getHeaderProps.push(getHeaderProps) | |
hooks.getCellProps.push(getCellProps) | |
} | |
usePercentageColumns.pluginName = 'usePercentageColumns' | |
const getRowStyles = (props, { instance }) => [ | |
props, | |
{ | |
style: { | |
display: 'flex', | |
}, | |
}, | |
] | |
const generateStyleForHeader = column => { | |
return { | |
width: 'auto', | |
// Allows sizing column smaller than the content. | |
minWidth: 0, | |
// If its a percentage, grow and fill with that percentage as the flex basis. | |
// If its an absolute value treat it as a fact that the column must be that size. | |
flex: /^[0-9]+%$/.test(column.totalWidth) | |
? `1 1 ${column.totalWidth}` | |
: `0 0 ${column.totalWidth}px`, | |
} | |
} | |
const getHeaderProps = (props, { column }) => [ | |
props, | |
{ | |
// We get a reference to each header cell so we can | |
// measure it later to aid in resizing. | |
headerCellRef: el => { | |
if (el !== null) column.el = el | |
}, | |
style: generateStyleForHeader(column), | |
}, | |
] | |
const getCellProps = (props, { cell }) => { | |
return [ | |
props, | |
{ | |
style: generateStyleForHeader(cell.column), | |
}, | |
] | |
} | |
const useInstance = instance => { | |
// This resets the totalWidth from NaN caused by react-table assumption that provided widths | |
// are absolute values and not percentages. By putting it back to the percentage, it makes its | |
// way down to the styles of the cell. | |
instance.headers.forEach(header => { | |
if (/^[0-9]+%$/.test(header.width)) { | |
header.totalWidth = header.width | |
} | |
}) | |
// The purpose of this block of code is to compose a new mouse over function | |
// with the existing one from the resize column plugin hook. In this handler, | |
// we change the width from the percentage value to an absolute value, just before | |
// we call the resize column plugin hook handler. This is because that handler is | |
// designed only to work with absolute values. | |
instance.flatHeaders.forEach(header => { | |
if (header.getResizerProps) { | |
const oldGetResizeProps = header.getResizerProps | |
header.getResizerProps = userProps => { | |
const { | |
onMouseDown: oldOnMouseDown, | |
...propsToSpread | |
} = oldGetResizeProps(userProps) | |
return { | |
...propsToSpread, | |
onMouseDown: e => { | |
const headersToResize = getLeafHeaders(header) | |
headersToResize.forEach((header, index) => { | |
header.totalWidth = header.el.getBoundingClientRect().width | |
}) | |
return oldOnMouseDown(e, header) | |
}, | |
} | |
} | |
} | |
}) | |
} | |
function getLeafHeaders(header) { | |
const leafHeaders = [] | |
const recurseHeader = header => { | |
if (header.columns && header.columns.length) { | |
header.columns.map(recurseHeader) | |
} | |
leafHeaders.push(header) | |
} | |
recurseHeader(header) | |
return leafHeaders | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi @adamscybot I need to use relative units for react-table columns dimensions. Your gist gets an error on
header.totalWidth = header.el.getBoundingClientRect().width
because thisheaderCellRef: el => { if (el !== null) column.el = el },
Can you explain me how to use your solution?
Thanks