Skip to content
13 changes: 4 additions & 9 deletions packages/adapters/react/src/provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import type { FormSchema } from '@schepta/core';
import type { MiddlewareFn } from '@schepta/core';
import type { RendererFn } from '@schepta/core';
import { defaultDebugConfig } from '@schepta/core';
import { getRendererRegistry } from '@schepta/core';

/**
* Provider configuration type (matches SpectraProviderProps from old project)
Expand Down Expand Up @@ -73,31 +72,27 @@ export function ScheptaProvider({
// Check if we're nested inside another ScheptaProvider (Material-UI pattern)
const parentContext = useContext(ScheptaContext);

const contextValue = useMemo<ScheptaContextType>(() => {
const contextValue = useMemo(() => {
// If we have a parent context, merge with it (hierarchical override)
if (parentContext) {
// Use renderer registry for hierarchical merging
const mergedRenderers = getRendererRegistry(parentContext.renderers, renderers);

return {
components: { ...parentContext.components, ...components },
customComponents: { ...parentContext.customComponents, ...customComponents },
renderers: mergedRenderers,
renderers: { ...parentContext.renderers, ...renderers },
middlewares: [...parentContext.middlewares, ...middlewares],
debug: { ...parentContext.debug, ...debug },
schema: schema || parentContext.schema,
externalContext: { ...parentContext.externalContext, ...externalContext },
};
}

// If we're the root provider, use renderer registry with defaults
const mergedRenderers = getRendererRegistry(undefined, renderers);
const mergedDebug = { ...defaultDebugConfig, ...debug };

return {
components,
customComponents,
renderers: mergedRenderers,
renderers,
middlewares,
debug: mergedDebug,
schema,
Expand All @@ -106,7 +101,7 @@ export function ScheptaProvider({
}, [parentContext, components, customComponents, renderers, middlewares, debug, schema, externalContext]);

return (
<ScheptaContext.Provider value={contextValue}>
<ScheptaContext.Provider value={contextValue as ScheptaContextType}>
{children}
</ScheptaContext.Provider>
);
Expand Down
6 changes: 3 additions & 3 deletions packages/adapters/react/src/runtime-adapter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
*/

import React from 'react';
import type { RuntimeAdapter, ComponentSpec, RenderResult } from '@schepta/core';
import type { RuntimeAdapter, ComponentSpec, RenderResult, RendererSpec } from '@schepta/core';

