-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathwidget-renderer.tsx
More file actions
122 lines (102 loc) · 3.01 KB
/
Copy pathwidget-renderer.tsx
File metadata and controls
122 lines (102 loc) · 3.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import React from 'react';
import { Box, Text } from '@chakra-ui/react';
import { usePluginConfig } from '../context/plugin-config';
import { ErrorBox } from './error-box';
import { SchemaField } from '../schema/types';
import { WidgetProps } from './types';
/**
* Renders the widget for a field.
* @param props.pointer The path to the field in the form data
* @param props.field The field schema to render
* @param props.isRequired Whether the field is required
*/
export function WidgetRenderer(props: WidgetProps) {
const { pointer, field, isRequired } = props;
const config = usePluginConfig();
const renderWidget = (widget: string) => {
const Widget = config['ui:widget'][widget];
return (
<WidgetErrorBoundary field={field} widgetName={widget} pointer={pointer}>
{Widget ? (
<Widget pointer={pointer} field={field} isRequired={isRequired} />
) : (
<ErrorBox>Widget "{widget}" not found</ErrorBox>
)}
</WidgetErrorBoundary>
);
};
// Explicitly defined widget
if (field['ui:widget']) {
return renderWidget(field['ui:widget']);
}
if (field.type === 'array') {
if (field.items.type === 'string' && field.items.enum) {
return renderWidget('checkbox');
}
if (['string', 'number'].includes(field.items.type)) {
return renderWidget('array:string');
}
return renderWidget('array');
}
if (field.type === 'root' || field.type === 'object') {
return renderWidget('object');
}
if (field.type === 'string' && field.enum) {
return renderWidget('radio');
}
if (field.type === 'json') {
return renderWidget('json');
}
if (field.type === 'number') {
return renderWidget('number');
}
return renderWidget('text');
}
interface WidgetErrorBoundaryProps {
children: React.ReactNode;
field: SchemaField;
widgetName: string;
pointer: string;
}
interface WidgetErrorBoundaryState {
error: Error | null;
}
class WidgetErrorBoundary extends React.Component<
WidgetErrorBoundaryProps,
WidgetErrorBoundaryState
> {
constructor(props: WidgetErrorBoundaryProps) {
super(props);
this.state = { error: null };
}
static getDerivedStateFromError(error: Error): WidgetErrorBoundaryState {
return { error };
}
render() {
if (this.state.error) {
return (
<ErrorBox color='base.500' alignItems='left' p={4}>
<Text textTransform='uppercase' color='red.500'>
💔 Error rendering widget ({this.props.widgetName})
</Text>
<Text>
{this.state.error.message || 'Something is wrong with this widget'}
</Text>
<Box
as='pre'
bg='base.100'
borderRadius='md'
p={2}
fontSize='small'
maxH={64}
overflow='auto'
>
@.{this.props.pointer} <br />
<code>{JSON.stringify(this.props.field, null, 2)}</code>
</Box>
</ErrorBox>
);
}
return this.props.children;
}
}