UNPKG

@progress/kendo-angular-layout

Version:

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

418 lines (407 loc) 20.6 kB
/**----------------------------------------------------------------------------------------- * Copyright © 2025 Progress Software Corporation. All rights reserved. * Licensed under commercial license. See LICENSE.md in the project root for more information *-------------------------------------------------------------------------------------------*/ import { Component, ElementRef, HostBinding, HostListener, Input, Renderer2, ViewChild } from '@angular/core'; import { chevronRightIcon } from '@progress/kendo-svg-icons'; import { Keys, isChanged } from '@progress/kendo-angular-common'; import { animate, state, style, transition, trigger } from '@angular/animations'; import { TimelineService } from './timeline.service'; import { TimelineCardHeaderTemplateDirective } from './templates/timeline-card-header.directive'; import { TimelineCardBodyTemplateDirective } from './templates/timeline-card-body.directive'; import { TimelineCardActionsTemplateDirective } from './templates/timeline-card-actions.directive'; import { CardActionsComponent } from '../card/card-actions.component'; import { CardMediaDirective } from '../card/directives/card-media.directive'; import { CardBodyComponent } from '../card/card-body.component'; import { CardSubtitleDirective } from '../card/directives/card-subtitle.directive'; import { ButtonComponent } from '@progress/kendo-angular-buttons'; import { CardTitleDirective } from '../card/directives/card-title.directive'; import { CardHeaderComponent } from '../card/card-header.component'; import { NgStyle, NgClass, NgIf, NgTemplateOutlet, NgFor } from '@angular/common'; import { CardComponent } from '../card/card.component'; import * as i0 from "@angular/core"; import * as i1 from "./timeline.service"; /** * @hidden */ export class TimelineCardComponent { element; timelineService; renderer; event; expanded = false; collapsible = true; reversed = false; orientation; navigable; tabIndex; animationDuration; index; eventWidth; eventHeight; headerTemplate; bodyTemplate; actionsTemplate; set calloutStyle(value) { // applies only to horizontal orientation where the callout points upwards if (!this.calloutElementRef || !this.calloutElementRef.nativeElement.classList.contains('k-callout-n')) { return; } this.calloutElementRef.nativeElement.style.left = value?.left; } calloutElementRef; hostClass = true; get collapsedClass() { return !this.expanded && !this.animationInProgress && this.animationState === 'collapsed'; } onComponentKeyDown(event) { if (!this.navigable) { return; } if (event.keyCode === Keys.Space || event.keyCode === Keys.Enter) { event.preventDefault(); if (this.collapsible && this.orientation === 'vertical') { this.expanded = !this.expanded; } } } get role() { return this.orientation === 'vertical' ? 'button' : 'tabpanel'; } get ariaLive() { return this.orientation === 'vertical' ? 'polite' : null; } get ariaExpanded() { return this.orientation === 'vertical' ? this.expanded : null; } calloutSvgIcon = chevronRightIcon; calloutFontIcon = 'arrow-chevron-right'; animationState = this.expanded ? 'expanded' : 'collapsed'; animationInProgress = false; constructor(element, timelineService, renderer) { this.element = element; this.timelineService = timelineService; this.renderer = renderer; } ngAfterViewInit() { this.makeOverflowVisible(); } ngOnChanges(changes) { if (isChanged('collapsible', changes, false)) { if (!this.collapsible) { this.expanded = true; } } } toggle() { if (this.orientation === 'vertical') { this.expanded = this.collapsible ? !this.expanded : true; this.timelineService.onToggle(this.index); } } expand() { if (!this.expanded) { this.expanded = true; this.timelineService.onToggle(this.index); } } collapse() { if (!this.collapsible || !this.expanded) { return; } this.expanded = false; this.timelineService.onToggle(this.index); } onActionClick(event) { event.stopPropagation(); this.timelineService.onActionClick(this.index); } animationStart() { this.animationInProgress = true; } animationDone(event) { this.animationInProgress = false; if (event.toState === 'expanded' && event.fromState !== 'expanded') { this.animationState = 'expanded'; this.makeOverflowVisible(); } else if (event.toState === 'collapsed' && event.fromState !== 'collapsed') { this.animationState = 'collapsed'; } } makeOverflowVisible() { if (this.orientation === 'vertical') { return; } const cardBody = this.element?.nativeElement.querySelector('.k-card-body'); if (cardBody) { this.renderer.setStyle(cardBody, 'overflow', 'auto'); } } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TimelineCardComponent, deps: [{ token: i0.ElementRef }, { token: i1.TimelineService }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: TimelineCardComponent, isStandalone: true, selector: "kendo-timeline-card", inputs: { event: "event", expanded: "expanded", collapsible: "collapsible", reversed: "reversed", orientation: "orientation", navigable: "navigable", tabIndex: "tabIndex", animationDuration: "animationDuration", index: "index", eventWidth: "eventWidth", eventHeight: "eventHeight", headerTemplate: "headerTemplate", bodyTemplate: "bodyTemplate", actionsTemplate: "actionsTemplate", calloutStyle: "calloutStyle" }, host: { listeners: { "keydown": "onComponentKeyDown($event)" }, properties: { "class.k-timeline-card": "this.hostClass", "class.k-collapsed": "this.collapsedClass" } }, providers: [], viewQueries: [{ propertyName: "calloutElementRef", first: true, predicate: ["callout"], descendants: true }], exportAs: ["kendoTimelineCard"], usesOnChanges: true, ngImport: i0, template: ` <kendo-card [ngStyle]="{ 'height': orientation === 'horizontal' ? eventHeight + 'px' : null }" [width]="orientation === 'horizontal' ? 'auto' : eventWidth + 'px'" class="k-card-with-callout k-card-vertical" (click)="toggle()" [attr.role]="role" [attr.aria-live]="ariaLive" [attr.aria-expanded]="ariaExpanded" [attr.tabindex]="tabIndex" > <span #callout class="k-timeline-card-callout k-card-callout" [ngClass]="{ 'k-callout-n': orientation === 'horizontal', 'k-callout-w': orientation === 'vertical' && !this.reversed, 'k-callout-e': orientation === 'vertical' && this.reversed }" > </span> <div *ngIf="event" class="k-card-inner"> <kendo-card-header> <ng-template *ngIf="headerTemplate" [ngTemplateOutlet]="headerTemplate?.templateRef" [ngTemplateOutletContext]="{ $implicit: event, index: index}"> > </ng-template> <div kendoCardTitle *ngIf="!headerTemplate"> <span class="k-event-title">{{ event.title }}</span> <button kendoButton *ngIf="collapsible && orientation === 'vertical'" [icon]="calloutFontIcon" [svgIcon]="calloutSvgIcon" class="k-event-collapse" fillMode="flat" [attr.aria-hidden]="true" tabindex="-1" type="button" ></button> </div> <div kendoCardSubtitle *ngIf="!headerTemplate">{{ event.subtitle }}</div> </kendo-card-header> <kendo-card-body *ngIf="event.description || event.images" [@toggle]="{value: expanded ? 'expanded' : 'collapsed', params: {animationDuration: this.animationDuration || 0}}" (@toggle.start)="animationStart()" (@toggle.done)="animationDone($event)" > <ng-template *ngIf="bodyTemplate" [ngTemplateOutlet]="bodyTemplate?.templateRef" [ngTemplateOutletContext]="{ $implicit: event, index: index}"> > </ng-template> <div *ngIf="!bodyTemplate" class="k-card-description"> <p *ngIf="event.description">{{ event.description }}</p> <ng-container *ngFor="let image of event.images"> <img *ngIf="image.alt" kendoCardMedia [src]="image.src" [alt]="image.alt" /> <img *ngIf="!image.alt" kendoCardMedia [src]="image.src" /> </ng-container> </div> </kendo-card-body> <kendo-card-actions *ngIf="event.actions" [@toggle]="{value: expanded ? 'expanded' : 'collapsed', params: {animationDuration: this.animationDuration || 0}}" > <ng-template *ngIf="actionsTemplate" [ngTemplateOutlet]="actionsTemplate?.templateRef" [ngTemplateOutletContext]="{ $implicit: event, index: index}"> > </ng-template> <ng-container *ngIf="!actionsTemplate"> <a *ngFor="let action of event.actions" [href]="action.url" [target]="action.target === 'blank' ? '_blank' : '_self'" (click)="onActionClick($event)" class="k-button k-button-md k-rounded-md k-button-flat k-button-flat-primary" role="button" > {{ action.text }} </a> </ng-container> </kendo-card-actions> </div> </kendo-card> `, isInline: true, dependencies: [{ kind: "component", type: CardComponent, selector: "kendo-card", inputs: ["orientation", "width"] }, { 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: CardHeaderComponent, selector: "kendo-card-header" }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: CardTitleDirective, selector: "[kendoCardTitle]" }, { 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: CardSubtitleDirective, selector: "[kendoCardSubtitle]" }, { kind: "component", type: CardBodyComponent, selector: "kendo-card-body" }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: CardMediaDirective, selector: "[kendoCardMedia]" }, { kind: "component", type: CardActionsComponent, selector: "kendo-card-actions", inputs: ["orientation", "layout", "actions"], outputs: ["action"] }], animations: [ trigger('toggle', [ state('collapsed', style({ height: '0', 'overflow-y': 'hidden', display: 'none' })), state('expanded', style({ height: '*', 'overflow-y': 'hidden', display: 'block' })), transition('collapsed <=> expanded', [ animate('{{animationDuration}}ms') ], { params: { animationDuration: '400' } }), ]) ] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TimelineCardComponent, decorators: [{ type: Component, args: [{ animations: [ trigger('toggle', [ state('collapsed', style({ height: '0', 'overflow-y': 'hidden', display: 'none' })), state('expanded', style({ height: '*', 'overflow-y': 'hidden', display: 'block' })), transition('collapsed <=> expanded', [ animate('{{animationDuration}}ms') ], { params: { animationDuration: '400' } }), ]) ], providers: [], exportAs: 'kendoTimelineCard', selector: 'kendo-timeline-card', template: ` <kendo-card [ngStyle]="{ 'height': orientation === 'horizontal' ? eventHeight + 'px' : null }" [width]="orientation === 'horizontal' ? 'auto' : eventWidth + 'px'" class="k-card-with-callout k-card-vertical" (click)="toggle()" [attr.role]="role" [attr.aria-live]="ariaLive" [attr.aria-expanded]="ariaExpanded" [attr.tabindex]="tabIndex" > <span #callout class="k-timeline-card-callout k-card-callout" [ngClass]="{ 'k-callout-n': orientation === 'horizontal', 'k-callout-w': orientation === 'vertical' && !this.reversed, 'k-callout-e': orientation === 'vertical' && this.reversed }" > </span> <div *ngIf="event" class="k-card-inner"> <kendo-card-header> <ng-template *ngIf="headerTemplate" [ngTemplateOutlet]="headerTemplate?.templateRef" [ngTemplateOutletContext]="{ $implicit: event, index: index}"> > </ng-template> <div kendoCardTitle *ngIf="!headerTemplate"> <span class="k-event-title">{{ event.title }}</span> <button kendoButton *ngIf="collapsible && orientation === 'vertical'" [icon]="calloutFontIcon" [svgIcon]="calloutSvgIcon" class="k-event-collapse" fillMode="flat" [attr.aria-hidden]="true" tabindex="-1" type="button" ></button> </div> <div kendoCardSubtitle *ngIf="!headerTemplate">{{ event.subtitle }}</div> </kendo-card-header> <kendo-card-body *ngIf="event.description || event.images" [@toggle]="{value: expanded ? 'expanded' : 'collapsed', params: {animationDuration: this.animationDuration || 0}}" (@toggle.start)="animationStart()" (@toggle.done)="animationDone($event)" > <ng-template *ngIf="bodyTemplate" [ngTemplateOutlet]="bodyTemplate?.templateRef" [ngTemplateOutletContext]="{ $implicit: event, index: index}"> > </ng-template> <div *ngIf="!bodyTemplate" class="k-card-description"> <p *ngIf="event.description">{{ event.description }}</p> <ng-container *ngFor="let image of event.images"> <img *ngIf="image.alt" kendoCardMedia [src]="image.src" [alt]="image.alt" /> <img *ngIf="!image.alt" kendoCardMedia [src]="image.src" /> </ng-container> </div> </kendo-card-body> <kendo-card-actions *ngIf="event.actions" [@toggle]="{value: expanded ? 'expanded' : 'collapsed', params: {animationDuration: this.animationDuration || 0}}" > <ng-template *ngIf="actionsTemplate" [ngTemplateOutlet]="actionsTemplate?.templateRef" [ngTemplateOutletContext]="{ $implicit: event, index: index}"> > </ng-template> <ng-container *ngIf="!actionsTemplate"> <a *ngFor="let action of event.actions" [href]="action.url" [target]="action.target === 'blank' ? '_blank' : '_self'" (click)="onActionClick($event)" class="k-button k-button-md k-rounded-md k-button-flat k-button-flat-primary" role="button" > {{ action.text }} </a> </ng-container> </kendo-card-actions> </div> </kendo-card> `, standalone: true, imports: [CardComponent, NgStyle, NgClass, NgIf, CardHeaderComponent, NgTemplateOutlet, CardTitleDirective, ButtonComponent, CardSubtitleDirective, CardBodyComponent, NgFor, CardMediaDirective, CardActionsComponent] }] }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i1.TimelineService }, { type: i0.Renderer2 }]; }, propDecorators: { event: [{ type: Input }], expanded: [{ type: Input }], collapsible: [{ type: Input }], reversed: [{ type: Input }], orientation: [{ type: Input }], navigable: [{ type: Input }], tabIndex: [{ type: Input }], animationDuration: [{ type: Input }], index: [{ type: Input }], eventWidth: [{ type: Input }], eventHeight: [{ type: Input }], headerTemplate: [{ type: Input }], bodyTemplate: [{ type: Input }], actionsTemplate: [{ type: Input }], calloutStyle: [{ type: Input }], calloutElementRef: [{ type: ViewChild, args: ['callout'] }], hostClass: [{ type: HostBinding, args: ['class.k-timeline-card'] }], collapsedClass: [{ type: HostBinding, args: ['class.k-collapsed'] }], onComponentKeyDown: [{ type: HostListener, args: ['keydown', ['$event']] }] } });