1
- import React , { useEffect , useRef , useState } from "react" ;
2
- import { Row , Col } from "antd" ;
3
- import {
4
- ObjectFieldTemplateProps ,
5
- getTemplate ,
6
- getUiOptions ,
7
- descriptionId ,
8
- titleId ,
9
- canExpand ,
10
- } from "@rjsf/utils" ;
11
- import { ConfigConsumer } from "antd/es/config-provider/context" ;
1
+ import React from 'react' ;
2
+ import { Row , Col } from 'antd' ;
3
+ import { ObjectFieldTemplateProps , getTemplate , getUiOptions , descriptionId , titleId , canExpand } from '@rjsf/utils' ;
4
+ import { ConfigConsumer } from 'antd/es/config-provider/context' ;
12
5
13
6
const DESCRIPTION_COL_STYLE = {
14
- paddingBottom : " 8px" ,
7
+ paddingBottom : ' 8px' ,
15
8
} ;
16
9
17
- interface ColSpan {
18
- xs : number ;
19
- sm : number ;
20
- md : number ;
21
- lg : number ;
22
- xl : number ;
23
- }
24
-
25
- interface UiOptions {
26
- colSpan : ColSpan ;
27
- rowGutter : number ;
28
- // other properties...
29
- }
30
-
31
10
const ObjectFieldTemplate = ( props : ObjectFieldTemplateProps ) => {
32
11
const {
33
12
title,
@@ -43,205 +22,81 @@ const ObjectFieldTemplate = (props: ObjectFieldTemplateProps) => {
43
22
registry,
44
23
} = props ;
45
24
46
- const containerRef = useRef < HTMLDivElement > ( null ) ;
47
- const [ containerWidth , setContainerWidth ] = useState ( 0 ) ;
48
-
49
- // Monitor the container's width
50
- useEffect ( ( ) => {
51
- const updateWidth = ( ) => {
52
- if ( containerRef . current ) {
53
- setContainerWidth ( containerRef . current . offsetWidth ) ;
54
- }
55
- } ;
56
-
57
- // Create a ResizeObserver to watch for width changes
58
- const resizeObserver = new ResizeObserver ( ( ) => {
59
- updateWidth ( ) ;
60
- } ) ;
61
-
62
- if ( containerRef . current ) {
63
- resizeObserver . observe ( containerRef . current ) ;
64
- }
65
-
66
- // Initial update
67
- updateWidth ( ) ;
68
-
69
- // Cleanup observer on unmount
70
- return ( ) => {
71
- resizeObserver . disconnect ( ) ;
72
- } ;
73
- } , [ ] ) ;
74
-
75
25
const uiOptions = getUiOptions ( uiSchema ) ;
76
- const TitleFieldTemplate = getTemplate ( " TitleFieldTemplate" , registry , uiOptions ) ;
77
- const DescriptionFieldTemplate = getTemplate ( " DescriptionFieldTemplate" , registry , uiOptions ) ;
26
+ const TitleFieldTemplate = getTemplate ( ' TitleFieldTemplate' , registry , uiOptions ) ;
27
+ const DescriptionFieldTemplate = getTemplate ( ' DescriptionFieldTemplate' , registry , uiOptions ) ;
78
28
const {
79
29
ButtonTemplates : { AddButton } ,
80
30
} = registry . templates ;
81
31
82
- const defaultResponsiveColSpan = ( width : number ) => {
83
- if ( width > 1200 ) return 8 ; // Wide screens
84
- if ( width > 768 ) return 12 ; // Tablets
85
- return 24 ; // Mobile
32
+ // Define responsive column spans based on the ui:props or fallback to defaults
33
+ const defaultResponsiveColSpan = {
34
+ xs : 24 , // Extra small devices
35
+ sm : 24 , // Small devices
36
+ md : 12 , // Medium devices
37
+ lg : 12 , // Large devices
38
+ xl : 8 , // Extra large devices
86
39
} ;
87
40
88
- const { rowGutter = 4 } = uiSchema ?. [ " ui:props" ] || { } ;
41
+ const { rowGutter = 4 , colSpan = defaultResponsiveColSpan } = uiSchema ?. [ ' ui:props' ] || { } ;
89
42
90
- const calculateResponsiveColSpan = ( element : any ) : { span : number } => {
43
+ // Generate responsive colSpan props for each element
44
+ const calculateResponsiveColSpan = ( element : any ) => {
45
+ const { type } = element . content . props . schema ;
46
+ const widget = getUiOptions ( element . content . props . uiSchema ) . widget ;
91
47
92
- const uiSchemaProps = getUiOptions ( element . content . props . uiSchema ) ?. [ "ui:props" ] as
93
- | { colSpan ?: Record < string , number > | number }
94
- | undefined ;
95
-
96
- const uiSchemaColSpan = uiSchemaProps ?. colSpan ;
97
- const defaultSpan = containerWidth > 1200 ? 8 : containerWidth > 768 ? 12 : 24 ;
98
-
99
- if ( uiSchemaColSpan ) {
100
- if ( typeof uiSchemaColSpan === "number" ) {
101
- return { span : uiSchemaColSpan } ;
102
- } else if ( typeof uiSchemaColSpan === "object" ) {
103
- if ( containerWidth > 1200 && uiSchemaColSpan . xl !== undefined ) {
104
- return { span : uiSchemaColSpan . xl } ;
105
- } else if ( containerWidth > 992 && uiSchemaColSpan . lg !== undefined ) {
106
- return { span : uiSchemaColSpan . lg } ;
107
- } else if ( containerWidth > 768 && uiSchemaColSpan . md !== undefined ) {
108
- return { span : uiSchemaColSpan . md } ;
109
- } else if ( containerWidth > 576 && uiSchemaColSpan . sm !== undefined ) {
110
- return { span : uiSchemaColSpan . sm } ;
111
- } else if ( uiSchemaColSpan . xs !== undefined ) {
112
- return { span : uiSchemaColSpan . xs } ;
113
- }
114
- }
115
- }
116
-
117
- return { span : defaultSpan } ;
118
- } ;
119
-
120
- const renderSectionLayout = ( properties : any [ ] , uiGrid : any , section : string ) => {
121
-
122
- if ( uiGrid && Array . isArray ( uiGrid ) ) {
123
- return (
124
- < Row gutter = { rowGutter } key = { section } >
125
- { uiGrid . map ( ( ui_row : Record < string , any > ) =>
126
- Object . keys ( ui_row ) . map ( ( row_item ) => {
127
- const element = properties . find ( ( p ) => p . name === row_item ) ;
128
- if ( element ) {
129
- const span = calculateResponsiveColSpan ( element ) . span ;
130
- return (
131
- < Col key = { element . name } span = { span } >
132
- { element . content }
133
- </ Col >
134
- ) ;
135
- }
136
- return null ;
137
- } )
138
- ) }
139
- </ Row >
140
- ) ;
141
- }
48
+ const defaultSpan = widget === 'textarea' || type === 'object' || type === 'array' ? 24 : colSpan ;
142
49
143
- // Default layout if no grid is provided
144
- return (
145
- < Row gutter = { rowGutter } key = { section } >
146
- { properties . map ( ( element ) => (
147
- < Col key = { element . name } { ...calculateResponsiveColSpan ( element ) } >
148
- { element . content }
149
- </ Col >
150
- ) ) }
151
- </ Row >
152
- ) ;
50
+ // Ensure the returned object is properly formatted for AntD responsive properties
51
+ return typeof defaultSpan === 'object' ? defaultSpan : { span : defaultSpan } ;
153
52
} ;
154
53
155
- const renderCustomLayout = ( ) => {
156
- const schemaType = schema . type as string ;
157
- switch ( schemaType ) {
158
- case "Group" :
159
- return (
160
- < div style = { { border : "1px solid #ccc" , padding : "15px" , marginBottom : "10px" } } >
161
- < h3 > { schema . label || "Group" } </ h3 >
162
- { renderSectionLayout ( properties , uiSchema ?. [ "ui:grid" ] , schema . label ) }
163
- </ div >
164
- ) ;
165
- case "HorizontalLayout" :
166
- return (
167
- < Row gutter = { rowGutter } style = { { display : "flex" , gap : "10px" } } >
168
- { properties . map ( ( element ) => (
169
- < Col key = { element . name } { ...calculateResponsiveColSpan ( element ) } >
170
- { element . content }
171
- </ Col >
172
- ) ) }
173
- </ Row >
174
- ) ;
175
- case "VerticalLayout" :
176
- return (
177
- < div style = { { display : "flex" , flexDirection : "column" , gap : "10px" } } >
178
- { properties . map ( ( element ) => (
179
- < div key = { element . name } > { element . content } </ div >
180
- ) ) }
181
- </ div >
182
- ) ;
183
- default :
184
- return null ; // Fall back to default rendering if no match
185
- }
186
- } ;
187
-
188
- // Check if the schema is a custom layout type
189
- const schemaType = schema . type as string ; // Extract schema type safely
190
- const isCustomLayout = [ "Group" , "HorizontalLayout" , "VerticalLayout" ] . includes ( schemaType ) ;
191
-
192
54
return (
193
- < div ref = { containerRef } >
194
- < ConfigConsumer >
195
- { ( configProps ) => (
196
- < fieldset id = { idSchema . $id } className = "form-section" >
197
- { ! isCustomLayout && (
198
- < >
199
- { schema . type === "object" && title && (
200
- < legend >
201
- < TitleFieldTemplate
202
- id = { titleId ( idSchema ) }
203
- title = { title }
204
- required = { props . required }
205
- schema = { schema }
206
- uiSchema = { uiSchema }
207
- registry = { registry }
208
- />
209
- </ legend >
210
- ) }
211
- { description && (
212
- < Col span = { 24 } style = { DESCRIPTION_COL_STYLE } >
213
- < DescriptionFieldTemplate
214
- id = { descriptionId ( idSchema ) }
215
- description = { description }
216
- schema = { schema }
217
- uiSchema = { uiSchema }
218
- registry = { registry }
219
- />
220
- </ Col >
221
- ) }
222
- { renderSectionLayout ( properties , uiSchema ?. [ "ui:grid" ] , "root" ) }
223
- </ >
55
+ < ConfigConsumer >
56
+ { ( configProps ) => (
57
+ < fieldset id = { idSchema . $id } className = "form-section" >
58
+ < Row gutter = { rowGutter } >
59
+ { schema . type === 'object' && title && (
60
+ < legend >
61
+ < TitleFieldTemplate id = { titleId ( idSchema ) } title = { title } required = { props . required } schema = { schema } uiSchema = { uiSchema } registry = { registry } />
62
+ </ legend >
224
63
) }
225
-
226
- { isCustomLayout && renderCustomLayout ( ) }
227
-
228
- { canExpand ( schema , uiSchema , formData ) && (
229
- < Row justify = "end" style = { { marginTop : "24px" } } >
230
- < Col >
231
- < AddButton
232
- className = "object-property-expand"
233
- onClick = { onAddClick ( schema ) }
234
- disabled = { disabled || readonly }
235
- registry = { registry }
236
- />
64
+ { description && (
65
+ < Col span = { 24 } style = { DESCRIPTION_COL_STYLE } >
66
+ < DescriptionFieldTemplate id = { descriptionId ( idSchema ) } description = { description } schema = { schema } uiSchema = { uiSchema } registry = { registry } />
67
+ </ Col >
68
+ ) }
69
+ { uiSchema ?. [ 'ui:grid' ] && Array . isArray ( uiSchema [ 'ui:grid' ] ) ? (
70
+ uiSchema [ 'ui:grid' ] . map ( ( ui_row : Record < string , any > ) => {
71
+ return Object . keys ( ui_row ) . map ( ( row_item ) => {
72
+ const element = properties . find ( ( p ) => p . name === row_item ) ;
73
+ return element ? (
74
+ // Pass responsive colSpan props using the calculated values
75
+ < Col key = { element . name } { ...ui_row [ row_item ] } >
76
+ { element . content }
77
+ </ Col >
78
+ ) : null ;
79
+ } ) ;
80
+ } )
81
+ ) : (
82
+ properties . map ( ( element ) => (
83
+ < Col key = { element . name } { ...calculateResponsiveColSpan ( element ) } >
84
+ { element . content }
237
85
</ Col >
238
- </ Row >
86
+ ) )
239
87
) }
240
- </ fieldset >
241
- ) }
242
- </ ConfigConsumer >
243
- </ div >
88
+ </ Row >
89
+ { canExpand ( schema , uiSchema , formData ) && (
90
+ < Row justify = "end" style = { { marginTop : '24px' } } >
91
+ < Col >
92
+ < AddButton className = "object-property-expand" onClick = { onAddClick ( schema ) } disabled = { disabled || readonly } registry = { registry } />
93
+ </ Col >
94
+ </ Row >
95
+ ) }
96
+ </ fieldset >
97
+ ) }
98
+ </ ConfigConsumer >
244
99
) ;
245
100
} ;
246
101
247
- export default ObjectFieldTemplate ;
102
+ export default ObjectFieldTemplate ;
0 commit comments