/* * Copyright (c) Jupyter Development Team. * Distributed under the terms of the Modified BSD License. */ import React, { ReactElement, ReactNode, useState } from 'react'; import { caretDownIcon, caretUpIcon } from '../icon'; export const TABLE_CLASS = 'jp-sortable-table'; /** * A namespace for Table. */ export namespace Table { /** * The state which will be restored from layout tracker. */ export interface ISortState { sortKey?: string | null; sortDirection: -1 | 1; } /** * The initialization options for the table. */ export interface IOptions extends Partial { rows: IRow[]; columns: IColumn[]; onRowClick?: React.MouseEventHandler; blankIndicator: () => ReactNode; } /** * Table row with data to display. */ export interface IRow { data: T; key: string; } /** * Column definition. */ export interface IColumn { id: string; label: string; renderCell(data: T): ReactNode; sort(a: T, b: T): number | undefined; isAvailable?(): boolean; isHidden?: boolean; } } /** * Sortable table component for small datasets. * * For large datasets use `DataGrid` from `@lumino/datagrid`. */ export function Table(props: Table.IOptions) { const [sortState, setSortState] = useState({ sortKey: props.sortKey, sortDirection: props.sortDirection || 1 }); const sort = (key: string) => { if (key === sortState.sortKey) { setSortState({ sortKey: key, sortDirection: (sortState.sortDirection * -1) as -1 | 1 }); } else { setSortState({ sortKey: key, sortDirection: 1 }); } }; let rows = props.rows; const sortedColumn = props.columns.filter( column => column.id === sortState.sortKey )[0]; if (sortedColumn) { const sorter = sortedColumn.sort.bind(sortedColumn); rows = props.rows.sort( (a, b) => sorter(a.data, b.data) * sortState.sortDirection ); } const visibleColumns = props.columns.filter( column => (column.isAvailable ? column.isAvailable() : true) && !column.isHidden ); const elements = rows.map(row => { const cells = visibleColumns.map(column => ( {column.renderCell(row.data)} )); return ( {cells} ); }); const columnsHeaders = visibleColumns.map(column => ( { sort(column.id); }} /> )); return ( {columnsHeaders}{elements}
); } function SortableTH(props: { id: string; label: string; state: Table.ISortState; onSort: () => void; }): ReactElement { const isSortKey = props.id === props.state.sortKey; const sortIcon = !isSortKey || props.state.sortDirection === 1 ? caretUpIcon : caretDownIcon; return ( props.onSort()} className={isSortKey ? 'jp-sorted-header' : undefined} data-id={props.id} >
); }