import { ReactNode } from 'react' export type CellRenderer = (value: any, row: TData) => ReactNode export interface RendererConfig { [columnId: string]: CellRenderer } export function createCellRenderer( render: (value: any, row: TData) => ReactNode ): CellRenderer { return render } export function getNestedValue(obj: any, path: string): any { if (!path || !obj) return obj const keys = path.split('.') let value = obj for (const key of keys) { if (value === null || value === undefined) return undefined value = value[key] } return value } export const commonRenderers = { text: createCellRenderer((value) => String(value || '-')), number: createCellRenderer((value) => { if (value === null || value === undefined) return '-' return new Intl.NumberFormat().format(Number(value)) }), currency: createCellRenderer((value, row, options?: { currency?: string; locale?: string }) => { if (value === null || value === undefined) return '-' return new Intl.NumberFormat(options?.locale || 'en-US', { style: 'currency', currency: options?.currency || 'USD', }).format(Number(value)) }), percentage: createCellRenderer((value) => { if (value === null || value === undefined) return '-' return `${Number(value).toFixed(2)}%` }), date: createCellRenderer((value) => { if (!value) return '-' const date = new Date(value) return date.toLocaleDateString() }), datetime: createCellRenderer((value) => { if (!value) return '-' const date = new Date(value) return date.toLocaleString() }), boolean: createCellRenderer((value) => { if (value === null || value === undefined) return '-' return value ? 'Yes' : 'No' }), badge: createCellRenderer((value, row, options?: { variant?: 'default' | 'success' | 'warning' | 'error' }) => { if (!value) return null return value }), truncate: createCellRenderer((value, row, options?: { maxLength?: number }) => { if (!value) return '-' const str = String(value) const maxLength = options?.maxLength || 50 if (str.length <= maxLength) return str return `${str.substring(0, maxLength)}...` }), array: createCellRenderer((value, row, options?: { separator?: string; maxItems?: number }) => { if (!Array.isArray(value) || value.length === 0) return '-' const maxItems = options?.maxItems || value.length const items = value.slice(0, maxItems) const separator = options?.separator || ', ' const display = items.join(separator) if (value.length > maxItems) { return `${display} +${value.length - maxItems} more` } return display }), } export function combineRenderers( ...renderers: CellRenderer[] ): CellRenderer { return (value, row) => { for (const renderer of renderers) { const result = renderer(value, row) if (result !== null && result !== undefined) { return result } } return value } }