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

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

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

export type ExpandedStateList = Record
export type ExpandedState = true | Record
export interface ExpandedTableState {
  expanded: ExpandedState
}

export interface ExpandedRow {
  toggleExpanded: (expanded?: boolean) => void
  getIsExpanded: () => boolean
  getCanExpand: () => boolean
  getToggleExpandedHandler: () => () => void
}

export interface ExpandedOptions {
  manualExpanding?: boolean
  onExpandedChange?: OnChangeFn
  autoResetExpanded?: boolean
  enableExpanding?: boolean
  getExpandedRowModel?: (table: Table) => () => RowModel
  getIsRowExpanded?: (row: Row) => boolean
  getRowCanExpand?: (row: Row) => boolean
  paginateExpandedRows?: boolean
}

export interface ExpandedInstance {
  _autoResetExpanded: () => void
  setExpanded: (updater: Updater) => void
  toggleAllRowsExpanded: (expanded?: boolean) => void
  resetExpanded: (defaultState?: boolean) => void
  getCanSomeRowsExpand: () => boolean
  getToggleAllRowsExpandedHandler: () => (event: unknown) => void
  getIsSomeRowsExpanded: () => boolean
  getIsAllRowsExpanded: () => boolean
  getExpandedDepth: () => number
  getExpandedRowModel: () => RowModel
  _getExpandedRowModel?: () => RowModel
  getPreExpandedRowModel: () => RowModel
}

//

export const Expanding: TableFeature = {
  getInitialState: (state): ExpandedTableState => {
    return {
      expanded: {},
      ...state,
    }
  },

  getDefaultOptions: (
    table: Table
  ): ExpandedOptions => {
    return {
      onExpandedChange: makeStateUpdater('expanded', table),
      paginateExpandedRows: true,
    }
  },

  createTable: (
    table: Table
  ): ExpandedInstance => {
    let registered = false
    let queued = false

    return {
      _autoResetExpanded: () => {
        if (!registered) {
          table._queue(() => {
            registered = true
          })
          return
        }

        if (
          table.options.autoResetAll ??
          table.options.autoResetExpanded ??
          !table.options.manualExpanding
        ) {
          if (queued) return
          queued = true
          table._queue(() => {
            table.resetExpanded()
            queued = false
          })
        }
      },
      setExpanded: updater => table.options.onExpandedChange?.(updater),
      toggleAllRowsExpanded: expanded => {
        if (expanded ?? !table.getIsAllRowsExpanded()) {
          table.setExpanded(true)
        } else {
          table.setExpanded({})
        }
      },
      resetExpanded: defaultState => {
        table.setExpanded(
          defaultState ? {} : table.initialState?.expanded ?? {}
        )
      },
      getCanSomeRowsExpand: () => {
        return table
          .getPrePaginationRowModel()
          .flatRows.some(row => row.getCanExpand())
      },
      getToggleAllRowsExpandedHandler: () => {
        return (e: unknown) => {
          ;(e as any).persist?.()
          table.toggleAllRowsExpanded()
        }
      },
      getIsSomeRowsExpanded: () => {
        const expanded = table.getState().expanded
        return expanded === true || Object.values(expanded).some(Boolean)
      },
      getIsAllRowsExpanded: () => {
        const expanded = table.getState().expanded

        // If expanded is true, save some cycles and return true
        if (typeof expanded === 'boolean') {
          return expanded === true
        }

        if (!Object.keys(expanded).length) {
          return false
        }

        // If any row is not expanded, return false
        if (table.getRowModel().flatRows.some(row => !row.getIsExpanded())) {
          return false
        }

        // They must all be expanded :shrug:
        return true
      },
      getExpandedDepth: () => {
        let maxDepth = 0

        const rowIds =
          table.getState().expanded === true
            ? Object.keys(table.getRowModel().rowsById)
            : Object.keys(table.getState().expanded)

        rowIds.forEach(id => {
          const splitId = id.split('.')
          maxDepth = Math.max(maxDepth, splitId.length)
        })

        return maxDepth
      },
      getPreExpandedRowModel: () => table.getSortedRowModel(),
      getExpandedRowModel: () => {
        if (!table._getExpandedRowModel && table.options.getExpandedRowModel) {
          table._getExpandedRowModel = table.options.getExpandedRowModel(table)
        }

        if (table.options.manualExpanding || !table._getExpandedRowModel) {
          return table.getPreExpandedRowModel()
        }

        return table._getExpandedRowModel()
      },
    }
  },

  createRow: (
    row: Row,
    table: Table
  ): ExpandedRow => {
    return {
      toggleExpanded: expanded => {
        table.setExpanded(old => {
          const exists = old === true ? true : !!old?.[row.id]

          let oldExpanded: ExpandedStateList = {}

          if (old === true) {
            Object.keys(table.getRowModel().rowsById).forEach(rowId => {
              oldExpanded[rowId] = true
            })
          } else {
            oldExpanded = old
          }

          expanded = expanded ?? !exists

          if (!exists && expanded) {
            return {
              ...oldExpanded,
              [row.id]: true,
            }
          }

          if (exists && !expanded) {
            const { [row.id]: _, ...rest } = oldExpanded
            return rest
          }

          return old
        })
      },
      getIsExpanded: () => {
        const expanded = table.getState().expanded

        return !!(
          table.options.getIsRowExpanded?.(row) ??
          (expanded === true || expanded?.[row.id])
        )
      },
      getCanExpand: () => {
        return (
          table.options.getRowCanExpand?.(row) ??
          ((table.options.enableExpanding ?? true) && !!row.subRows?.length)
        )
      },
      getToggleExpandedHandler: () => {
        const canExpand = row.getCanExpand()

        return () => {
          if (!canExpand) return
          row.toggleExpanded()
        }
      },
    }
  },
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy