@progress/kendo-angular-toolbar
Version:
Kendo UI Angular Toolbar component - a single UI element that organizes buttons and other navigation elements
160 lines (159 loc) • 6.52 kB
JavaScript
/**-----------------------------------------------------------------------------------------
* Copyright © 2025 Progress Software Corporation. All rights reserved.
* Licensed under commercial license. See LICENSE.md in the project root for more information
*-------------------------------------------------------------------------------------------*/
import { Injectable, NgZone } from '@angular/core';
import { take } from 'rxjs/operators';
import { isPresent } from './util';
import * as i0 from "@angular/core";
/**
* @hidden
*/
export class NavigationService {
zone;
overflowButton;
focused = { renderedTool: null, index: -1 };
renderedTools = [];
isPopupFocused = false;
isOverflowButtonFocused = false;
constructor(zone) {
this.zone = zone;
}
setRenderedTools(rts) {
this.renderedTools = rts;
}
click({ context, event: ev }) {
if (this.focused.renderedTool !== context && ev) {
this.focus(context, ev);
}
}
moveFocusToToolBar() {
this.isPopupFocused = false;
this.focusOverflowButton();
}
moveFocusToPopup() {
this.isPopupFocused = true;
this.resetNavigation();
this.focus();
}
focusNext(ev) {
if (this.isOverflowButtonFocused) {
const firstFocusableRT = this.getFocusableTools()[0];
this.focus(firstFocusableRT, ev);
}
else if (!this.isOverflowButtonFocused && this.focused.renderedTool && !this.focused.renderedTool.tool.handleKey(ev)) {
const nextRT = this.getFocusableTools().slice(this.focused.index + 1)[0];
if (nextRT) {
this.focus(nextRT, ev);
}
else {
if (this.isOverflowButtonVisible() && !this.isPopupFocused) {
this.focusOverflowButton();
}
else {
const firstRT = this.getFocusableTools()[0];
this.focus(firstRT, ev);
}
}
}
}
focusPrev(ev) {
if (this.isOverflowButtonFocused) {
const lastFocusableRT = this.getFocusableTools().reverse()[0];
this.focus(lastFocusableRT, ev);
}
else if (!this.isOverflowButtonFocused && this.focused.renderedTool && !this.focused.renderedTool.tool.handleKey(ev)) {
const prevRT = this.getFocusableTools()
.slice(0, this.focused.index)
.reverse()[0];
if (prevRT) {
this.focus(prevRT, ev);
}
else {
if (this.isOverflowButtonVisible() && !this.isPopupFocused) {
this.focusOverflowButton();
}
else {
const lastRT = this.getFocusableTools().reverse()[0];
this.focus(lastRT, ev);
}
}
}
}
resetNavigation() {
this.blurOverflowButton();
this.focused.renderedTool = null;
this.focused.index = -1;
}
focusFirst(ev) {
const firstTool = this.getFocusableTools()[0];
const overFlowButton = this.overflowButton;
if (firstTool) {
this.focused.renderedTool = firstTool;
this.focused.index = this.getFocusableTools().findIndex(rt => rt === firstTool);
this.focus(firstTool, ev);
}
else if (overFlowButton) {
overFlowButton.nativeElement.focus();
}
}
focusLast(ev) {
const lastTool = this.getFocusableTools().reverse()[0];
const overFlowButton = this.overflowButton;
if (lastTool) {
this.focused.renderedTool = lastTool;
this.focused.index = this.getFocusableTools().findIndex(rt => rt === lastTool);
this.focus(lastTool, ev);
}
else if (overFlowButton) {
overFlowButton.nativeElement.focus();
}
}
getFocusableTools() {
return this.renderedTools.filter(rt => (rt.tool.overflows === this.isPopupFocused) && rt.tool.canFocus());
}
focus(renderedTool, ev) {
// running the code below in onStable fixes issue #2939
this.zone.onStable.pipe(take(1)).subscribe(() => {
if (!renderedTool) {
const focusableRTs = this.getFocusableTools();
const lastFocusedRT = focusableRTs.find(rt => rt === this.focused.renderedTool) || focusableRTs[0];
// guard against only disabled tools
if (lastFocusedRT) {
this.focused.renderedTool = lastFocusedRT;
this.focused.index = this.getFocusableTools().findIndex(rt => rt === lastFocusedRT);
// if event is undefined, then this means that the tool is the first one in the overflow popup
lastFocusedRT.tool.focus(ev);
}
}
else if (renderedTool.tool.canFocus && renderedTool.tool.canFocus()) {
this.focused.renderedTool = renderedTool;
this.focused.index = this.getFocusableTools().findIndex(rt => rt === renderedTool);
renderedTool.tool.focus(ev);
this.blurOverflowButton();
}
});
}
blurOverflowButton() {
if (this.overflowButton) {
this.isOverflowButtonFocused = false;
this.overflowButton.nativeElement.tabIndex = -1;
}
}
focusOverflowButton() {
if (this.overflowButton) {
this.isOverflowButtonFocused = true;
this.overflowButton.nativeElement.tabIndex = 0;
this.overflowButton.nativeElement.focus();
}
}
isOverflowButtonVisible() {
return (isPresent(this.overflowButton) &&
window.getComputedStyle(this.overflowButton.nativeElement).getPropertyValue('visibility') === 'visible');
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NavigationService, deps: [{ token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NavigationService });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NavigationService, decorators: [{
type: Injectable
}], ctorParameters: function () { return [{ type: i0.NgZone }]; } });