UNPKG

use-table-drag-select

Version:
248 lines (243 loc) 8.8 kB
import { useRef, useState, useCallback, useEffect } from 'react'; function _iterableToArrayLimit(arr, i) { var _i = null == arr ? null : "undefined" != typeof Symbol && arr[Symbol.iterator] || arr["@@iterator"]; if (null != _i) { var _s, _e, _x, _r, _arr = [], _n = !0, _d = !1; try { if (_x = (_i = _i.call(arr)).next, 0 === i) { if (Object(_i) !== _i) return; _n = !1; } else for (; !(_n = (_s = _x.call(_i)).done) && (_arr.push(_s.value), _arr.length !== i); _n = !0); } catch (err) { _d = !0, _e = err; } finally { try { if (!_n && null != _i.return && (_r = _i.return(), Object(_r) !== _r)) return; } finally { if (_d) throw _e; } } return _arr; } } function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); } function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function isMouseEvent(event) { return event instanceof MouseEvent; } function isTouchEvent(event) { return 'ontouchstart' in window && event.type.startsWith('touch'); } function convertIndexToString(rowIndex, colIndex) { return "".concat(rowIndex, "-").concat(colIndex); } function convertStringToIndex(indexString) { if (!indexString.includes('-')) { throw new Error('indexString must be in the format of "rowIndex-colIndex"'); } return indexString.split('-').map(Number); } function getTableCellElement(e) { var target; if (isTouchEvent(e) && e.touches) { var _e$touches$ = e.touches[0], clientX = _e$touches$.clientX, clientY = _e$touches$.clientY; target = document.elementFromPoint(clientX, clientY); } else if (isMouseEvent(e)) { target = e.target; } if (target instanceof HTMLTableCellElement && target.tagName === 'TD') { return target; } return null; } function getTableCellIndex(e) { var rowIndex = null; var colIndex = null; var target = getTableCellElement(e); if (!target) { return null; } if (target.parentNode instanceof HTMLTableRowElement) { var tr = target.parentNode; rowIndex = tr.sectionRowIndex; var tds = tr.querySelectorAll('td'); for (var i = 0; i < tds.length; i++) { if (tds[i] === target) { colIndex = i; break; } } } if (rowIndex === null || colIndex === null) { return null; } return { rowIndex: rowIndex, colIndex: colIndex }; } function useTableDragSelect(initialTable) { var startIndex = useRef(''); var currentIndex = useRef(''); var startTable = useRef([]); var mode = useRef(false); var tableRef = useRef(null); var _useState = useState(initialTable !== null && initialTable !== void 0 ? initialTable : []), _useState2 = _slicedToArray(_useState, 2), tableValue = _useState2[0], setTableValue = _useState2[1]; var handlePointerStart = useCallback(function (e) { var index = getTableCellIndex(e); if (index === null) { return; } if (isTouchEvent(e) && e.cancelable) { e.preventDefault(); } var rowIndex = index.rowIndex, colIndex = index.colIndex; startTable.current = _toConsumableArray(tableValue); startIndex.current = convertIndexToString(rowIndex, colIndex); var newTableValues = _toConsumableArray(tableValue); mode.current = !newTableValues[rowIndex][colIndex]; newTableValues[rowIndex][colIndex] = mode.current; setTableValue(newTableValues); }, [tableValue]); var handlePointerMove = useCallback(function (e) { if (startIndex.current === '') { return; } if (isMouseEvent(e) && e.buttons !== 1) { return; } var index = getTableCellIndex(e); if (index === null) { return; } var rowIndex = index.rowIndex, colIndex = index.colIndex; var indexString = convertIndexToString(rowIndex, colIndex); var isSameAsPrevIndex = indexString === currentIndex.current; if (isSameAsPrevIndex) { return; } currentIndex.current = indexString; var _convertStringToIndex = convertStringToIndex(startIndex.current), _convertStringToIndex2 = _slicedToArray(_convertStringToIndex, 2), startRowIndex = _convertStringToIndex2[0], startColIndex = _convertStringToIndex2[1]; var _sort = [startRowIndex, rowIndex].sort(function (a, b) { return a - b; }), _sort2 = _slicedToArray(_sort, 2), minRow = _sort2[0], maxRow = _sort2[1]; var _sort3 = [startColIndex, colIndex].sort(function (a, b) { return a - b; }), _sort4 = _slicedToArray(_sort3, 2), minCol = _sort4[0], maxCol = _sort4[1]; var newTableValues = tableValue.map(function (row) { return row.slice(); }); newTableValues.forEach(function (r, i) { r.forEach(function (_, j) { if (i < minRow || i > maxRow || j < minCol || j > maxCol) { newTableValues[i][j] = startTable.current[i][j]; } else { newTableValues[i][j] = mode.current; } }); }); setTableValue(newTableValues); }, [tableValue]); var handlePointerEnd = useCallback(function (e) { startIndex.current = ''; if (e.cancelable) { e.preventDefault(); } }, []); useEffect(function () { var _tableRef$current$que, _tableRef$current; var node = (_tableRef$current$que = (_tableRef$current = tableRef.current) === null || _tableRef$current === void 0 ? void 0 : _tableRef$current.querySelector('tbody')) !== null && _tableRef$current$que !== void 0 ? _tableRef$current$que : tableRef.current; if (!initialTable && node) { var trs = node.querySelectorAll('tr'); var newTableValues = []; trs.forEach(function (tr) { var tds = tr.querySelectorAll('td'); var row = []; tds.forEach(function () { row.push(false); }); if (tds.length > 0) { newTableValues.push(row); } }); setTableValue(newTableValues); } }, [initialTable]); useEffect(function () { var _tableRef$current$que2, _tableRef$current2; var node = (_tableRef$current$que2 = (_tableRef$current2 = tableRef.current) === null || _tableRef$current2 === void 0 ? void 0 : _tableRef$current2.querySelector('tbody')) !== null && _tableRef$current$que2 !== void 0 ? _tableRef$current$que2 : tableRef.current; if (!node) { return; } node.addEventListener('touchstart', handlePointerStart); node.addEventListener('mousedown', handlePointerStart); node.addEventListener('touchmove', handlePointerMove); node.addEventListener('mouseover', handlePointerMove); node.addEventListener('touchend', handlePointerEnd); node.addEventListener('mouseup', handlePointerEnd); return function () { node.removeEventListener('touchstart', handlePointerStart); node.removeEventListener('mousedown', handlePointerStart); node.removeEventListener('touchmove', handlePointerMove); node.removeEventListener('mouseover', handlePointerMove); node.removeEventListener('touchend', handlePointerEnd); node.addEventListener('mouseup', handlePointerEnd); }; }, [handlePointerStart, handlePointerMove, handlePointerEnd]); return [tableRef, tableValue]; } export { useTableDragSelect };