Extending
MonkeyTab is extensible through props passed directly to <MonkeyTable>. All extensions are registered on mount and cleaned up on unmount — no global state, no side effects outside the component.
Custom computed functions
Add your own functions to the formula builder. They appear in the picker under your chosen category.
import { MonkeyTable, type FunctionDef } from '@datasketch/monkeytab';
const functions: FunctionDef[] = [
{
name: 'percent',
category: 'number',
description: 'Percentage of a value relative to a total',
inputTypes: ['Number', 'Number'],
params: [
{ name: 'decimals', type: 'number', default: 1 },
],
compute: ([value, total], params) => {
const v = Number(value), t = Number(total);
if (!t || isNaN(v) || isNaN(t)) return null;
const d = Number(params?.decimals ?? 1);
return Math.round((v / t) * 100 * 10 ** d) / 10 ** d;
},
},
];
<MonkeyTable functions={functions} columns={columns} rows={rows} />The FunctionDef interface:
| Field | Type | Description |
|---|---|---|
name |
string |
Unique function name |
category |
'text' | 'number' | 'date' | 'logic' |
Groups in the picker |
description |
string |
Shown in the formula builder |
inputTypes |
FieldType[] |
Expected column types, in order |
params |
Array<{name, type, default?}> |
Optional named parameters |
compute |
(inputs, params?) => Value |
The computation |
Custom field constraints
Add domain-specific validators. Constraints appear in the column options panel and show inline errors on invalid values.
import { type FieldTypeConstraint } from '@datasketch/monkeytab';
const constraints: FieldTypeConstraint[] = [
{
name: 'postalCode',
label: 'Postal Code',
description: 'Must be a 5-digit postal code',
appliesTo: ['Text'],
validate: (value) =>
/^\d{5}$/.test(String(value ?? ''))
? null // valid
: '5-digit code required', // error message
},
{
name: 'futureDate',
label: 'Future date',
description: 'Date must be in the future',
appliesTo: ['Date'],
validate: (value) =>
value && new Date(String(value)) > new Date()
? null
: 'Must be a future date',
},
];
<MonkeyTable constraints={constraints} columns={columns} rows={rows} />The validate function receives:
value— the current cell valueparams— parameter values if the constraint hasparamsfield—{ id: string, type: FieldType }— the field being validated
Return null for valid, a string for an error message.
Custom type-level renderers
Override the built-in renderer for a field type. Applies to all columns of that type in this <MonkeyTable> instance.
import { type CellRendererProps } from '@datasketch/monkeytab';
function HeartRating({ value }: CellRendererProps) {
const n = typeof value === 'number' ? Math.max(0, Math.min(5, value)) : 0;
return (
<span style={{ fontSize: 14, letterSpacing: 1 }}>
{'❤️'.repeat(n)}{'🤍'.repeat(5 - n)}
</span>
);
}
<MonkeyTable
renderers={{ Rating: HeartRating }}
columns={columns}
rows={rows}
/>CellRendererProps:
| Prop | Type | Description |
|---|---|---|
value |
Value |
The cell value |
field |
FieldSpec |
The column definition (id, type, options) |
rowId |
string |
The row's id |
cellHeight |
number | undefined |
Current cell height in px |
Custom type-level editors
Override the built-in editor for a field type.
import { type CellEditorProps } from '@datasketch/monkeytab';
function SliderEditor({ value, field, onSave, onCancel }: CellEditorProps) {
const opts = field.options as { min?: number; max?: number } | undefined;
const [val, setVal] = useState(typeof value === 'number' ? value : 0);
return (
<div style={{ padding: 12, background: '#fff', border: '1px solid #e5e7eb', borderRadius: 8 }}>
<input
type="range"
min={opts?.min ?? 0}
max={opts?.max ?? 100}
value={val}
onChange={(e) => setVal(Number(e.target.value))}
style={{ width: '100%' }}
/>
<div style={{ textAlign: 'center', marginTop: 4 }}>{val}</div>
<div style={{ display: 'flex', gap: 8, marginTop: 8 }}>
<button onClick={() => onSave(val)}>Save</button>
<button onClick={onCancel}>Cancel</button>
</div>
</div>
);
}
<MonkeyTable
editors={{ Number: SliderEditor }}
columns={columns}
rows={rows}
/>CellEditorProps:
| Prop | Type | Description |
|---|---|---|
value |
Value |
Current cell value |
field |
FieldSpec |
The column definition |
rowId |
string |
The row's id |
onSave |
(value: Value) => void |
Call to commit the new value |
onCancel |
() => void |
Call to discard changes |
onUpload |
(file, fieldType) => Promise<string> |
Forwarded onUpload prop (for file-type editors) |
Per-column custom renderer
To render a single column differently (without overriding the whole type), use the render prop on the column definition:
<MonkeyTable
columns={[
{ id: 'Name' },
{
id: 'Health',
type: 'Number',
render: (value, row, fieldId) => {
const n = typeof value === 'number' ? value : 0;
const color = n > 80 ? '#16a34a' : n > 50 ? '#d97706' : '#dc2626';
return (
<span style={{ color, fontWeight: 600 }}>
{n}%
</span>
);
},
},
]}
rows={rows}
/>The render function signature: (value: Value, row: Record<string, Value>, fieldId: string) => ReactNode.
Custom translations (i18n)
Override individual UI strings via the translations prop. All ~288 string keys are typed as I18nStrings:
<MonkeyTable
locale="es-CO"
language="es"
translations={{
'toolbar.addRow': 'Nueva fila',
'toolbar.search.placeholder': 'Buscar…',
'toolbar.filter': 'Filtrar',
'column.delete': 'Eliminar columna',
'fieldType.SingleSelect': 'Selección única',
}}
columns={columns}
rows={rows}
/>Built-in languages: English (en) and Spanish (es). For other languages, provide the full translations object.
Lifecycle notes
- All
functions,constraints,renderers, andeditorsare registered when the component mounts and unregistered when it unmounts. - If two
<MonkeyTable>instances register the same function/constraint name, the second wins while it's mounted; the first is restored when the second unmounts. - Registry extensions are scoped to the component instance — multiple tables on the same page are fully independent.
Built-in function catalog
27 functions are built in:
| Category | Functions |
|---|---|
| Text | concat, upper, lower, trim, length, slice, replace, startsWith, endsWith, contains |
| Number | round, floor, ceil, abs, percent, sum, avg |
| Date | dateFormat, dateDiff, dateAdd, now |
| Logic | if, and, or, not, coalesce |
Built-in constraint catalog
9 constraints are built in: required, minLength, maxLength, min, max, pattern, email, url, enum.