Skip to content

Commit 1276405

Browse files
committed
feat: Serialization takes tile's width and height into account when saving/loading
Adjusted tests. Dropped `dragAction` from the public API.
1 parent b038da1 commit 1276405

11 files changed

+89
-73
lines changed

src/components/resize-container/resize-container.ts

+23-4
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ export default class IgcResizeContainerComponent extends EventEmitterMixin<
5151

5252
private _controller: ReturnType<typeof addResizeController>;
5353

54+
private _enabled = true;
5455
private _mode: ResizeMode = 'immediate';
5556
private _ghostFactory?: ResizeGhostFactory;
5657

@@ -67,6 +68,17 @@ export default class IgcResizeContainerComponent extends EventEmitterMixin<
6768
@state()
6869
private _isActive = false;
6970

71+
/** Whether the resize behavior is enabled. */
72+
@property({ type: Boolean })
73+
public set enabled(value: boolean) {
74+
this._enabled = value;
75+
this._controller.set({ enabled: value });
76+
}
77+
78+
public get enabled(): boolean {
79+
return this._enabled;
80+
}
81+
7082
/**
7183
* Whether to always show the resize element adorners.
7284
*/
@@ -94,10 +106,15 @@ export default class IgcResizeContainerComponent extends EventEmitterMixin<
94106
return this._mode;
95107
}
96108

