import { TableFeature } from '../core/table' import { Cell, Column, OnChangeFn, Table, Updater, Row, RowData, } from '../types' import { makeStateUpdater, memo } from '../utils' export type VisibilityState = Record export interface VisibilityTableState { columnVisibility: VisibilityState } export interface VisibilityOptions { onColumnVisibilityChange?: OnChangeFn enableHiding?: boolean } export interface VisibilityDefaultOptions { onColumnVisibilityChange: OnChangeFn } export interface VisibilityInstance { getVisibleFlatColumns: () => Column[] getVisibleLeafColumns: () => Column[] getLeftVisibleLeafColumns: () => Column[] getRightVisibleLeafColumns: () => Column[] getCenterVisibleLeafColumns: () => Column[] setColumnVisibility: (updater: Updater) => void resetColumnVisibility: (defaultState?: boolean) => void toggleAllColumnsVisible: (value?: boolean) => void getIsAllColumnsVisible: () => boolean getIsSomeColumnsVisible: () => boolean getToggleAllColumnsVisibilityHandler: () => (event: unknown) => void } export interface VisibilityColumnDef { enableHiding?: boolean } export interface VisibilityRow { _getAllVisibleCells: () => Cell[] getVisibleCells: () => Cell[] } export interface VisibilityColumn { getCanHide: () => boolean getIsVisible: () => boolean toggleVisibility: (value?: boolean) => void getToggleVisibilityHandler: () => (event: unknown) => void } // export const Visibility: TableFeature = { getInitialState: (state): VisibilityTableState => { return { columnVisibility: {}, ...state, } }, getDefaultOptions: ( table: Table ): VisibilityDefaultOptions => { return { onColumnVisibilityChange: makeStateUpdater('columnVisibility', table), } }, createColumn: ( column: Column, table: Table ): VisibilityColumn => { return { toggleVisibility: value => { if (column.getCanHide()) { table.setColumnVisibility(old => ({ ...old, [column.id]: value ?? !column.getIsVisible(), })) } }, getIsVisible: () => { return table.getState().columnVisibility?.[column.id] ?? true }, getCanHide: () => { return ( (column.columnDef.enableHiding ?? true) && (table.options.enableHiding ?? true) ) }, getToggleVisibilityHandler: () => { return (e: unknown) => { column.toggleVisibility?.( ((e as MouseEvent).target as HTMLInputElement).checked ) } }, } }, createRow: ( row: Row, table: Table ): VisibilityRow => { return { _getAllVisibleCells: memo( () => [row.getAllCells(), table.getState().columnVisibility], cells => { return cells.filter(cell => cell.column.getIsVisible()) }, { key: process.env.NODE_ENV === 'production' && 'row._getAllVisibleCells', debug: () => table.options.debugAll ?? table.options.debugRows, } ), getVisibleCells: memo( () => [ row.getLeftVisibleCells(), row.getCenterVisibleCells(), row.getRightVisibleCells(), ], (left, center, right) => [...left, ...center, ...right], { key: process.env.NODE_ENV === 'development' && 'row.getVisibleCells', debug: () => table.options.debugAll ?? table.options.debugRows, } ), } }, createTable: ( table: Table ): VisibilityInstance => { const makeVisibleColumnsMethod = ( key: string, getColumns: () => Column[] ): (() => Column[]) => { return memo( () => [ getColumns(), getColumns() .filter(d => d.getIsVisible()) .map(d => d.id) .join('_'), ], columns => { return columns.filter(d => d.getIsVisible?.()) }, { key, debug: () => table.options.debugAll ?? table.options.debugColumns, } ) } return { getVisibleFlatColumns: makeVisibleColumnsMethod( 'getVisibleFlatColumns', () => table.getAllFlatColumns() ), getVisibleLeafColumns: makeVisibleColumnsMethod( 'getVisibleLeafColumns', () => table.getAllLeafColumns() ), getLeftVisibleLeafColumns: makeVisibleColumnsMethod( 'getLeftVisibleLeafColumns', () => table.getLeftLeafColumns() ), getRightVisibleLeafColumns: makeVisibleColumnsMethod( 'getRightVisibleLeafColumns', () => table.getRightLeafColumns() ), getCenterVisibleLeafColumns: makeVisibleColumnsMethod( 'getCenterVisibleLeafColumns', () => table.getCenterLeafColumns() ), setColumnVisibility: updater => table.options.onColumnVisibilityChange?.(updater), resetColumnVisibility: defaultState => { table.setColumnVisibility( defaultState ? {} : table.initialState.columnVisibility ?? {} ) }, toggleAllColumnsVisible: value => { value = value ?? !table.getIsAllColumnsVisible() table.setColumnVisibility( table.getAllLeafColumns().reduce( (obj, column) => ({ ...obj, [column.id]: !value ? !column.getCanHide?.() : value, }), {} ) ) }, getIsAllColumnsVisible: () => !table.getAllLeafColumns().some(column => !column.getIsVisible?.()), getIsSomeColumnsVisible: () => table.getAllLeafColumns().some(column => column.getIsVisible?.()), getToggleAllColumnsVisibilityHandler: () => { return (e: unknown) => { table.toggleAllColumnsVisible( ((e as MouseEvent).target as HTMLInputElement)?.checked ) } }, } }, }