UNPKG

@itwin/itwinui-react

Version:

A react component library for iTwinUI

115 lines (114 loc) 3.62 kB
import { actions, makePropGetter, useGetLatest } from 'react-table'; import { styles } from '../../../styles.js'; let leftClassName = styles['iui-table-reorder-column-left']; let rightClassName = styles['iui-table-reorder-column-right']; let REORDER_ACTIONS = { columnDragStart: 'columnDragStart', columnDragEnd: 'columnDragEnd', }; export const useColumnDragAndDrop = (isEnabled) => (hooks) => { hooks.getDragAndDropProps = [defaultGetDragAndDropProps(isEnabled)]; hooks.stateReducers.push(reducer); hooks.useInstance.push(useInstance); }; let defaultGetDragAndDropProps = (isEnabled) => (props, { instance, header }) => { if (!isEnabled || header.disableReordering) return props; let onDragStart = () => { instance.dispatch({ type: REORDER_ACTIONS.columnDragStart, columnIndex: instance.flatHeaders.indexOf(header), }); }; let setOnDragColumnStyle = (event, position) => { let columnElement = event.currentTarget; if ('left' === position) { columnElement.classList.remove(rightClassName); columnElement.classList.add(leftClassName); } else if ('right' === position) { columnElement.classList.remove(leftClassName); columnElement.classList.add(rightClassName); } else { columnElement.classList.remove(leftClassName); columnElement.classList.remove(rightClassName); } }; let reorderColumns = (tableColumns, srcIndex, dstIndex) => { let newTableColumns = [...tableColumns]; let [removed] = newTableColumns.splice(srcIndex, 1); newTableColumns.splice(dstIndex, 0, removed); return newTableColumns; }; let onDragOver = (event) => { event.preventDefault(); let headerIndex = instance.flatHeaders.indexOf(header); if (instance.state.columnReorderStartIndex !== headerIndex) setOnDragColumnStyle( event, instance.state.columnReorderStartIndex > headerIndex ? 'left' : 'right', ); }; let onDragLeave = (event) => { setOnDragColumnStyle(event); }; let onDrop = (event) => { event.preventDefault(); setOnDragColumnStyle(event); let columnIds = instance.allColumns.map((x) => x.id); let srcIndex = instance.state.columnReorderStartIndex; let dstIndex = columnIds.findIndex((x) => x === header.id); if (srcIndex === dstIndex || -1 === srcIndex || -1 === dstIndex) return; instance.setColumnOrder(reorderColumns(columnIds, srcIndex, dstIndex)); instance.dispatch({ type: REORDER_ACTIONS.columnDragEnd, columnIndex: -1, }); }; return [ props, { draggable: true, onDragStart, onDragOver, onDragLeave, onDrop, }, ]; }; let reducer = (newState, action) => { switch (action.type) { case actions.init: return { ...newState, columnReorderStartIndex: -1, }; case REORDER_ACTIONS.columnDragStart: return { ...newState, columnReorderStartIndex: action.columnIndex, }; case REORDER_ACTIONS.columnDragEnd: return { ...newState, columnReorderStartIndex: -1, }; default: return newState; } }; let useInstance = (instance) => { let { flatHeaders, getHooks } = instance; let getInstance = useGetLatest(instance); flatHeaders.forEach((header) => { header.getDragAndDropProps = makePropGetter( getHooks().getDragAndDropProps, { instance: getInstance(), header, }, ); }); };