ra-core
Version:
Core components of react-admin, a frontend Framework for building admin applications on top of REST services, using ES6, React
117 lines • 6.12 kB
JavaScript
import * as React from 'react';
import { useEffect, useMemo, useRef } from 'react';
import union from 'lodash/union';
import difference from 'lodash/difference';
import { OptionalResourceContextProvider, useResourceContext } from '../core';
import { useEvent } from '../util';
import { useListContextWithProps } from '../controller/list/useListContextWithProps';
import { DataTableConfigContext } from './DataTableConfigContext';
import { DataTableCallbacksContext } from './DataTableCallbacksContext';
import { DataTableDataContext } from './DataTableDataContext';
import { DataTableSelectedIdsContext } from './DataTableSelectedIdsContext';
import { DataTableSortContext } from './DataTableSortContext';
import { DataTableStoreContext } from './DataTableStoreContext';
export var DataTableBase = function DataTable(props) {
var resourceFromContext = useResourceContext(props);
var children = props.children, empty = props.empty, expand = props.expand, _a = props.hiddenColumns, hiddenColumns = _a === void 0 ? emptyArray : _a, hasBulkActions = props.hasBulkActions, hover = props.hover, loading = props.loading, isRowSelectable = props.isRowSelectable, isRowExpandable = props.isRowExpandable, resource = props.resource, rowClick = props.rowClick, _b = props.expandSingle, expandSingle = _b === void 0 ? false : _b;
var _c = useListContextWithProps(props), sort = _c.sort, data = _c.data, isPending = _c.isPending, onSelect = _c.onSelect, onToggleItem = _c.onToggleItem, selectedIds = _c.selectedIds, setSort = _c.setSort, total = _c.total;
var storeKey = props.storeKey || "".concat(resourceFromContext, ".datatable");
var handleSort = useEvent(function (event) {
event.stopPropagation();
if (!setSort)
return;
var newField = event.currentTarget.dataset.field || 'id';
var newOrder = (sort === null || sort === void 0 ? void 0 : sort.field) === newField
? (sort === null || sort === void 0 ? void 0 : sort.order) === 'ASC'
? 'DESC'
: 'ASC'
: event.currentTarget.dataset.order || 'ASC';
setSort({ field: newField, order: newOrder });
});
var lastSelected = useRef(null);
useEffect(function () {
if (!selectedIds || selectedIds.length === 0) {
lastSelected.current = null;
}
}, [JSON.stringify(selectedIds)]); // eslint-disable-line react-hooks/exhaustive-deps
// we manage row selection here instead of in the rows level to allow shift+click to select an array of rows
var handleToggleItem = useEvent(function (id, event) {
if (!data)
return;
var ids = data.map(function (record) { return record.id; });
var lastSelectedIndex = ids.indexOf(lastSelected.current);
// @ts-ignore FIXME useEvent prevents using event.currentTarget
lastSelected.current = event.target.checked ? id : null;
if (event.shiftKey && lastSelectedIndex !== -1) {
var index = ids.indexOf(id);
var idsBetweenSelections = ids.slice(Math.min(lastSelectedIndex, index), Math.max(lastSelectedIndex, index) + 1);
// @ts-ignore FIXME useEvent prevents using event.currentTarget
var newSelectedIds = event.target.checked
? union(selectedIds, idsBetweenSelections)
: difference(selectedIds, idsBetweenSelections);
onSelect === null || onSelect === void 0 ? void 0 : onSelect(isRowSelectable
? newSelectedIds.filter(function (id) {
return isRowSelectable(data.find(function (record) { return record.id === id; }));
})
: newSelectedIds);
}
else {
onToggleItem === null || onToggleItem === void 0 ? void 0 : onToggleItem(id);
}
});
var storeContextValue = useMemo(function () { return ({
storeKey: storeKey,
defaultHiddenColumns: hiddenColumns,
}); }, [storeKey, hiddenColumns]);
var configContextValue = useMemo(function () { return ({
expand: expand,
expandSingle: expandSingle,
hasBulkActions: hasBulkActions,
hover: hover,
}); }, [expand, expandSingle, hasBulkActions, hover]);
var callbacksContextValue = useMemo(function () { return ({
handleSort: setSort ? handleSort : undefined,
handleToggleItem: onToggleItem ? handleToggleItem : undefined,
isRowExpandable: isRowExpandable,
isRowSelectable: isRowSelectable,
onSelect: onSelect,
rowClick: rowClick,
}); }, [
setSort,
handleSort,
handleToggleItem,
isRowExpandable,
isRowSelectable,
onSelect,
onToggleItem,
rowClick,
]);
if (isPending === true) {
return loading;
}
/**
* Once loaded, the data for the list may be empty. Instead of
* displaying the table header with zero data rows,
* the DataTable displays the empty component.
*/
if (data == null || data.length === 0 || total === 0) {
if (empty) {
return empty;
}
return null;
}
/**
* After the initial load, if the data for the list isn't empty,
* and even if the data is refreshing (e.g. after a filter change),
* the DataTable displays the current data.
*/
return (React.createElement(DataTableStoreContext.Provider, { value: storeContextValue },
React.createElement(DataTableSortContext.Provider, { value: sort },
React.createElement(DataTableSelectedIdsContext.Provider, { value: selectedIds },
React.createElement(DataTableCallbacksContext.Provider, { value: callbacksContextValue },
React.createElement(DataTableConfigContext.Provider, { value: configContextValue },
React.createElement(OptionalResourceContextProvider, { value: resource },
React.createElement(DataTableDataContext.Provider, { value: data }, children))))))));
};
var emptyArray = [];
//# sourceMappingURL=DataTableBase.js.map