Skip to content

Commit e35374e

Browse files
committed
feat: Added drag contorller internal state
1 parent cb8b629 commit e35374e

File tree

4 files changed

+71
-63
lines changed

4 files changed

+71
-63
lines changed

src/components/common/controllers/drag-and-drop.spec.ts renamed to src/components/common/controllers/drag.spec.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@ import {
1414
simulateLostPointerCapture,
1515
simulatePointerDown,
1616
} from '../utils.spec.js';
17-
import { addDragDropController } from './drag-and-drop.js';
17+
import { addDragController } from './drag.js';
1818
import { escapeKey } from './key-bindings.js';
1919

2020
describe('Drag and drop controller', () => {
2121
type DragElement = LitElement & {
22-
controller: ReturnType<typeof addDragDropController>;
22+
controller: ReturnType<typeof addDragController>;
2323
};
2424

2525
let tag: string;
@@ -36,7 +36,7 @@ describe('Drag and drop controller', () => {
3636
}
3737
`;
3838

39-
public controller = addDragDropController(this);
39+
public controller = addDragController(this);
4040

4141
protected override render() {
4242
return html`<slot></slot>`;

src/components/common/controllers/drag-and-drop.ts renamed to src/components/common/controllers/drag.ts

Lines changed: 40 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@ import type {
44
ReactiveControllerHost,
55
} from 'lit';
66
import type { Ref } from 'lit/directives/ref.js';
7-
import { findElementFromEventPath } from '../util.js';
87

9-
type DragDropCallback = () => unknown;
8+
import { findElementFromEventPath } from '../util.js';
109

1110
type DragEnterCallback = (target: Element) => unknown;
1211

@@ -16,9 +15,18 @@ type DragCallbackParams = {
1615
event: PointerEvent;
1716
};
1817

18+
type State = {
19+
initial: DOMRect;
20+
current: DOMRect;
21+
offset: {
22+
dx: number;
23+
dy: number;
24+
};
25+
};
26+
1927
// TODO: Start providing callback params for the hooks and type them
2028

21-
type DragDropConfig = {
29+
type DragConfig = {
2230
/** Whether the drag and drop feature is enabled for the current host. */
2331
enabled?: boolean;
2432
/**
@@ -62,7 +70,7 @@ type DragDropConfig = {
6270
/** Callback invoked at the beginning of a drag operation. */
6371
dragStart?: DragCallback;
6472
/** Callback invoked while dragging the target element. */
65-
dragMove?: DragDropCallback;
73+
dragMove?: DragCallback;
6674

6775
dragEnter?: DragEnterCallback;
6876

@@ -71,22 +79,23 @@ type DragDropConfig = {
7179
dragOver?: DragEnterCallback;
7280

7381
/** Callback invoked during a drop operation. */
74-
dragEnd?: DragDropCallback;
82+
dragEnd?: DragCallback;
7583
/** Callback invoked when a drag and drop is cancelled */
76-
dragCancel?: DragDropCallback;
84+
dragCancel?: DragCallback;
7785
};
7886

7987
const additionalEvents = ['pointermove', 'lostpointercapture'] as const;
8088

81-
class DragDropController implements ReactiveController {
89+
class DragController implements ReactiveController {
8290
private _host: ReactiveControllerHost & LitElement;
83-
private _config: DragDropConfig = {
91+
private _config: DragConfig = {
8492
enabled: true,
8593
mode: 'deferred',
8694
snapToCursor: false,
8795
};
8896

89-
private _dragOffset = { dx: 0, dy: 0 };
97+
private _state!: State;
98+
9099
private _previousMatch!: Element | null;
91100

92101
private _id = -1;
@@ -145,10 +154,7 @@ class DragDropController implements ReactiveController {
145154
return Boolean(this._config.enabled);
146155
}
147156

148-
constructor(
149-
host: ReactiveControllerHost & LitElement,
150-
config?: DragDropConfig
151-
) {
157+
constructor(host: ReactiveControllerHost & LitElement, config?: DragConfig) {
152158
this._host = host;
153159
this._host.addController(this);
154160
this.setConfig(config);
@@ -174,10 +180,13 @@ class DragDropController implements ReactiveController {
174180
const rect = this._host.getBoundingClientRect();
175181

176182
this._id = pointerId;
177-
178-
this._dragOffset = {
179-
dx: rect.x - clientX,
180-
dy: rect.y - clientY,
183+
this._state = {
184+
initial: rect,
185+
current: structuredClone(rect),
186+
offset: {
187+
dx: rect.x - clientX,
188+
dy: rect.y - clientY,
189+
},
181190
};
182191
}
183192

@@ -231,8 +240,10 @@ class DragDropController implements ReactiveController {
231240

232241
private _setPosition(x: number, y: number) {
233242
const { top, left } = this._layer.getBoundingClientRect();
234-
const posX = this._hasSnapping ? x - left : x - left + this._dragOffset.dx;
235-
const posY = this._hasSnapping ? y - top : y - top + this._dragOffset.dy;
243+
const { offset } = this._state;
244+
245+
const posX = this._hasSnapping ? x - left : x - left + offset.dx;
246+
const posY = this._hasSnapping ? y - top : y - top + offset.dy;
236247

237248
this._dragItem.style.transform = `translate(${posX}px,${posY}px)`;
238249
}
@@ -242,19 +253,17 @@ class DragDropController implements ReactiveController {
242253
return;
243254
}
244255

245-
this._ghost = this._config.ghost
246-
? this._config.ghost.call(this._host)
247-
: createDefaultDragGhost(this._host.getBoundingClientRect());
256+
this._ghost =
257+
this._config.ghost?.call(this._host) ??
258+
createDefaultDragGhost(this._host.getBoundingClientRect());
248259

249260
this._setPosition(clientX, clientY);
250261
this._layer.append(this._ghost);
251262
}
252263

253264
private _removeGhost(): void {
254-
if (this._ghost) {
255-
this._ghost.remove();
256-
this._ghost = null;
257-
}
265+
this._ghost?.remove();
266+
this._ghost = null;
258267
}
259268

260269
private _shouldSkip(event: PointerEvent): boolean {
@@ -308,7 +317,7 @@ class DragDropController implements ReactiveController {
308317
}
309318

310319
/** Updates the drag and drop controller configuration. */
311-
public setConfig(value?: DragDropConfig): void {
320+
public setConfig(value?: DragConfig): void {
312321
Object.assign(this._config, value);
313322
}
314323

@@ -378,9 +387,9 @@ function createDefaultDragGhost(rect: DOMRect): HTMLElement {
378387
/**
379388
* Adds a drag and drop controller to the given host
380389
*/
381-
export function addDragDropController(
390+
export function addDragController(
382391
host: ReactiveControllerHost & LitElement,
383-
config?: DragDropConfig
384-
): DragDropController {
385-
return new DragDropController(host, config);
392+
config?: DragConfig
393+
): DragController {
394+
return new DragController(host, config);
386395
}

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

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,11 @@ class ResizeController implements ReactiveController {
2323
private _ghost: HTMLElement | null = null;
2424

2525
private get _element(): HTMLElement {
26-
return this._activeRef || this._host;
26+
return this._activeRef ?? this._host;
2727
}
2828

2929
private get _resizeTarget(): HTMLElement {
30-
return this._config.resizeTarget
31-
? this._config.resizeTarget.call(this._host)
32-
: this._host;
30+
return this._config.resizeTarget?.call(this._host) ?? this._host;
3331
}
3432

3533
/** Whether the controller is in deferred mode. */
@@ -148,9 +146,8 @@ class ResizeController implements ReactiveController {
148146
this._config.end?.call(this._host, parameters);
149147
this._state.current = parameters.state.current;
150148

151-
parameters.state.commit
152-
? parameters.state.commit.call(this._host)
153-
: this._updatePosition(this._resizeTarget);
149+
parameters.state.commit?.call(this._host) ??
150+
this._updatePosition(this._resizeTarget);
154151

155152
this.dispose();
156153
}
@@ -173,9 +170,7 @@ class ResizeController implements ReactiveController {
173170
}
174171

175172
private _setActiveRef(event: Event): void {
176-
const refs = this._config.ref
177-
? this._config.ref.map(({ value }) => value)
178-
: [this._host];
173+
const refs = this._config.ref?.map(({ value }) => value) ?? [this._host];
179174

180175
this._activeRef =
181176
findElementFromEventPath<HTMLElement>(
@@ -234,22 +229,20 @@ class ResizeController implements ReactiveController {
234229
return;
235230
}
236231

237-
this._ghost = this._config.deferredFactory
238-
? this._config.deferredFactory.call(this._host)
239-
: createDefaultGhostElement(
240-
this._state.initial.width,
241-
this._state.initial.height
242-
);
232+
this._ghost =
233+
this._config.deferredFactory?.call(this._host) ??
234+
createDefaultGhostElement(
235+
this._state.initial.width,
236+
this._state.initial.height
237+
);
243238

244239
this._ghost.setAttribute('data-resize-ghost', '');
245240
this._host.append(this._ghost);
246241
}
247242

248243
private _removeGhostElement(): void {
249-
if (this._ghost) {
250-
this._ghost.remove();
251-
this._ghost = null;
252-
}
244+
this._ghost?.remove();
245+
this._ghost = null;
253246
}
254247

255248
// #endregion

src/components/tile-manager/tile.ts

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@ import {
1010
tileManagerContext,
1111
} from '../common/context.js';
1212
import { createAsyncContext } from '../common/controllers/async-consumer.js';
13-
import { addDragDropController } from '../common/controllers/drag-and-drop.js';
13+
import { addDragController } from '../common/controllers/drag.js';
1414
import { registerComponent } from '../common/definitions/register.js';
1515
import type { Constructor } from '../common/mixins/constructor.js';
1616
import { EventEmitterMixin } from '../common/mixins/event-emitter.js';
1717
import {
1818
asNumber,
1919
createCounter,
20-
isElement,
20+
findElementFromEventPath,
2121
partNameMap,
2222
} from '../common/util.js';
2323
import IgcDividerComponent from '../divider/divider.js';
@@ -91,10 +91,10 @@ export default class IgcTileComponent extends EventEmitterMixin<
9191

9292
private static readonly increment = createCounter();
9393

94-
private _dragController = addDragDropController(this, {
94+
private _dragController = addDragController(this, {
9595
skip: this._skipDrag,
9696
matchTarget: this._match,
97-
layer: () => this._tileManager!.overlay.value!,
97+
layer: () => this._tileOverlay,
9898
ghost: this._createDragGhost,
9999
dragStart: this._handleDragStart,
100100
dragMove: this._handleDragMove,
@@ -144,6 +144,11 @@ export default class IgcTileComponent extends EventEmitterMixin<
144144
return this._managerContext.value;
145145
}
146146

147+
/** Returns the overlay container of the tile manager. */
148+
private get _tileOverlay(): HTMLElement {
149+
return this._tileManager?.overlay.value!;
150+
}
151+
147152
/** Returns the tile manager internal CSS grid container. */
148153
private get _cssContainer(): HTMLElement {
149154
return this._tileManager?.grid.value!;
@@ -378,12 +383,13 @@ export default class IgcTileComponent extends EventEmitterMixin<
378383
}
379384

380385
private _skipDrag(event: PointerEvent): boolean {
386+
if (this._maximized) {
387+
return true;
388+
}
389+
381390
return Boolean(
382-
(this._resizeContainer &&
383-
event
384-
.composedPath()
385-
.some((e) => isElement(e) && e.matches('[part*=trigger]'))) ||
386-
this.maximized
391+
this._resizeContainer &&
392+
findElementFromEventPath('[part*=trigger]', event)
387393
);
388394
}
389395

0 commit comments

Comments
 (0)