@itwin/itwinui-react
Version:
A react component library for iTwinUI
115 lines (114 loc) • 3.62 kB
JavaScript
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,
},
);
});
};