All Downloads are FREE. Search and download functionalities are using the official Maven repository.

package.src.features.Pinning.ts Maven / Gradle / Ivy

The newest version!
import { TableFeature } from '../core/table'
import {
  OnChangeFn,
  Updater,
  Table,
  Column,
  Row,
  Cell,
  RowData,
} from '../types'
import { makeStateUpdater, memo } from '../utils'

export type ColumnPinningPosition = false | 'left' | 'right'

export interface ColumnPinningState {
  left?: string[]
  right?: string[]
}

export interface ColumnPinningTableState {
  columnPinning: ColumnPinningState
}

export interface ColumnPinningOptions {
  onColumnPinningChange?: OnChangeFn
  enablePinning?: boolean
}

export interface ColumnPinningDefaultOptions {
  onColumnPinningChange: OnChangeFn
}

export interface ColumnPinningColumnDef {
  enablePinning?: boolean
}

export interface ColumnPinningColumn {
  getCanPin: () => boolean
  getPinnedIndex: () => number
  getIsPinned: () => ColumnPinningPosition
  pin: (position: ColumnPinningPosition) => void
}

export interface ColumnPinningRow {
  getLeftVisibleCells: () => Cell[]
  getCenterVisibleCells: () => Cell[]
  getRightVisibleCells: () => Cell[]
}

export interface ColumnPinningInstance {
  setColumnPinning: (updater: Updater) => void
  resetColumnPinning: (defaultState?: boolean) => void
  getIsSomeColumnsPinned: (position?: ColumnPinningPosition) => boolean
  getLeftLeafColumns: () => Column[]
  getRightLeafColumns: () => Column[]
  getCenterLeafColumns: () => Column[]
}

//

const getDefaultPinningState = (): ColumnPinningState => ({
  left: [],
  right: [],
})

