Skip to content

Instantly share code, notes, and snippets.

@gargroh
Created December 12, 2019 11:26
Show Gist options
  • Save gargroh/8229b17c3dca3eecfdc7d5fc0e777f18 to your computer and use it in GitHub Desktop.
Save gargroh/8229b17c3dca3eecfdc7d5fc0e777f18 to your computer and use it in GitHub Desktop.

Revisions

  1. gargroh created this gist Dec 12, 2019.
    158 changes: 158 additions & 0 deletions useCellRangeSelection.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,158 @@
    import React from 'react';

    import {
    actions,
    makePropGetter,
    ensurePluginOrder,
    functionalUpdate,
    useConsumeHookGetter,
    useGetLatest
    } from '../../react-table/utils';

    // Actions
    actions.cellRangeSelectionStart = 'cellRangeSelectionStart';
    actions.cellRangeSelecting = 'cellRangeSelecting';
    actions.cellRangeSelectionEnd = 'cellRangeSelectionEnd';

    const defaultgetCellRangeSelectionProps = (props, instance, row, cell) => {
    const { dispatch } = instance;

    const dispatchStart = (from) => dispatch({ type: actions.cellRangeSelectionStart, from });
    const dispatchEnd = (to) => dispatch({ type: actions.cellRangeSelectionEnd, to });

    return [
    props,
    {
    onMouseDown: (e) => {
    const from = [row.selectIndex, cell.column.selectIndex];

    dispatchStart(from);

    console.log(e, from);
    console.log('row', row);
    console.log('cell', cell);
    },
    onMouseUp: (e) => {
    const to = [row.selectIndex, cell.column.selectIndex];
    dispatchEnd(to);
    }
    }
    ];
    };

    export const useCellRangeSelection = (hooks) => {
    hooks.getCellRangeSelectionProps = [defaultgetCellRangeSelectionProps];
    hooks.stateReducers.push(reducer);
    hooks.useInstance.push(useInstance);
    };

    useCellRangeSelection.pluginName = 'useCellRangeSelection';

    // Reducer
    function reducer(state, action) {
    if (action.type === actions.init) {
    return {
    selectedCells: [],
    ...state
    };
    }

    if (action.type === actions.cellRangeSelectionStart) {
    // todo: use actions.from to derive selectedCells;

    return {
    ...state,
    selectedCells: []
    };
    }
    if (action.type === actions.cellRangeSelecting) {
    // todo: use actions.... to derive selectedCells;

    return {
    ...state,
    selectedCells: []
    };
    }
    if (action.type === actions.cellRangeSelectionEnd) {
    // todo: use actions.to to derive selectedCells;

    return {
    ...state,
    selectedCells: []
    };
    }
    }

    function useInstance(instance) {
    const {
    hooks,
    plugins,
    selectableCells = true,
    state: { selectedCells },
    dispatch
    } = instance;

    ensurePluginOrder(
    plugins,
    ['useFilters', 'useGroupBy', 'useSortBy'],
    'useCellRangeSelection',
    []
    );

    const cellRangeSelectionStart = React.useCallback(
    (clickedRow) => {
    return dispatch({ type: actions.cellRangeSelectionStart, clickedRow });
    },
    [dispatch]
    );

    const getInstance = useGetLatest(instance);

    const getCellRangeSelectionProps = useConsumeHookGetter(
    getInstance().hooks,
    'getCellRangeSelectionProps'
    );

    hooks.prepareRow.push((row) => {
    // todo: Get row index in final set of rows
    row.selectIndex = 0;

    if (selectableCells) {
    row.cells.forEach((cell, index) => {
    cell.selectIndex = index;

    // todo: use selectedCells state to mark cell as selected
    if (false) {
    cell.selected = true;
    }

    cell.getCellRangeSelectionProps = makePropGetter(
    getCellRangeSelectionProps(),
    getInstance(),
    row,
    cell
    );
    });
    }
    });

    Object.assign(instance, {
    cellRangeSelectionStart
    });
    }

    function getBetweenCells(r1, c1, r2, c2, data) {
    const startRow = Math.min(r1, r2);
    const endRow = Math.max(r1, r2);
    const startCol = Math.min(c1, c2);
    const endCol = Math.max(c1, c2);

    const arr = [];

    for (let i = startRow; i <= endRow; i++) {
    for (let j = startCol; j <= endCol; j++) {
    arr.push(data[i][j]);
    }
    }
    return arr;
    }