97-
public setSize(width: number, height: number): void {
109+
public setSize(width: number | null, height: number | null): void {
98110
this._controller.setSize(width, height);
99111
}
100112

113+
public getSize() {
114+
const { width, height } = this._container.value!.style;
115+
return { width, height };
116+
}
117+
101118
constructor() {
102119
super();
103120

@@ -174,7 +191,7 @@ export default class IgcResizeContainerComponent extends EventEmitterMixin<
174191
}
175192

176193
protected _renderAdorners() {
177-
if (!this._isActive && !this.active) {
194+
if (!this._enabled || (!this._isActive && !this.active)) {
178195
return nothing;
179196
}
180197

@@ -191,12 +208,14 @@ export default class IgcResizeContainerComponent extends EventEmitterMixin<
191208
active: this._isActive || this.active,
192209
});
193210

211+
const skipHandlers = this.active || !this._enabled;
212+
194213
return html`
195214
<div
196215
${ref(this._container)}
197216
part=${parts}
198-
@pointerenter=${this.active ? nothing : this._handlePointerEnter}
199-
@pointerleave=${this.active ? nothing : this._handlePointerLeave}
217+
@pointerenter=${skipHandlers ? nothing : this._handlePointerEnter}
218+
@pointerleave=${skipHandlers ? nothing : this._handlePointerLeave}
200219
>
201220
<slot></slot>
202221
${this._renderAdorners()}

src/components/resize-container/resize-controller.ts

+13-4
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ type State = {
1313

1414
class ResizeController implements ReactiveController {
1515
private _host: ReactiveControllerHost & HTMLElement;
16-
private _options: ResizeControllerConfiguration = {};
16+
private _options: ResizeControllerConfiguration = { enabled: true };
1717

1818
private _id = -1;
1919
private _hasPointerCapture = false;
@@ -60,6 +60,11 @@ class ResizeController implements ReactiveController {
6060

6161
// #region Public API
6262

63+
/** Whether the controller is enabled and will listen for events. */
64+
public get enabled(): boolean {
65+
return Boolean(this._options.enabled);
66+
}
67+
6368
/** Updates the configuration of the resize controller. */
6469
public set(options?: ResizeControllerConfiguration): void {
6570
Object.assign(this._options, options);
@@ -73,11 +78,11 @@ class ResizeController implements ReactiveController {
7378
}
7479

7580
/** Assign the given width and height in pixels to the resize target of the controller. */
76-
public setSize(width: number, height: number): void {
81+
public setSize(width: number | null, height: number | null): void {
7782
if (this._resizeTarget) {
7883
Object.assign(this._resizeTarget.style, {
79-
width: `${width}px`,
80-
height: `${height}px`,
84+
width: width ? `${width}px` : '',
85+
height: height ? `${height}px` : '',
8186
});
8287
}
8388
}
@@ -97,6 +102,10 @@ class ResizeController implements ReactiveController {
97102

98103
/** @internal */
99104
public handleEvent(event: PointerEvent & KeyboardEvent): void {
105+
if (!this.enabled) {
106+
return;
107+
}
108+
100109
switch (event.type) {
101110
case 'touchstart':
102111
event.preventDefault();

src/components/resize-container/types.ts

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export type ResizeCallbackParams = {
2020
};
2121

2222
export type ResizeControllerConfiguration = {
23+
enabled?: boolean;
2324
ref?: Ref<HTMLElement>[];
2425
mode?: ResizeMode;
2526
deferredFactory?: ResizeGhostFactory;

src/components/tile-manager/serializer.ts

+21-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import { omit, pick } from '../common/util.js';
1+
import { asNumber, omit, pick } from '../common/util.js';
22
import type IgcTileManagerComponent from './tile-manager.js';
3+
import type IgcTileComponent from './tile.js';
34

45
export interface SerializedTile {
56
colSpan: number;
@@ -12,6 +13,8 @@ export interface SerializedTile {
1213
rowSpan: number;
1314
rowStart: number | null;
1415
tileId: string | null;
16+
width: number | null;
17+
height: number | null;
1518
}
1619

1720
class TileManagerSerializer {
@@ -21,9 +24,15 @@ class TileManagerSerializer {
2124
this.tileManager = tileManager;
2225
}
2326

27+
private _getResizeContainer(tile: IgcTileComponent) {
28+
// biome-ignore lint/complexity/useLiteralKeys: Until we migrate to a symbol
29+
return tile['_resizeContainer']!;
30+
}
31+
2432
public save(): SerializedTile[] {
2533
return this.tileManager.tiles.map((tile) => {
2634
const { gridColumn, gridRow } = getComputedStyle(tile);
35+
const { width, height } = this._getResizeContainer(tile).getSize();
2736

2837
return {
2938
colSpan: tile.colSpan,
@@ -36,6 +45,8 @@ class TileManagerSerializer {
3645
rowSpan: tile.rowSpan,
3746
rowStart: tile.rowStart,
3847
tileId: tile.tileId,
48+
width: asNumber(width) || null,
49+
height: asNumber(height) || null,
3950
};
4051
});
4152
}
@@ -46,18 +57,26 @@ class TileManagerSerializer {
4657

4758
public load(tiles: SerializedTile[]): void {
4859
const mapped = new Map(tiles.map((tile) => [tile.tileId, tile]));
60+
const keys: (keyof SerializedTile)[] = [
61+
'gridColumn',
62+
'gridRow',
63+
'width',
64+
'height',
65+
];
4966

5067
for (const tile of this.tileManager.tiles) {
5168
if (!mapped.has(tile.tileId)) {
5269
continue;
5370
}
5471

5572
const serialized = mapped.get(tile.tileId)!;
56-
const properties = omit(serialized, 'gridColumn', 'gridRow');
73+
const properties = omit(serialized, ...keys);
5774
const styles = pick(serialized, 'gridColumn', 'gridRow');
75+
const { width, height } = pick(serialized, 'width', 'height');
5876

5977
Object.assign(tile, properties);
6078
Object.assign(tile.style, styles);
79+
this._getResizeContainer(tile).setSize(width, height);
6180
}
6281
}
6382

src/components/tile-manager/tile-dnd.spec.ts

-6
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,6 @@ describe('Tile drag and drop', () => {
184184
const draggedTile = getTile(0);
185185
const dropTarget = getTile(1);
186186

187-
expect(tileManager.dragAction).to.equal('slide');
188187
tileManager.tiles.forEach((tile, index) => {
189188
expect(tile.id).to.equal(`tile${index}`);
190189
});
@@ -211,7 +210,6 @@ describe('Tile drag and drop', () => {
211210
const initialTiles = tileManager.tiles;
212211
const tile = getTile(0);
213212

214-
expect(tileManager.dragAction).to.equal('slide');
215213
expect(tileManager.tiles[0].id).to.equal('tile0');
216214
expect(tileManager.tiles[1].id).to.equal('tile1');
217215

@@ -226,13 +224,11 @@ describe('Tile drag and drop', () => {
226224
const draggedTile = getTile(0);
227225
const dropTarget = getTile(4);
228226

229-
expect(tileManager.dragAction).to.equal('slide');
230227
expect(tileManager.tiles[0].id).to.equal('tile0');
231228
expect(tileManager.tiles[4].id).to.equal('tile4');
232229
expect(draggedTile.position).to.equal(0);
233230
expect(dropTarget.position).to.equal(4);
234231

235-
tileManager.dragAction = 'swap';
236232
await dragAndDrop(draggedTile, dropTarget);
237233

238234
expect(tileManager.tiles[0].id).to.equal('tile4');
@@ -245,11 +241,9 @@ describe('Tile drag and drop', () => {
245241
const initialTiles = tileManager.tiles;
246242
const tile = getTile(0);
247243

248-
expect(tileManager.dragAction).to.equal('slide');
249244
expect(tileManager.tiles[0].id).to.equal('tile0');
250245
expect(tileManager.tiles[1].id).to.equal('tile1');
251246

252-
tileManager.dragAction = 'swap';
253247
await dragAndDrop(tile, tile);
254248

255249
expect(tileManager.tiles).eql(initialTiles);

src/components/tile-manager/tile-manager.spec.ts

+21-6
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,6 @@ describe('Tile Manager component', () => {
9494

9595
it('is correctly initialized with its default component state', () => {
9696
expect(tileManager.columnCount).to.equal(0);
97-
expect(tileManager.dragAction).to.equal('slide');
9897
expect(tileManager.dragMode).to.equal('none');
9998
expect(tileManager.gap).to.equal(undefined);
10099
expect(tileManager.minColumnWidth).to.equal(undefined);
@@ -148,6 +147,7 @@ describe('Tile Manager component', () => {
148147

149148
expect(tiles[0]).shadowDom.to.equal(
150149
`
150+
<igc-resize mode="deferred" part="resize">
151151
<div
152152
part="base"
153153
style="--ig-col-span:1;--ig-row-span:1;"
@@ -185,6 +185,18 @@ describe('Tile Manager component', () => {
185185
<slot></slot>
186186
</div>
187187
</div>
188+
<slot name="side-adorner" slot="side-adorner">
189+
<div part="adorner-indicator"></div>
190+
</slot>
191+
192+
<slot name="corner-adorner" slot="corner-adorner">
193+
<div part="adorner-indicator"></div>
194+
</slot>
195+
196+
<slot name="bottom-adorner" slot="bottom-adorner">
197+
<div part="adorner-indicator"></div>
198+
</slot>
199+
</igc-resize>
188200
`
189201
);
190202
});
@@ -472,17 +484,16 @@ describe('Tile Manager component', () => {
472484
});
473485
});
474486

475-
it('should hide igc-resize component and not render adorners in igc-tile when resize mode is "none"', async () => {
487+
it('should disable igc-resize component when resize mode is "none"', async () => {
476488
const tile = tileManager.tiles[0];
477489

478490
tileManager.resizeMode = 'none';
479491
await elementUpdated(tileManager);
480492

481-
const resize = tile.shadowRoot?.querySelector('igc-resize');
482-
const adorners = tile.shadowRoot?.querySelectorAll('[slot$="-adorner"]');
493+
const resize = tile.renderRoot.querySelector('igc-resize')!;
483494

484-
expect(resize).to.be.null;
485-
expect(adorners).lengthOf(0);
495+
expect(resize).is.not.null;
496+
expect(resize.enabled).to.be.false;
486497
});
487498
});
488499

@@ -709,6 +720,8 @@ describe('Tile Manager component', () => {
709720
rowSpan: 1,
710721
rowStart: null,
711722
tileId: 'custom-id1',
723+
width: null,
724+
height: null,
712725
},
713726
{
714727
colSpan: 10,
@@ -721,6 +734,8 @@ describe('Tile Manager component', () => {
721734
rowSpan: 7,
722735
rowStart: 7,
723736
tileId: 'custom-id2',
737+
width: null,
738+
height: null,
724739
},
725740
];
726741

src/components/tile-manager/tile-manager.ts

+1-12
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,7 @@ import { registerComponent } from '../common/definitions/register.js';
1616
import type { Constructor } from '../common/mixins/constructor.js';
1717
import { EventEmitterMixin } from '../common/mixins/event-emitter.js';
1818
import { asNumber, partNameMap } from '../common/util.js';
19-
import type {
20-
TileManagerDragAction,
21-
TileManagerDragMode,
22-
TileManagerResizeMode,
23-
} from '../types.js';
19+
import type { TileManagerDragMode, TileManagerResizeMode } from '../types.js';
2420
import { createTilesState } from './position.js';
2521
import { createSerializer } from './serializer.js';
2622
import { all } from './themes/container.js';
@@ -132,13 +128,6 @@ export default class IgcTileManagerComponent extends EventEmitterMixin<
132128
return this._dragMode;
133129
}
134130

135-
/**
136-
* Whether the tiles will slide or swap on drop during a drag and drop operation.
137-
* @attr drag-action
138-
*/
139-
@property({ attribute: 'drag-action' })
140-
public dragAction: TileManagerDragAction = 'slide';
141-
142131
/**
143132
* Sets the number of columns for the tile manager.
144133
* Setting value <= than zero will trigger a responsive layout.

src/components/tile-manager/tile-resize.spec.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -389,15 +389,17 @@ describe('Tile resize', () => {
389389
assertRectsAreEqual(firstTile.getBoundingClientRect(), tileRect);
390390
});
391391

392-
it('should not have resizeElement when `disableResize` is true', async () => {
392+
it('should disable igc-resize behavior when `disableResize` is true', async () => {
393393
const DOM = getTileDOM(firstTile);
394394

395-
expect(DOM.resizeElement).not.to.be.null;
395+
expect(DOM.resizeElement).is.not.null;
396+
expect(DOM.resizeElement.enabled).is.true;
396397

397398
firstTile.disableResize = true;
398399
await elementUpdated(firstTile);
399400

400-
expect(DOM.resizeElement).to.be.null;
401+
expect(DOM.resizeElement).is.not.null;
402+
expect(DOM.resizeElement.enabled).is.false;
401403
});
402404

403405
it('should update tile parts on resizing', async () => {

0 commit comments

Comments
 (0)