@ux-aspects/ux-aspects
Version:
Open source user interface framework for building modern, responsive, mobile big data applications
101 lines • 16.3 kB
JavaScript
import { inject, Injectable } from '@angular/core';
import { Subject } from 'rxjs';
import { filter, takeUntil } from 'rxjs/operators';
import { DashboardService } from '../dashboard.service';
import * as i0 from "@angular/core";
export class DashboardGrabHandleService {
constructor() {
this._dashboard = inject(DashboardService);
/** Self-registered drag handles in the dashboard. */
this._handles = [];
/** Automatically unsubscribe from all observables when destroyed */
this._onDestroy = new Subject();
// if a drag is performed by the mouse we should update the focusable item to be the first again
this._dashboard.layout$.pipe(takeUntil(this._onDestroy), filter(() => !this._dashboard.isGrabbing$.value))
.subscribe(() => this.setFirstItemFocusable());
}
/** Perform unsubscriptions */
ngOnDestroy() {
this._onDestroy.next();
this._onDestroy.complete();
}
/** Register a new grab handle. */
addHandle(handle) {
this._handles = this.getHandlesInOrder([...this._handles, handle]);
// we want to make the first item focusable (raf to avoid expression changed error)
requestAnimationFrame(() => this.ensureFocusable());
}
/** Unregister a removed grab handle. */
removeHandle(handle) {
this._handles = this._handles.filter(h => h !== handle);
// Make sure there is still a focusable handle
this.ensureFocusable();
}
/** Make the first visual item in the list focusable */
setFirstItemFocusable() {
this.setItemFocus(0, false);
}
/** Set an item at a given index focused */
setItemFocus(index, focusElement = true) {
// if the list is empty then do nothing
if (!this._handles || this._handles.length === 0) {
return;
}
// check if the index is out of bounds
if (index < 0) {
return this.setItemFocus(0);
}
if (index > this._handles.length - 1) {
return this.setItemFocus(this._handles.length - 1);
}
// try focusing a specific index
this.getHandlesInOrder().forEach((handle, idx) => idx === index ? handle.focus(focusElement) : handle.blur());
// for safety we want to ensure one of the items is definitely still focusabled
this.ensureFocusable();
}
/** Focus the previous grab handle */
setPreviousItemFocus(handle) {
this.setItemFocus(this.getHandleIndex(handle) - 1);
}
/** Focus the next grab handle */
setNextItemFocus(handle) {
this.setItemFocus(this.getHandleIndex(handle) + 1);
}
/** Focus the grab handle on the widget above */
setSiblingItemFocus(widget, direction) {
// find all widgets that are directly above and have grab handles
const target = this._dashboard.getSurroundingWidgets(widget, direction)
.map(_widget => this._handles.find(handle => handle.widget === _widget))
.filter(handle => !!handle)
.reduce((handle, current) => !handle || current.widget.getColumn() > handle.widget.getColumn() ? current : handle, null);
// ensure we have a target before focusing
if (!target) {
return;
}
// get the index of the target handle
const index = this.getHandleIndex(target);
// focus the item
this.setItemFocus(index);
}
/** Get handles in the order they appear rather than the order they are in the DOM */
getHandlesInOrder(handles = this._handles) {
const widgets = this._dashboard.getWidgetsByOrder();
// sort the handles according to the position of the widget it belongs to
return handles.sort((handleOne, handleTwo) => widgets.indexOf(handleOne.widget) - widgets.indexOf(handleTwo.widget));
}
getHandleIndex(handle) {
return this.getHandlesInOrder().findIndex(_handle => _handle === handle);
}
/** If the current focusable handle is removed we need to make another one focusable */
ensureFocusable() {
if (!this._handles.find(handle => handle.tabIndex === 0)) {
this.setFirstItemFocusable();
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: DashboardGrabHandleService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: DashboardGrabHandleService }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: DashboardGrabHandleService, decorators: [{
type: Injectable
}], ctorParameters: () => [] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ3JhYi1oYW5kbGUuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9jb21wb25lbnRzL2Rhc2hib2FyZC9ncmFiLWhhbmRsZS9ncmFiLWhhbmRsZS5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFhLE1BQU0sZUFBZSxDQUFDO0FBQzlELE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDL0IsT0FBTyxFQUFFLE1BQU0sRUFBRSxTQUFTLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUNuRCxPQUFPLEVBQW1CLGdCQUFnQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7O0FBS3pFLE1BQU0sT0FBTywwQkFBMEI7SUFVbkM7UUFSaUIsZUFBVSxHQUFHLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO1FBRXZELHFEQUFxRDtRQUM3QyxhQUFRLEdBQW1DLEVBQUUsQ0FBQztRQUV0RCxvRUFBb0U7UUFDbkQsZUFBVSxHQUFHLElBQUksT0FBTyxFQUFRLENBQUM7UUFJOUMsZ0dBQWdHO1FBQ2hHLElBQUksQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxDQUFDO2FBQ3JHLFNBQVMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMscUJBQXFCLEVBQUUsQ0FBQyxDQUFDO0lBQ3ZELENBQUM7SUFFRCw4QkFBOEI7SUFDOUIsV0FBVztRQUNQLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDdkIsSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUMvQixDQUFDO0lBRUQsa0NBQWtDO0lB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QzsrR0FwSFEsMEJBQTBCO21IQUExQiwwQkFBMEI7OzRGQUExQiwwQkFBMEI7a0JBRHRDLFVBQVUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBpbmplY3QsIEluamVjdGFibGUsIE9uRGVzdHJveSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgU3ViamVjdCB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgZmlsdGVyLCB0YWtlVW50aWwgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgeyBBY3Rpb25EaXJlY3Rpb24sIERhc2hib2FyZFNlcnZpY2UgfSBmcm9tICcuLi9kYXNoYm9hcmQuc2VydmljZSc7XG5pbXBvcnQgeyBEYXNoYm9hcmRXaWRnZXRDb21wb25lbnQgfSBmcm9tICcuLi93aWRnZXQvZGFzaGJvYXJkLXdpZGdldC5jb21wb25lbnQnO1xuaW1wb3J0IHsgRGFzaGJvYXJkR3JhYkhhbmRsZURpcmVjdGl2ZSB9IGZyb20gJy4vZ3JhYi1oYW5kbGUuZGlyZWN0aXZlJztcblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIERhc2hib2FyZEdyYWJIYW5kbGVTZXJ2aWNlIGltcGxlbWVudHMgT25EZXN0cm95IHtcblxuICAgIHByaXZhdGUgcmVhZG9ubHkgX2Rhc2hib2FyZCA9IGluamVjdChEYXNoYm9hcmRTZXJ2aWNlKTtcblxuICAgIC8qKiBTZWxmLXJlZ2lzdGVyZWQgZHJhZyBoYW5kbGVzIGluIHRoZSBkYXNoYm9hcmQuICovXG4gICAgcHJpdmF0ZSBfaGFuZGxlczogRGFzaGJvYXJkR3JhYkhhbmRsZURpcmVjdGl2ZVtdID0gW107XG5cbiAgICAvKiogQXV0b21hdGljYWxseSB1bnN1YnNjcmliZSBmcm9tIGFsbCBvYnNlcnZhYmxlcyB3aGVuIGRlc3Ryb3llZCAqL1xuICAgIHByaXZhdGUgcmVhZG9ubHkgX29uRGVzdHJveSA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG5cbiAgICBjb25zdHJ1Y3RvcigpIHtcblxuICAgICAgICAvLyBpZiBhIGRyYWcgaXMgcGVyZm9ybWVkIGJ5IHRoZSBtb3VzZSB3ZSBzaG91bGQgdXBkYXRlIHRoZSBmb2N1c2FibGUgaXRlbSB0byBiZSB0aGUgZmlyc3QgYWdhaW5cbiAgICAgICAgdGhpcy5fZGFzaGJvYXJkLmxheW91dCQucGlwZSh0YWtlVW50aWwodGhpcy5fb25EZXN0cm95KSwgZmlsdGVyKCgpID0+ICF0aGlzLl9kYXNoYm9hcmQuaXNHcmFiYmluZyQudmFsdWUpKVxuICAgICAgICAgICAgLnN1YnNjcmliZSgoKSA9PiB0aGlzLnNldEZpcnN0SXRlbUZvY3VzYWJsZSgpKTtcbiAgICB9XG5cbiAgICAvKiogUGVyZm9ybSB1bnN1YnNjcmlwdGlvbnMgKi9cbiAgICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5fb25EZXN0cm95Lm5leHQoKTtcbiAgICAgICAgdGhpcy5fb25EZXN0cm95LmNvbXBsZXRlKCk7XG4gICAgfVxuXG4gICAgLyoqIFJlZ2lzdGVyIGEgbmV3IGdyYWIgaGFuZGxlLiAqL1xuICAgIGFkZEhhbmRsZShoYW5kbGU6IERhc2hib2FyZEdyYWJIYW5kbGVEaXJlY3RpdmUpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5faGFuZGxlcyA9IHRoaXMuZ2V0SGFuZGxlc0luT3JkZXIoWy4uLnRoaXMuX2hhbmRsZXMsIGhhbmRsZV0pO1xuXG4gICAgICAgIC8vIHdlIHdhbnQgdG8gbWFrZSB0aGUgZmlyc3QgaXRlbSBmb2N1c2FibGUgKHJhZiB0byBhdm9pZCBleHByZXNzaW9uIGNoYW5nZWQgZXJyb3IpXG4gICAgICAgIHJlcXVlc3RBbmltYXRpb25GcmFtZSgoKSA9PiB0aGlzLmVuc3VyZUZvY3VzYWJsZSgpKTtcbiAgICB9XG5cbiAgICAvKiogVW5yZWdpc3RlciBhIHJlbW92ZWQgZ3JhYiBoYW5kbGUuICovXG4gICAgcmVtb3ZlSGFuZGxlKGhhbmRsZTogRGFzaGJvYXJkR3JhYkhhbmRsZURpcmVjdGl2ZSk6IHZvaWQge1xuICAgICAgICB0aGlzLl9oYW5kbGVzID0gdGhpcy5faGFuZGxlcy5maWx0ZXIoaCA9PiBoICE9PSBoYW5kbGUpO1xuXG4gICAgICAgIC8vIE1ha2Ugc3VyZSB0aGVyZSBpcyBzdGlsbCBhIGZvY3VzYWJsZSBoYW5kbGVcbiAgICAgICAgdGhpcy5lbnN1cmVGb2N1c2FibGUoKTtcbiAgICB9XG5cbiAgICAvKiogTWFrZSB0aGUgZmlyc3QgdmlzdWFsIGl0ZW0gaW4gdGhlIGxpc3QgZm9jdXNhYmxlICovXG4gICAgc2V0Rmlyc3RJdGVtRm9jdXNhYmxlKCk6IHZvaWQge1xuICAgICAgICB0aGlzLnNldEl0ZW1Gb2N1cygwLCBmYWxzZSk7XG4gICAgfVxuXG4gICAgLyoqIFNldCBhbiBpdGVtIGF0IGEgZ2l2ZW4gaW5kZXggZm9jdXNlZCAqL1xuICAgIHNldEl0ZW1Gb2N1cyhpbmRleDogbnVtYmVyLCBmb2N1c0VsZW1lbnQ6IGJvb2xlYW4gPSB0cnVlKTogdm9pZCB7XG5cbiAgICAgICAgLy8gaWYgdGhlIGxpc3QgaXMgZW1wdHkgdGhlbiBkbyBub3RoaW5nXG4gICAgICAgIGlmICghdGhpcy5faGFuZGxlcyB8fCB0aGlzLl9oYW5kbGVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gY2hlY2sgaWYgdGhlIGluZGV4IGlzIG91dCBvZiBib3VuZHNcbiAgICAgICAgaWYgKGluZGV4IDwgMCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuc2V0SXRlbUZvY3VzKDApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGluZGV4ID4gdGhpcy5faGFuZGxlcy5sZW5ndGggLSAxKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5zZXRJdGVtRm9jdXModGhpcy5faGFuZGxlcy5sZW5ndGggLSAxKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHRyeSBmb2N1c2luZyBhIHNwZWNpZmljIGluZGV4XG4gICAgICAgIHRoaXMuZ2V0SGFuZGxlc0luT3JkZXIoKS5mb3JFYWNoKChoYW5kbGUsIGlkeCkgPT4gaWR4ID09PSBpbmRleCA/IGhhbmRsZS5mb2N1cyhmb2N1c0VsZW1lbnQpIDogaGFuZGxlLmJsdXIoKSk7XG5cbiAgICAgICAgLy8gZm9yIHNhZmV0eSB3ZSB3YW50IHRvIGVuc3VyZSBvbmUgb2YgdGhlIGl0ZW1zIGlzIGRlZmluaXRlbHkgc3RpbGwgZm9jdXNhYmxlZFxuICAgICAgICB0aGlzLmVuc3VyZUZvY3VzYWJsZSgpO1xuICAgIH1cblxuICAgIC8qKiBGb2N1cyB0aGUgcHJldmlvdXMgZ3JhYiBoYW5kbGUgKi9cbiAgICBzZXRQcmV2aW91c0l0ZW1Gb2N1cyhoYW5kbGU6IERhc2hib2FyZEdyYWJIYW5kbGVEaXJlY3RpdmUpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zZXRJdGVtRm9jdXModGhpcy5nZXRIYW5kbGVJbmRleChoYW5kbGUpIC0gMSk7XG4gICAgfVxuXG4gICAgLyoqIEZvY3VzIHRoZSBuZXh0IGdyYWIgaGFuZGxlICovXG4gICAgc2V0TmV4dEl0ZW1Gb2N1cyhoYW5kbGU6IERhc2hib2FyZEdyYWJIYW5kbGVEaXJlY3RpdmUpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zZXRJdGVtRm9jdXModGhpcy5nZXRIYW5kbGVJbmRleChoYW5kbGUpICsgMSk7XG4gICAgfVxuXG4gICAgLyoqIEZvY3VzIHRoZSBncmFiIGhhbmRsZSBvbiB0aGUgd2lkZ2V0IGFib3ZlICovXG4gICAgc2V0U2libGluZ0l0ZW1Gb2N1cyh3aWRnZXQ6IERhc2hib2FyZFdpZGdldENvbXBvbmVudCwgZGlyZWN0aW9uOiBBY3Rpb25EaXJlY3Rpb24pOiB2b2lkIHtcblxuICAgICAgICAvLyBmaW5kIGFsbCB3aWRnZXRzIHRoYXQgYXJlIGRpcmVjdGx5IGFib3ZlIGFuZCBoYXZlIGdyYWIgaGFuZGxlc1xuICAgICAgICBjb25zdCB0YXJnZXQgPSB0aGlzLl9kYXNoYm9hcmQuZ2V0U3Vycm91bmRpbmdXaWRnZXRzKHdpZGdldCwgZGlyZWN0aW9uKVxuICAgICAgICAgICAgLm1hcChfd2lkZ2V0ID0+IHRoaXMuX2hhbmRsZXMuZmluZChoYW5kbGUgPT4gaGFuZGxlLndpZGdldCA9PT0gX3dpZGdldCkpXG4gICAgICAgICAgICAuZmlsdGVyKGhhbmRsZSA9PiAhIWhhbmRsZSlcbiAgICAgICAgICAgIC5yZWR1Y2UoKGhhbmRsZSwgY3VycmVudCkgPT4gIWhhbmRsZSB8fCBjdXJyZW50LndpZGdldC5nZXRDb2x1bW4oKSA+IGhhbmRsZS53aWRnZXQuZ2V0Q29sdW1uKCkgPyBjdXJyZW50IDogaGFuZGxlLCBudWxsKTtcblxuICAgICAgICAvLyBlbnN1cmUgd2UgaGF2ZSBhIHRhcmdldCBiZWZvcmUgZm9jdXNpbmdcbiAgICAgICAgaWYgKCF0YXJnZXQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGdldCB0aGUgaW5kZXggb2YgdGhlIHRhcmdldCBoYW5kbGVcbiAgICAgICAgY29uc3QgaW5kZXggPSB0aGlzLmdldEhhbmRsZUluZGV4KHRhcmdldCk7XG5cbiAgICAgICAgLy8gZm9jdXMgdGhlIGl0ZW1cbiAgICAgICAgdGhpcy5zZXRJdGVtRm9jdXMoaW5kZXgpO1xuICAgIH1cblxuICAgIC8qKiBHZXQgaGFuZGxlcyBpbiB0aGUgb3JkZXIgdGhleSBhcHBlYXIgcmF0aGVyIHRoYW4gdGhlIG9yZGVyIHRoZXkgYXJlIGluIHRoZSBET00gKi9cbiAgICBnZXRIYW5kbGVzSW5PcmRlcihoYW5kbGVzID0gdGhpcy5faGFuZGxlcyk6IERhc2hib2FyZEdyYWJIYW5kbGVEaXJlY3RpdmVbXSB7XG4gICAgICAgIGNvbnN0IHdpZGdldHMgPSB0aGlzLl9kYXNoYm9hcmQuZ2V0V2lkZ2V0c0J5T3JkZXIoKTtcblxuICAgICAgICAvLyBzb3J0IHRoZSBoYW5kbGVzIGFjY29yZGluZyB0byB0aGUgcG9zaXRpb24gb2YgdGhlIHdpZGdldCBpdCBiZWxvbmdzIHRvXG4gICAgICAgIHJldHVybiBoYW5kbGVzLnNvcnQoKGhhbmRsZU9uZSwgaGFuZGxlVHdvKSA9PiB3aWRnZXRzLmluZGV4T2YoaGFuZGxlT25lLndpZGdldCkgLSB3aWRnZXRzLmluZGV4T2YoaGFuZGxlVHdvLndpZGdldCkpO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0SGFuZGxlSW5kZXgoaGFuZGxlOiBEYXNoYm9hcmRHcmFiSGFuZGxlRGlyZWN0aXZlKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0SGFuZGxlc0luT3JkZXIoKS5maW5kSW5kZXgoX2hhbmRsZSA9PiBfaGFuZGxlID09PSBoYW5kbGUpO1xuICAgIH1cblxuICAgIC8qKiBJZiB0aGUgY3VycmVudCBmb2N1c2FibGUgaGFuZGxlIGlzIHJlbW92ZWQgd2UgbmVlZCB0byBtYWtlIGFub3RoZXIgb25lIGZvY3VzYWJsZSAqL1xuICAgIHByaXZhdGUgZW5zdXJlRm9jdXNhYmxlKCk6IHZvaWQge1xuICAgICAgICBpZiAoIXRoaXMuX2hhbmRsZXMuZmluZChoYW5kbGUgPT4gaGFuZGxlLnRhYkluZGV4ID09PSAwKSkge1xuICAgICAgICAgICAgdGhpcy5zZXRGaXJzdEl0ZW1Gb2N1c2FibGUoKTtcbiAgICAgICAgfVxuICAgIH1cblxufSJdfQ==