import { For } from 'solid-js' import { coreFeatures, stockFeatures } from '@tanstack/table-core' import { useTableDevtoolsContext } from '../TableContextProvider' import { useTableStore } from '../useTableStore' import { useStyles } from '../styles/use-styles' import { ResizableSplit } from './ResizableSplit' type FnBuckets = Partial< Record<'filterFns' | 'sortFns' | 'aggregationFns', Record> > function toFnBuckets(value: unknown): FnBuckets { return typeof value === 'object' && value != null ? (value as FnBuckets) : {} } const CORE_FEATURE_NAMES: Array = Object.keys(coreFeatures) const STOCK_FEATURE_NAMES: Array = Object.keys(stockFeatures) const ROW_MODEL_TO_FN_KIND: Record< string, 'filterFns' | 'sortFns' | 'aggregationFns' | null > = { filteredRowModel: 'filterFns', preFilteredRowModel: 'filterFns', sortedRowModel: 'sortFns', preSortedRowModel: 'sortFns', groupedRowModel: 'aggregationFns', preGroupedRowModel: 'aggregationFns', } const EXECUTION_ORDER_GETTERS = [ 'getCoreRowModel', 'getFilteredRowModel', 'getGroupedRowModel', 'getSortedRowModel', 'getExpandedRowModel', 'getPaginatedRowModel', 'getRowModel', ] as const function getterToRowModelKey(getter: string): string | null { if (getter === 'getRowModel') return 'paginatedRowModel' const withoutGet = getter.slice(3) return withoutGet.charAt(0).toLowerCase() + withoutGet.slice(1) } const ROW_MODEL_TO_GETTER: Record< string, (typeof EXECUTION_ORDER_GETTERS)[number] > = { coreRowModel: 'getCoreRowModel', filteredRowModel: 'getFilteredRowModel', preFilteredRowModel: 'getFilteredRowModel', groupedRowModel: 'getGroupedRowModel', preGroupedRowModel: 'getGroupedRowModel', sortedRowModel: 'getSortedRowModel', preSortedRowModel: 'getSortedRowModel', expandedRowModel: 'getExpandedRowModel', paginatedRowModel: 'getRowModel', } function getRowCountForModel( tableInstance: { [key: string]: unknown } | undefined, rowModelName: string, ): number { const getter = ROW_MODEL_TO_GETTER[rowModelName] if (!getter || typeof tableInstance?.[getter] !== 'function') return 0 const result = (tableInstance[getter] as () => { rows?: Array })() return result.rows?.length ?? 0 } export function FeaturesPanel() { const styles = useStyles() const { table } = useTableDevtoolsContext() const tableInstance = table() const tableState = useTableStore( tableInstance ? tableInstance.store : undefined, (state) => state, ) const getTableFeatures = (): Set => { tableState?.() return new Set(Object.keys(tableInstance?._features ?? {})) } const getRowModelNames = (): Array => { tableState?.() return Object.keys(tableInstance?.options._rowModels ?? {}) } const getFnNames = ( kind: 'filterFns' | 'sortFns' | 'aggregationFns', ): Array => { tableState?.() const rowModelFns = toFnBuckets(tableInstance?._rowModelFns) const optionFns = toFnBuckets(tableInstance?.options) return Object.keys(rowModelFns[kind] ?? optionFns[kind] ?? {}) } const getAdditionalPlugins = (): Array => { const tableFeatures = getTableFeatures() const knownFeatures = new Set([ ...CORE_FEATURE_NAMES, ...STOCK_FEATURE_NAMES, ]) return [...tableFeatures].filter((f) => !knownFeatures.has(f)).sort() } const getRowModelFunctions = (rowModelName: string): Array => { const fnKind = ROW_MODEL_TO_FN_KIND[rowModelName] if (!fnKind) return [] return getFnNames(fnKind) } const tableFeatures = getTableFeatures() const rowModelNames = getRowModelNames() return (
Features
Core Features
{(name) => (
{tableFeatures.has(name) ? '✓' : '○'} {name}
)}
Stock Features
{(name) => (
{tableFeatures.has(name) ? '✓' : '○'} {name}
)}
{getAdditionalPlugins().length > 0 && (
Additional Plugins
{(name) => (
{name}
)}
)} } right={ <>
Client Side Row Models and Fns
{(rowModelName) => { const fns = getRowModelFunctions(rowModelName) return (
{rowModelName}
{(fnName) => (
{fnName}
)}
) }}
{rowModelNames.length === 0 && (
No row models configured
)}
Execution Order
{(getter, index) => { const rowModelKey = getterToRowModelKey(getter) const isPresent = rowModelKey !== null && rowModelNames.includes(rowModelKey) return ( <> {index() > 0 && ' → '} {getter} ) }}
} />
) }