UNPKG

@progress/kendo-angular-layout

Version:

Kendo UI for Angular Layout Package - a collection of components to create professional application layoyts

452 lines (443 loc) 17.2 kB
/**----------------------------------------------------------------------------------------- * Copyright © 2025 Progress Software Corporation. All rights reserved. * Licensed under commercial license. See LICENSE.md in the project root for more information *-------------------------------------------------------------------------------------------*/ /* eslint-disable @typescript-eslint/no-explicit-any */ import { Component, ContentChild, ElementRef, EventEmitter, HostBinding, Input, Output, isDevMode } from '@angular/core'; import { validatePackage } from '@progress/kendo-licensing'; import { packageMetadata } from '../package-metadata'; import { DrawerTemplateDirective, DrawerItemTemplateDirective, DrawerHeaderTemplateDirective, DrawerFooterTemplateDirective } from './template-directives'; import { DrawerService } from './drawer.service'; import { isPresent } from '../common/util'; import { AnimationBuilder } from '@angular/animations'; import { collapseAnimation, expandAnimation } from './animations'; import { take } from 'rxjs/operators'; import { L10N_PREFIX, LocalizationService } from '@progress/kendo-angular-l10n'; import { shouldShowValidationUI, WatermarkOverlayComponent } from '@progress/kendo-angular-common'; import { DrawerListComponent } from './list.component'; import { NgIf, NgTemplateOutlet } from '@angular/common'; import * as i0 from "@angular/core"; import * as i1 from "@angular/animations"; import * as i2 from "@progress/kendo-angular-l10n"; import * as i3 from "./drawer.service"; const DEFAULT_ANIMATION = { type: 'slide', duration: 200 }; /** * Represents the [Kendo UI Drawer component for Angular]({% slug overview_drawer %}). * * @example * ```ts-preview * _@Component({ * selector: 'my-app', * template: ` * <kendo-drawer-container> * <kendo-drawer #drawer * [items]="items" * mode="overlay" * [(expanded)]="expanded"> * </kendo-drawer> * <kendo-drawer-content> * <button class="k-button" (click)="drawer.toggle()">Open the Drawer</button> * </kendo-drawer-content> * </kendo-drawer-container> * ` * }) * class AppComponent { * public expanded = false; * * public items: any[] = [ * { text: 'Inbox', icon: 'k-i-inbox' }, * { text: 'Notifications', icon: 'k-i-bell' }, * { text: 'Date', icon: 'k-i-calendar' } * ]; * } * ``` */ export class DrawerComponent { element; builder; localizationService; drawerService; hostClasses = true; get startPositionClass() { return this.position === 'start'; } get endPositionClass() { return this.position === 'end'; } get overlayTransofrmStyles() { if (this.mode === 'push') { return; } if (this.expanded || this.minimized) { return `translateX(0px)`; } return `translateX(-100%)`; } get flexStyles() { if (this.mode === 'overlay') { return; } if (!this.expanded && !this.minimized) { return 0; } return this.drawerWidth; } /** * Specifies the mode in which the Drawer will be displayed. * * The possible values are: * * (Default) `overlay` * * `push` */ mode = 'overlay'; /** * Specifies the position of the Drawer * ([see example]({% slug positioning_drawer %})). * * The possible values are: * * (Default) `start` * * `end` */ position = 'start'; /** * Enables the mini (compact) view of the Drawer which is displayed when the component is collapsed * ([see example]({% slug expandmodespositions_drawer %}#toc-mini-view)). */ mini = false; /** * Specifies the state of the Drawer. */ expanded = false; /** * Defines the width of the Drawer when it is expanded. * Defaults to `240`. */ width = 240; /** * Defines the width of the Drawer when the mini view is enabled * and the component is collapsed. Defaults to `60`. */ miniWidth = 50; /** * Specifies if the Drawer will be automatically collapsed when an item * or the overlay is clicked. Defaults to `true`. */ autoCollapse = true; /** * The collection of items that will be rendered in the Drawer. */ items = []; /** * Defines a callback function which determines if an item should be expanded. */ set isItemExpanded(fn) { if (isDevMode && isPresent(fn) && typeof fn !== 'function') { throw new Error(`isItemExpanded must be a function, but received ${JSON.stringify(fn)}.`); } this.drawerService.isItemExpanded = fn; } get isItemExpanded() { return this.drawerService.isItemExpanded; } /** * @hidden */ direction; /** * Specifies the animation settings of the Drawer. * ([see example]({% slug interaction_drawer %}#toc-toggling-between-states)). * * The possible values are: * * Boolean * * (Default) `true` * * `false` * * `DrawerAnimation` * * (Default) `type?: 'slide'` * * `duration`&mdash;Accepts a number in milliseconds. Defaults to `300ms`. */ animation = DEFAULT_ANIMATION; /** * Fires when the Drawer is expanded and its animation is complete. */ expand = new EventEmitter(); /** * Fires when the Drawer is collapsed and its animation is complete. */ collapse = new EventEmitter(); /** * Fires when a Drawer item is selected. This event is preventable. */ select = new EventEmitter(); /** * Fires when the `expanded` property of the component was updated. * Used to provide a two-way binding for the `expanded` property. */ expandedChange = new EventEmitter(); /** * @hidden */ drawerTemplate; /** * @hidden */ footerTemplate; /** * @hidden */ headerTemplate; /** * @hidden */ itemTemplate; /** * @hidden */ showLicenseWatermark = false; viewItems; animationEnd = new EventEmitter(); dynamicRTLSubscription; rtl = false; constructor(element, builder, localizationService, drawerService) { this.element = element; this.builder = builder; this.localizationService = localizationService; this.drawerService = drawerService; const isValid = validatePackage(packageMetadata); this.showLicenseWatermark = shouldShowValidationUI(isValid); this.dynamicRTLSubscription = this.localizationService.changes.subscribe(({ rtl }) => { this.rtl = rtl; this.direction = this.rtl ? 'rtl' : 'ltr'; }); this.drawerService.owner = this; } ngOnChanges(changes) { if (changes && changes['items']) { this.drawerService.resetSelection(); this.drawerService.init(); this.viewItems = this.drawerService.view; } } ngOnDestroy() { if (this.dynamicRTLSubscription) { this.dynamicRTLSubscription.unsubscribe(); } } /** * @hidden */ get minimized() { return this.mini && !this.expanded; } /** * @hidden */ get drawerWidth() { return this.minimized ? this.miniWidth : this.width; } /** * Toggles the visibility of the Drawer. * * @param expanded? - Boolean. Specifies if the Drawer will be expanded or collapsed. */ toggle(expanded) { const previous = this.expanded; const current = isPresent(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.animate(current); } else { this[current ? 'expand' : 'collapse'].emit(); } } /** * @hidden */ onSelect(e) { this.select.emit(Object.assign(e, { sender: this })); } onAnimationEnd(currentExpanded) { if (currentExpanded) { this.expand.emit(); } else { this.setExpanded(false); this.collapse.emit(); } } setExpanded(value) { this.expanded = value; this.expandedChange.emit(value); } animate(expanded) { const settings = { mode: this.mode, mini: this.mini, miniWidth: this.miniWidth, width: this.width, rtl: this.rtl, position: this.position, animation: (typeof this.animation !== 'boolean') ? this.animation : DEFAULT_ANIMATION }; const animation = expanded ? expandAnimation(settings) : collapseAnimation(settings); const player = this.createPlayer(animation, this.element.nativeElement); player.play(); } createPlayer(animation, animatedElement) { const factory = this.builder.build(animation); let player = factory.create(animatedElement); player.onDone(() => { if (player) { this.animationEnd.emit(); player.destroy(); player = null; } }); return player; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DrawerComponent, deps: [{ token: i0.ElementRef }, { token: i1.AnimationBuilder }, { token: i2.LocalizationService }, { token: i3.DrawerService }], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: DrawerComponent, isStandalone: true, selector: "kendo-drawer", inputs: { mode: "mode", position: "position", mini: "mini", expanded: "expanded", width: "width", miniWidth: "miniWidth", autoCollapse: "autoCollapse", items: "items", isItemExpanded: "isItemExpanded", animation: "animation" }, outputs: { expand: "expand", collapse: "collapse", select: "select", expandedChange: "expandedChange" }, host: { properties: { "class.k-drawer": "this.hostClasses", "class.k-drawer-start": "this.startPositionClass", "class.k-drawer-end": "this.endPositionClass", "style.transform": "this.overlayTransofrmStyles", "style.flexBasis.px": "this.flexStyles", "attr.dir": "this.direction" } }, providers: [ LocalizationService, DrawerService, { provide: L10N_PREFIX, useValue: 'kendo.drawer' } ], queries: [{ propertyName: "drawerTemplate", first: true, predicate: DrawerTemplateDirective, descendants: true }, { propertyName: "footerTemplate", first: true, predicate: DrawerFooterTemplateDirective, descendants: true }, { propertyName: "headerTemplate", first: true, predicate: DrawerHeaderTemplateDirective, descendants: true }, { propertyName: "itemTemplate", first: true, predicate: DrawerItemTemplateDirective, descendants: true }], exportAs: ["kendoDrawer"], usesOnChanges: true, ngImport: i0, template: ` <div class="k-drawer-wrapper" *ngIf="expanded || mini" [style.width.px]="drawerWidth"> <ng-container *ngIf="!drawerTemplate"> <ng-template *ngIf="headerTemplate" [ngTemplateOutlet]="headerTemplate?.templateRef"> </ng-template> <ul kendoDrawerList role="menubar" orientation="vertical" (select)="onSelect($event)" [mini]="mini" [expanded]="expanded" [view]="viewItems" [itemTemplate]="itemTemplate?.templateRef" class="k-drawer-items"> </ul> <ng-template *ngIf="footerTemplate" [ngTemplateOutlet]="footerTemplate?.templateRef"> </ng-template> </ng-container> <ng-template *ngIf="drawerTemplate" [ngTemplateOutlet]="drawerTemplate?.templateRef"> </ng-template> </div> <div kendoWatermarkOverlay *ngIf="showLicenseWatermark"></div> `, 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: DrawerListComponent, selector: "[kendoDrawerList]", inputs: ["itemTemplate", "mini", "expanded", "view"], outputs: ["select"] }, { kind: "component", type: WatermarkOverlayComponent, selector: "div[kendoWatermarkOverlay]" }] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DrawerComponent, decorators: [{ type: Component, args: [{ exportAs: 'kendoDrawer', providers: [ LocalizationService, DrawerService, { provide: L10N_PREFIX, useValue: 'kendo.drawer' } ], selector: 'kendo-drawer', template: ` <div class="k-drawer-wrapper" *ngIf="expanded || mini" [style.width.px]="drawerWidth"> <ng-container *ngIf="!drawerTemplate"> <ng-template *ngIf="headerTemplate" [ngTemplateOutlet]="headerTemplate?.templateRef"> </ng-template> <ul kendoDrawerList role="menubar" orientation="vertical" (select)="onSelect($event)" [mini]="mini" [expanded]="expanded" [view]="viewItems" [itemTemplate]="itemTemplate?.templateRef" class="k-drawer-items"> </ul> <ng-template *ngIf="footerTemplate" [ngTemplateOutlet]="footerTemplate?.templateRef"> </ng-template> </ng-container> <ng-template *ngIf="drawerTemplate" [ngTemplateOutlet]="drawerTemplate?.templateRef"> </ng-template> </div> <div kendoWatermarkOverlay *ngIf="showLicenseWatermark"></div> `, standalone: true, imports: [NgIf, NgTemplateOutlet, DrawerListComponent, WatermarkOverlayComponent] }] }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i1.AnimationBuilder }, { type: i2.LocalizationService }, { type: i3.DrawerService }]; }, propDecorators: { hostClasses: [{ type: HostBinding, args: ['class.k-drawer'] }], startPositionClass: [{ type: HostBinding, args: ['class.k-drawer-start'] }], endPositionClass: [{ type: HostBinding, args: ['class.k-drawer-end'] }], overlayTransofrmStyles: [{ type: HostBinding, args: ['style.transform'] }], flexStyles: [{ type: HostBinding, args: ['style.flexBasis.px'] }], mode: [{ type: Input }], position: [{ type: Input }], mini: [{ type: Input }], expanded: [{ type: Input }], width: [{ type: Input }], miniWidth: [{ type: Input }], autoCollapse: [{ type: Input }], items: [{ type: Input }], isItemExpanded: [{ type: Input }], direction: [{ type: HostBinding, args: ['attr.dir'] }], animation: [{ type: Input }], expand: [{ type: Output }], collapse: [{ type: Output }], select: [{ type: Output }], expandedChange: [{ type: Output }], drawerTemplate: [{ type: ContentChild, args: [DrawerTemplateDirective] }], footerTemplate: [{ type: ContentChild, args: [DrawerFooterTemplateDirective] }], headerTemplate: [{ type: ContentChild, args: [DrawerHeaderTemplateDirective] }], itemTemplate: [{ type: ContentChild, args: [DrawerItemTemplateDirective] }] } });