@appbuckets/react-ui
Version:
Just Another React UI Framework
316 lines (309 loc) • 9.09 kB
JavaScript
;
var tslib = require('tslib');
var React = require('react');
var invariant = require('tiny-invariant');
var areEqualStringArray = require('../../utils/areEqualStringArray.js');
require('clsx');
function _interopDefaultLegacy(e) {
return e && typeof e === 'object' && 'default' in e ? e : { default: e };
}
function _interopNamespace(e) {
if (e && e.__esModule) return e;
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(
n,
k,
d.get
? d
: {
enumerable: true,
get: function () {
return e[k];
},
}
);
}
});
}
n['default'] = e;
return Object.freeze(n);
}
var React__namespace = /*#__PURE__*/ _interopNamespace(React);
var invariant__default = /*#__PURE__*/ _interopDefaultLegacy(invariant);
/* --------
* 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__namespace.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__default['default'](
typeof getRowKey === 'function',
'To correctly use selectable table the getRowKey' +
'function must be declared'
);
}
// ----
// Build a Map with all data keys
// ----
var dataKeys = React__namespace.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__namespace.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 = tslib.__read(
React__namespace.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__namespace.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__namespace.useCallback(
function (currentSelected) {
if (typeof onSelectedDataChange === 'function') {
onSelectedDataChange(getSelectedData(currentSelected));
}
},
[getSelectedData, onSelectedDataChange]
);
// ----
// Public Helpers
// ----
var isRowSelected = React__namespace.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__namespace.useCallback(
function () {
/** Build an array of new Selected item using all keys */
var newSelected = tslib.__spreadArray(
[],
tslib.__read(
new Set(
tslib.__spreadArray(
tslib.__spreadArray([], tslib.__read(selectedKeys), false),
tslib.__read(Array.from(filteredDataKeys.values())),
false
)
)
),
false
);
/** Update the state */
setSelectedKeys(function () {
handleSelectedDataChange(newSelected);
return newSelected;
});
},
[filteredDataKeys, selectedKeys, handleSelectedDataChange]
);
var deselectAllRows = React__namespace.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__namespace.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 = tslib.__spreadArray(
tslib.__spreadArray([], tslib.__read(selectedKeys), false),
tslib.__read(rowsKey),
false
);
setSelectedKeys(function () {
handleSelectedDataChange(newSelected_1);
return newSelected_1;
});
}
},
[dataKeys, handleSelectedDataChange, selectedKeys]
);
var deselectRow = React__namespace.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 = tslib
.__spreadArray([], tslib.__read(selectedKeys), false)
.filter(function (key) {
return !rowsKey.includes(key);
});
setSelectedKeys(function () {
handleSelectedDataChange(newSelected_2);
return newSelected_2;
});
}
},
[dataKeys, handleSelectedDataChange, selectedKeys]
);
var toggleSelectRow = React__namespace.useCallback(
function (rowToToggle) {
if (isRowSelected(rowToToggle)) {
deselectRow(rowToToggle);
} else {
selectRow(rowToToggle);
}
},
[isRowSelected, deselectRow, selectRow]
);
// ----
// Assert selectedKeys validity on data change
// ----
React__namespace.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 = tslib
.__spreadArray([], tslib.__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,
};
}
module.exports = useDataSelector;