Skip to content

Commit bf8ae72

Browse files
committed
feat: enhance SchemaRenderer to evaluate schema expressions and utilize context data source
1 parent 4a0ad5a commit bf8ae72

File tree

2 files changed

+42
-12
lines changed

2 files changed

+42
-12
lines changed

packages/react/src/SchemaRenderer.tsx

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,33 +6,61 @@
66
* LICENSE file in the root directory of this source tree.
77
*/
88

9-
import React, { forwardRef } from 'react';
10-
import { SchemaNode, ComponentRegistry } from '@object-ui/core';
9+
import React, { forwardRef, useContext, useMemo } from 'react';
10+
import { SchemaNode, ComponentRegistry, ExpressionEvaluator } from '@object-ui/core';
11+
import { SchemaRendererContext } from './context/SchemaRendererContext';
1112

1213
export const SchemaRenderer = forwardRef<any, { schema: SchemaNode } & Record<string, any>>(({ schema, ...props }, _ref) => {
13-
if (!schema) return null;
14+
const context = useContext(SchemaRendererContext);
15+
const dataSource = context?.dataSource || {};
16+
17+
// Evaluate schema expressions against the data source
18+
const evaluatedSchema = useMemo(() => {
19+
if (!schema || typeof schema === 'string') return schema;
20+
21+
const evaluator = new ExpressionEvaluator({ data: dataSource });
22+
const newSchema = { ...schema };
23+
24+
// Evaluate 'content' (common in Text, Button)
25+
if (typeof newSchema.content === 'string') {
26+
newSchema.content = evaluator.evaluate(newSchema.content);
27+
}
28+
29+
// Evaluate 'props'
30+
if (newSchema.props) {
31+
const newProps = { ...newSchema.props };
32+
for (const [key, val] of Object.entries(newProps)) {
33+
newProps[key] = evaluator.evaluate(val);
34+
}
35+
newSchema.props = newProps;
36+
}
37+
38+
return newSchema;
39+
}, [schema, dataSource]);
40+
41+
if (!evaluatedSchema) return null;
1442
// If schema is just a string, render it as text
15-
if (typeof schema === 'string') return <>{schema}</>;
43+
if (typeof evaluatedSchema === 'string') return <>{evaluatedSchema}</>;
1644

17-
const Component = ComponentRegistry.get(schema.type);
45+
const Component = ComponentRegistry.get(evaluatedSchema.type);
1846

1947
if (!Component) {
2048
return (
2149
<div className="p-4 border border-red-500 rounded text-red-500 bg-red-50 my-2">
22-
Unknown component type: <strong>{schema.type}</strong>
23-
<pre className="text-xs mt-2 overflow-auto">{JSON.stringify(schema, null, 2)}</pre>
50+
Unknown component type: <strong>{evaluatedSchema.type}</strong>
51+
<pre className="text-xs mt-2 overflow-auto">{JSON.stringify(evaluatedSchema, null, 2)}</pre>
2452
</div>
2553
);
2654
}
2755

2856
// Note: We don't forward the ref to the Component because components in the registry
2957
// may not support refs. The SchemaRenderer itself can still receive refs for its own use.
3058
return React.createElement(Component, {
31-
schema,
32-
...(schema.props || {}),
33-
className: schema.className,
34-
'data-obj-id': schema.id,
35-
'data-obj-type': schema.type,
59+
schema: evaluatedSchema,
60+
...(evaluatedSchema.props || {}),
61+
className: evaluatedSchema.className,
62+
'data-obj-id': evaluatedSchema.id,
63+
'data-obj-type': evaluatedSchema.type,
3664
...props
3765
});
3866
});

packages/react/src/context/SchemaRendererContext.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ interface SchemaRendererContextType {
77

88
const SchemaRendererContext = createContext<SchemaRendererContextType | null>(null);
99

10+
export { SchemaRendererContext };
11+
1012
export const SchemaRendererProvider = ({
1113
children,
1214
dataSource,

0 commit comments

Comments
 (0)