1- import { compact , CompactType , getFirstCollision , Layout , LayoutItem , moveElement } from './react-grid-layout.utils' ;
1+ import { compact , CompactType , getFirstCollision , Layout , LayoutItem , moveElement , sortLayoutItems } from './react-grid-layout.utils' ;
22import {
3- KtdDraggingData , KtdGridCfg , KtdGridCompactType , KtdGridItemRect , KtdGridItemRenderData , KtdGridLayout , KtdGridLayoutItem
3+ KtdDraggingData , KtdDraggingMultipleData , KtdGridCfg , KtdGridCompactType , KtdGridItemRect , KtdGridItemRenderData , KtdGridLayout , KtdGridLayoutItem
44} from '../grid.definitions' ;
55import { ktdPointerClientX , ktdPointerClientY } from './pointer.utils' ;
66import { KtdDictionary } from '../../types' ;
77import { KtdGridItemComponent } from '../grid-item/grid-item.component' ;
8+ import { KtdMoveMultipleElements } from './react-grid-layout-multiple.utils' ;
89
910/** Tracks items by id. This function is mean to be used in conjunction with the ngFor that renders the 'ktd-grid-items' */
1011export function ktdTrackById ( index : number , item : { id : string } ) {
@@ -31,6 +32,19 @@ export function ktdGridCompact(layout: KtdGridLayout, compactType: KtdGridCompac
3132 . map ( item => ( { id : item . id , x : item . x , y : item . y , w : item . w , h : item . h , minW : item . minW , minH : item . minH , maxW : item . maxW , maxH : item . maxH } ) ) ;
3233}
3334
35+ /**
36+ * Call react-grid-layout utils 'sortLayoutItems()' function to return the 'layout' sorted by 'compactType'
37+ * @param {Layout } layout
38+ * @param {CompactType } compactType
39+ * @returns {Layout }
40+ */
41+ export function ktdGridSortLayoutItems (
42+ layout : Layout ,
43+ compactType : CompactType ,
44+ ) : Layout {
45+ return sortLayoutItems ( layout , compactType )
46+ }
47+
3448function screenXToGridX ( screenXPos : number , cols : number , width : number , gap : number ) : number {
3549 if ( cols <= 1 ) {
3650 return 0 ;
@@ -152,6 +166,121 @@ export function ktdGridItemDragging(gridItem: KtdGridItemComponent, config: KtdG
152166 } ;
153167}
154168
169+
170+
171+ /**
172+ * Given the grid config & layout data and the current drag position & information, returns the corresponding layout and drag item position
173+ * @param gridItem grid item that is been dragged
174+ * @param config current grid configuration
175+ * @param compactionType type of compaction that will be performed
176+ * @param draggingData contains all the information about the drag
177+ */
178+ export function ktdGridItemsDragging ( gridItems : KtdGridItemComponent [ ] , config : KtdGridCfg , compactionType : CompactType , draggingData : KtdDraggingMultipleData ) : { layout : KtdGridLayoutItem [ ] ; draggedItemPos : KtdDictionary < KtdGridItemRect > } {
179+ const { pointerDownEvent, pointerDragEvent, gridElemClientRect, dragElementsClientRect, scrollDifference} = draggingData ;
180+
181+ const draggingElemPrevItem : KtdDictionary < KtdGridLayoutItem > = { }
182+ gridItems . forEach ( gridItem => {
183+ draggingElemPrevItem [ gridItem . id ] = config . layout . find ( item => item . id === gridItem . id ) !
184+ } ) ;
185+
186+ const clientStartX = ktdPointerClientX ( pointerDownEvent ) ;
187+ const clientStartY = ktdPointerClientY ( pointerDownEvent ) ;
188+ const clientX = ktdPointerClientX ( pointerDragEvent ) ;
189+ const clientY = ktdPointerClientY ( pointerDragEvent ) ;
190+
191+ // Grid element positions taking into account the possible scroll total difference from the beginning.
192+ const gridElementLeftPosition = gridElemClientRect . left + scrollDifference . left ;
193+ const gridElementTopPosition = gridElemClientRect . top + scrollDifference . top ;
194+
195+ const rowHeightInPixels = config . rowHeight === 'fit'
196+ ? ktdGetGridItemRowHeight ( config . layout , config . height ?? gridElemClientRect . height , config . gap )
197+ : config . rowHeight ;
198+
199+ const layoutItemsToMove : KtdDictionary < KtdGridLayoutItem > = { } ;
200+ const gridRelPos : KtdDictionary < { x :number , y :number } > = { }
201+ let maxXMove : number = 0 ;
202+ let maxYMove : number = 0 ;
203+ gridItems . forEach ( ( gridItem : KtdGridItemComponent ) => {
204+ const offsetX = clientStartX - dragElementsClientRect [ gridItem . id ] . left ;
205+ const offsetY = clientStartY - dragElementsClientRect [ gridItem . id ] . top ;
206+ // Calculate position relative to the grid element.
207+ gridRelPos [ gridItem . id ] = {
208+ x : clientX - gridElementLeftPosition - offsetX ,
209+ y : clientY - gridElementTopPosition - offsetY
210+ } ;
211+ // Get layout item position
212+ layoutItemsToMove [ gridItem . id ] = {
213+ ...draggingElemPrevItem [ gridItem . id ] ,
214+ x : screenXToGridX ( gridRelPos [ gridItem . id ] . x , config . cols , gridElemClientRect . width , config . gap ) ,
215+ y : screenYToGridY ( gridRelPos [ gridItem . id ] . y , rowHeightInPixels , gridElemClientRect . height , config . gap )
216+ } ;
217+ // Determine the maximum X and Y displacement where an item has gone outside the grid
218+ if ( 0 > layoutItemsToMove [ gridItem . id ] . x && maxXMove > layoutItemsToMove [ gridItem . id ] . x ) {
219+ maxXMove = layoutItemsToMove [ gridItem . id ] . x ;
220+ }
221+ if ( 0 > layoutItemsToMove [ gridItem . id ] . y && maxYMove > layoutItemsToMove [ gridItem . id ] . y ) {
222+ maxYMove = layoutItemsToMove [ gridItem . id ] . y ;
223+ }
224+ if ( layoutItemsToMove [ gridItem . id ] . x + layoutItemsToMove [ gridItem . id ] . w > config . cols && maxXMove < layoutItemsToMove [ gridItem . id ] . w + layoutItemsToMove [ gridItem . id ] . x - config . cols ) {
225+ maxXMove = layoutItemsToMove [ gridItem . id ] . w + layoutItemsToMove [ gridItem . id ] . x - config . cols
226+ }
227+ } )
228+ // Correct all the x and y position of the group decreasing/increasing the maximum overflow of an item, to maintain the structure
229+ Object . entries ( layoutItemsToMove ) . forEach ( ( [ key , item ] ) => {
230+ layoutItemsToMove [ key ] = {
231+ ...item ,
232+ x : item . x - maxXMove ,
233+ y : item . y - maxYMove
234+ } ;
235+ } )
236+
237+ // Parse to LayoutItem array data in order to use 'react.grid-layout' utils
238+ const layoutItems : LayoutItem [ ] = config . layout ;
239+ const draggedLayoutItems : {
240+ l : LayoutItem ,
241+ x : number | null | undefined ,
242+ y : number | null | undefined
243+ } [ ] = gridItems . map ( ( gridItem :KtdGridItemComponent ) => {
244+ const draggedLayoutItem : LayoutItem = layoutItems . find ( item => item . id === gridItem . id ) ! ;
245+ draggedLayoutItem . static = true ;
246+ return {
247+ l : draggedLayoutItem ,
248+ x : layoutItemsToMove [ gridItem . id ] . x ,
249+ y : layoutItemsToMove [ gridItem . id ] . y
250+ }
251+ } ) ;
252+
253+ // Move all elements in group
254+ let newLayoutItems : LayoutItem [ ] = KtdMoveMultipleElements (
255+ layoutItems ,
256+ draggedLayoutItems ,
257+ true ,
258+ compactionType ,
259+ config . cols ,
260+ ) ;
261+
262+ // Compact with selected items as static to preserve the structure of the selected items group
263+ newLayoutItems = compact ( newLayoutItems , compactionType , config . cols ) ;
264+ gridItems . forEach ( gridItem => newLayoutItems . find ( layoutItem => layoutItem . id === gridItem . id ) ! . static = false ) ;
265+ // Compact normal to display the layout correctly
266+ newLayoutItems = compact ( newLayoutItems , compactionType , config . cols ) ;
267+
268+ const draggedItemPos : KtdDictionary < KtdGridItemRect > = { } ;
269+ gridItems . forEach ( gridItem =>
270+ draggedItemPos [ gridItem . id ] = {
271+ left : gridRelPos [ gridItem . id ] . x ,
272+ top : gridRelPos [ gridItem . id ] . y ,
273+ width : dragElementsClientRect [ gridItem . id ] . width ,
274+ height : dragElementsClientRect [ gridItem . id ] . height ,
275+ }
276+ ) ;
277+
278+ return {
279+ layout : newLayoutItems ,
280+ draggedItemPos
281+ } ;
282+ }
283+
155284/**
156285 * Given the grid config & layout data and the current drag position & information, returns the corresponding layout and drag item position
157286 * @param gridItem grid item that is been dragged
0 commit comments