/**
* React runtime adapter implementation
*/
export class ReactRuntimeAdapter implements RuntimeAdapter {
create(spec: ComponentSpec, props: Record<string, any>): RenderResult {
const component = spec.factory(props, this);
create(spec: ComponentSpec | RendererSpec, props: Record<string, any>): RenderResult {
const component = spec.component(props, this);
// If factory returns a React component type, create element
if (typeof component === 'function' || typeof component === 'object') {
return React.createElement(component as any, props);
Expand Down
12 changes: 6 additions & 6 deletions packages/adapters/vanilla/src/provider.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ describe('Vanilla Provider', () => {
it('should create provider and store config', () => {
const componentSpec = createComponentSpec({
id: 'TestComponent',
factory: () => null,
component: () => null,
type: 'field',
});

Expand All @@ -43,7 +43,7 @@ describe('Vanilla Provider', () => {
it('should get context from container', () => {
const componentSpec = createComponentSpec({
id: 'TestComponent',
factory: () => null,
component: () => null,
type: 'field',
});

Expand All @@ -58,7 +58,7 @@ describe('Vanilla Provider', () => {
it('should get context from child container (parent lookup)', () => {
const componentSpec = createComponentSpec({
id: 'TestComponent',
factory: () => null,
component: () => null,
type: 'field',
});

Expand All @@ -73,13 +73,13 @@ describe('Vanilla Provider', () => {
it('should support nested providers with hierarchical merge', () => {
const ParentComponent = createComponentSpec({
id: 'ParentComponent',
factory: () => null,
component: () => null,
type: 'field',
});

const ChildComponent = createComponentSpec({
id: 'ChildComponent',
factory: () => null,
component: () => null,
type: 'field',
});

Expand Down Expand Up @@ -157,7 +157,7 @@ describe('Vanilla Provider', () => {
it('should destroy provider and remove config', () => {
const componentSpec = createComponentSpec({
id: 'TestComponent',
factory: () => null,
component: () => null,
type: 'field',
});

Expand Down
10 changes: 4 additions & 6 deletions packages/adapters/vanilla/src/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import type { FormSchema } from '@schepta/core';
import type { MiddlewareFn } from '@schepta/core';
import type { RendererFn } from '@schepta/core';
import { defaultDebugConfig } from '@schepta/core';
import { getRendererRegistry } from '@schepta/core';

/**
* Provider configuration type
Expand Down Expand Up @@ -56,10 +55,10 @@ export function createScheptaProvider(
const parentContext = getParentProviderContext(container);

// Compute merged context value
const contextValue: ScheptaContextType = (() => {
const contextValue = (() => {
if (parentContext) {
// Merge with parent (hierarchical override)
const mergedRenderers = getRendererRegistry(parentContext.renderers, props.renderers);
const mergedRenderers = { ...parentContext.renderers, ...props.renderers };

return {
components: { ...parentContext.components, ...(props.components || {}) },
Expand All @@ -72,12 +71,11 @@ export function createScheptaProvider(
}

// Root provider
const mergedRenderers = getRendererRegistry(undefined, props.renderers);
const mergedDebug = { ...defaultDebugConfig, ...props.debug };

return {
components: props.components || {},
renderers: mergedRenderers,
renderers: props.renderers,
middlewares: props.middlewares || [],
debug: mergedDebug,
schema: props.schema,
Expand All @@ -86,7 +84,7 @@ export function createScheptaProvider(
})();

// Store provider config in map
providerMap.set(container, contextValue);
providerMap.set(container, contextValue as ScheptaContextType);

return {
destroy: () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/adapters/vanilla/src/runtime-adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import type { DOMElement } from './types';
*/
export class VanillaRuntimeAdapter implements RuntimeAdapter {
create(spec: ComponentSpec, props: Record<string, any>): RenderResult {
const component = spec.factory(props, this);
const component = spec.component(props, this);

// If component returns a DOM element directly
if (component instanceof HTMLElement) {
Expand Down
6 changes: 3 additions & 3 deletions packages/adapters/vue/src/provider.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ describe('Vue Provider', () => {
it('should provide components configuration', () => {
const componentSpec = createComponentSpec({
id: 'TestComponent',
factory: () => null,
component: () => null,
type: 'field',
});

Expand Down Expand Up @@ -60,13 +60,13 @@ describe('Vue Provider', () => {
it('should support nested providers with hierarchical merge', () => {
const ParentComponent = createComponentSpec({
id: 'ParentComponent',
factory: () => null,
component: () => null,
type: 'field',
});

const ChildComponent = createComponentSpec({
id: 'ChildComponent',
factory: () => null,
component: () => null,
type: 'field',
});

Expand Down
8 changes: 3 additions & 5 deletions packages/adapters/vue/src/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@
* Vue implementation of schepta Provider
*/

import { provide, inject, defineComponent, h, type Component } from 'vue';
import { provide, inject, defineComponent, h } from 'vue';
import type { ComponentSpec, ComponentType, DebugConfig } from '@schepta/core';
import type { FormSchema } from '@schepta/core';
import type { MiddlewareFn } from '@schepta/core';
import type { RendererFn } from '@schepta/core';
import { defaultDebugConfig } from '@schepta/core';
import { getRendererRegistry } from '@schepta/core';

/**
* Provider configuration type
Expand Down Expand Up @@ -84,7 +83,7 @@ export function createScheptaProvider(props: ScheptaProviderProps = {}) {

if (parentContext) {
// Merge with parent (hierarchical override)
const mergedRenderers = getRendererRegistry(parentContext.renderers, componentProps.renderers);
const mergedRenderers = { ...parentContext.renderers, ...componentProps.renderers };

return {
components: { ...parentContext.components, ...componentProps.components },
Expand All @@ -97,12 +96,11 @@ export function createScheptaProvider(props: ScheptaProviderProps = {}) {
}

// Root provider
const mergedRenderers = getRendererRegistry(undefined, componentProps.renderers);
const mergedDebug = { ...defaultDebugConfig, ...componentProps.debug };

return {
components: componentProps.components || {},
renderers: mergedRenderers,
renderers: componentProps.renderers,
middlewares: localMiddlewares,
debug: mergedDebug,
schema: componentProps.schema as FormSchema | undefined,
Expand Down
2 changes: 1 addition & 1 deletion packages/adapters/vue/src/runtime-adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import type { RuntimeAdapter, ComponentSpec, RenderResult } from '@schepta/core'
*/
export class VueRuntimeAdapter implements RuntimeAdapter {
create(spec: ComponentSpec, props: Record<string, any>): RenderResult {
const component = spec.factory(props, this) as any;
const component = spec.component(props, this) as any;

// Extract children from props if present (Vue passes children as third argument to h())
const { children, ...restProps } = props;
Expand Down
6 changes: 3 additions & 3 deletions packages/core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ npm install @schepta/core
import {
ComponentRegistry,
RendererRegistry,
RendererOrchestrator,
componentOrchestrator,
createComponentSpec
} from '@schepta/core';

Expand All @@ -30,8 +30,8 @@ registry.register(
})
);

// Create renderer orchestrator
const orchestrator = new RendererOrchestrator(registry);
// Create component orchestrator
const orchestrator = new componentOrchestrator(registry);
```

## Documentation
Expand Down
3 changes: 1 addition & 2 deletions packages/core/src/defaults/register-default-renderers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const defaultRenderers: Record<ComponentType, RendererFn> = {
: props;
return runtime.create(spec, propsWithChildren);
},
'field-wrapper': (spec, props, runtime, children) => {
button: (spec, props, runtime, children) => {
const propsWithChildren = children && children.length > 0
? { ...props, children }
: props;
Expand Down Expand Up @@ -50,5 +50,4 @@ export const defaultRenderers: Record<ComponentType, RendererFn> = {
: props;
return runtime.create(spec, propsWithChildren);
},

}
2 changes: 1 addition & 1 deletion packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export * from './registries/renderer-registry';
export * from './defaults/register-default-renderers'

// Orchestrator
export * from './orchestrator/renderer-orchestrator';
export * from './orchestrators/component-orchestrator';

// Middleware system
export * from './middleware/types';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
/**
* Renderer Orchestrator
* Component Orchestrator
*
* Framework-agnostic orchestrator that processes schemas, resolves components,
* applies middlewares, and coordinates rendering.
*/

import type { RuntimeAdapter, ComponentSpec, DebugContextValue } from '../runtime/types';
import type { RuntimeAdapter, ComponentSpec, DebugContextValue, RenderResult } from '../runtime/types';
import type { FormAdapter } from '../forms/types';
import type { MiddlewareFn, MiddlewareContext } from '../middleware/types';
import { getRendererForType } from '../registries/renderer-registry';
import { applyMiddlewares } from '../middleware/types';
import { processValue } from '../expressions/template-processor';
import { createDefaultResolver } from '../expressions/variable-resolver';
import { createRendererOrchestrator } from './renderer-orchestrator';

/**
* Resolution result - successful component resolution
*/
export interface ResolutionSuccess {
componentSpec: ComponentSpec;
rendererFn: ReturnType<typeof getRendererForType>;
rendererFn: (componentSpec: ComponentSpec, props: Record<string, any>, runtime: RuntimeAdapter, children?: any[]) => RenderResult;
}

/**
Expand Down Expand Up @@ -49,7 +49,7 @@ export function resolveSpec(
componentKey: string,
components: Record<string, ComponentSpec>,
customComponents?: Record<string, ComponentSpec>,
localRenderers?: Partial<Record<string, any>>,
renderers?: Partial<Record<string, any>>,
debugEnabled?: boolean
): ResolutionResult {
const componentName = schema['x-component'] || componentKey;
Expand All @@ -58,9 +58,9 @@ export function resolveSpec(
let componentSpec = null;

if (isCustomComponent && customComponents) {
componentSpec = customComponents[componentKey];
componentSpec = customComponents[componentKey];
} else {
componentSpec = components[componentName];
componentSpec = components[componentName];
}

if (!componentSpec) {
Expand All @@ -72,12 +72,7 @@ export function resolveSpec(
}

const componentType = componentSpec.type || 'field';
const rendererFn = getRendererForType(
componentType,
undefined,
localRenderers as any,
debugEnabled
);
const rendererFn = createRendererOrchestrator(renderers?.[componentType]);

return {
componentSpec,
Expand All @@ -86,10 +81,10 @@ export function resolveSpec(
}

/**
* Renderer orchestrator factory
* Component orchestrator factory
* Returns a renderer function that processes schemas
*/
export function createRendererOrchestrator(
export function createComponentOrchestrator(
getFactorySetup: () => FactorySetupResult,
runtime: RuntimeAdapter
) {
Expand All @@ -103,7 +98,7 @@ export function createRendererOrchestrator(
const {
components,
customComponents,
renderers: localRenderers,
renderers,
externalContext,
state,
middlewares,
Expand Down Expand Up @@ -144,7 +139,7 @@ export function createRendererOrchestrator(
componentKey,
components,
customComponents,
localRenderers,
renderers,
debug?.isEnabled
);

Expand Down Expand Up @@ -234,5 +229,4 @@ export function createRendererOrchestrator(
// Final Rendering using renderer function with children
return rendererFn(componentSpec, mergedProps, runtime, children.length > 0 ? children : undefined);
};
}

}
Loading