@@ -42,6 +42,8 @@ export default class IgcTileManagerComponent extends EventEmitterMixin<
4242 }
4343
4444 private draggedItem : IgcTileComponent | null = null ;
45+ private finalOrder : IgcTileComponent [ ] = [ ] ;
46+ private positionedTiles : IgcTileComponent [ ] = [ ] ;
4547
4648 // @query ('[part="base"]', true)
4749 // private _baseWrapper!: HTMLDivElement;
@@ -58,20 +60,11 @@ export default class IgcTileManagerComponent extends EventEmitterMixin<
5860 }
5961
6062 private _observerCallback ( {
61- changes : { added } ,
63+ changes : { added, removed } ,
6264 } : MutationControllerParams < IgcTileComponent > ) {
63- // FIX: currently the newly added tile has the specified position+1 in the layout
64- added . forEach ( ( newTile ) => {
65- const specifiedPosition = newTile . position ;
66-
67- if ( specifiedPosition !== undefined ) {
68- this . tiles . splice ( specifiedPosition - 1 , 0 , newTile ) ;
69- } else {
70- this . tiles . push ( newTile ) ;
71- }
72- } ) ;
65+ removed . forEach ( this . handleTileRemoval . bind ( this ) ) ;
66+ added . forEach ( this . handleTileAddition . bind ( this ) ) ;
7367
74- this . assignPositions ( ) ;
7568 this . updateSlotAssignment ( ) ;
7669 }
7770
@@ -90,9 +83,7 @@ export default class IgcTileManagerComponent extends EventEmitterMixin<
9083 * @attr
9184 */
9285 public get tiles ( ) {
93- return Array . from ( this . _tiles ) . sort (
94- ( a , b ) => ( a . position ?? 0 ) - ( b . position ?? 0 )
95- ) ;
86+ return Array . from ( this . _tiles ) . sort ( ( a , b ) => a . position - b . position ) ;
9687 }
9788
9889 @watch ( 'columnCount' , { waitUntilFirstUpdate : true } )
@@ -126,13 +117,113 @@ export default class IgcTileManagerComponent extends EventEmitterMixin<
126117 }
127118
128119 private assignPositions ( ) {
129- this . tiles . forEach ( ( tile , index ) => {
130- tile . position = index ;
120+ const finalOrder : IgcTileComponent [ ] = [ ] ;
121+ const unpositionedTiles = this . _tiles . filter (
122+ ( tile ) => tile . position === - 1
123+ ) ;
124+
125+ this . positionedTiles = this . _tiles . filter ( ( tile ) => tile . position !== - 1 ) ;
126+ this . positionedTiles . sort ( ( a , b ) => a . position - b . position ) ;
127+
128+ let nextFreePosition = 0 ;
129+
130+ this . positionedTiles . forEach ( ( tile ) => {
131+ // Fill any unassigned slots before the next assigned tile's position
132+ while ( nextFreePosition < tile . position && unpositionedTiles . length > 0 ) {
133+ const unpositionedTile = unpositionedTiles . shift ( ) ! ;
134+ unpositionedTile . position = nextFreePosition ++ ;
135+ finalOrder . push ( unpositionedTile ) ;
136+ }
137+ tile . position = finalOrder . length ;
138+ finalOrder . push ( tile ) ;
139+ nextFreePosition = tile . position + 1 ;
140+ } ) ;
141+
142+ unpositionedTiles . forEach ( ( tile ) => {
143+ tile . position = nextFreePosition ++ ;
144+ finalOrder . push ( tile ) ;
131145 } ) ;
146+
147+ this . finalOrder = finalOrder ;
148+ }
149+
150+ private handleTileRemoval ( removedTile : IgcTileComponent ) {
151+ const removedPosition = removedTile . position ;
152+
153+ this . finalOrder = this . finalOrder . filter ( ( tile ) => tile !== removedTile ) ;
154+ this . positionedTiles = this . positionedTiles . filter (
155+ ( tile ) => tile !== removedTile
156+ ) ;
157+
158+ // Shift only non-positioned tiles
159+ this . finalOrder . forEach ( ( tile ) => {
160+ if (
161+ tile . position > removedPosition &&
162+ ! this . positionedTiles . includes ( tile )
163+ ) {
164+ tile . position -= 1 ;
165+ }
166+ } ) ;
167+
168+ this . reassignUnpositionedTiles ( ) ;
169+ }
170+
171+ private handleTileAddition ( newTile : IgcTileComponent ) {
172+ let specifiedPosition = newTile . position ;
173+
174+ if ( specifiedPosition !== - 1 ) {
175+ // Place at specified position, shift non-positioned tiles only
176+ this . finalOrder . forEach ( ( tile ) => {
177+ if (
178+ tile . position >= specifiedPosition &&
179+ ! this . positionedTiles . includes ( tile )
180+ ) {
181+ tile . position += 1 ;
182+ }
183+ } ) ;
184+
185+ this . finalOrder . splice ( specifiedPosition , 0 , newTile ) ;
186+ this . positionedTiles . push ( newTile ) ;
187+ } else {
188+ // Find next available position in DOM for unpositioned tile
189+ specifiedPosition = this . getAvailablePosition ( newTile ) ;
190+ newTile . position = specifiedPosition ;
191+ this . finalOrder . push ( newTile ) ;
192+ }
193+
194+ this . reassignUnpositionedTiles ( ) ;
195+ }
196+
197+ private reassignUnpositionedTiles ( ) {
198+ let nextPosition = 0 ;
199+
200+ this . finalOrder . sort ( ( a , b ) => a . position - b . position ) ;
201+ this . finalOrder . forEach ( ( tile ) => {
202+ if ( ! this . positionedTiles . includes ( tile ) ) {
203+ while (
204+ this . finalOrder . some (
205+ ( posTile ) =>
206+ posTile . position === nextPosition &&
207+ this . positionedTiles . includes ( posTile )
208+ )
209+ ) {
210+ nextPosition += 1 ;
211+ }
212+ tile . position = nextPosition ++ ;
213+ }
214+ } ) ;
215+ }
216+
217+ private getAvailablePosition ( newTile : IgcTileComponent ) : number {
218+ let domIndex = Array . from ( this . children ) . indexOf ( newTile ) ;
219+ while ( this . positionedTiles . some ( ( tile ) => tile . position === domIndex ) ) {
220+ domIndex += 1 ;
221+ }
222+ return domIndex ;
132223 }
133224
134225 private updateSlotAssignment ( ) {
135- this . slotElement . assign ( ...this . tiles ) ;
226+ this . slotElement . assign ( ...this . _tiles ) ;
136227 }
137228
138229 private handleTileDragStart ( e : CustomEvent ) {
@@ -169,20 +260,18 @@ export default class IgcTileManagerComponent extends EventEmitterMixin<
169260 const targetPos = target . position ?? 0 ;
170261
171262 this . tiles . forEach ( ( tile ) => {
172- if ( tile . position ) {
173- if (
174- draggedPos < targetPos &&
175- tile . position > draggedPos &&
176- tile . position <= targetPos
177- ) {
178- tile . position -= 1 ;
179- } else if (
180- draggedPos > targetPos &&
181- tile . position >= targetPos &&
182- tile . position < draggedPos
183- ) {
184- tile . position += 1 ;
185- }
263+ if (
264+ draggedPos < targetPos &&
265+ tile . position > draggedPos &&
266+ tile . position <= targetPos
267+ ) {
268+ tile . position -= 1 ;
269+ } else if (
270+ draggedPos > targetPos &&
271+ tile . position >= targetPos &&
272+ tile . position < draggedPos
273+ ) {
274+ tile . position += 1 ;
186275 }
187276 } ) ;
188277
0 commit comments