Registries
Scoped registries
fieldRegistry is a process-wide singleton shared by every adapter. To give part of an app its own renderers, construct an isolated FieldRegistry and provide it with your framework's mechanism (React FieldRegistryProvider, Vue provideFieldRegistry, Angular FIELD_REGISTRY token). Code that never provides one keeps using the global singleton.
ts
import { FieldRegistry } from '@dynamic-field-kit/core';
const registry = new FieldRegistry();
registry.register('text', myRenderer);
registry.has('text'); // true
registry.list(); // ['text']
registry.unregister('text'); // trueRegister renderers through an adapter
core owns the shared registry instance, but renderer registration should happen through the framework adapter so the adapter can expose the correct renderer type for that framework.
Typical adapter imports:
ts
import { fieldRegistry as reactRegistry } from '@dynamic-field-kit/react';
import { fieldRegistry as vueRegistry } from '@dynamic-field-kit/vue';
import { fieldRegistry as angularRegistry } from '@dynamic-field-kit/angular';Then register a renderer using the adapter that matches your UI framework.
React:
tsx
import { fieldRegistry } from '@dynamic-field-kit/react';
fieldRegistry.register('text', ({ value, onValueChange, label }) => (
<label>
<span>{label}</span>
<input
value={value ?? ''}
onChange={(e) => onValueChange?.(e.target.value)}
/>
</label>
));Vue:
ts
import { defineComponent, h } from 'vue';
import { fieldRegistry } from '@dynamic-field-kit/vue';
fieldRegistry.register(
'text',
defineComponent({
setup() {
return () => h('input');
},
}),
);Angular:
ts
import { fieldRegistry } from '@dynamic-field-kit/angular';
import { TextFieldComponent } from './text-field.component';
fieldRegistry.register('text', TextFieldComponent as any);