@progress/kendo-angular-toolbar
Version:
Kendo UI Angular Toolbar component - a single UI element that organizes buttons and other navigation elements
425 lines (424 loc) • 20.1 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 { Component, forwardRef, ViewChild, ContentChildren, QueryList, Input, ViewChildren } from '@angular/core';
import { LocalizationService } from '@progress/kendo-angular-l10n';
import { ToolBarToolComponent } from './toolbar-tool.component';
import { ToolBarButtonComponent } from './toolbar-button.component';
import { makePeeker, getIndexOfFocused, seekFocusedIndex, getNextKey, getPrevKey, areEqual } from '../util';
import { ButtonGroupComponent, ButtonComponent } from '@progress/kendo-angular-buttons';
import { IconWrapperComponent } from '@progress/kendo-angular-icons';
import { NgFor, NgStyle, NgClass, NgIf } from '@angular/common';
import { ToolBarComponent } from '../toolbar.component';
import * as i0 from "@angular/core";
import * as i1 from "@progress/kendo-angular-l10n";
import * as i2 from "../toolbar.component";
/**
* Represents the Kendo UI Toolbar ButtonGroup for Angular.
*/
export class ToolBarButtonGroupComponent extends ToolBarToolComponent {
localization;
host;
/**
* By default, the ButtonGroup is enabled. To disable the whole group of buttons, set its `disabled`
* attribute to `true`. To disable a specific button, set the `disabled` attribute of the button to
* `true` and leave the `disabled` attribute of the ButtonGroup undefined. If you define the `disabled`
* attribute of the ButtonGroup, it will take precedence over the `disabled` attributes of the underlying
* buttons and they will be ignored.
*/
disabled;
/**
* @hidden
*
* Used to set different fillmode in Spreadsheet and Toolbar to comply with referent rendering.
*/
fillMode = 'solid';
/**
* By default, the selection mode of the ButtonGroup is set to `multiple`.
*/
selection = 'multiple';
/**
* Sets the width of the ButtonGroup.
*
* If the width of the ButtonGroup is set:
* - The buttons resize automatically to fill the full width of the group wrapper.
* - The buttons acquire the same width.
*/
width;
/**
* @hidden
*/
set look(look) {
if (look) {
this.buttonComponents.forEach(b => b.fillMode = look === 'default' ? 'solid' : look);
}
}
toolbarButtonGroup;
sectionButtonGroup;
overflowListItems;
buttonComponents;
get buttonElements() {
if (this.overflows && this.location === 'overflow') {
return [...this.overflowListItems.toArray().filter(el => !el.nativeElement.classList.contains('k-disabled'))].map(el => el.nativeElement);
}
else if (this.overflows && this.location === 'section') {
return this.sectionButtonGroup
.buttons.filter(b => !b.isDisabled)
.map(b => b.element);
}
else {
return this.toolbarButtonGroup
.buttons.filter(b => !b.isDisabled)
.map(b => b.element);
}
}
focusedIndex = -1;
getNextKey;
getPrevKey;
constructor(localization, host) {
super();
this.localization = localization;
this.host = host;
this.getNextKey = getNextKey(this.localization.rtl);
this.getPrevKey = getPrevKey(this.localization.rtl);
this.isBuiltInTool = true;
}
/**
* @hidden
*/
onFocus() {
// triggered on tabin
this.focusedIndex = 0;
}
/**
* @hidden
*/
onNavigate(ev) {
ev.preventDefault();
}
/**
* @hidden
*/
selectedChangeHandler(state, button) {
button.selected = state;
button.selectedChange.emit(state);
}
/**
* @hidden
*/
overflowSelectedChangeHandler(button) {
if (this.selection === 'multiple') {
button.selected = !button.selected;
}
else {
const filteredButtons = this.buttonComponents.filter(b => b !== button);
filteredButtons.forEach(b => b.selected = false);
button.selected = !button.selected;
}
button.selectedChange.emit(button.selected);
}
/**
* @hidden
*/
onButtonClick(ev) {
this.focusedIndex = this.buttonElements.findIndex(be => be === ev.target || be.contains(ev.target));
this.focusButton(this.focusedIndex, ev);
}
/**
* @hidden
*/
canFocus() {
return !(this.disabled || this.buttonElements.length === 0);
}
/**
* @hidden
*/
focus(ev = {}) {
const nextKey = this.getNextKey((this.overflows && this.location === 'overflow'));
const prevKey = this.getPrevKey((this.overflows && this.location === 'overflow'));
this.focusedIndex = getIndexOfFocused(prevKey, nextKey, this.buttonElements)(ev);
this.focusButton(this.focusedIndex, ev);
}
/**
* @hidden
*/
handleKey(ev) {
const nextKey = this.getNextKey((this.overflows && this.location === 'overflow'));
const prevKey = this.getPrevKey((this.overflows && this.location === 'overflow'));
const peekAtIndex = makePeeker(this.buttonElements);
const isUnmodified = areEqual(this.focusedIndex);
this.focusedIndex = seekFocusedIndex(prevKey, nextKey, peekAtIndex)(this.focusedIndex, ev);
this.focusButton(this.focusedIndex, ev);
return !isUnmodified(this.focusedIndex);
}
/**
* @hidden
*/
handleClick(ev, button) {
button.click.emit(ev);
this.onButtonClick(ev);
this.overflowSelectedChangeHandler(button);
}
/**
* @hidden
*/
getIconClasses(button) {
if (button.overflowOptions.icon) {
return `${button.overflowOptions.icon}`;
}
if (button.overflowOptions.iconClass) {
return button.overflowOptions.iconClass;
}
if (button.overflowOptions.svgIcon) {
return button.overflowOptions.svgIcon;
}
}
/**
* @hidden
*/
get size() {
return this.host.size;
}
focusButton(index, ev) {
// Guard against focusing twice on mousedown.
if (!ev.type || ev.type === 'focus' || ev.type === 'keydown') {
this.buttonElements[index]?.focus();
}
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ToolBarButtonGroupComponent, deps: [{ token: i1.LocalizationService }, { token: i2.ToolBarComponent }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: ToolBarButtonGroupComponent, isStandalone: true, selector: "kendo-toolbar-buttongroup", inputs: { disabled: "disabled", fillMode: "fillMode", selection: "selection", width: "width", look: "look" }, providers: [LocalizationService, { provide: ToolBarToolComponent, useExisting: forwardRef(() => ToolBarButtonGroupComponent) }], queries: [{ propertyName: "buttonComponents", predicate: i0.forwardRef(function () { return ToolBarButtonComponent; }) }], viewQueries: [{ propertyName: "toolbarButtonGroup", first: true, predicate: ["toolbarButtonGroup"], descendants: true }, { propertyName: "sectionButtonGroup", first: true, predicate: ["sectionButtonGroup"], descendants: true }, { propertyName: "overflowListItems", predicate: ["listItem"], descendants: true }], exportAs: ["kendoToolBarButtonGroup"], usesInheritance: true, ngImport: i0, template: `
<ng-template #toolbarTemplate>
<kendo-buttongroup
class="k-toolbar-button-group k-button-group-{{fillMode}}"
#toolbarButtonGroup
[tabIndex]="-1"
[selection]="selection"
[disabled]="disabled"
[width]="width"
(navigate)="onNavigate($event)"
(focus)="onFocus()"
>
<button
kendoButton
type="button"
*ngFor="let button of buttonComponents"
[ngStyle]="button.style"
[ngClass]="button.className"
[attr.title]="button.title"
[disabled]="button.disabled"
[size]="size"
[togglable]="button.togglable"
[selected]="button.selected"
[attr.aria-pressed]="button.selected ? true : false"
[fillMode]="button.fillMode"
[themeColor]="button.fillMode ? button.themeColor : null"
[icon]="button.toolbarOptions.icon"
[iconClass]="button.toolbarOptions.iconClass"
[svgIcon]="button.toolbarOptions.svgIcon"
[imageUrl]="button.toolbarOptions.imageUrl"
(click)="button.click.emit($event); onButtonClick($event)"
(pointerdown)="button.pointerdown.emit($event)"
(selectedChange)="selectedChangeHandler($event, button)"
>
{{ button.toolbarOptions.text }}
</button>
</kendo-buttongroup>
</ng-template>
<ng-template #popupTemplate>
<div
*ngFor="let button of buttonComponents"
#listItem
tabindex="-1"
role="menuitem"
class="k-item k-menu-item"
[class.k-disabled]="disabled || button.disabled"
[ngStyle]="button.style"
[ngClass]="button.className"
(click)="handleClick($event, button)">
<span
class="k-link k-menu-link"
[class.k-selected]="button.selected"
>
<kendo-icon-wrapper
*ngIf="button.overflowOptions.icon || button.overflowOptions.iconClass || button.overflowOptions.svgIcon"
[name]="button.overflowOptions.icon"
[customFontClass]="button.overflowOptions.iconClass"
[svgIcon]="button.overflowOptions.svgIcon"
></kendo-icon-wrapper>
<span *ngIf="button.overflowOptions.text" class="k-menu-link-text">{{button.overflowOptions.text}}</span>
</span>
</div>
</ng-template>
<ng-template #sectionTemplate>
<kendo-buttongroup
class="k-toolbar-button-group k-button-group-{{fillMode}}"
#sectionButtonGroup
[tabIndex]="-1"
[selection]="selection"
[disabled]="disabled"
[width]="width"
(navigate)="onNavigate($event)"
(focus)="onFocus()"
>
<button
kendoButton
type="button"
*ngFor="let button of buttonComponents"
[ngStyle]="button.style"
[ngClass]="button.className"
[attr.title]="button.title"
[disabled]="button.disabled"
[size]="size"
[togglable]="button.togglable"
[selected]="button.selected"
[attr.aria-pressed]="button.selected ? true : false"
[fillMode]="button.fillMode"
[themeColor]="button.fillMode ? button.themeColor : null"
[icon]="button.toolbarOptions.icon"
[iconClass]="button.toolbarOptions.iconClass"
[svgIcon]="button.toolbarOptions.svgIcon"
[imageUrl]="button.toolbarOptions.imageUrl"
(click)="button.click.emit($event); onButtonClick($event)"
(pointerdown)="button.pointerdown.emit($event)"
(selectedChange)="selectedChangeHandler($event, button)"
>
{{ button.toolbarOptions.text }}
</button>
</kendo-buttongroup>
</ng-template>
`, isInline: true, dependencies: [{ kind: "component", type: ButtonGroupComponent, selector: "kendo-buttongroup", inputs: ["disabled", "selection", "width", "tabIndex", "navigable"], outputs: ["navigate"], exportAs: ["kendoButtonGroup"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: ButtonComponent, selector: "button[kendoButton]", inputs: ["arrowIcon", "toggleable", "togglable", "selected", "tabIndex", "imageUrl", "iconClass", "icon", "disabled", "size", "rounded", "fillMode", "themeColor", "svgIcon", "primary", "look"], outputs: ["selectedChange", "click"], exportAs: ["kendoButton"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: IconWrapperComponent, selector: "kendo-icon-wrapper", inputs: ["name", "svgIcon", "innerCssClass", "customFontClass", "size"], exportAs: ["kendoIconWrapper"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ToolBarButtonGroupComponent, decorators: [{
type: Component,
args: [{
exportAs: 'kendoToolBarButtonGroup',
providers: [LocalizationService, { provide: ToolBarToolComponent, useExisting: forwardRef(() => ToolBarButtonGroupComponent) }],
selector: 'kendo-toolbar-buttongroup',
template: `
<ng-template #toolbarTemplate>
<kendo-buttongroup
class="k-toolbar-button-group k-button-group-{{fillMode}}"
#toolbarButtonGroup
[tabIndex]="-1"
[selection]="selection"
[disabled]="disabled"
[width]="width"
(navigate)="onNavigate($event)"
(focus)="onFocus()"
>
<button
kendoButton
type="button"
*ngFor="let button of buttonComponents"
[ngStyle]="button.style"
[ngClass]="button.className"
[attr.title]="button.title"
[disabled]="button.disabled"
[size]="size"
[togglable]="button.togglable"
[selected]="button.selected"
[attr.aria-pressed]="button.selected ? true : false"
[fillMode]="button.fillMode"
[themeColor]="button.fillMode ? button.themeColor : null"
[icon]="button.toolbarOptions.icon"
[iconClass]="button.toolbarOptions.iconClass"
[svgIcon]="button.toolbarOptions.svgIcon"
[imageUrl]="button.toolbarOptions.imageUrl"
(click)="button.click.emit($event); onButtonClick($event)"
(pointerdown)="button.pointerdown.emit($event)"
(selectedChange)="selectedChangeHandler($event, button)"
>
{{ button.toolbarOptions.text }}
</button>
</kendo-buttongroup>
</ng-template>
<ng-template #popupTemplate>
<div
*ngFor="let button of buttonComponents"
#listItem
tabindex="-1"
role="menuitem"
class="k-item k-menu-item"
[class.k-disabled]="disabled || button.disabled"
[ngStyle]="button.style"
[ngClass]="button.className"
(click)="handleClick($event, button)">
<span
class="k-link k-menu-link"
[class.k-selected]="button.selected"
>
<kendo-icon-wrapper
*ngIf="button.overflowOptions.icon || button.overflowOptions.iconClass || button.overflowOptions.svgIcon"
[name]="button.overflowOptions.icon"
[customFontClass]="button.overflowOptions.iconClass"
[svgIcon]="button.overflowOptions.svgIcon"
></kendo-icon-wrapper>
<span *ngIf="button.overflowOptions.text" class="k-menu-link-text">{{button.overflowOptions.text}}</span>
</span>
</div>
</ng-template>
<ng-template #sectionTemplate>
<kendo-buttongroup
class="k-toolbar-button-group k-button-group-{{fillMode}}"
#sectionButtonGroup
[tabIndex]="-1"
[selection]="selection"
[disabled]="disabled"
[width]="width"
(navigate)="onNavigate($event)"
(focus)="onFocus()"
>
<button
kendoButton
type="button"
*ngFor="let button of buttonComponents"
[ngStyle]="button.style"
[ngClass]="button.className"
[attr.title]="button.title"
[disabled]="button.disabled"
[size]="size"
[togglable]="button.togglable"
[selected]="button.selected"
[attr.aria-pressed]="button.selected ? true : false"
[fillMode]="button.fillMode"
[themeColor]="button.fillMode ? button.themeColor : null"
[icon]="button.toolbarOptions.icon"
[iconClass]="button.toolbarOptions.iconClass"
[svgIcon]="button.toolbarOptions.svgIcon"
[imageUrl]="button.toolbarOptions.imageUrl"
(click)="button.click.emit($event); onButtonClick($event)"
(pointerdown)="button.pointerdown.emit($event)"
(selectedChange)="selectedChangeHandler($event, button)"
>
{{ button.toolbarOptions.text }}
</button>
</kendo-buttongroup>
</ng-template>
`,
standalone: true,
imports: [ButtonGroupComponent, NgFor, ButtonComponent, NgStyle, NgClass, NgIf, IconWrapperComponent]
}]
}], ctorParameters: function () { return [{ type: i1.LocalizationService }, { type: i2.ToolBarComponent }]; }, propDecorators: { disabled: [{
type: Input
}], fillMode: [{
type: Input
}], selection: [{
type: Input
}], width: [{
type: Input
}], look: [{
type: Input
}], toolbarButtonGroup: [{
type: ViewChild,
args: ['toolbarButtonGroup', { static: false }]
}], sectionButtonGroup: [{
type: ViewChild,
args: ['sectionButtonGroup', { static: false }]
}], overflowListItems: [{
type: ViewChildren,
args: ['listItem']
}], buttonComponents: [{
type: ContentChildren,
args: [forwardRef(() => ToolBarButtonComponent)]
}] } });