igniteui-webcomponents
Version:
Ignite UI for Web Components is a complete library of UI components, giving you the ability to build modern web applications using encapsulation and the concept of reusable components in a dependency-free approach.
192 lines • 6.36 kB
JavaScript
import { findElementFromEventPath } from '../common/util.js';
import { createDefaultGhostElement, getDefaultLayer } from './default-ghost.js';
const additionalEvents = [
'pointermove',
'lostpointercapture',
'contextmenu',
];
class ResizeController {
get _element() {
return this._activeRef ?? this._host;
}
get _resizeTarget() {
return this._options.resizeTarget?.call(this._host) ?? this._host;
}
get _layer() {
if (!this._isDeferred) {
return this._host;
}
return this._options.layer?.() ?? this._host;
}
get _isDeferred() {
return this._options.mode === 'deferred';
}
get _stateParameters() {
const { initial, current } = this._state;
return {
initial,
current,
deltaX: current.width - initial.width,
deltaY: current.height - initial.height,
ghost: this._ghost,
trigger: this._activeRef,
};
}
constructor(host, options) {
this._options = {
enabled: true,
layer: getDefaultLayer,
};
this._id = -1;
this._hasPointerCapture = false;
this._activeRef = null;
this._ghost = null;
this._host = host;
this._host.addController(this);
this.set(options);
}
get enabled() {
return Boolean(this._options.enabled);
}
set(options) {
Object.assign(this._options, options);
}
dispose() {
this._setResizeState(false);
this._removeGhostElement();
this._activeRef = null;
}
hostConnected() {
this._host.addEventListener('pointerdown', this);
this._host.addEventListener('touchstart', this, { passive: false });
}
hostDisconnected() {
this._host.removeEventListener('pointerdown', this);
this._host.removeEventListener('touchstart', this);
this._setResizeCancelListener(false);
this._removeGhostElement();
}
handleEvent(event) {
if (!this.enabled) {
return;
}
switch (event.type) {
case 'touchstart':
case 'contextmenu':
event.preventDefault();
break;
case 'keydown':
this._handleCancel(event);
break;
case 'pointerdown':
this._handlePointerDown(event);
break;
case 'pointermove':
this._handlePointerMove(event);
break;
case 'lostpointercapture':
this._handlePointerEnd(event);
break;
}
}
_handlePointerDown(event) {
if (event.button || this._shouldSkip(event)) {
return;
}
this._setInitialState(event);
this._createGhostElement();
const parameters = { event, state: this._stateParameters };
if (this._options.start?.call(this._host, parameters) === false) {
this.dispose();
return;
}
this._setResizeState();
}
_handlePointerMove(event) {
if (!this._hasPointerCapture) {
return;
}
this._updateState(event);
const parameters = { event, state: this._stateParameters };
this._options.resize?.call(this._host, parameters);
this._state.current = parameters.state.current;
this._updatePosition(this._isDeferred ? this._ghost : this._resizeTarget);
}
_handlePointerEnd(event) {
const parameters = { event, state: this._stateParameters };
this._options.end?.call(this._host, parameters);
this._state.current = parameters.state.current;
parameters.state.commit?.() ?? this._updatePosition(this._resizeTarget);
this.dispose();
}
_handleCancel(event) {
const key = event.key.toLowerCase();
if (this._hasPointerCapture && key === 'escape') {
this._options.cancel?.call(this._host, this._stateParameters);
}
}
_shouldSkip(event) {
this._setActiveRef(event);
return !this._activeRef;
}
_setActiveRef(event) {
const refs = this._options.ref?.map(({ value }) => value) ?? [this._host];
this._activeRef =
findElementFromEventPath((e) => refs.includes(e), event) ?? null;
}
_setResizeState(enabled = true) {
this._hasPointerCapture = enabled;
enabled
? this._element.setPointerCapture(this._id)
: this._element.releasePointerCapture(this._id);
this._setResizeCancelListener(enabled);
for (const type of additionalEvents) {
enabled
? this._host.addEventListener(type, this)
: this._host.removeEventListener(type, this);
}
}
_setResizeCancelListener(enabled = true) {
enabled
? globalThis.addEventListener('keydown', this)
: globalThis.removeEventListener('keydown', this);
}
_setInitialState({ pointerId }) {
const dimensions = this._resizeTarget.getBoundingClientRect();
this._id = pointerId;
this._state = {
initial: dimensions,
current: structuredClone(dimensions),
};
}
_updateState({ clientX, clientY }) {
this._state.current.width = clientX - this._state.initial.x;
this._state.current.height = clientY - this._state.initial.y;
}
_updatePosition(element) {
if (element) {
Object.assign(element.style, {
width: `${this._state.current.width}px`,
height: `${this._state.current.height}px`,
});
}
}
_createGhostElement() {
if (!this._isDeferred) {
return;
}
this._ghost =
this._options.deferredFactory?.call(this._host) ??
createDefaultGhostElement(this._resizeTarget.getBoundingClientRect());
this._ghost.setAttribute('data-resize-ghost', '');
this._layer.append(this._ghost);
}
_removeGhostElement() {
this._ghost?.remove();
this._ghost = null;
}
}
export function addResizeController(host, options) {
return new ResizeController(host, options);
}
//# sourceMappingURL=resize-controller.js.map