Skip to content

Commit 014dfd3

Browse files
Latest resizing changes (#1517)
* tile resizing enhancment * fix: improve ghost snapping for rows --------- Co-authored-by: onlyexeption <[email protected]>
1 parent f54e347 commit 014dfd3

File tree

2 files changed

+120
-30
lines changed

2 files changed

+120
-30
lines changed
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
export class ResizeUtil {
2+
public static calculateSnappedHeight(
3+
deltaY: number,
4+
startingY: number,
5+
rowHeights: number[],
6+
rowGap: number,
7+
initialTop: number,
8+
initialHeight: number
9+
): number {
10+
const snappedHeight = startingY + deltaY;
11+
const rowsAbove =
12+
ResizeUtil.calculate(initialTop, rowHeights, rowGap).targetIndex || 0;
13+
const res = ResizeUtil.calculate(snappedHeight, rowHeights, rowGap)!;
14+
const accumulatedHeight = res.accumulatedHeight;
15+
const startRowIndex = res.targetIndex;
16+
const aboveRowsHeight = ResizeUtil.accumulateHeight(
17+
rowsAbove,
18+
rowHeights,
19+
rowGap
20+
);
21+
22+
let result = initialHeight;
23+
let previousRowsHeight = ResizeUtil.accumulateHeight(
24+
startRowIndex,
25+
rowHeights,
26+
rowGap
27+
);
28+
29+
if (deltaY > 0) {
30+
const rowHeight = rowHeights[startRowIndex];
31+
const halfwayThreshold = previousRowsHeight + rowGap + rowHeight / 2;
32+
33+
if (snappedHeight >= halfwayThreshold) {
34+
result = accumulatedHeight - aboveRowsHeight;
35+
} else {
36+
result = initialHeight + deltaY;
37+
}
38+
39+
result = result <= 0 ? rowHeights[startRowIndex - 1] : result;
40+
} else if (deltaY < 0) {
41+
previousRowsHeight =
42+
previousRowsHeight === 0 ? rowHeights[0] : previousRowsHeight;
43+
const currentRowHeight = rowHeights[startRowIndex];
44+
const halfwayThreshold =
45+
accumulatedHeight - currentRowHeight / 2 - rowGap;
46+
47+
if (startRowIndex !== 0 && startRowIndex >= startRowIndex - 1) {
48+
if (snappedHeight <= halfwayThreshold) {
49+
result =
50+
accumulatedHeight - currentRowHeight - rowGap - aboveRowsHeight;
51+
} else {
52+
result = rowHeights
53+
.slice(rowsAbove, startRowIndex)
54+
.reduce((sum, height) => sum + height, 0);
55+
}
56+
} else {
57+
result = snappedHeight - aboveRowsHeight;
58+
}
59+
}
60+
61+
return result;
62+
}
63+
64+
private static calculate(
65+
initialTop: number,
66+
rowHeights: number[],
67+
rowGap: number
68+
): any {
69+
let targetIndex = 0;
70+
let accumulatedHeight = 0;
71+
72+
for (let i = 0; i < rowHeights.length; i++) {
73+
accumulatedHeight += rowHeights[i] + (i > 0 ? rowGap : 0);
74+
if (initialTop <= accumulatedHeight) {
75+
targetIndex = i;
76+
break;
77+
}
78+
}
79+
80+
return { targetIndex, accumulatedHeight };
81+
}
82+
83+
private static accumulateHeight(
84+
rowIndex: number,
85+
rowHeights: number[],
86+
rowGap: number
87+
): number {
88+
let accumulatedHeight = 0;
89+
for (let i = 0; i < rowIndex; i++) {
90+
accumulatedHeight += rowHeights[i] + rowGap;
91+
}
92+
93+
return accumulatedHeight;
94+
}
95+
}

src/components/tile-manager/tile.ts

Lines changed: 25 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { styles as shared } from './themes/shared/tile/tile.common.css.js';
2121
import { styles } from './themes/tile.base.css.js';
2222
import { all } from './themes/tile.js';
2323
import IgcTileHeaderComponent from './tile-header.js';
24+
import { ResizeUtil } from './tile-util.js';
2425

2526
type IgcTileChangeState = {
2627
tile: IgcTileComponent;
@@ -101,6 +102,8 @@ export default class IgcTileComponent extends EventEmitterMixin<
101102
background?: string;
102103
border?: string;
103104
borderRadius?: string;
105+
rowHeights?: number[];
106+
initialTop?: number;
104107
} = {};
105108

106109
// Tile manager context properties and helpers
@@ -371,6 +374,12 @@ export default class IgcTileComponent extends EventEmitterMixin<
371374
private cacheStyles() {
372375
//use util
373376
const computedStyle = getComputedStyle(this);
377+
const parentWrapper =
378+
this.parentElement!.shadowRoot!.querySelector('[part="base"]')!;
379+
380+
const rowHeights = getComputedStyle(parentWrapper)
381+
.gridTemplateRows.split(' ')
382+
.map((height) => Number.parseFloat(height.trim()));
374383

375384
this._cachedStyles = {
376385
columnCount: Number.parseFloat(
@@ -385,6 +394,8 @@ export default class IgcTileComponent extends EventEmitterMixin<
385394
minHeight: Number.parseFloat(
386395
computedStyle.getPropertyValue('--ig-min-row-height')
387396
),
397+
rowHeights,
398+
initialTop: parentWrapper.getBoundingClientRect().top,
388399
};
389400
}
390401

@@ -403,6 +414,7 @@ export default class IgcTileComponent extends EventEmitterMixin<
403414
this._isResizing = true;
404415

405416
const ghostElement = event.detail.state.current;
417+
const rowHeights = this._cachedStyles.rowHeights!;
406418

407419
if (ghostElement) {
408420
const deltaX = event.detail.event.clientX - this._initialPointerX!;
@@ -414,10 +426,20 @@ export default class IgcTileComponent extends EventEmitterMixin<
414426
event.detail.state.initial.width,
415427
columnGap
416428
);
417-
const snappedHeight = this._calculateSnappedHeight(
429+
430+
const actualTop = this._cachedStyles.initialTop! + window.scrollY;
431+
const initialTop = event.detail.state.initial.top + window.scrollY;
432+
const actualBottom = event.detail.state.initial.bottom + window.scrollY;
433+
434+
const startingY = actualBottom - actualTop;
435+
436+
const snappedHeight = ResizeUtil.calculateSnappedHeight(
418437
deltaY,
419-
event.detail.state.initial.height,
420-
columnGap
438+
startingY,
439+
rowHeights,
440+
columnGap,
441+
initialTop,
442+
event.detail.state.initial.height
421443
);
422444

423445
ghostElement.width = snappedWidth;
@@ -446,33 +468,6 @@ export default class IgcTileComponent extends EventEmitterMixin<
446468
return snappedWidth < colWidth ? colWidth : snappedWidth;
447469
}
448470

449-
private _calculateSnappedHeight(
450-
deltaY: number,
451-
initialHeight: number,
452-
rowGap: number
453-
): number {
454-
const minHeight = this._cachedStyles.minHeight!;
455-
let snappedHeight = initialHeight;
456-
457-
if (deltaY > 0) {
458-
// For resizing down, add the gaps and the rows multiplied by min height to the initial tile height
459-
const additionalHeight = initialHeight + deltaY;
460-
const wholeRows = Math.floor(additionalHeight / (minHeight + rowGap));
461-
const totalHeight = wholeRows * (minHeight + rowGap) - rowGap;
462-
463-
snappedHeight = Math.max(totalHeight, minHeight); // Ensure it at least snaps to minHeight
464-
} else if (deltaY < 0 && initialHeight > minHeight) {
465-
// For resizing up, subtract the gaps and the rows multiplied by min height from the initial tile height
466-
const reducedHeight = initialHeight + deltaY;
467-
const wholeRows = Math.floor(reducedHeight / (minHeight + rowGap));
468-
const totalHeight = wholeRows * (minHeight + rowGap) - rowGap;
469-
470-
snappedHeight = Math.max(totalHeight, minHeight);
471-
}
472-
473-
return snappedHeight;
474-
}
475-
476471
private _handleResizeEnd(event: CustomEvent<ResizeCallbackParams>) {
477472
const state = event.detail.state;
478473
const width = state.current.width; // - state.current.x;

0 commit comments

Comments
 (0)