Skip to content

Commit f18d17b

Browse files
committed
feat: resize snapping initial implementatiton
1 parent 71889e4 commit f18d17b

File tree

1 file changed

+105
-22
lines changed

1 file changed

+105
-22
lines changed

src/components/tile-manager/tile.ts

Lines changed: 105 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -71,11 +71,12 @@ export default class IgcTileComponent extends EventEmitterMixin<
7171
private _initialPointerX: number | null = null;
7272
private _initialPointerY: number | null = null;
7373
private _cachedStyles: {
74-
ghostBackground?: string;
75-
ghostBorder?: string;
76-
ghostBorderRadius?: string;
77-
ghostMinWidth?: string;
78-
ghostMinHeight?: string;
74+
columnCount?: number;
75+
minWidth?: number;
76+
minHeight?: number;
77+
background?: string;
78+
border?: string;
79+
borderRadius?: string;
7980
} = {};
8081
private _context = new ContextProvider(this, {
8182
context: tileContext,
@@ -343,16 +344,22 @@ export default class IgcTileComponent extends EventEmitterMixin<
343344
}
344345

345346
private cacheStyles() {
346-
const computedStyle = window.getComputedStyle(this);
347+
//use util
348+
const computedStyle = getComputedStyle(this);
347349

348350
this._cachedStyles = {
349-
ghostBackground: computedStyle.getPropertyValue(
350-
'--placeholder-background'
351+
columnCount: Number.parseFloat(
352+
computedStyle.getPropertyValue('--ig-column-count')
353+
),
354+
background: computedStyle.getPropertyValue('--placeholder-background'),
355+
border: computedStyle.getPropertyValue('--ghost-border'),
356+
borderRadius: computedStyle.getPropertyValue('--border-radius'),
357+
minWidth: Number.parseFloat(
358+
computedStyle.getPropertyValue('--ig-min-col-width')
359+
),
360+
minHeight: Number.parseFloat(
361+
computedStyle.getPropertyValue('--ig-min-row-height')
351362
),
352-
ghostBorder: computedStyle.getPropertyValue('--ghost-border'),
353-
ghostBorderRadius: computedStyle.getPropertyValue('--border-radius'),
354-
ghostMinWidth: computedStyle.getPropertyValue('--ig-min-col-width'),
355-
ghostMinHeight: computedStyle.getPropertyValue('--ig-min-row-height'),
356363
};
357364
}
358365

@@ -362,8 +369,8 @@ export default class IgcTileComponent extends EventEmitterMixin<
362369
this._initialPointerY = event.detail.event.clientY;
363370

364371
if (ghostElement) {
365-
ghostElement.style.minWidth = this._cachedStyles.ghostMinWidth!;
366-
ghostElement.style.minHeight = this._cachedStyles.ghostMinHeight!;
372+
ghostElement.style.minWidth = `${this._cachedStyles.minWidth!}px`;
373+
ghostElement.style.minHeight = `${this._cachedStyles.minHeight!}px`;
367374
}
368375
}
369376

@@ -375,10 +382,70 @@ export default class IgcTileComponent extends EventEmitterMixin<
375382
if (ghostElement) {
376383
const deltaX = event.detail.event.clientX - this._initialPointerX!;
377384
const deltaY = event.detail.event.clientY - this._initialPointerY!;
385+
const minWidth = this._cachedStyles.minWidth!;
386+
const minHeight = this._cachedStyles.minHeight!;
387+
const columnGap = 10;
388+
389+
const snappedWidth = this._calculateSnappedWidth(
390+
deltaX,
391+
event.detail.state.initial.width,
392+
minWidth,
393+
columnGap
394+
);
395+
const snappedHeight = this._calculateSnappedHeight(
396+
deltaY,
397+
event.detail.state.initial.height,
398+
minHeight,
399+
columnGap
400+
);
401+
402+
ghostElement.width = snappedWidth;
403+
ghostElement.height = snappedHeight;
404+
}
405+
}
378406

