Mapping your data
This is the point of the library: you should not have to transform your backend response before rendering it.
Say your API returns this:
json
{
"document_id": 123,
"document_title": "Architecture.pdf",
"kind": "FILE",
"folder_id": 55,
"file_size": 2450000,
"extra": { "owner": "Nitesh", "status": "approved" }
}Describe the shape once:
ts
const mapper = {
id: (d) => d.document_id,
name: (d) => d.document_title,
type: (d) => (d.kind === 'FOLDER' ? 'folder' : 'file'),
parentId: (d) => d.folder_id,
size: 'file_size',
metadata: 'extra',
};tsx
<DocumentExplorer data={apiResponse} mapper={mapper} />Three ways to describe a field
Every field accepts any of these:
ts
{
// 1. A key of the source object
size: 'file_size',
// 2. A dot path, for nested payloads
owner: 'audit.created_by.name',
// 3. A function, for anything else
type: (d) => (d.is_directory ? 'folder' : 'file'),
}The function form is what makes essentially any backend consumable.
Coercions done for you
- Ids are stringified. A numeric
document_id: 123becomes'123', so SQL backends need no casting. - Types are normalized.
'folder','FOLDER','directory','dir'andtrueall mean folder; anything else means file. - Sizes are parsed. The string
'2048'becomes the number2048. - Extensions are derived from the name when absent — and never assigned to folders, so a folder called
v1.2is not treated as having an extension.
Nested payloads
If your rows carry children, point children at them and the tree is flattened for you:
ts
const mapper = {
id: 'documentId',
name: 'title',
children: 'items', // or (d) => d.items
};An explicit parentId on a row wins over its position in the nesting.
Full field list
id · name · type · parentId · children · mimeType · extension · size · createdAt · updatedAt · viewUrl · downloadUrl · metadata
Only id, name and type really matter; everything else is optional and simply will not be displayed if absent.
TypeScript
The mapper is generic over your row type, so the function forms are fully typed:
ts
import type { DocumentMapper } from '@document-explorer/core';
interface ApiDoc { document_id: number; document_title: string; kind: string }
const mapper: DocumentMapper<ApiDoc> = {
id: (d) => d.document_id, // d is ApiDoc
name: (d) => d.document_title,
type: (d) => (d.kind === 'FOLDER' ? 'folder' : 'file'),
};