import PropTypes from 'prop-types';
import * as React from 'react';
import classNames from 'classnames';
import getProp from 'lodash/get';
import AutoSizer from '@box/react-virtualized/dist/commonjs/AutoSizer';
import Column from '@box/react-virtualized/dist/commonjs/Table/Column';
import Table from '@box/react-virtualized/dist/commonjs/Table';
import defaultTableRowRenderer from '@box/react-virtualized/dist/commonjs/Table/defaultRowRenderer';
import '@box/react-virtualized/styles.css';
import { withInfiniteLoader } from '../../../components/react-virtualized-helpers';
import { ContentExplorerModePropType, ItemsPropType, ItemsMapPropType } from '../prop-types';
import ItemListIcon from './ItemListIcon';
import ItemListLoadingPlaceholder from './ItemListLoadingPlaceholder';
import ItemListName from './ItemListName';
import ItemListButton from './ItemListButton';
import './ItemList.scss';
const TABLE_CELL_CLASS = 'table-cell';
const InfiniteLoaderTable = withInfiniteLoader(Table);
const DEFAULT_ROW_HEIGHT = 40;
const withAutoSizer = WrappedComponent => {
return props => {
return (
{({ width: w, height: h }) => }
);
};
};
const TableResponsive = withAutoSizer(Table);
const itemIconCellRenderer = rendererParams => {
const {
rowData: { type, extension, hasCollaborations, isExternallyOwned, archiveType },
columnData: { itemIconRenderer },
} = rendererParams;
return (
{itemIconRenderer ? (
itemIconRenderer(rendererParams)
) : (
)}
);
};
const isItemSelected = (itemId, selectedItems) => selectedItems[itemId] !== undefined;
const itemNameCellRenderer = rendererParams => {
const {
rowIndex,
rowData: { id, type, name, label },
columnData: { selectedItems, onItemNameClick, itemNameLinkRenderer },
} = rendererParams;
// loading placeholder may not have name and ItemListName requires name
return (
name && (
onItemNameClick(event, rowIndex)}
linkRenderer={itemNameLinkRenderer}
/>
)
);
};
const renderItemListButton = (contentExplorerMode, id, isActionDisabled, isDisabled, name, selectedItems) =>
name && (
);
const itemButtonCellRenderer = rendererParams => {
const {
columnData: { contentExplorerMode, itemButtonRenderer, selectedItems },
rowData: { id, isActionDisabled, isDisabled, name },
} = rendererParams;
return (
!isDisabled && (
{itemButtonRenderer
? itemButtonRenderer(rendererParams)
: renderItemListButton(contentExplorerMode, id, isActionDisabled, isDisabled, name, selectedItems)}
)
);
};
const itemLoadingPlaceholderRenderer = rendererParams => {
const { loadingPlaceholderColumnWidths, columnIndex } = rendererParams;
return (
);
};
const ItemList = ({
additionalColumns,
contentExplorerMode,
className = '',
isResponsive = false,
items,
numItemsPerPage,
numTotalItems,
selectedItems = {},
onItemClick,
onItemDoubleClick,
onItemNameClick,
onLoadMoreItems,
headerHeight,
headerRenderer,
itemIconRenderer,
itemNameLinkRenderer,
itemButtonRenderer,
itemRowRenderer = defaultTableRowRenderer,
noItemsRenderer,
width,
height,
rowHeight = DEFAULT_ROW_HEIGHT,
}) => {
const getRow = ({ index }) => items[index];
const getRowClassNames = (index, item) => {
let result = index === -1 ? 'table-header' : 'table-row';
if (isItemSelected(item.id, selectedItems)) {
result = classNames('is-selected', result);
}
if (item && (item.isDisabled || item.isLoading)) {
result = classNames('disabled', result);
}
return result;
};
const renderRow = rendererParams => {
const { index, key, style, className: rowClassName, columns } = rendererParams;
const item = items[index];
const itemRowClassname = classNames(rowClassName, getRowClassNames(index, item));
const testId = getProp(rendererParams, 'rowData.id', '');
if (item.isLoading) {
return (
{columns.map((column, columnIndex) => (
{itemLoadingPlaceholderRenderer({
item,
columnIndex,
})}
))}
);
}
const defaultRow = itemRowRenderer({
...rendererParams,
className: itemRowClassname,
});
return React.cloneElement(defaultRow, { 'data-testid': `item-row-${testId}` });
};
let TableComponent = isResponsive ? TableResponsive : Table;
const tableProps = {};
if (onLoadMoreItems) {
TableComponent = InfiniteLoaderTable;
tableProps.infiniteLoaderProps = {
isRowLoaded: getRow,
loadMoreRows: onLoadMoreItems,
minimumBatchSize: numItemsPerPage,
rowCount: numTotalItems,
threshold: numItemsPerPage,
};
}
if (!noItemsRenderer || items.length > 0) {
tableProps.headerHeight = headerHeight;
tableProps.headerRowRenderer = headerRenderer;
}
return (
);
};
ItemList.displayName = 'ItemList';
ItemList.propTypes = {
additionalColumns: PropTypes.arrayOf(PropTypes.element),
className: PropTypes.string,
contentExplorerMode: ContentExplorerModePropType.isRequired,
isResponsive: PropTypes.bool,
items: ItemsPropType.isRequired,
numItemsPerPage: PropTypes.number,
numTotalItems: PropTypes.number,
selectedItems: ItemsMapPropType.isRequired,
onItemClick: PropTypes.func,
onItemDoubleClick: PropTypes.func,
onItemNameClick: PropTypes.func,
onLoadMoreItems: PropTypes.func,
headerHeight: PropTypes.number,
headerRenderer: PropTypes.func,
itemIconRenderer: PropTypes.func,
itemNameLinkRenderer: PropTypes.func,
itemButtonRenderer: PropTypes.func,
itemRowRenderer: PropTypes.func,
noItemsRenderer: PropTypes.func,
width: PropTypes.number.isRequired,
height: PropTypes.number.isRequired,
rowHeight: PropTypes.number,
};
export { ItemList as ItemListBase };
export default ItemList;