Skip to content

Commit dd7663b

Browse files
committed
Add field registry and dynamic renderer registration for custom field types
1 parent 307eccb commit dd7663b

1 file changed

Lines changed: 37 additions & 6 deletions

File tree

packages/fields/src/index.tsx

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -438,11 +438,32 @@ export function UserCellRenderer({ value }: CellRendererProps): React.ReactEleme
438438
);
439439
}
440440

441+
/**
442+
* Field Registry
443+
* Stores mapping between field types and their renderers.
444+
*/
445+
const fieldRegistry = new Map<string, React.FC<CellRendererProps>>();
446+
447+
/**
448+
* Register a custom field renderer
449+
* @param type Field type (e.g. 'text', 'location', 'my-custom-type')
450+
* @param renderer React component to render the field
451+
*/
452+
export function registerFieldRenderer(type: string, renderer: React.FC<CellRendererProps>) {
453+
fieldRegistry.set(type, renderer);
454+
}
455+
441456
/**
442457
* Get the appropriate cell renderer for a field type
443458
*/
444459
export function getCellRenderer(fieldType: string): React.FC<CellRendererProps> {
445-
const rendererMap: Record<string, React.FC<CellRendererProps>> = {
460+
// 1. Try exact match in registry
461+
if (fieldRegistry.has(fieldType)) {
462+
return fieldRegistry.get(fieldType)!;
463+
}
464+
465+
// 2. Fallback to standard mappings if not overridden
466+
const standardMap: Record<string, React.FC<CellRendererProps>> = {
446467
text: TextCellRenderer,
447468
textarea: TextCellRenderer,
448469
markdown: TextCellRenderer,
@@ -455,28 +476,38 @@ export function getCellRenderer(fieldType: string): React.FC<CellRendererProps>
455476
datetime: DateTimeCellRenderer,
456477
time: TextCellRenderer,
457478
select: SelectCellRenderer,
479+
lookup: SelectCellRenderer, // Default fallback
480+
master_detail: SelectCellRenderer, // Default fallback
458481
email: EmailCellRenderer,
459482
url: UrlCellRenderer,
460483
phone: PhoneCellRenderer,
461484
file: FileCellRenderer,
462485
image: ImageCellRenderer,
463-
lookup: LookupCellRenderer,
464-
master_detail: LookupCellRenderer,
465486
formula: FormulaCellRenderer,
466487
summary: FormulaCellRenderer,
467488
auto_number: TextCellRenderer,
468489
user: UserCellRenderer,
469490
owner: UserCellRenderer,
470491
password: () => <span>••••••</span>,
471-
location: TextCellRenderer,
492+
location: TextCellRenderer, // Default fallback
472493
object: () => <span className="text-gray-500 italic">[Object]</span>,
473494
vector: () => <span className="text-gray-500 italic">[Vector]</span>,
474495
grid: () => <span className="text-gray-500 italic">[Grid]</span>,
475496
};
476-
477-
return rendererMap[fieldType] || TextCellRenderer;
497+
498+
// 3. Register standard renderers implicitly if not present
499+
// This ensures that if we call registerFieldRenderer('text', Custom), it works,
500+
// but if we don't, we get the standard one.
501+
return standardMap[fieldType] || TextCellRenderer;
478502
}
479503

504+
// Register standard renderers immediately
505+
registerFieldRenderer('lookup', LookupCellRenderer);
506+
registerFieldRenderer('master_detail', LookupCellRenderer);
507+
registerFieldRenderer('select', SelectCellRenderer);
508+
509+
510+
480511
/**
481512
* Map field type to form component type
482513
*

0 commit comments

Comments
 (0)