UNPKG

@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
/**----------------------------------------------------------------------------------------- * 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 }]; } });