UNPKG

@appbuckets/react-ui

Version:
283 lines (280 loc) 8.04 kB
import { __read, __spreadArray } from 'tslib'; import * as React from 'react'; import invariant from 'tiny-invariant'; import areEqualStringArray from '../../utils/areEqualStringArray.js'; import 'clsx'; /* -------- * Main Hook Definition * -------- */ function useDataSelector(config) { var allData = config.allData, filteredData = config.filteredData, selectable = config.selectable, defaultSelectedData = config.defaultSelectedData, userDefinedGetRowKey = config.getRowKey, onSelectedDataChange = config.onSelectedDataChange; // ---- // Memoize the RowKey extractor // ---- var getRowKey = React.useCallback( function (row, index, array) { if (typeof userDefinedGetRowKey === 'function') { return userDefinedGetRowKey(row, index, array); } if (typeof userDefinedGetRowKey === 'string') { return row[userDefinedGetRowKey]; } return ''; }, [userDefinedGetRowKey] ); // ---- // Invariant Check selectable and getRowKey // ---- if (process.env.NODE_ENV === 'development' && selectable) { invariant( typeof getRowKey === 'function', 'To correctly use selectable table the getRowKey' + 'function must be declared' ); } // ---- // Build a Map with all data keys // ---- var dataKeys = React.useMemo( function () { /** Build a new Map to save all data keys */ var keys = new Map(); /** Loop each row and get it's own key */ allData.forEach(function (row, index, array) { keys.set(row, getRowKey(row, index, array)); }); return keys; }, [allData, getRowKey] ); var filteredDataKeys = React.useMemo( function () { /** Build a new Map to save all data keys */ var keys = new Map(); /** Loop filtered data only and save key */ filteredData.forEach(function (row) { /** Get key from dataKeys */ var key = dataKeys.get(row); /** If exists, push into keys */ if (key !== undefined) { keys.set(row, key); } }); return keys; }, [dataKeys, filteredData] ); // ---- // Initialize Internal State to keep tracking of Selected Keys // ---- var _a = __read( React.useState( defaultSelectedData && selectable ? defaultSelectedData .filter(function (row) { return dataKeys.has(row); }) .map(function (row) { return dataKeys.get(row); }) : [] ), 2 ), selectedKeys = _a[0], setSelectedKeys = _a[1]; // ---- // Internal Helpers // ---- var getSelectedData = React.useCallback( function (currentSelected) { if (currentSelected === void 0) { currentSelected = selectedKeys; } return allData.filter(function (row) { /** Get the row key */ var key = dataKeys.get(row); /** Return key exists and is included into selectedKeys */ return key !== undefined && currentSelected.includes(key); }); }, [allData, dataKeys, selectedKeys] ); // ---- // Handlers // ---- var handleSelectedDataChange = React.useCallback( function (currentSelected) { if (typeof onSelectedDataChange === 'function') { onSelectedDataChange(getSelectedData(currentSelected)); } }, [getSelectedData, onSelectedDataChange] ); // ---- // Public Helpers // ---- var isRowSelected = React.useCallback( function (rowToCheck) { /** Get the row key */ var key = dataKeys.get(rowToCheck); /** Check if is selected */ return key !== undefined && selectedKeys.includes(key); }, [dataKeys, selectedKeys] ); var selectAllRows = React.useCallback( function () { /** Build an array of new Selected item using all keys */ var newSelected = __spreadArray( [], __read( new Set( __spreadArray( __spreadArray([], __read(selectedKeys), false), __read(Array.from(filteredDataKeys.values())), false ) ) ), false ); /** Update the state */ setSelectedKeys(function () { handleSelectedDataChange(newSelected); return newSelected; }); }, [filteredDataKeys, selectedKeys, handleSelectedDataChange] ); var deselectAllRows = React.useCallback( function () { /** Build a new empty array of selected keys */ var newSelected = []; /** Update the state */ setSelectedKeys(function () { handleSelectedDataChange(newSelected); return newSelected; }); }, [handleSelectedDataChange] ); var selectRow = React.useCallback( function () { var rows = []; for (var _i = 0; _i < arguments.length; _i++) { rows[_i] = arguments[_i]; } /** Transform rows into a React.Key array */ var rowsKey = rows .map(function (row) { return dataKeys.get(row); }) .filter(function (key) { return key !== undefined && !selectedKeys.includes(key); }); if (rowsKey.length) { var newSelected_1 = __spreadArray( __spreadArray([], __read(selectedKeys), false), __read(rowsKey), false ); setSelectedKeys(function () { handleSelectedDataChange(newSelected_1); return newSelected_1; }); } }, [dataKeys, handleSelectedDataChange, selectedKeys] ); var deselectRow = React.useCallback( function () { var rows = []; for (var _i = 0; _i < arguments.length; _i++) { rows[_i] = arguments[_i]; } /** Transform rows into a React.Key array */ var rowsKey = rows .map(function (row) { return dataKeys.get(row); }) .filter(function (key) { return key !== undefined && selectedKeys.includes(key); }); /** Remove found keys */ if (rowsKey.length) { var newSelected_2 = __spreadArray( [], __read(selectedKeys), false ).filter(function (key) { return !rowsKey.includes(key); }); setSelectedKeys(function () { handleSelectedDataChange(newSelected_2); return newSelected_2; }); } }, [dataKeys, handleSelectedDataChange, selectedKeys] ); var toggleSelectRow = React.useCallback( function (rowToToggle) { if (isRowSelected(rowToToggle)) { deselectRow(rowToToggle); } else { selectRow(rowToToggle); } }, [isRowSelected, deselectRow, selectRow] ); // ---- // Assert selectedKeys validity on data change // ---- React.useEffect( function () { /** Avoid is selecting is disabled */ if (!selectable) { return; } /** Get all selected keys */ var dataIDs = Array.from(dataKeys.values()); /** Build a new array of selected keys */ var newSelected = __spreadArray([], __read(selectedKeys), false).filter( function (key) { return dataIDs.includes(key); } ); /** If selected data is different, update state */ if (!areEqualStringArray(newSelected, selectedKeys)) { setSelectedKeys(function () { handleSelectedDataChange(newSelected); return newSelected; }); } }, [dataKeys, handleSelectedDataChange, selectable, selectedKeys] ); // ---- // Return Controller // ---- return { areAllRowsSelected: selectedKeys.length === allData.length, deselectAllRows: deselectAllRows, deselectRow: deselectRow, getRowKey: getRowKey, isRowSelected: isRowSelected, selectAllRows: selectAllRows, selectedData: getSelectedData(), selectedCount: selectedKeys.length, selectRow: selectRow, toggleSelectRow: toggleSelectRow, }; } export { useDataSelector as default };