@@ -37,6 +37,7 @@ import { renderEmptyItem } from '@ts/ui/form/components/empty_item';
3737import { renderFieldItem } from '@ts/ui/form/components/field_item' ;
3838import {
3939 FIELD_ITEM_CLASS ,
40+ FORM_FIELD_ITEM_COL_CLASS ,
4041 FORM_LAYOUT_MANAGER_CLASS ,
4142 LAYOUT_MANAGER_ONE_COLUMN ,
4243 ROOT_SIMPLE_ITEM_CLASS ,
@@ -54,10 +55,10 @@ import ResponsiveBox from '@ts/ui/responsive_box';
5455
5556const FORM_EDITOR_BY_DEFAULT = 'dxTextBox' ;
5657
57- const LAYOUT_MANAGER_FIRST_ROW_CLASS = 'dx-first-row' ;
58- const LAYOUT_MANAGER_LAST_ROW_CLASS = 'dx-last-row' ;
59- const LAYOUT_MANAGER_FIRST_COL_CLASS = 'dx-first-col' ;
60- const LAYOUT_MANAGER_LAST_COL_CLASS = 'dx-last-col' ;
58+ export const LAYOUT_MANAGER_FIRST_ROW_CLASS = 'dx-first-row' ;
59+ export const LAYOUT_MANAGER_LAST_ROW_CLASS = 'dx-last-row' ;
60+ export const LAYOUT_MANAGER_FIRST_COL_CLASS = 'dx-first-col' ;
61+ export const LAYOUT_MANAGER_LAST_COL_CLASS = 'dx-last-col' ;
6162
6263const MIN_COLUMN_WIDTH = 200 ;
6364
@@ -72,6 +73,15 @@ type ExtendedItem = Item & {
7273 allowIndeterminateState ?: boolean ;
7374} ;
7475
76+ type Location = Required < Omit < LocationItem , 'screen' > > ;
77+
78+ interface LocationBoundaryFlags {
79+ isFirstCol : boolean ;
80+ isLastCol : boolean ;
81+ isFirstRow : boolean ;
82+ isLastRow : boolean ;
83+ }
84+
7585export interface TemplatesInfo {
7686 itemType ?: string ;
7787 // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -130,7 +140,7 @@ class LayoutManager extends Widget<LayoutManagerProperties> {
130140
131141 _labelTemplateRenderedCallCount ?: number ;
132142
133- _cashedColCount ?: number ;
143+ _cachedColCount ?: number | null ;
134144
135145 _getDefaultOptions ( ) : ExtendedLayoutManagerProperties {
136146 return {
@@ -500,40 +510,21 @@ class LayoutManager extends Widget<LayoutManagerProperties> {
500510 }
501511 const $itemElement = $ ( itemElement ) ;
502512
503- const itemRenderedCountInPreviousRows = location . row * colCount ;
504-
505- const item = that . _items ?. [ location . col + itemRenderedCountInPreviousRows ] ;
513+ const item = that . _getLayoutManagerItemByLocation ( location ) ;
506514 if ( ! item ) {
507515 return ;
508516 }
509517
510- const itemCssClassList : string [ ] = [ item . cssClass ?? '' ] ;
511-
512- $itemElement . toggleClass ( SINGLE_COLUMN_ITEM_CONTENT , that . isSingleColumnMode ( this ) ) ;
513-
514- if ( location . row === 0 ) {
515- itemCssClassList . push ( LAYOUT_MANAGER_FIRST_ROW_CLASS ) ;
516- }
517- if ( location . col === 0 ) {
518- itemCssClassList . push ( LAYOUT_MANAGER_FIRST_COL_CLASS ) ;
519- }
520-
521518 const { isRoot } = that . option ( ) ;
522519
523520 if ( item . itemType === SIMPLE_ITEM_TYPE && isRoot ) {
524521 $itemElement . addClass ( ROOT_SIMPLE_ITEM_CLASS ) ;
525522 }
526- const isLastColumn = ( location . col === colCount - 1 )
527- || ( location . col + location . colspan === colCount ) ;
528- const rowsCount = that . _getRowsCount ( ) ;
529- const isLastRow = location . row === rowsCount - 1 ;
530523
531- if ( isLastColumn ) {
532- itemCssClassList . push ( LAYOUT_MANAGER_LAST_COL_CLASS ) ;
533- }
534- if ( isLastRow ) {
535- itemCssClassList . push ( LAYOUT_MANAGER_LAST_ROW_CLASS ) ;
536- }
524+ $itemElement . toggleClass ( SINGLE_COLUMN_ITEM_CONTENT , that . isSingleColumnMode ( this ) ) ;
525+
526+ const itemCssClassList : string [ ] = [ item . cssClass ?? '' ] ;
527+ itemCssClassList . push ( ...that . _getLocationCssClasses ( location ) ) ;
537528
538529 if ( item . itemType !== 'empty' ) {
539530 itemCssClassList . push ( FIELD_ITEM_CLASS ) ;
@@ -543,7 +534,7 @@ class LayoutManager extends Widget<LayoutManagerProperties> {
543534 itemCssClassList . push ( cssItemClass ) ;
544535
545536 if ( isDefined ( item . col ) ) {
546- itemCssClassList . push ( `dx-col- ${ item . col } ` ) ;
537+ itemCssClassList . push ( `${ FORM_FIELD_ITEM_COL_CLASS } ${ item . col } ` ) ;
547538 }
548539 }
549540
@@ -578,12 +569,12 @@ class LayoutManager extends Widget<LayoutManagerProperties> {
578569 }
579570
580571 if ( colCount === 'auto' ) {
581- if ( this . _cashedColCount ) {
582- return this . _cashedColCount ;
572+ if ( this . _cachedColCount ) {
573+ return this . _cachedColCount ;
583574 }
584575
585576 colCount = this . _getMaxColCount ( ) ;
586- this . _cashedColCount = colCount ;
577+ this . _cachedColCount = colCount ;
587578 }
588579 // @ts -expect-error ts-error
589580 return colCount < 1 ? 1 : colCount ;
@@ -607,7 +598,7 @@ class LayoutManager extends Widget<LayoutManagerProperties> {
607598 }
608599
609600 isCachedColCountObsolete ( ) : boolean {
610- return ! ! this . _cashedColCount && this . _getMaxColCount ( ) !== this . _cashedColCount ;
601+ return ! ! this . _cachedColCount && this . _getMaxColCount ( ) !== this . _cachedColCount ;
611602 }
612603
613604 _prepareItemsWithMerging ( colCount : number ) : void {
@@ -644,8 +635,7 @@ class LayoutManager extends Widget<LayoutManagerProperties> {
644635
645636 _setItems ( items : ExtendedItem [ ] ) : void {
646637 this . _items = items ;
647- // @ts -expect-error ts-error
648- this . _cashedColCount = null ; // T923489
638+ this . _cachedColCount = null ; // T923489
649639 }
650640
651641 _generateLayoutItems ( ) : ResponsiveBoxItem [ ] {
@@ -1128,11 +1118,127 @@ class LayoutManager extends Widget<LayoutManagerProperties> {
11281118 }
11291119
11301120 _resetColCount ( ) : void {
1131- // @ts -expect-error ts-error
1132- this . _cashedColCount = null ;
1121+ this . _cachedColCount = null ;
11331122 this . _invalidate ( ) ;
11341123 }
11351124
1125+ updateResponsiveBoxLayout ( ) : void {
1126+ if ( ! this . _responsiveBox ) {
1127+ return ;
1128+ }
1129+
1130+ this . _cachedColCount = null ;
1131+
1132+ this . _items = ( this . _items ?? [ ] ) . filter ( ( item ) => ! item . merged ) ;
1133+
1134+ const colCount = this . _getColCount ( ) ;
1135+ this . _prepareItemsWithMerging ( colCount ) ;
1136+
1137+ const newLayoutItems = this . _generateLayoutItems ( ) ;
1138+
1139+ const { items : responsiveBoxItems } = this . _responsiveBox . option ( ) ;
1140+ const existingItems : ResponsiveBoxItem [ ] = responsiveBoxItems ?? [ ] ;
1141+
1142+ for ( let i = 0 ; i < existingItems . length && i < newLayoutItems . length ; i += 1 ) {
1143+ existingItems [ i ] . location = newLayoutItems [ i ] . location ;
1144+ }
1145+
1146+ const newCols = this . _generateRatio ( colCount ) ;
1147+ const newRows = this . _generateRatio ( this . _getRowsCount ( ) , true ) ;
1148+
1149+ this . _responsiveBox . _options . silent ( {
1150+ cols : newCols ,
1151+ rows : newRows ,
1152+ } ) ;
1153+
1154+ this . _responsiveBox . repaint ( ) ;
1155+ this . _updateItemsCssClasses ( ) ;
1156+ }
1157+
1158+ _getLocationBoundaryFlags ( location : Required < Omit < LocationItem , 'screen' > > ) : LocationBoundaryFlags {
1159+ const colCount = this . _getColCount ( ) ;
1160+ const rowsCount = this . _getRowsCount ( ) ;
1161+
1162+ return {
1163+ isFirstCol : location . col === 0 ,
1164+ isLastCol : ( location . col === colCount - 1 )
1165+ || ( location . col + location . colspan === colCount ) ,
1166+ isFirstRow : location . row === 0 ,
1167+ isLastRow : location . row === rowsCount - 1 ,
1168+ } ;
1169+ }
1170+
1171+ _getLocationCssClasses ( location : Location ) : string [ ] {
1172+ const cssClasses : string [ ] = [ ] ;
1173+ const locationFlags = this . _getLocationBoundaryFlags ( location ) ;
1174+
1175+ if ( locationFlags . isFirstRow ) {
1176+ cssClasses . push ( LAYOUT_MANAGER_FIRST_ROW_CLASS ) ;
1177+ }
1178+ if ( locationFlags . isFirstCol ) {
1179+ cssClasses . push ( LAYOUT_MANAGER_FIRST_COL_CLASS ) ;
1180+ }
1181+ if ( locationFlags . isLastCol ) {
1182+ cssClasses . push ( LAYOUT_MANAGER_LAST_COL_CLASS ) ;
1183+ }
1184+ if ( locationFlags . isLastRow ) {
1185+ cssClasses . push ( LAYOUT_MANAGER_LAST_ROW_CLASS ) ;
1186+ }
1187+
1188+ return cssClasses ;
1189+ }
1190+
1191+ _getLayoutManagerItemByLocation ( location : Location ) : ExtendedItem | undefined {
1192+ const colCount = this . _getColCount ( ) ;
1193+ const index = location . row * colCount + location . col ;
1194+ return this . _items ?. [ index ] ;
1195+ }
1196+
1197+ _updateItemsCssClasses ( ) : void {
1198+ const { items : responsiveBoxItems } = this . _responsiveBox . option ( ) ;
1199+ responsiveBoxItems ?. forEach ( (
1200+ responsiveBoxItem : ResponsiveBoxItem ,
1201+ ) : void => {
1202+ const { location } = responsiveBoxItem ;
1203+ if ( ! location || Array . isArray ( location ) ) {
1204+ return ;
1205+ }
1206+
1207+ const typedLocation = location as Location ;
1208+
1209+ const {
1210+ isFirstCol,
1211+ isLastCol,
1212+ isFirstRow,
1213+ isLastRow,
1214+ } = this . _getLocationBoundaryFlags ( typedLocation ) ;
1215+
1216+ const item = this . _getLayoutManagerItemByLocation ( typedLocation ) ;
1217+ if ( ! item || item . itemType === 'empty' ) {
1218+ return ;
1219+ }
1220+
1221+ const $itemContainer = this . _itemsRunTimeInfo . findItemContainerByItem ( item ) ;
1222+ $itemContainer . parent ( ) . toggleClass ( SINGLE_COLUMN_ITEM_CONTENT , this . isSingleColumnMode ( ) ) ;
1223+ $itemContainer
1224+ . toggleClass ( LAYOUT_MANAGER_FIRST_COL_CLASS , isFirstCol )
1225+ . toggleClass ( LAYOUT_MANAGER_LAST_COL_CLASS , isLastCol )
1226+ . toggleClass ( LAYOUT_MANAGER_FIRST_ROW_CLASS , isFirstRow )
1227+ . toggleClass ( LAYOUT_MANAGER_LAST_ROW_CLASS , isLastRow ) ;
1228+
1229+ const element = $itemContainer . get ( 0 ) ;
1230+ if ( element ) {
1231+ element . className = [ ...element . classList ]
1232+ . filter ( ( name : string ) : boolean => ! name . startsWith ( FORM_FIELD_ITEM_COL_CLASS ) )
1233+ . join ( ' ' ) ;
1234+ }
1235+
1236+ if ( isDefined ( typedLocation . col ) ) {
1237+ $itemContainer . addClass ( `${ FORM_FIELD_ITEM_COL_CLASS } ${ typedLocation . col } ` ) ;
1238+ }
1239+ } ) ;
1240+ }
1241+
11361242 linkEditorToDataField ( editorInstance : Editor , dataField : string ) : void {
11371243 this . on ( 'optionChanged' , ( args : OptionChanged < FormProperties > ) : void => {
11381244 if ( args . fullName === `layoutData.${ dataField } ` ) {
0 commit comments