export const Pinning: TableFeature = {
  getInitialState: (state): ColumnPinningTableState => {
    return {
      columnPinning: getDefaultPinningState(),
      ...state,
    }
  },

  getDefaultOptions: (
    table: Table
  ): ColumnPinningDefaultOptions => {
    return {
      onColumnPinningChange: makeStateUpdater('columnPinning', table),
    }
  },

  createColumn: (
    column: Column,
    table: Table
  ): ColumnPinningColumn => {
    return {
      pin: position => {
        const columnIds = column
          .getLeafColumns()
          .map(d => d.id)
          .filter(Boolean) as string[]

        table.setColumnPinning(old => {
          if (position === 'right') {
            return {
              left: (old?.left ?? []).filter(d => !columnIds?.includes(d)),
              right: [
                ...(old?.right ?? []).filter(d => !columnIds?.includes(d)),
                ...columnIds,
              ],
            }
          }

          if (position === 'left') {
            return {
              left: [
                ...(old?.left ?? []).filter(d => !columnIds?.includes(d)),
                ...columnIds,
              ],
              right: (old?.right ?? []).filter(d => !columnIds?.includes(d)),
            }
          }

          return {
            left: (old?.left ?? []).filter(d => !columnIds?.includes(d)),
            right: (old?.right ?? []).filter(d => !columnIds?.includes(d)),
          }
        })
      },

      getCanPin: () => {
        const leafColumns = column.getLeafColumns()

        return leafColumns.some(
          d =>
            (d.columnDef.enablePinning ?? true) &&
            (table.options.enablePinning ?? true)
        )
      },

      getIsPinned: () => {
        const leafColumnIds = column.getLeafColumns().map(d => d.id)

        const { left, right } = table.getState().columnPinning

        const isLeft = leafColumnIds.some(d => left?.includes(d))
        const isRight = leafColumnIds.some(d => right?.includes(d))

        return isLeft ? 'left' : isRight ? 'right' : false
      },

      getPinnedIndex: () => {
        const position = column.getIsPinned()

        return position
          ? table.getState().columnPinning?.[position]?.indexOf(column.id) ?? -1
          : 0
      },
    }
  },

  createRow: (
    row: Row,
    table: Table
  ): ColumnPinningRow => {
    return {
      getCenterVisibleCells: memo(
        () => [
          row._getAllVisibleCells(),
          table.getState().columnPinning.left,
          table.getState().columnPinning.right,
        ],
        (allCells, left, right) => {
          const leftAndRight: string[] = [...(left ?? []), ...(right ?? [])]

          return allCells.filter(d => !leftAndRight.includes(d.column.id))
        },
        {
          key:
            process.env.NODE_ENV === 'production' &&
            'row.getCenterVisibleCells',
          debug: () => table.options.debugAll ?? table.options.debugRows,
        }
      ),
      getLeftVisibleCells: memo(
        () => [
          row._getAllVisibleCells(),
          table.getState().columnPinning.left,
          ,
        ],
        (allCells, left) => {
          const cells = (left ?? [])
            .map(
              columnId => allCells.find(cell => cell.column.id === columnId)!
            )
            .filter(Boolean)
            .map(d => ({ ...d, position: 'left' } as Cell))

          return cells
        },
        {
          key:
            process.env.NODE_ENV === 'production' && 'row.getLeftVisibleCells',
          debug: () => table.options.debugAll ?? table.options.debugRows,
        }
      ),
      getRightVisibleCells: memo(
        () => [row._getAllVisibleCells(), table.getState().columnPinning.right],
        (allCells, right) => {
          const cells = (right ?? [])
            .map(
              columnId => allCells.find(cell => cell.column.id === columnId)!
            )
            .filter(Boolean)
            .map(d => ({ ...d, position: 'right' } as Cell))

          return cells
        },
        {
          key:
            process.env.NODE_ENV === 'production' && 'row.getRightVisibleCells',
          debug: () => table.options.debugAll ?? table.options.debugRows,
        }
      ),
    }
  },

  createTable: (
    table: Table
  ): ColumnPinningInstance => {
    return {
      setColumnPinning: updater =>
        table.options.onColumnPinningChange?.(updater),

      resetColumnPinning: defaultState =>
        table.setColumnPinning(
          defaultState
            ? getDefaultPinningState()
            : table.initialState?.columnPinning ?? getDefaultPinningState()
        ),

      getIsSomeColumnsPinned: position => {
        const pinningState = table.getState().columnPinning

        if (!position) {
          return Boolean(
            pinningState.left?.length || pinningState.right?.length
          )
        }
        return Boolean(pinningState[position]?.length)
      },

      getLeftLeafColumns: memo(
        () => [table.getAllLeafColumns(), table.getState().columnPinning.left],
        (allColumns, left) => {
          return (left ?? [])
            .map(columnId => allColumns.find(column => column.id === columnId)!)
            .filter(Boolean)
        },
        {
          key: process.env.NODE_ENV === 'development' && 'getLeftLeafColumns',
          debug: () => table.options.debugAll ?? table.options.debugColumns,
        }
      ),

      getRightLeafColumns: memo(
        () => [table.getAllLeafColumns(), table.getState().columnPinning.right],
        (allColumns, right) => {
          return (right ?? [])
            .map(columnId => allColumns.find(column => column.id === columnId)!)
            .filter(Boolean)
        },
        {
          key: process.env.NODE_ENV === 'development' && 'getRightLeafColumns',
          debug: () => table.options.debugAll ?? table.options.debugColumns,
        }
      ),

      getCenterLeafColumns: memo(
        () => [
          table.getAllLeafColumns(),
          table.getState().columnPinning.left,
          table.getState().columnPinning.right,
        ],
        (allColumns, left, right) => {
          const leftAndRight: string[] = [...(left ?? []), ...(right ?? [])]

          return allColumns.filter(d => !leftAndRight.includes(d.id))
        },
        {
          key: process.env.NODE_ENV === 'development' && 'getCenterLeafColumns',
          debug: () => table.options.debugAll ?? table.options.debugColumns,
        }
      ),
    }
  },
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy