package.src.features.Expanding.ts Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of table-core Show documentation
Show all versions of table-core Show documentation
Headless UI for building powerful tables & datagrids for TS/JS.
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