UNPKG

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
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