@progress/kendo-angular-navigation
Version:
Kendo UI Navigation for Angular
1,184 lines (1,162 loc) • 137 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 * as i0 from '@angular/core';
import { Component, HostBinding, Input, Directive, Optional, EventEmitter, Output, ViewChild, ContentChildren, forwardRef, ContentChild, Host, ViewChildren, isDevMode, ElementRef, NgModule } from '@angular/core';
import * as i1 from '@progress/kendo-angular-l10n';
import { LocalizationService, L10N_PREFIX } from '@progress/kendo-angular-l10n';
import { validatePackage } from '@progress/kendo-licensing';
import { focusableSelector, closestInScope as closestInScope$1, isPresent as isPresent$1, isDocumentAvailable, Keys, ResizeSensorComponent, ResizeBatchService } from '@progress/kendo-angular-common';
import { NgIf, NgTemplateOutlet, NgFor, NgClass, NgStyle, AsyncPipe } from '@angular/common';
import { Subscription, fromEvent, merge, ReplaySubject, Subject } from 'rxjs';
import * as i2 from '@angular/animations';
import { style, animate } from '@angular/animations';
import { take, filter, map, startWith, share } from 'rxjs/operators';
import { IconWrapperComponent, IconsService } from '@progress/kendo-angular-icons';
import { ButtonDirective } from '@progress/kendo-angular-buttons';
import { chevronRightIcon, chevronLeftIcon } from '@progress/kendo-svg-icons';
/**
* @hidden
*/
const packageMetadata = {
name: '@progress/kendo-angular-navigation',
productName: 'Kendo UI for Angular',
productCode: 'KENDOUIANGULAR',
productCodes: ['KENDOUIANGULAR'],
publishDate: 1756992643,
version: '20.0.3',
licensingDocsUrl: 'https://www.telerik.com/kendo-angular-ui/my-license/'
};
const DEFAULT_THEME_COLOR = 'light';
const DEFAULT_POSITION = 'top';
const DEFAULT_POSITION_MODE = 'static';
/**
* Represents the [Kendo UI AppBar component for Angular]({% slug overview_appbar %}).
*
* Use the AppBar component to display information, actions, brand titles, and additional navigation on the current screen.
*
* @example
* ```html
* <kendo-appbar>
* <kendo-appbar-section>
* <h2>Page Title</h2>
* </kendo-appbar-section>
* </kendo-appbar>
* ```
*
* @remarks
* Supported children components are: {@link AppBarSectionComponent}, {@link AppBarSpacerComponent}
*/
class AppBarComponent {
localizationService;
host;
renderer;
hostClass = true;
/**
* @hidden
*/
direction;
/**
* Specifies the position of the AppBar
* ([see example]({% slug positioning_appbar %}#toc-position)).
*
* @default 'top'
*/
set position(position) {
const newPosition = position ? position : DEFAULT_POSITION;
this.handleHostClasses(newPosition, this.position);
this._position = newPosition;
}
get position() {
return this._position;
}
/**
* Sets the position mode of the AppBar ([see example](slug:positioning_appbar#toc-position-mode)).
*
* @default 'static'
*/
set positionMode(positionMode) {
const newPositionMode = positionMode ? positionMode : DEFAULT_POSITION_MODE;
this.handleHostClasses(newPositionMode, this.positionMode);
this._positionMode = newPositionMode;
}
get positionMode() {
return this._positionMode;
}
/**
* Sets the theme color of the AppBar. The theme color is applied as the background color of the component.
*
* @default 'light'
*/
set themeColor(themeColor) {
const newThemeColor = themeColor ? themeColor : DEFAULT_THEME_COLOR;
this.handleHostClasses(newThemeColor, this.themeColor);
this._themeColor = newThemeColor;
}
get themeColor() {
return this._themeColor;
}
dynamicRTLSubscription;
rtl = false;
_themeColor = DEFAULT_THEME_COLOR;
_position = DEFAULT_POSITION;
_positionMode = DEFAULT_POSITION_MODE;
constructor(localizationService, host, renderer) {
this.localizationService = localizationService;
this.host = host;
this.renderer = renderer;
validatePackage(packageMetadata);
this.dynamicRTLSubscription = this.localizationService.changes.subscribe(({ rtl }) => {
this.rtl = rtl;
this.direction = this.rtl ? 'rtl' : 'ltr';
});
}
ngAfterViewInit() {
const stylingOptions = ['position', 'positionMode', 'themeColor'];
stylingOptions.forEach(input => {
this.handleHostClasses(this[input]);
});
}
ngOnDestroy() {
if (this.dynamicRTLSubscription) {
this.dynamicRTLSubscription.unsubscribe();
}
}
handleHostClasses(newValue, previousValue) {
const elem = this.host.nativeElement;
if (previousValue && newValue === previousValue) {
return;
}
if (previousValue) {
this.renderer.removeClass(elem, `k-appbar-${previousValue}`);
}
if (newValue) {
this.renderer.addClass(elem, `k-appbar-${newValue}`);
}
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AppBarComponent, deps: [{ token: i1.LocalizationService }, { token: i0.ElementRef }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: AppBarComponent, isStandalone: true, selector: "kendo-appbar", inputs: { position: "position", positionMode: "positionMode", themeColor: "themeColor" }, host: { properties: { "class.k-appbar": "this.hostClass", "attr.dir": "this.direction" } }, providers: [
LocalizationService,
{
provide: L10N_PREFIX,
useValue: 'kendo.appbar.component'
}
], exportAs: ["kendoAppBar"], ngImport: i0, template: `
<ng-content></ng-content>
`, isInline: true });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AppBarComponent, decorators: [{
type: Component,
args: [{
exportAs: 'kendoAppBar',
selector: 'kendo-appbar',
template: `
<ng-content></ng-content>
`,
providers: [
LocalizationService,
{
provide: L10N_PREFIX,
useValue: 'kendo.appbar.component'
}
],
standalone: true
}]
}], ctorParameters: function () { return [{ type: i1.LocalizationService }, { type: i0.ElementRef }, { type: i0.Renderer2 }]; }, propDecorators: { hostClass: [{
type: HostBinding,
args: ['class.k-appbar']
}], direction: [{
type: HostBinding,
args: ['attr.dir']
}], position: [{
type: Input
}], positionMode: [{
type: Input
}], themeColor: [{
type: Input
}] } });
/**
* Represents the [Kendo UI AppBarSection component for Angular]({% slug contentarrangement_appbar %}#toc-sections).
*
* Use the AppBarSection component to group content, actions, or navigation items within the AppBar.
*
* @example
* ```html
* <kendo-appbar>
* <kendo-appbar-section>
* <h2>Page Title</h2>
* </kendo-appbar-section>
* </kendo-appbar>
* ```
*/
class AppBarSectionComponent {
hostClass = true;
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AppBarSectionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: AppBarSectionComponent, isStandalone: true, selector: "kendo-appbar-section", host: { properties: { "class.k-appbar-section": "this.hostClass" } }, ngImport: i0, template: `
<ng-content></ng-content>
`, isInline: true });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AppBarSectionComponent, decorators: [{
type: Component,
args: [{
selector: 'kendo-appbar-section',
template: `
<ng-content></ng-content>
`,
standalone: true
}]
}], propDecorators: { hostClass: [{
type: HostBinding,
args: ['class.k-appbar-section']
}] } });
/**
* @hidden
*/
const isPresent = (value) => value !== null && value !== undefined;
/**
* @hidden
*/
const outerWidth = (element) => {
const style = getComputedStyle(element);
let width = parseFloat(style.width);
width += (parseFloat(style.marginLeft) || 0) + (parseFloat(style.marginRight) || 0);
return width;
};
/**
* @hidden
*/
const getFirstAndLastFocusable = (parent) => {
const all = getAllFocusableChildren(parent);
const firstFocusable = all.length > 0 ? all[0] : parent;
const lastFocusable = all.length > 0 ? all[all.length - 1] : parent;
return [firstFocusable, lastFocusable];
};
/**
* @hidden
*/
const getAllFocusableChildren = (parent) => {
return parent.querySelectorAll(focusableSelector);
};
/**
* @hidden
*/
let idx = 0;
/**
* @hidden
*/
const hexColorRegex = /^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/;
/**
* @hidden
*/
const getId = (prefix) => {
return `${prefix}${++idx}`;
};
/**
* @hidden
*/
const ACTIONSHEET_ITEM_INDEX_ATTRIBUTE = 'kendo-actionsheet-item-index';
/**
* @hidden
*/
const getActionSheetItemIndex = (target, targetAttr, scope) => {
const item = closestItem$1(target, targetAttr, scope);
if (item) {
return itemIndex$1(item, targetAttr);
}
};
const itemIndex$1 = (item, indexAttr) => +item.getAttribute(indexAttr);
const hasItemIndex$1 = (item, indexAttr) => isPresent(item.getAttribute(indexAttr));
const closestItem$1 = (target, targetAttr, scope) => closestInScope$1(target, el => hasItemIndex$1(el, targetAttr), scope);
/**
* Represents the [Kendo UI AppBarSpacer component for Angular]({% slug contentarrangement_appbar %}#toc-spacings).
*
* Use the AppBarSpacer component to add white space between AppBar sections and customize its width.
*
* @example
* ```html
* <kendo-appbar>
* <kendo-appbar-section>
* <button kendoButton fillMode="flat" [svgIcon]="menuIcon"></button>
* </kendo-appbar-section>
*
* <kendo-appbar-spacer></kendo-appbar-spacer>
*
* <kendo-appbar-section>
* <h2>Page Title</h2>
* </kendo-appbar-section>
* </kendo-appbar>
* ```
*/
class AppBarSpacerComponent {
renderer;
element;
hostClass = true;
get sizedClass() {
return isPresent(this.width);
}
/**
* Specifies the width of the AppBarSpacer.
*
* If not set, the AppBarSpacer will take all of the available space.
*/
width;
constructor(renderer, element) {
this.renderer = renderer;
this.element = element;
}
ngAfterViewInit() {
if (isPresent(this.width)) {
const element = this.element.nativeElement;
this.renderer.setStyle(element, 'flexBasis', this.width);
}
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AppBarSpacerComponent, deps: [{ token: i0.Renderer2 }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: AppBarSpacerComponent, isStandalone: true, selector: "kendo-appbar-spacer", inputs: { width: "width" }, host: { properties: { "class.k-spacer": "this.hostClass", "class.k-spacer-sized": "this.sizedClass" } }, ngImport: i0, template: ``, isInline: true });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AppBarSpacerComponent, decorators: [{
type: Component,
args: [{
selector: 'kendo-appbar-spacer',
template: ``,
standalone: true
}]
}], ctorParameters: function () { return [{ type: i0.Renderer2 }, { type: i0.ElementRef }]; }, propDecorators: { hostClass: [{
type: HostBinding,
args: ['class.k-spacer']
}], sizedClass: [{
type: HostBinding,
args: ['class.k-spacer-sized']
}], width: [{
type: Input
}] } });
/**
* Provides the event data for the `itemClick` event of the ActionSheet component.
*
* Use this event to access the clicked item and the original DOM event.
*/
class ActionSheetItemClickEvent {
/**
* Provides the ActionSheet item that was clicked.
*/
item;
/**
* Represents the original DOM event that triggered the `itemClick` event.
*/
originalEvent;
}
/**
* Represents a template for customizing the header content of the ActionSheet. If you implement this template, it will override the `title` and `subtitle` of the ActionSheet.
* To define the template, nest an `<ng-template>` tag
* with the `kendoActionSheetHeaderTemplate` directive inside the `<kendo-actionsheet>` tag.
*
* @example
* ```html
* <kendo-actionsheet>
* <ng-template kendoActionSheetHeaderTemplate>
* <h3>Custom Header</h3>
* </ng-template>
* </kendo-actionsheet>
* ```
*/
class ActionSheetHeaderTemplateDirective {
templateRef;
constructor(templateRef) {
this.templateRef = templateRef;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ActionSheetHeaderTemplateDirective, deps: [{ token: i0.TemplateRef, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: ActionSheetHeaderTemplateDirective, isStandalone: true, selector: "[kendoActionSheetHeaderTemplate]", ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ActionSheetHeaderTemplateDirective, decorators: [{
type: Directive,
args: [{
selector: '[kendoActionSheetHeaderTemplate]',
standalone: true
}]
}], ctorParameters: function () { return [{ type: i0.TemplateRef, decorators: [{
type: Optional
}] }]; } });
/**
* Represents a template for customizing the content of each ActionSheet item.
* To define the template, nest an `<ng-template>` tag
* with the `kendoActionSheetItemTemplate` directive inside the `<kendo-actionsheet>` tag.
*
* @example
* ```html
* <kendo-actionsheet [items]="items">
* <ng-template kendoActionSheetItemTemplate let-item>
* <span>{{ item.title }} (custom)</span>
* </ng-template>
* </kendo-actionsheet>
* ```
*/
class ActionSheetItemTemplateDirective {
templateRef;
constructor(templateRef) {
this.templateRef = templateRef;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ActionSheetItemTemplateDirective, deps: [{ token: i0.TemplateRef, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: ActionSheetItemTemplateDirective, isStandalone: true, selector: "[kendoActionSheetItemTemplate]", ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ActionSheetItemTemplateDirective, decorators: [{
type: Directive,
args: [{
selector: '[kendoActionSheetItemTemplate]',
standalone: true
}]
}], ctorParameters: function () { return [{ type: i0.TemplateRef, decorators: [{
type: Optional
}] }]; } });
/**
* Represents a template for customizing the list content of the ActionSheet items.
* To define the template, nest an `<ng-template>` tag
* with the `kendoActionSheetContentTemplate` directive inside the `<kendo-actionsheet>` tag.
*
* @example
* ```html
* <kendo-actionsheet [items]="items">
* <ng-template kendoActionSheetContentTemplate>
* <div>Custom content here</div>
* </ng-template>
* </kendo-actionsheet>
* ```
*/
class ActionSheetContentTemplateDirective {
templateRef;
constructor(templateRef) {
this.templateRef = templateRef;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ActionSheetContentTemplateDirective, deps: [{ token: i0.TemplateRef, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: ActionSheetContentTemplateDirective, isStandalone: true, selector: "[kendoActionSheetContentTemplate]", ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ActionSheetContentTemplateDirective, decorators: [{
type: Directive,
args: [{
selector: '[kendoActionSheetContentTemplate]',
standalone: true
}]
}], ctorParameters: function () { return [{ type: i0.TemplateRef, decorators: [{
type: Optional
}] }]; } });
/**
* Represents a template for customizing the footer of the ActionSheet.
* To define the template, nest an `<ng-template>` tag
* with the `kendoActionSheetFooterTemplate` directive inside the `<kendo-actionsheet>` tag.
*
* @example
* ```html
* <kendo-actionsheet>
* <ng-template kendoActionSheetFooterTemplate>
* <button kendoButton>Custom Footer Button</button>
* </ng-template>
* </kendo-actionsheet>
* ```
*/
class ActionSheetFooterTemplateDirective {
templateRef;
constructor(templateRef) {
this.templateRef = templateRef;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ActionSheetFooterTemplateDirective, deps: [{ token: i0.TemplateRef, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: ActionSheetFooterTemplateDirective, isStandalone: true, selector: "[kendoActionSheetFooterTemplate]", ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ActionSheetFooterTemplateDirective, decorators: [{
type: Directive,
args: [{
selector: '[kendoActionSheetFooterTemplate]',
standalone: true
}]
}], ctorParameters: function () { return [{ type: i0.TemplateRef, decorators: [{
type: Optional
}] }]; } });
/**
* Represents a template for customizing the overall content of the ActionSheet.
* To define the template, nest an `<ng-template>` tag
* with the `kendoActionSheetTemplate` directive inside the `<kendo-actionsheet>` tag.
*
* @example
* ```html
* <kendo-actionsheet>
* <ng-template kendoActionSheetTemplate>
* <div>Custom ActionSheet content</div>
* </ng-template>
* </kendo-actionsheet>
* ```
*/
class ActionSheetTemplateDirective {
templateRef;
constructor(templateRef) {
this.templateRef = templateRef;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ActionSheetTemplateDirective, deps: [{ token: i0.TemplateRef, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: ActionSheetTemplateDirective, isStandalone: true, selector: "[kendoActionSheetTemplate]", ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ActionSheetTemplateDirective, decorators: [{
type: Directive,
args: [{
selector: '[kendoActionSheetTemplate]',
standalone: true
}]
}], ctorParameters: function () { return [{ type: i0.TemplateRef, decorators: [{
type: Optional
}] }]; } });
/**
* @hidden
*/
function slideUp(duration, height) {
return [
style({ overflow: 'hidden', display: 'block', height: 0 }),
animate(`${duration}ms ease-in`, style({ height: `${height}` }))
];
}
/**
* @hidden
*/
function slideDown(duration, height) {
return [
style({ overflow: 'hidden', height: `${height}` }),
animate(`${duration}ms ease-in`, style({ overflow: 'hidden', height: 0 }))
];
}
/**
* @hidden
*/
class ActionSheetItemComponent {
itemTemplate;
item;
pointerClass = true;
manageIconClasses(item) {
const classes = ['k-actionsheet-item-icon'];
const isHexColor = isPresent(item.iconColor) && hexColorRegex.test(item.iconColor);
const isThemeColor = isPresent(item.iconColor) && item.iconColor !== '' && !isHexColor;
if (isThemeColor) {
classes.push(`k-text-${item.iconColor}`);
}
return classes.join(' ');
}
manageIconStyles(item) {
const isHexColor = isPresent(item.iconColor) && hexColorRegex.test(item.iconColor);
const isSizeSet = isPresent(item.iconSize) && item.iconSize !== '';
const styles = {};
if (isHexColor) {
styles.color = item.iconColor;
}
if (isSizeSet) {
styles.fontSize = item.iconSize;
}
return styles;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ActionSheetItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: ActionSheetItemComponent, isStandalone: true, selector: "[kendoActionSheetItem]", inputs: { itemTemplate: "itemTemplate", item: "item" }, host: { properties: { "class.k-cursor-pointer": "this.pointerClass" } }, ngImport: i0, template: `
<ng-template *ngIf="itemTemplate; else defaultTemplate"
[ngTemplateOutlet]="itemTemplate"
[ngTemplateOutletContext]="{
$implicit: item
}">
</ng-template>
<ng-template #defaultTemplate>
<span class="k-actionsheet-action">
<span *ngIf="item.icon || item.iconClass || item.svgIcon" class="k-icon-wrap">
<kendo-icon-wrapper
[name]="item.icon"
[customFontClass]="item.iconClass"
[class]="manageIconClasses(item)"
[svgIcon]="item.svgIcon"
[style]="manageIconStyles(item)"
>
</kendo-icon-wrapper>
</span>
<span *ngIf="item.title || item.description" class="k-actionsheet-item-text">
<span *ngIf="item.title" class="k-actionsheet-item-title">{{item.title}}</span>
<span *ngIf="item.description" class="k-actionsheet-item-description">{{item.description}}</span>
</span>
</span>
</ng-template>
`, isInline: true, dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { 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: ActionSheetItemComponent, decorators: [{
type: Component,
args: [{
// eslint-disable-next-line @angular-eslint/component-selector
selector: '[kendoActionSheetItem]',
template: `
<ng-template *ngIf="itemTemplate; else defaultTemplate"
[ngTemplateOutlet]="itemTemplate"
[ngTemplateOutletContext]="{
$implicit: item
}">
</ng-template>
<ng-template #defaultTemplate>
<span class="k-actionsheet-action">
<span *ngIf="item.icon || item.iconClass || item.svgIcon" class="k-icon-wrap">
<kendo-icon-wrapper
[name]="item.icon"
[customFontClass]="item.iconClass"
[class]="manageIconClasses(item)"
[svgIcon]="item.svgIcon"
[style]="manageIconStyles(item)"
>
</kendo-icon-wrapper>
</span>
<span *ngIf="item.title || item.description" class="k-actionsheet-item-text">
<span *ngIf="item.title" class="k-actionsheet-item-title">{{item.title}}</span>
<span *ngIf="item.description" class="k-actionsheet-item-description">{{item.description}}</span>
</span>
</span>
</ng-template>
`,
standalone: true,
imports: [NgIf, NgTemplateOutlet, IconWrapperComponent]
}]
}], propDecorators: { itemTemplate: [{
type: Input
}], item: [{
type: Input
}], pointerClass: [{
type: HostBinding,
args: ['class.k-cursor-pointer']
}] } });
/**
* @hidden
*/
class ActionSheetListComponent {
renderer;
ngZone;
element;
groupItems = [];
allItems = [];
itemTemplate;
itemClick = new EventEmitter();
subscriptions = new Subscription();
constructor(renderer, ngZone, element) {
this.renderer = renderer;
this.ngZone = ngZone;
this.element = element;
}
ngAfterViewInit() {
this.initDomEvents();
}
ngOnDestroy() {
this.subscriptions.unsubscribe();
}
initDomEvents() {
if (!this.element) {
return;
}
this.ngZone.runOutsideAngular(() => {
const nativeElement = this.element.nativeElement;
this.subscriptions.add(this.renderer.listen(nativeElement, 'click', this.clickHandler.bind(this)));
});
}
clickHandler(e) {
const itemIndex = getActionSheetItemIndex(e.target, ACTIONSHEET_ITEM_INDEX_ATTRIBUTE, this.element.nativeElement);
const item = this.allItems[itemIndex];
if (!item) {
return;
}
if (item.disabled) {
e.preventDefault();
return;
}
this.ngZone.run(() => {
this.itemClick.emit({ item, originalEvent: e });
});
}
setAttrIndex(item) {
return this.allItems.indexOf(item);
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ActionSheetListComponent, deps: [{ token: i0.Renderer2 }, { token: i0.NgZone }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: ActionSheetListComponent, isStandalone: true, selector: "[kendoActionSheetList]", inputs: { groupItems: "groupItems", allItems: "allItems", itemTemplate: "itemTemplate" }, outputs: { itemClick: "itemClick" }, ngImport: i0, template: "\n <span *ngFor=\"let item of groupItems\" kendoActionSheetItem\n tabindex=\"0\"\n role=\"button\"\n [attr.aria-disabled]=\"item.disabled\"\n [class.k-actionsheet-item]=\"true\"\n [attr.kendo-actionsheet-item-index]=\"setAttrIndex(item)\"\n [class.k-disabled]=\"item.disabled\"\n [ngClass]=\"item.cssClass\"\n [ngStyle]=\"item.cssStyle\"\n [itemTemplate]=\"itemTemplate\"\n [item]=\"item\">\n </span>\n ", isInline: true, dependencies: [{ kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: ActionSheetItemComponent, selector: "[kendoActionSheetItem]", inputs: ["itemTemplate", "item"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ActionSheetListComponent, decorators: [{
type: Component,
args: [{
// eslint-disable-next-line @angular-eslint/component-selector
selector: '[kendoActionSheetList]',
template: `
<span *ngFor="let item of groupItems" kendoActionSheetItem
tabindex="0"
role="button"
[attr.aria-disabled]="item.disabled"
[class.k-actionsheet-item]="true"
[attr.${ACTIONSHEET_ITEM_INDEX_ATTRIBUTE}]="setAttrIndex(item)"
[class.k-disabled]="item.disabled"
[ngClass]="item.cssClass"
[ngStyle]="item.cssStyle"
[itemTemplate]="itemTemplate"
[item]="item">
</span>
`,
standalone: true,
imports: [NgFor, ActionSheetItemComponent, NgClass, NgStyle]
}]
}], ctorParameters: function () { return [{ type: i0.Renderer2 }, { type: i0.NgZone }, { type: i0.ElementRef }]; }, propDecorators: { groupItems: [{
type: Input
}], allItems: [{
type: Input
}], itemTemplate: [{
type: Input
}], itemClick: [{
type: Output
}] } });
const DEFAULT_ANIMATION_CONFIG = { duration: 300 };
/**
* Represents the [Kendo UI ActionSheet component for Angular](slug:overview_actionsheet).
* Use this component to display a set of choices related to a user-initiated task in a modal sheet that slides up from the bottom of the screen.
*
* @example
* ```html
* <kendo-actionsheet [items]="actionItems" [expanded]="true">
* </kendo-actionsheet>
* ```
*/
class ActionSheetComponent {
element;
ngZone;
renderer;
localizationService;
builder;
cdr;
/**
* @hidden
*/
currentView = 1;
/**
* @hidden
*/
get hostClass() {
return this.expanded;
}
/**
* @hidden
*/
direction;
/**
* Specifies the action buttons displayed in the ActionSheet footer.
*/
actions;
/**
* Configures the layout of the action buttons in the footer. By default, actions are arranged horizontally and stretched to fill the container.
*/
actionsLayout = {
orientation: 'horizontal',
alignment: 'stretched'
};
/**
* Determines whether the ActionSheet closes when the overlay is clicked.
*
* @default false
*/
overlayClickClose = false;
/**
* Sets the title text displayed in the ActionSheet header.
*/
title;
/**
* Sets the subtitle text displayed below the title in the header.
*/
subtitle;
/**
* Provides the collection of items rendered in the ActionSheet content area.
*/
items;
/**
* Applies CSS classes to the inner ActionSheet element. Accepts any value supported by [`ngClass`](link:site.data.urls.angular['ngclassapi']).
*/
cssClass;
/**
* Applies inline styles to the inner ActionSheet element. Accepts any value supported by [`ngStyle`](link:site.data.urls.angular['ngstyleapi']).
*/
cssStyle;
/**
* Configures the opening and closing animations for the ActionSheet ([see example](slug:animations_actionsheet)).
*
* @default true
*/
animation = true;
/**
* Controls whether the ActionSheet is expanded or collapsed.
*
* @default false
*/
expanded = false;
/**
* Sets the `aria-labelledby` attribute of the ActionSheet wrapper element.
* Use this option when the built-in header element is replaced through the [`ActionSheetHeaderTemplate`](slug:api_navigation_actionsheetheadertemplatedirective)
* or [`ActionSheetContentTemplate`](slug:api_navigation_actionsheetcontenttemplatedirective).
*/
titleId = getId('k-actionsheet-title');
/**
* @hidden
*
* Determines if the ActionSheet should focus the first focusable element when opened.
*/
initialFocus = true;
/**
* Fires when the `expanded` property of the component is updated.
* You can use this event to provide two-way binding for the `expanded` property.
*/
expandedChange = new EventEmitter();
/**
* Fires when any of the ActionSheet action buttons is clicked.
*/
action = new EventEmitter();
/**
* Fires when the ActionSheet is expanded and its animation is complete.
*/
expand = new EventEmitter();
/**
* Fires when the ActionSheet is collapsed and its animation is complete.
*/
collapse = new EventEmitter();
/**
* Fires when an ActionSheet item is clicked.
*/
itemClick = new EventEmitter();
/**
* Fires when the modal overlay is clicked.
*/
overlayClick = new EventEmitter();
/**
* @hidden
*/
childContainer;
/**
* @hidden
*/
actionSheetViews;
/**
* @hidden
*/
actionSheetTemplate;
/**
* @hidden
*/
headerTemplate;
/**
* @hidden
*/
contentTemplate;
/**
* @hidden
*/
itemTemplate;
/**
* @hidden
*/
footerTemplate;
dynamicRTLSubscription;
rtl = false;
domSubs = new Subscription();
player;
animationEnd = new EventEmitter();
constructor(element, ngZone, renderer, localizationService, builder, cdr) {
this.element = element;
this.ngZone = ngZone;
this.renderer = renderer;
this.localizationService = localizationService;
this.builder = builder;
this.cdr = cdr;
validatePackage(packageMetadata);
this.dynamicRTLSubscription = this.localizationService.changes.subscribe(({ rtl }) => {
this.rtl = rtl;
this.direction = this.rtl ? 'rtl' : 'ltr';
});
}
ngAfterViewInit() {
this.initDomEvents();
this.setCssVariables();
}
ngOnChanges(changes) {
if (changes['expanded'] && this.expanded) {
this.setExpanded(true);
}
}
ngOnDestroy() {
this.domSubs.unsubscribe();
if (this.dynamicRTLSubscription) {
this.dynamicRTLSubscription.unsubscribe();
}
if (this.player) {
this.player.destroy();
}
}
/**
* @hidden
* Navigates to the next view.
*/
nextView() {
if (this.currentView < this.actionSheetViews.length) {
this.currentView += 1;
}
}
/**
* @hidden
* Navigates to the previous view.
*/
prevView() {
if (this.currentView > 1) {
this.currentView -= 1;
}
}
/**
* Toggles the visibility of the ActionSheet.
*
* @param expanded? - Boolean. Specifies if the ActionSheet will be expanded or collapsed.
*/
toggle(expanded) {
const previous = this.expanded;
const current = isPresent$1(expanded) ? expanded : !previous;
if (current === previous) {
return;
}
if (current === true) {
this.setExpanded(true);
}
else if (current === false && !this.animation) {
this.setExpanded(false);
}
if (this.animation) {
this.animationEnd.pipe(take(1))
.subscribe(() => { this.onAnimationEnd(current); });
this.playAnimation(current);
}
else {
this[current ? 'expand' : 'collapse'].emit();
}
}
/**
* @hidden
*/
get orientationClass() {
return this.actionsLayout.orientation ? `k-actions-${this.actionsLayout.orientation}` : '';
}
/**
* @hidden
*/
get alignmentClass() {
return this.actionsLayout.alignment ? `k-actions-${this.actionsLayout.alignment}` : '';
}
/**
* @hidden
*/
get topGroupItems() {
return this.items?.filter(item => !item.group || item.group === 'top');
}
/**
* @hidden
*/
get bottomGroupItems() {
return this.items?.filter(item => item.group === 'bottom');
}
/**
* @hidden
*/
onItemClick(ev) {
this.itemClick.emit(ev);
}
/**
* @hidden
*/
onOverlayClick() {
this.overlayClick.emit();
if (this.overlayClickClose) {
this.toggle(false);
}
}
/**
* @hidden
*/
get shouldRenderSeparator() {
return this.topGroupItems?.length > 0 && this.bottomGroupItems?.length > 0;
}
initDomEvents() {
if (!this.element) {
return;
}
this.ngZone.runOutsideAngular(() => {
this.domSubs.add(this.renderer.listen(this.element.nativeElement, 'keydown', (ev) => {
this.onKeyDown(ev);
}));
});
}
setCssVariables() {
if (!this.element || !isDocumentAvailable()) {
return;
}
// The following syntax is used as it does not violate CSP compliance
this.element.nativeElement.style.setProperty('--kendo-actionsheet-height', 'auto');
this.element.nativeElement.style.setProperty('--kendo-actionsheet-max-height', 'none');
}
onKeyDown(event) {
const target = event.target;
if (event.code === Keys.Tab) {
this.ngZone.run(() => {
this.keepFocusWithinComponent(target, event);
});
}
if (event.code === Keys.Escape) {
this.ngZone.run(() => {
this.overlayClick.emit();
});
}
if (event.code === Keys.Enter || event.code === Keys.NumpadEnter) {
this.ngZone.run(() => {
this.triggerItemClick(target, event);
});
}
}
handleInitialFocus() {
const [firstFocusable] = getFirstAndLastFocusable(this.element.nativeElement);
if (firstFocusable && this.initialFocus) {
firstFocusable.focus();
}
}
keepFocusWithinComponent(target, event) {
const wrapper = this.element.nativeElement;
const [firstFocusable, lastFocusable] = getFirstAndLastFocusable(wrapper);
const tabAfterLastFocusable = !event.shiftKey && target === lastFocusable;
const shiftTabAfterFirstFocusable = event.shiftKey && target === firstFocusable;
if (tabAfterLastFocusable) {
event.preventDefault();
firstFocusable.focus();
}
if (shiftTabAfterFirstFocusable) {
event.preventDefault();
lastFocusable.focus();
}
}
triggerItemClick(target, event) {
const itemIndex = getActionSheetItemIndex(target, ACTIONSHEET_ITEM_INDEX_ATTRIBUTE, this.element.nativeElement);
const item = isPresent$1(itemIndex) ? this.items[itemIndex] : null;
if (!item || item.disabled) {
return;
}
this.itemClick.emit({ item, originalEvent: event });
}
setExpanded(value) {
this.expanded = value;
this.expandedChange.emit(value);
if (this.expanded) {
this.cdr.detectChanges();
this.handleInitialFocus();
}
}
onAnimationEnd(currentExpanded) {
if (currentExpanded) {
this.expand.emit();
}
else {
this.setExpanded(false);
this.collapse.emit();
}
}
playAnimation(expanded) {
const duration = typeof this.animation !== 'boolean' && this.animation.duration ? this.animation.duration : DEFAULT_ANIMATION_CONFIG.duration;
const contentHeight = getComputedStyle(this.childContainer.nativeElement).height;
const animation = expanded ? slideUp(duration, contentHeight) : slideDown(duration, contentHeight);
const factory = this.builder.build(animation);
this.player = factory.create(this.childContainer.nativeElement);
this.player.onDone(() => {
if (this.player) {
this.animationEnd.emit();
this.player.destroy();
this.player = null;
}
});
this.player.play();
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ActionSheetComponent, deps: [{ token: i0.ElementRef }, { token: i0.NgZone }, { token: i0.Renderer2 }, { token: i1.LocalizationService }, { token: i2.AnimationBuilder }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: ActionSheetComponent, isStandalone: true, selector: "kendo-actionsheet", inputs: { actions: "actions", actionsLayout: "actionsLayout", overlayClickClose: "overlayClickClose", title: "title", subtitle: "subtitle", items: "items", cssClass: "cssClass", cssStyle: "cssStyle", animation: "animation", expanded: "expanded", titleId: "titleId", initialFocus: "initialFocus" }, outputs: { expandedChange: "expandedChange", action: "action", expand: "expand", collapse: "collapse", itemClick: "itemClick", overlayClick: "overlayClick" }, host: { properties: { "class.k-actionsheet-container": "this.hostClass", "attr.dir": "this.direction" } }, providers: [
LocalizationService,
{
provide: L10N_PREFIX,
useValue: 'kendo.actionsheet.component'
}
], queries: [{ propertyName: "actionSheetTemplate", first: true, predicate: ActionSheetTemplateDirective, descendants: true }, { propertyName: "headerTemplate", first: true, predicate: ActionSheetHeaderTemplateDirective, descendants: true }, { propertyName: "contentTemplate", first: true, predicate: ActionSheetContentTemplateDirective, descendants: true }, { propertyName: "itemTemplate", first: true, predicate: ActionSheetItemTemplateDirective, descendants: true }, { propertyName: "footerTemplate", first: true, predicate: ActionSheetFooterTemplateDirective, descendants: true }, { propertyName: "actionSheetViews", predicate: i0.forwardRef(function () { return ActionSheetViewComponent; }) }], viewQueries: [{ propertyName: "childContainer", first: true, predicate: ["childContainer"], descendants: true }], exportAs: ["kendoActionSheet"], usesOnChanges: true, ngImport: i0, template: `
<ng-container *ngIf="expanded">
<div class="k-overlay" (click)="onOverlayClick()"></div>
<div class="k-animation-container k-animation-container-shown">
<div #childContainer class="k-child-animation-container" [style]="'bottom: 0px; width: 100%;'">
<div
class="k-actionsheet k-actionsheet-bottom"
[ngClass]="cssClass"
[ngStyle]="cssStyle"
role="dialog"
aria-modal="true"
[attr.aria-labelledby]="titleId"
[style.--kendo-actionsheet-view-current]="actionSheetViews?.length > 0 ? currentView : null"
>
<ng-content *ngIf="actionSheetViews?.length > 0" select="kendo-actionsheet-view"></ng-content>
<div *ngIf="actionSheetViews?.length === 0" class="k-actionsheet-view">
<ng-template *ngIf="actionSheetTemplate; else defaultTemplate"
[ngTemplateOutlet]="actionSheetTemplate?.templateRef">
</ng-template>
<ng-template #defaultTemplate>
<div *ngIf="title || subtitle || headerTemplate" class="k-actionsheet-titlebar">
<ng-template *ngIf="headerTemplate; else defaultHeaderTemplate"
[ngTemplateOutlet]="headerTemplate?.templateRef">
</ng-template>
<ng-template #defaultHeaderTemplate>
<div class="k-actionsheet-titlebar-group k-hbox">
<div class="k-actionsheet-title" [id]="titleId">
<div *ngIf="title" class="k-text-center">{{title}}</div>
<div *ngIf="subtitle" class="k-actionsheet-subtitle k-text-center">{{subtitle}}</div>
</div>
</div>
</ng-template>
</div>
<div *ngIf="items || contentTemplate" class="k-actionsheet-content">
<ng-template *ngIf="contentTemplate; else defaultContentTemplate"
[ngTemplateOutlet]="contentTemplate?.templateRef">
</ng-template>
<ng-template #defaultContentTemplate>
<div *ngIf="topGroupItems" kendoActionSheetList
class="k-list-ul"
role="group"
[groupItems]="topGroupItems"
[allItems]="items"
[itemTemplate]="itemTemplate?.templateRef"
(itemClick)="onItemClick($event)">
</div>
<hr *ngIf="shouldRenderSeparator" class="k-hr"/>
<div *ngIf="bottomGroupItems" kendoActionSheetList
class="k-list-ul"
role="group"
[groupItems]="bottomGroupItems"
[allItems]="items"
[itemTemplate]="itemTemplate?.templateRef"
(itemClick)="onItemClick($event)">
</div>
</ng-template>
</div>
<div *ngIf="footerTemplate || actions" [ngClass]="[orientationClass, alignmentClass, 'k-actions', 'k-actionsheet-footer']">
<ng-template
*ngIf="footerTemplate"
[ngTemplateOutlet]="footerTemplate?.templateRef">
</ng-template>
<ng-container *ngIf="!footerTemplate && actions">
<button
*ngFor="let actionButton of actions"
kendoButton
type="button"
[icon]="actionButton.icon"
[title]="actionButton.title"
[svgIcon]="actionButton.svgIcon"
[themeColor]="actionButton.themeColor"
[fillMode]="actionButton.fillMode"
[size]="actionButton.size"
[attr.aria-label]="actionButton.text"
(click)="action.emit(actionButton)"
>
{{ actionButton.text }}
</button>
</ng-container>
</div>
</ng-template>
</div>
</div>
</div>
</div>
</ng-container>
`, isInline: true, dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext"