UNPKG

@coreui/react-pro

Version:

UI Components Library for React.js

378 lines (309 loc) 9.21 kB
import type { Column, ColumnFilter, ColumnFilterValue, Group, Item, Sorter, SorterValue, TableFilter, } from './types' export const filterColumns = ( items: Item[], columnFilter: boolean | ColumnFilter | undefined, columnFilterState: ColumnFilterValue, itemsDataColumns: string[], ): Item[] => { if (columnFilter && typeof columnFilter === 'object' && columnFilter.external) { return items } if (Object.entries(columnFilterState).length === 0) { return items } let filteredItems = [...items] for (const [key, value] of Object.entries(columnFilterState)) { if (typeof value === 'function') { filteredItems = filteredItems.filter((item) => value(item[key])) } else { const columnFilterValue = String(value).toLowerCase() if (columnFilterValue && itemsDataColumns.includes(key)) { filteredItems = filteredItems.filter((item) => String(item[key]).toLowerCase().includes(columnFilterValue), ) } } } return filteredItems } export const filterTable = ( items: Item[], tableFilter: boolean | TableFilter | undefined, tableFilterState: string, itemsDataColumns: string[], ): Item[] => { if ( !tableFilterState || (tableFilter && typeof tableFilter === 'object' && tableFilter.external) ) { return items } const filter = tableFilterState.toLowerCase() return items.filter((item) => itemsDataColumns.some((key) => String(item[key]).toLowerCase().includes(filter)), ) } export const getClickedColumnName = ( target: HTMLElement, columnNames: string[], selectable?: boolean, ): string => { const clickedCell = target.closest('td') if (!clickedCell) { return '' } const row = clickedCell.closest('tr') if (!row) { return '' } const cells = Array.from(row.children) let index = cells.indexOf(clickedCell) if (selectable) { index -= 1 } return columnNames[index] || '' } export const getColumnKey = (column: Column | string): string => typeof column === 'object' ? column.key : column export const getColumnLabel = (column: Column | string): string => typeof column === 'object' ? (column.label ?? pretifyName(column.key)) : pretifyName(column) export const getColumnName = (column: Column | string): string => typeof column === 'object' ? column.key : column export const getColumnNames = ( columns: (string | Column)[] | undefined, items: Item[], ): string[] => { if (columns) { const _columns = [] for (const column of columns) { if (typeof column === 'object' && column.children) { _columns.push(...getColumnNames(column.children, [])) continue } typeof column === 'object' ? _columns.push(column.key) : _columns.push(column) } return _columns } return getColumnNamesFromItems(items) } export const getColumns = (_columns: (Column | Group | string)[]): (Column | string)[] => { const columns = [] for (const column of _columns) { if (typeof column === 'object' && column.group && column.children) { columns.push(...getColumns(column.children)) continue } if (typeof column === 'object' && column.children) { columns.push(...getColumns(column.children)) } columns.push(column) } return columns } export const countColumns = (columns: Column[]): number => { let count = 0 for (const column of columns) { if (!column.children || column.children.length === 0) { count++ } else { count += countColumns(column.children) } } return count } export const getColumnGroups = (columns: (string | Column)[] | undefined): Group[][] => { const groups: Group[][] = [] const traverseColumns = (column: Column, deep = 0, colSpan = 0): Group[] => { const groups = [] if (column.children) { for (const _column of column.children) { if (!_column.group) { colSpan++ } groups.push(...traverseColumns(_column, deep + 1, colSpan)) } } if (typeof column === 'object' && column.group) { const { children, group, ...rest } = column groups.push({ deep: deep, label: group, ...(children && { colspan: countColumns(children) }), ...rest, }) } return groups } if (columns) { for (const column of columns) { if (typeof column === 'object' && column.group) { const objects = traverseColumns(column) if (objects) { for (const object of objects) { const { deep, ...rest } = object if (deep === undefined) { continue } for (let i = 0; i < deep; i++) { if (groups[i]) { continue } groups.push([]) } if (groups[deep]) { groups[deep].push(rest) } else { groups.push([rest]) } } } } } } return groups } export const getColumnNamesFromItems = (items: Item[]): string[] => Object.keys(items[0] || {}).filter((el) => el.charAt(0) !== '_') export const getColumnSorterFunction = (column: Column | undefined) => { if ( column && typeof column === 'object' && column.sorter && typeof column.sorter === 'function' ) { return column.sorter } return } export const getColumnSorterState = (key: string, sorterState?: SorterValue[]): string | number => { const state = sorterState && sorterState.find((el) => el.column === key) return state ? state.state : 0 } export const getColumnValues = (items: Item[], key: string): any[] => items.map((item) => item[key]) export const getTableDataCellProps = ( column: Column | string, item: Item, colName: string, ): Record<string, any> => { const props = { ...(typeof column === 'object' && column._colProps), ...item._cellProps?.all, ...item._cellProps?.[colName], } return props } export const getTableDataCellStyles = ( column: Column | string, item: Item, colName: string, ): Record<string, any> => { const styles = { ...(typeof column === 'object' && column._colStyle), ...item._cellStyle?.all, ...item._cellStyle?.[colName], } return styles } export const getTableHeaderCellProps = (column: Column | string) => typeof column === 'object' && column._props ? column._props : {} export const getTableHeaderCellStyles = ( column: Column | string, columnSorter: boolean | Sorter | undefined, ): Record<string, any> => { const style: Record<string, any> = {} const isSortable = columnSorter && (typeof column !== 'object' || (typeof column === 'object' && (column.sorter === undefined || column.sorter))) if (isSortable) { style.cursor = 'pointer' } if (typeof column === 'object' && column._style) { Object.assign(style, column._style) } return style } export const isSortable = ( index: number, columns: (string | Column)[] | undefined, columnSorter: boolean | Sorter | undefined, itemsDataColumns: string[], columnNames: string[], ): boolean => { const key = columnNames[index] const isDataColumn = itemsDataColumns.includes(key) const column = columns ? columns[index] : undefined return ( !!columnSorter && (!columns || typeof column !== 'object' || (typeof column === 'object' && (column.sorter === undefined || column.sorter))) && isDataColumn ) } export const pretifyName = (name: string): string => { return name .replace(/[-_.]/g, ' ') .replace(/ +/g, ' ') .replace(/([a-z0-9])([A-Z])/g, '$1 $2') .split(' ') .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) .join(' ') } export const sortBy = ( column: Column | undefined, items: Item[], key: string, order: SorterValue['state'], ): Item[] => { const sorterFunction = getColumnSorterFunction(column) const sortedItems = [...items].sort( sorterFunction || ((a, b) => { const valA = a[key] const valB = b[key] const aValue = typeof valA === 'number' ? valA : String(valA).toLowerCase() const bValue = typeof valB === 'number' ? valB : String(valB).toLowerCase() return aValue > bValue ? 1 : bValue > aValue ? -1 : 0 }), ) return order === 'desc' ? sortedItems.reverse() : sortedItems } export const sortItems = ( columns: (Column | string)[] | undefined, columnSorter: boolean | Sorter | undefined, items: Item[], itemsDataColumns: string[], sorterState: SorterValue[], ): Item[] => { if ( (columnSorter && typeof columnSorter === 'object' && columnSorter.external) || sorterState.length === 0 ) { return items } let sortedItems = [...items] for (const sorter of [...sorterState].reverse()) { const key = sorter.column const order = sorter.state const column = columns && (columns.find((column) => typeof column === 'object' && column.key === key) as | Column | undefined) if (!key || !itemsDataColumns.includes(key)) { continue } sortedItems = sortBy(column, sortedItems, key, order) } return sortedItems }