UNPKG

@progress/kendo-angular-gantt

Version:
84 lines (83 loc) 4.03 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 { Subscription, Subject, fromEvent } from 'rxjs'; import { distinctUntilChanged, map, take } from 'rxjs/operators'; import * as i0 from "@angular/core"; /** * @hidden */ export class ScrollSyncService { ngZone; changes = new Subject(); elements = []; subscriptions = new Subscription(); syncingTimeline; syncingTreeList; constructor(ngZone) { this.ngZone = ngZone; this.subscriptions.add(this.changes.subscribe(args => { this.scroll(args); })); } registerElement(el, sourceType) { this.elements.push({ element: el, sourceType }); if (sourceType === "timeline" || sourceType === "treelist") { this.ngZone.runOutsideAngular(() => { const obs = fromEvent(el, 'scroll').pipe(map(({ target: { scrollTop, scrollLeft } }) => ({ scrollTop, scrollLeft, sourceType }))); const comparisonFn = sourceType === 'timeline' ? (x, y) => (x.scrollTop === y.scrollTop) && (x.scrollLeft === y.scrollLeft) : (x, y) => (x.scrollTop === y.scrollTop); this.subscriptions.add(obs.pipe(distinctUntilChanged(comparisonFn)) .subscribe((event) => this.changes.next(event))); }); } } ngOnDestroy() { this.subscriptions.unsubscribe(); this.elements = null; } syncScrollTop(sourceType, targetType) { const source = this.elements.find(element => element.sourceType === sourceType); const target = this.elements.find(element => element.sourceType === targetType); // Need to wait for the splitter pane's content to be rendered this.ngZone.onStable.pipe(take(1)).subscribe(() => target.element.scrollTop = source.element.scrollTop); } resetTimelineScrollLeft() { const source = this.elements.find(element => element.sourceType === 'timeline'); source.element.scrollLeft = 0; } scroll({ scrollTop, scrollLeft, sourceType }) { this.ngZone.runOutsideAngular(() => { if (sourceType === 'timeline') { const header = this.elements.find(element => element.sourceType === 'header').element; header.scrollLeft = scrollLeft; if (!this.syncingTimeline) { this.syncingTreeList = true; const treelist = this.elements.find(element => element.sourceType === 'treelist').element; treelist.scrollTop = scrollTop; } this.syncingTimeline = false; } if (sourceType === 'treelist') { if (!this.syncingTreeList) { this.syncingTimeline = true; const timeline = this.elements.find(element => element.sourceType === 'timeline').element; timeline.scrollTop = scrollTop; } this.syncingTreeList = false; } }); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScrollSyncService, deps: [{ token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScrollSyncService }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScrollSyncService, decorators: [{ type: Injectable }], ctorParameters: () => [{ type: i0.NgZone }] });