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' ;
125
136const DESCRIPTION_COL_STYLE = {
14- paddingBottom : " 8px" ,
7+ paddingBottom : ' 8px' ,
158} ;
169
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-
3110const ObjectFieldTemplate = ( props : ObjectFieldTemplateProps ) => {
3211 const {
3312 title,
@@ -43,205 +22,81 @@ const ObjectFieldTemplate = (props: ObjectFieldTemplateProps) => {
4322 registry,
4423 } = props ;
4524
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-
7525 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 ) ;
7828 const {
7929 ButtonTemplates : { AddButton } ,
8030 } = registry . templates ;
8131
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
8639 } ;
8740
88- const { rowGutter = 4 } = uiSchema ?. [ " ui:props" ] || { } ;
41+ const { rowGutter = 4 , colSpan = defaultResponsiveColSpan } = uiSchema ?. [ ' ui:props' ] || { } ;
8942
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 ;
9147
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 ;
14249
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 } ;
15352 } ;
15453
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-
19254 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 >
22463 ) }
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 }
23785 </ Col >
238- </ Row >
86+ ) )
23987 ) }
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 >
24499 ) ;
245100} ;
246101
247- export default ObjectFieldTemplate ;
102+ export default ObjectFieldTemplate ;
0 commit comments