379-
ghostElement.width = event.detail.state.initial.width + deltaX;
380-
ghostElement.height = event.detail.state.initial.height + deltaY;
407+
private _calculateSnappedWidth(
408+
deltaX: number,
409+
initialWidth: number,
410+
minWidth: number,
411+
gap: number
412+
): number {
413+
const newSize = initialWidth + deltaX;
414+
const wholeUnits = Math.floor(newSize / (minWidth + gap));
415+
const fraction = newSize / (minWidth + gap) - wholeUnits;
416+
const gapMultiplier =
417+
fraction > 0.5 ? wholeUnits : wholeUnits > 1 ? wholeUnits - 1 : 0;
418+
419+
return fraction > 0.5
420+
? (wholeUnits + 1) * minWidth + gapMultiplier * gap
421+
: wholeUnits * minWidth + gapMultiplier * gap;
422+
}
423+
424+
private _calculateSnappedHeight(
425+
deltaY: number,
426+
initialHeight: number,
427+
minHeight: number,
428+
rowGap: number
429+
): number {
430+
let snappedHeight = initialHeight;
431+
432+
if (deltaY > 0) {
433+
// For resizing down, add the gaps and the rows multiplied by min height to the initial tile height
434+
const wholeRows = Math.floor(deltaY / minHeight);
435+
const totalGaps = Math.max(wholeRows - 1, 0) * rowGap;
436+
snappedHeight = initialHeight + wholeRows * minHeight + totalGaps;
437+
} else if (deltaY < 0 && initialHeight > minHeight) {
438+
// For resizing up, subtract the gaps and the rows multiplied by min height from the initial tile height
439+
const extraHeight = Math.abs(deltaY);
440+
const wholeRows = Math.floor(extraHeight / minHeight);
441+
const totalGaps = Math.max(wholeRows - 1, 0) * rowGap;
442+
snappedHeight = Math.max(
443+
initialHeight - (wholeRows * minHeight + totalGaps),
444+
minHeight
445+
);
381446
}
447+
448+
return snappedHeight;
382449
}
383450

384451
private _handleResizeEnd(event: CustomEvent<ResizeCallbackParams>) {
@@ -388,15 +455,31 @@ export default class IgcTileComponent extends EventEmitterMixin<
388455

389456
const resizeElement = event.target as HTMLElement;
390457

458+
const parentWrapper =
459+
this.parentElement!.shadowRoot!.querySelector('[part="base"]')!;
460+
const computedStyle = window.getComputedStyle(parentWrapper);
461+
const tm = parentWrapper.getBoundingClientRect();
462+
463+
tm.height -=
464+
Number.parseFloat(computedStyle.paddingTop) +
465+
Number.parseFloat(computedStyle.paddingBottom);
466+
tm.width -=
467+
Number.parseFloat(computedStyle.paddingLeft) +
468+
Number.parseFloat(computedStyle.paddingRight);
469+
470+
const gridColumnWidth = tm.width / this._cachedStyles.columnCount!;
471+
let colSpan = Math.round(width / gridColumnWidth);
472+
colSpan = Math.max(1, Math.min(colSpan, this._cachedStyles.columnCount!));
473+
474+
const minH = this._cachedStyles.minHeight;
475+
const rowSpan = Math.max(1, Math.floor(height / minH!));
476+
391477
// REVIEW
392478
Object.assign(resizeElement.style, {
393479
width: '',
394480
height: '',
395481
});
396482

397-
const colSpan = Math.max(1, Math.floor(width / 200));
398-
const rowSpan = Math.max(1, Math.floor(height / 200));
399-
400483
Object.assign(this.style, {
401484
gridRow: `span ${rowSpan}`,
402485
gridColumn: `span ${colSpan}`,
@@ -418,9 +501,9 @@ export default class IgcTileComponent extends EventEmitterMixin<
418501
top: 0,
419502
left: 0,
420503
zIndex: 1000,
421-
background: this._cachedStyles.ghostBackground,
422-
border: `1px solid ${this._cachedStyles.ghostBorder}`,
423-
borderRadius: this._cachedStyles.ghostBorderRadius,
504+
background: this._cachedStyles.background,
505+
border: `1px solid ${this._cachedStyles.border}`,
506+
borderRadius: this._cachedStyles.borderRadius,
424507
width: '100%',
425508
height: '100%',
426509
gridRow: '',

0 commit comments

Comments
 (0)