ahooks
Version:
react hooks library
90 lines (89 loc) • 3.2 kB
JavaScript
import isPlainObject from 'lodash/isPlainObject';
import useMemoizedFn from '../useMemoizedFn';
import { isFunction, isString } from '../utils';
import { useMemo, useState } from 'react';
function useSelections(items, options) {
var _a, _b;
let defaultSelected = [];
let itemKey;
if (Array.isArray(options)) {
defaultSelected = options;
}
else if (isPlainObject(options)) {
defaultSelected = (_a = options === null || options === void 0 ? void 0 : options.defaultSelected) !== null && _a !== void 0 ? _a : defaultSelected;
itemKey = (_b = options === null || options === void 0 ? void 0 : options.itemKey) !== null && _b !== void 0 ? _b : itemKey;
}
const getKey = (item) => {
if (isFunction(itemKey)) {
return itemKey(item);
}
if (isString(itemKey) && isPlainObject(item)) {
return item[itemKey];
}
return item;
};
const [selected, setSelected] = useState(defaultSelected);
const selectedMap = useMemo(() => {
const keyToItemMap = new Map();
if (!Array.isArray(selected)) {
return keyToItemMap;
}
selected.forEach((item) => {
keyToItemMap.set(getKey(item), item);
});
return keyToItemMap;
}, [selected]);
const isSelected = (item) => selectedMap.has(getKey(item));
const select = (item) => {
selectedMap.set(getKey(item), item);
setSelected(Array.from(selectedMap.values()));
};
const unSelect = (item) => {
selectedMap.delete(getKey(item));
setSelected(Array.from(selectedMap.values()));
};
const toggle = (item) => {
if (isSelected(item)) {
unSelect(item);
}
else {
select(item);
}
};
const selectAll = () => {
items.forEach((item) => {
selectedMap.set(getKey(item), item);
});
setSelected(Array.from(selectedMap.values()));
};
const unSelectAll = () => {
items.forEach((item) => {
selectedMap.delete(getKey(item));
});
setSelected(Array.from(selectedMap.values()));
};
const noneSelected = useMemo(() => items.every((item) => !selectedMap.has(getKey(item))), [items, selectedMap]);
const allSelected = useMemo(() => items.every((item) => selectedMap.has(getKey(item))) && !noneSelected, [items, selectedMap, noneSelected]);
const partiallySelected = useMemo(() => !noneSelected && !allSelected, [noneSelected, allSelected]);
const toggleAll = () => (allSelected ? unSelectAll() : selectAll());
const clearAll = () => {
selectedMap.clear();
setSelected([]);
};
return {
selected,
noneSelected,
allSelected,
partiallySelected,
setSelected,
isSelected,
select: useMemoizedFn(select),
unSelect: useMemoizedFn(unSelect),
toggle: useMemoizedFn(toggle),
selectAll: useMemoizedFn(selectAll),
unSelectAll: useMemoizedFn(unSelectAll),
clearAll: useMemoizedFn(clearAll),
toggleAll: useMemoizedFn(toggleAll),
};
}
export default useSelections;