Created
November 14, 2019 10:14
-
-
Save gargroh/ab11066424a0bdc775fe0f7eeb451a16 to your computer and use it in GitHub Desktop.
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
import React from 'react'; | |
import PropTypes from 'prop-types'; | |
import { | |
ensurePluginOrder, | |
getFirstDefined, | |
makeHeaderGroups, | |
applyPropHooks, | |
mergeProps, | |
flexRender | |
} from '../utils'; | |
import { addActions, actions } from '../actions'; | |
import { defaultState, calculateHeaderWidths, renderErr } from '../hooks/useTable'; | |
defaultState.pinnedColumns = {}; | |
addActions('setColumnPin'); | |
const propTypes = {}; | |
export const usePinColumns = (hooks) => { | |
hooks.useMain.push(useMain); | |
}; | |
usePinColumns.pluginName = 'usePinColumns'; | |
const COLUMN_PINS = { | |
left: -1, | |
center: 0, | |
right: 1 | |
}; | |
function useMain(instance) { | |
PropTypes.checkPropTypes(propTypes, instance, 'property', 'usePinColumns'); | |
const { | |
plugins, | |
flatHeaders, | |
disablePinning, | |
state: { pinnedColumns }, | |
setState | |
} = instance; | |
ensurePluginOrder(plugins, ['useColumnOrder'], 'usePinColumns', []); | |
const setColumnPin = React.useCallback( | |
(updater) => { | |
return setState((old) => { | |
return { | |
...old, | |
pinnedColumns: typeof updater === 'function' ? updater(old.pinnedColumns) : updater | |
}; | |
}, actions.setColumnPin); | |
}, | |
[setState] | |
); | |
flatHeaders.forEach((column) => { | |
const { disablePinning: columnDisablePinning, accessor } = column; | |
const canPin = accessor | |
? getFirstDefined( | |
columnDisablePinning === true ? false : undefined, | |
disablePinning === true ? false : undefined, | |
true | |
) | |
: false; | |
column.canPin = canPin; | |
column.pinType = pinnedColumns[column.id] || 0; | |
column.setColumnPin = (pinType) => { | |
column.pinType = pinType; | |
setColumnPin({ | |
...pinnedColumns, | |
[column.id]: pinType | |
}); | |
}; | |
column.toggleColumnPin = (pinType) => { | |
let setPinValue = column.pinType === pinType ? 0 : pinType; | |
column.setColumnPin(setPinValue); | |
}; | |
}); | |
const pinnedDetails = getPinnedHeaderGroups(instance); | |
return { | |
...instance, | |
setColumnPin, | |
...pinnedDetails | |
}; | |
} | |
function getPinnedHeaderGroups(instance) { | |
const { | |
state: { pinnedColumns }, | |
flatColumns, | |
defaultColumn | |
} = instance; | |
let columnMapBySegments = { | |
left: [], | |
right: [], | |
center: [] | |
}; | |
flatColumns.forEach((column) => { | |
const pinValue = pinnedColumns[column.id]; | |
switch (pinValue) { | |
case COLUMN_PINS.left: | |
columnMapBySegments.left.push(column); | |
break; | |
case COLUMN_PINS.right: | |
columnMapBySegments.right.push(column); | |
break; | |
default: | |
columnMapBySegments.center.push(column); | |
} | |
}); | |
let pinnedHeaderGroup = []; | |
let pinnedflatHeaders = []; | |
//todo, use constants | |
['left', 'center', 'right'].forEach((segment, index) => { | |
const hgrp = makeHeaderGroups(columnMapBySegments[segment], defaultColumn); | |
addPinTypeInfo(hgrp, index - 1); | |
determineHeaderVisibility(hgrp[0].headers, instance); | |
calculateHeaderWidths(hgrp[0].headers); | |
const flatHeaders = hgrp.reduce((all, headerGroup) => [...all, ...headerGroup.headers], []); | |
pinnedflatHeaders = [...pinnedflatHeaders, ...flatHeaders]; | |
materializeHeaders(flatHeaders, instance); | |
materializeHeaderGroups(hgrp, instance); | |
pinnedHeaderGroup = [...pinnedHeaderGroup, ...hgrp]; | |
}); | |
return { | |
headerGroups: pinnedHeaderGroup, | |
flatHeaders: pinnedflatHeaders | |
}; | |
} | |
// Todo: This will come via common place i.e. utils for both useTable and usePinColumns | |
function materializeHeaders(flatHeaders, instance) { | |
flatHeaders.forEach((column) => { | |
// Give columns/headers rendering power | |
column.render = (type, userProps = {}) => { | |
const Comp = typeof type === 'string' ? column[type] : type; | |
if (typeof Comp === 'undefined') { | |
throw new Error(renderErr); | |
} | |
return flexRender(Comp, { | |
...instance, | |
column, | |
...userProps | |
}); | |
}; | |
// Give columns/headers a default getHeaderProps | |
column.getHeaderProps = (props) => | |
mergeProps( | |
{ | |
key: ['header', column.id].join('_'), | |
colSpan: column.totalVisibleHeaderCount | |
}, | |
applyPropHooks(instance.hooks.getHeaderProps, column, instance.current), | |
props | |
); | |
}); | |
} | |
// Todo: This will come via common place i.e. utils for both useTable and usePinColumns | |
function materializeHeaderGroups(headerGroups, instance) { | |
headerGroups.forEach((headerGroup, i) => { | |
// Filter out any headers and headerGroups that don't have visible columns | |
headerGroup.headers = headerGroup.headers.filter((header) => { | |
const recurse = (headers) => | |
headers.filter((header) => { | |
if (header.headers) { | |
return recurse(header.headers); | |
} | |
return header.isVisible; | |
}).length; | |
if (header.headers) { | |
return recurse(header.headers); | |
} | |
return header.isVisible; | |
}); | |
// Give headerGroups getRowProps | |
if (headerGroup.headers.length) { | |
headerGroup.getHeaderGroupProps = (props = {}) => | |
mergeProps( | |
{ | |
key: [`header${i}`].join('_') | |
}, | |
applyPropHooks(instance.hooks.getHeaderGroupProps, headerGroup, instance), | |
props | |
); | |
return true; | |
} | |
}); | |
} | |
// Todo: This will come via common place i.e. utils for both useTable and usePinColumns | |
function determineHeaderVisibility(headers, instance) { | |
const handleColumn = (column, parentVisible) => { | |
column.isVisible = parentVisible | |
? typeof column.show === 'function' | |
? column.show(instance) | |
: true //!!column.show // todo | |
: false; | |
let totalVisibleHeaderCount = 0; | |
if (column.headers && column.headers.length) { | |
column.headers.forEach( | |
(subColumn) => (totalVisibleHeaderCount += handleColumn(subColumn, column.isVisible)) | |
); | |
} else { | |
totalVisibleHeaderCount = column.isVisible ? 1 : 0; | |
} | |
column.totalVisibleHeaderCount = totalVisibleHeaderCount; | |
console.log(column.id, totalVisibleHeaderCount, column.headers, column.isVisible); | |
return totalVisibleHeaderCount; | |
}; | |
let totalVisibleHeaderCount = 0; | |
headers.forEach((subHeader) => (totalVisibleHeaderCount += handleColumn(subHeader, true))); | |
} | |
function addPinTypeInfo(headerGroups, pinType) { | |
const recurse = (headers) => { | |
headers.forEach((header) => { | |
// console.log(header.id, 'id'); | |
header.pinType = pinType; | |
if (header.headers && header.headers.length) { | |
recurse(header.headers); | |
} | |
}); | |
}; | |
headerGroups.forEach((headerGroup) => { | |
headerGroup.pinType = pinType; | |
recurse(headerGroup.headers); | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment