ColumnConverter#
@palmyralabs/rt-forms · src/palmyra/grid/base/utils/ColumnConverter.tsx
Overview#
Not a component — a factory function that compiles a list of Palmyra-flavoured ColumnDefinitions into @tanstack/react-table ColumnDefs. Handles grouping (columnGroup), sort/search flags, value conversion (via FormatterFactory), and per-column cellRenderer overrides. Dispatches header/footer/cell rendering through a GridCustomizer so themes (Mantine / MUI / plain) can inject their own chrome.
Grid templates like SummaryGrid call this under the hood; you’ll mostly touch it when building a bespoke grid.
Exports#
function generateColumns(
columnDefs: ColumnDefinition[],
customizer?: GridCustomizer,
): ColumnDef<RowData, any>[];ColumnDefinition shape#
interface ColumnDefinition {
attribute: string; // bean attribute (matches the backend @PalmyraField)
name: string; // stable id
label?: string; // header text
type?: string; // 'STRING' | 'NUMERIC' | 'DATE' | 'BIT' | ...
sortable?: boolean;
searchable?: boolean;
width?: number | string;
columnGroup?: string; // groups adjacent columns under one header
cellRenderer?: (ctx: CellContext<any, any>) => React.ReactNode;
displayPattern?: any; // consumed by CellFormatter for BIT / enum columns
// ... more fields from src/palmyra/grid/base/types.ts
}Example — bespoke grid built from definitions#
import { useMemo } from 'react';
import { flexRender, getCoreRowModel, useReactTable } from '@tanstack/react-table';
import { generateColumns, type ColumnDefinition } from '@palmyralabs/rt-forms';
const defs: ColumnDefinition[] = [
{ attribute: 'name', name: 'name', label: 'Name', searchable: true, sortable: true },
{ attribute: 'contactMobile', name: 'contactMobile', label: 'Mobile' },
{ attribute: 'rating', name: 'rating', label: 'Rating', type: 'NUMERIC', sortable: true },
{ attribute: 'active', name: 'active', label: 'Active', type: 'BIT',
displayPattern: [{ '1': 'Yes' }, { '0': 'No' }] },
];
export function ManufacturerTable({ rows }: { rows: any[] }) {
const columns = useMemo(() => generateColumns(defs), []);
const table = useReactTable({ data: rows, columns, getCoreRowModel: getCoreRowModel() });
return (
<table>
<thead>{table.getHeaderGroups().map(hg => (
<tr key={hg.id}>{hg.headers.map(h => (
<th key={h.id}>{flexRender(h.column.columnDef.header, h.getContext())}</th>
))}</tr>
))}</thead>
<tbody>{table.getRowModel().rows.map(r => (
<tr key={r.id}>{r.getVisibleCells().map(c => (
<td key={c.id}>{flexRender(c.column.columnDef.cell, c.getContext())}</td>
))}</tr>
))}</tbody>
</table>
);
}The second argument — customizer — lets a theme library replace headers, footers, and cell wrappers without rewriting the whole grid.