UNPKG

@bimeister/pupakit.tree

Version:
695 lines (681 loc) 76 kB
import * as i0 from '@angular/core'; import { Component, ViewEncapsulation, ChangeDetectionStrategy, Input, Directive, ContentChild, NgModule, ViewChild, HostListener, Injectable } from '@angular/core'; import * as i4 from '@angular/cdk/tree'; import { CdkTreeModule, FlatTreeControl } from '@angular/cdk/tree'; import * as i1 from '@angular/common'; import { CommonModule } from '@angular/common'; import * as i1$1 from '@bimeister/pupakit.icons'; import { PupaIconsModule, appCircle, appChevronDownIcon, appChevronRightIcon, iosArrowDownIcon, iosArrowForwardIcon } from '@bimeister/pupakit.icons'; import * as i2 from '@bimeister/pupakit.kit'; import { PupaButtonsModule, PupaCheckboxModule, PupaSpinnerModule, PupaSkeletonModule, PupaScrollableModule } from '@bimeister/pupakit.kit'; import { BehaviorSubject, combineLatest, Subscription, Subject, NEVER, timer, interval, animationFrameScheduler } from 'rxjs'; import { isNil, shareReplayWithRefCount, getUuid, filterTruthy, filterNotNil, getClampedValue } from '@bimeister/utilities'; import * as i3 from '@angular/cdk/scrolling'; import { ScrollingModule } from '@angular/cdk/scrolling'; import { DataSource } from '@angular/cdk/collections'; import { EventBus } from '@bimeister/event-bus/rxjs'; import { filter, map, take, switchMap, mapTo, withLatestFrom, debounce, observeOn } from 'rxjs/operators'; import { BusEventBase, QueueEvents, EventsQueue } from '@bimeister/pupakit.common'; const TREE_NODE_OFFSET = 16; class TreeNodeSkeletonComponent { get offset() { return `${this.level * TREE_NODE_OFFSET}px`; } } TreeNodeSkeletonComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: TreeNodeSkeletonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); TreeNodeSkeletonComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.12", type: TreeNodeSkeletonComponent, selector: "pupa-tree-node-skeleton", inputs: { level: "level" }, ngImport: i0, template: "<div class=\"tree-node-skeleton\">\n <div [style.margin-left]=\"offset\" class=\"tree-node-skeleton__left\"></div>\n <div class=\"tree-node-skeleton__center\"></div>\n <div class=\"tree-node-skeleton__right\"></div>\n</div>\n", styles: [":host{display:block;width:100%}.tree-node-skeleton{display:flex;padding:1rem 2rem}.tree-node-skeleton__left,.tree-node-skeleton__center,.tree-node-skeleton__right{background-color:rgba(var(--color_neutral-4),var(--alpha-1000))}.tree-node-skeleton__left{min-width:6rem;height:6rem;border-radius:.5rem}.tree-node-skeleton__center{width:100%;height:6rem;margin:0 3rem;border-radius:1rem}.tree-node-skeleton__right{min-width:6rem;height:6rem;border-radius:1rem}:host-context(.dark-theme) .tree-node-skeleton__left,:host-context(.dark-theme) .tree-node-skeleton__center,:host-context(.dark-theme) .tree-node-skeleton__right{background-color:rgba(var(--color_neutral-400),var(--alpha-1000))}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: TreeNodeSkeletonComponent, decorators: [{ type: Component, args: [{ selector: 'pupa-tree-node-skeleton', encapsulation: ViewEncapsulation.Emulated, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"tree-node-skeleton\">\n <div [style.margin-left]=\"offset\" class=\"tree-node-skeleton__left\"></div>\n <div class=\"tree-node-skeleton__center\"></div>\n <div class=\"tree-node-skeleton__right\"></div>\n</div>\n", styles: [":host{display:block;width:100%}.tree-node-skeleton{display:flex;padding:1rem 2rem}.tree-node-skeleton__left,.tree-node-skeleton__center,.tree-node-skeleton__right{background-color:rgba(var(--color_neutral-4),var(--alpha-1000))}.tree-node-skeleton__left{min-width:6rem;height:6rem;border-radius:.5rem}.tree-node-skeleton__center{width:100%;height:6rem;margin:0 3rem;border-radius:1rem}.tree-node-skeleton__right{min-width:6rem;height:6rem;border-radius:1rem}:host-context(.dark-theme) .tree-node-skeleton__left,:host-context(.dark-theme) .tree-node-skeleton__center,:host-context(.dark-theme) .tree-node-skeleton__right{background-color:rgba(var(--color_neutral-400),var(--alpha-1000))}\n"] }] }], propDecorators: { level: [{ type: Input }] } }); class TreeNodeActionsDirective { constructor(templateRef) { this.templateRef = templateRef; this.isDisplayed$ = new BehaviorSubject(true); } ngOnChanges() { this.isDisplayed$.next(Boolean(this.pupaTreeNodeActions)); } } TreeNodeActionsDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: TreeNodeActionsDirective, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive }); TreeNodeActionsDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.2.12", type: TreeNodeActionsDirective, selector: "[pupaTreeNodeActions]", inputs: { pupaTreeNodeActions: "pupaTreeNodeActions" }, usesOnChanges: true, ngImport: i0 }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: TreeNodeActionsDirective, decorators: [{ type: Directive, args: [{ selector: '[pupaTreeNodeActions]', }] }], ctorParameters: function () { return [{ type: i0.TemplateRef }]; }, propDecorators: { pupaTreeNodeActions: [{ type: Input }] } }); class TreeNodeComponent { get arrowIcon() { if (this.treeNodeProperties.isExpanded) { return 'app-chevron-down'; } return 'app-chevron-right'; } get arrowOffset() { return `${this.treeNodeProperties.level * TREE_NODE_OFFSET}px`; } get isSelected() { return this.treeNodeProperties.isSelected || this.treeNodeProperties.isHighlighted; } expand(event) { event.stopPropagation(); if (isNil(this.treeNodeProperties.expand)) { return; } this.treeNodeProperties.expand(); } } TreeNodeComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: TreeNodeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); TreeNodeComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.12", type: TreeNodeComponent, selector: "pupa-tree-node", inputs: { treeNodeProperties: "treeNodeProperties" }, queries: [{ propertyName: "treeNodeActionsTemplate", first: true, predicate: TreeNodeActionsDirective, descendants: true }], ngImport: i0, template: "<div\n class=\"tree-node\"\n [class.tree-node--selected]=\"isSelected\"\n [class.tree-node--disabled]=\"treeNodeProperties.isDisabled\"\n [class.tree-node--expanded]=\"treeNodeProperties.isExpanded\"\n>\n <svg\n class=\"tree-node__selection\"\n width=\"2\"\n height=\"31\"\n viewBox=\"0 0 2 31\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path d=\"M2 31V0C0.4 0 0 2 0 3V28C0 30.4 1.33333 31 2 31Z\" fill=\"currentColor\" />\n </svg>\n <div class=\"tree-node__left\">\n <div [style.margin-left]=\"arrowOffset\" class=\"tree-node__arrow-container\">\n <ng-container *ngIf=\"treeNodeProperties.isDirectory\">\n <pupa-button-icon\n (click)=\"expand($event)\"\n *ngIf=\"treeNodeProperties.hasChildren\"\n [icon]=\"arrowIcon\"\n [disabled]=\"treeNodeProperties.isDisabled\"\n [loading]=\"treeNodeProperties.isLoading\"\n size=\"s\"\n kind=\"secondary\"\n ></pupa-button-icon>\n <pupa-icon\n *ngIf=\"!treeNodeProperties.hasChildren\"\n class=\"tree-node__without-children\"\n name=\"app-circle\"\n ></pupa-icon>\n </ng-container>\n </div>\n <div class=\"tree-node__text\">\n <ng-content></ng-content>\n </div>\n </div>\n <div class=\"tree-node__right\">\n <div\n *ngIf=\"treeNodeActionsTemplate?.isDisplayed$ | async\"\n (click)=\"$event.stopPropagation()\"\n class=\"tree-node__right-container\"\n >\n <ng-container [ngTemplateOutlet]=\"treeNodeActionsTemplate?.templateRef\"></ng-container>\n </div>\n </div>\n</div>\n", styles: [":host{display:block;height:8rem}.tree-node{display:flex;flex-direction:row;align-items:center;justify-content:normal;flex-wrap:nowrap;min-width:48.5rem;height:100%;background-color:rgba(var(--color_neutral-1),var(--alpha-1000));border-radius:1rem;cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none;-webkit-tap-highlight-color:transparent;pointer-events:auto;-webkit-user-select:none;user-select:none}.tree-node__selection{position:sticky;left:0;width:2px;min-width:2px;height:8rem;opacity:0}.tree-node__left{display:flex;flex-direction:row;align-items:center;justify-content:normal;flex-wrap:nowrap;overflow:hidden;padding:1rem 0 1rem 1.5rem;margin-right:-4rem}.tree-node__right{display:flex;flex-direction:row;align-items:normal;justify-content:normal;flex-wrap:nowrap;position:sticky;right:0;height:6rem;margin:1rem 0 1rem auto;padding-left:4rem;padding-right:2rem;background:linear-gradient(90deg,rgba(var(--color_neutral-1),var(--alpha-500)) -95%,rgba(var(--color_neutral-1),var(--alpha-1000)) 70%)}.tree-node__right-container{display:flex;flex-direction:row;align-items:center;justify-content:flex-end;flex-wrap:nowrap;position:relative;z-index:2;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content}.tree-node__arrow-container{display:flex;flex-direction:row;align-items:center;justify-content:center;flex-wrap:nowrap;min-width:9rem;height:6rem;padding-right:3rem;box-sizing:border-box}.tree-node__without-children{width:1rem;height:1rem;color:rgba(var(--color_neutral-60),var(--alpha-1000))}.tree-node__text{font-family:NotoSans,sans-serif;font-weight:400;font-size:11px;line-height:16px;color:rgba(var(--color_neutral-1000),var(--alpha-1000));white-space:nowrap;padding-right:4rem}@media (hover: hover){.tree-node:hover{background-color:rgba(var(--color_neutral-6),var(--alpha-1000))}.tree-node:hover .tree-node__right{background:linear-gradient(90deg,rgba(var(--color_neutral-6),var(--alpha-500)) -95%,rgba(var(--color_neutral-6),var(--alpha-1000)) 70%)}}.tree-node:active{background-color:rgba(var(--color_neutral-7),var(--alpha-1000))}.tree-node:active .tree-node__right{background:linear-gradient(90deg,rgba(var(--color_neutral-7),var(--alpha-500)) -95%,rgba(var(--color_neutral-7),var(--alpha-1000)) 70%)}.tree-node:focus{border:2px solid rgba(var(--color_primary-500),var(--alpha-1000))}.tree-node--dragover{border:1px solid rgba(var(--color_primary-500),var(--alpha-1000))}.tree-node--selected{background-color:rgba(var(--color_neutral-4),var(--alpha-1000))}.tree-node--selected .tree-node__selection{opacity:1;color:rgba(var(--color_primary-500),var(--alpha-1000))}.tree-node--selected .tree-node__right{background:linear-gradient(90deg,rgba(var(--color_neutral-4),var(--alpha-500)) -95%,rgba(var(--color_neutral-4),var(--alpha-1000)) 70%)}.tree-node--disabled.tree-node{cursor:not-allowed;background-color:rgba(var(--color_neutral-1),var(--alpha-1000))}.tree-node--disabled.tree-node .tree-node__right{background:linear-gradient(90deg,rgba(var(--color_neutral-1),var(--alpha-500)) -95%,rgba(var(--color_neutral-1),var(--alpha-1000)) 70%)}.tree-node--disabled.tree-node .tree-node__text{color:rgba(var(--color_neutral-60),var(--alpha-1000))}.tree-node--disabled.tree-node--selected{background-color:rgba(var(--color_neutral-4),var(--alpha-1000))}.tree-node--disabled.tree-node--selected .tree-node__selection{color:rgba(var(--color_primary-500),var(--alpha-1000));opacity:1}.tree-node--disabled.tree-node--selected .tree-node__right{background:linear-gradient(90deg,rgba(var(--color_neutral-4),var(--alpha-500)) -95%,rgba(var(--color_neutral-4),var(--alpha-1000)) 70%)}.tree-node--expanded .tree-node__text{font-family:NotoSans,sans-serif;font-weight:500;font-size:11px;line-height:16px}:host-context(.dark-theme) .tree-node{background-color:rgba(var(--color_neutral-1000),var(--alpha-1000))}:host-context(.dark-theme) .tree-node__right{background:linear-gradient(90deg,rgba(var(--color_neutral-1000),var(--alpha-500)) -95%,rgba(var(--color_neutral-1000),var(--alpha-1000)) 70%)}:host-context(.dark-theme) .tree-node__text{color:rgba(var(--color_neutral-1),var(--alpha-1000))}@media (hover: hover){:host-context(.dark-theme) .tree-node:hover{background-color:rgba(var(--color_neutral-600),var(--alpha-1000))}:host-context(.dark-theme) .tree-node:hover .tree-node__right{background:linear-gradient(90deg,rgba(var(--color_neutral-600),var(--alpha-500)) -95%,rgba(var(--color_neutral-600),var(--alpha-1000)) 70%)}}:host-context(.dark-theme) .tree-node:active{background-color:rgba(var(--color_neutral-700),var(--alpha-1000))}:host-context(.dark-theme) .tree-node:active .tree-node__right{background:linear-gradient(90deg,rgba(var(--color_neutral-700),var(--alpha-500)) -95%,rgba(var(--color_neutral-700),var(--alpha-1000)) 70%)}:host-context(.dark-theme) .tree-node--selected{background-color:rgba(var(--color_neutral-500),var(--alpha-1000))}:host-context(.dark-theme) .tree-node--selected .tree-node__selection{color:rgba(var(--color_primary-40),var(--alpha-1000))}:host-context(.dark-theme) .tree-node--selected .tree-node__right{background:linear-gradient(90deg,rgba(var(--color_neutral-500),var(--alpha-500)) -95%,rgba(var(--color_neutral-500),var(--alpha-1000)) 70%)}:host-context(.dark-theme) .tree-node.tree-node--disabled{background-color:rgba(var(--color_neutral-1000),var(--alpha-1000))}:host-context(.dark-theme) .tree-node.tree-node--disabled .tree-node__right{background:linear-gradient(90deg,rgba(var(--color_neutral-1000),var(--alpha-500)) -95%,rgba(var(--color_neutral-1000),var(--alpha-1000)) 70%)}:host-context(.dark-theme) .tree-node.tree-node--disabled .tree-node__text{color:rgba(var(--color_neutral-60),var(--alpha-1000))}:host-context(.dark-theme) .tree-node.tree-node--disabled.tree-node--selected{background-color:rgba(var(--color_neutral-500),var(--alpha-1000))}:host-context(.dark-theme) .tree-node.tree-node--disabled.tree-node--selected .tree-node__right{background:linear-gradient(90deg,rgba(var(--color_neutral-500),var(--alpha-500)) -95%,rgba(var(--color_neutral-500),var(--alpha-1000)) 70%)}:host-context(.dark-theme) .tree-node.tree-node--disabled.tree-node--selected .tree-node__text{color:rgba(var(--color_neutral-60),var(--alpha-1000))}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i2.ButtonIconComponent, selector: "pupa-button-icon", inputs: ["size", "kind", "type", "disabled", "icon", "loading", "active", "tabIndex"] }, { kind: "component", type: i1$1.IconComponent, selector: "pupa-icon", inputs: ["name"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: TreeNodeComponent, decorators: [{ type: Component, args: [{ selector: 'pupa-tree-node', encapsulation: ViewEncapsulation.Emulated, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n class=\"tree-node\"\n [class.tree-node--selected]=\"isSelected\"\n [class.tree-node--disabled]=\"treeNodeProperties.isDisabled\"\n [class.tree-node--expanded]=\"treeNodeProperties.isExpanded\"\n>\n <svg\n class=\"tree-node__selection\"\n width=\"2\"\n height=\"31\"\n viewBox=\"0 0 2 31\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path d=\"M2 31V0C0.4 0 0 2 0 3V28C0 30.4 1.33333 31 2 31Z\" fill=\"currentColor\" />\n </svg>\n <div class=\"tree-node__left\">\n <div [style.margin-left]=\"arrowOffset\" class=\"tree-node__arrow-container\">\n <ng-container *ngIf=\"treeNodeProperties.isDirectory\">\n <pupa-button-icon\n (click)=\"expand($event)\"\n *ngIf=\"treeNodeProperties.hasChildren\"\n [icon]=\"arrowIcon\"\n [disabled]=\"treeNodeProperties.isDisabled\"\n [loading]=\"treeNodeProperties.isLoading\"\n size=\"s\"\n kind=\"secondary\"\n ></pupa-button-icon>\n <pupa-icon\n *ngIf=\"!treeNodeProperties.hasChildren\"\n class=\"tree-node__without-children\"\n name=\"app-circle\"\n ></pupa-icon>\n </ng-container>\n </div>\n <div class=\"tree-node__text\">\n <ng-content></ng-content>\n </div>\n </div>\n <div class=\"tree-node__right\">\n <div\n *ngIf=\"treeNodeActionsTemplate?.isDisplayed$ | async\"\n (click)=\"$event.stopPropagation()\"\n class=\"tree-node__right-container\"\n >\n <ng-container [ngTemplateOutlet]=\"treeNodeActionsTemplate?.templateRef\"></ng-container>\n </div>\n </div>\n</div>\n", styles: [":host{display:block;height:8rem}.tree-node{display:flex;flex-direction:row;align-items:center;justify-content:normal;flex-wrap:nowrap;min-width:48.5rem;height:100%;background-color:rgba(var(--color_neutral-1),var(--alpha-1000));border-radius:1rem;cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none;-webkit-tap-highlight-color:transparent;pointer-events:auto;-webkit-user-select:none;user-select:none}.tree-node__selection{position:sticky;left:0;width:2px;min-width:2px;height:8rem;opacity:0}.tree-node__left{display:flex;flex-direction:row;align-items:center;justify-content:normal;flex-wrap:nowrap;overflow:hidden;padding:1rem 0 1rem 1.5rem;margin-right:-4rem}.tree-node__right{display:flex;flex-direction:row;align-items:normal;justify-content:normal;flex-wrap:nowrap;position:sticky;right:0;height:6rem;margin:1rem 0 1rem auto;padding-left:4rem;padding-right:2rem;background:linear-gradient(90deg,rgba(var(--color_neutral-1),var(--alpha-500)) -95%,rgba(var(--color_neutral-1),var(--alpha-1000)) 70%)}.tree-node__right-container{display:flex;flex-direction:row;align-items:center;justify-content:flex-end;flex-wrap:nowrap;position:relative;z-index:2;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content}.tree-node__arrow-container{display:flex;flex-direction:row;align-items:center;justify-content:center;flex-wrap:nowrap;min-width:9rem;height:6rem;padding-right:3rem;box-sizing:border-box}.tree-node__without-children{width:1rem;height:1rem;color:rgba(var(--color_neutral-60),var(--alpha-1000))}.tree-node__text{font-family:NotoSans,sans-serif;font-weight:400;font-size:11px;line-height:16px;color:rgba(var(--color_neutral-1000),var(--alpha-1000));white-space:nowrap;padding-right:4rem}@media (hover: hover){.tree-node:hover{background-color:rgba(var(--color_neutral-6),var(--alpha-1000))}.tree-node:hover .tree-node__right{background:linear-gradient(90deg,rgba(var(--color_neutral-6),var(--alpha-500)) -95%,rgba(var(--color_neutral-6),var(--alpha-1000)) 70%)}}.tree-node:active{background-color:rgba(var(--color_neutral-7),var(--alpha-1000))}.tree-node:active .tree-node__right{background:linear-gradient(90deg,rgba(var(--color_neutral-7),var(--alpha-500)) -95%,rgba(var(--color_neutral-7),var(--alpha-1000)) 70%)}.tree-node:focus{border:2px solid rgba(var(--color_primary-500),var(--alpha-1000))}.tree-node--dragover{border:1px solid rgba(var(--color_primary-500),var(--alpha-1000))}.tree-node--selected{background-color:rgba(var(--color_neutral-4),var(--alpha-1000))}.tree-node--selected .tree-node__selection{opacity:1;color:rgba(var(--color_primary-500),var(--alpha-1000))}.tree-node--selected .tree-node__right{background:linear-gradient(90deg,rgba(var(--color_neutral-4),var(--alpha-500)) -95%,rgba(var(--color_neutral-4),var(--alpha-1000)) 70%)}.tree-node--disabled.tree-node{cursor:not-allowed;background-color:rgba(var(--color_neutral-1),var(--alpha-1000))}.tree-node--disabled.tree-node .tree-node__right{background:linear-gradient(90deg,rgba(var(--color_neutral-1),var(--alpha-500)) -95%,rgba(var(--color_neutral-1),var(--alpha-1000)) 70%)}.tree-node--disabled.tree-node .tree-node__text{color:rgba(var(--color_neutral-60),var(--alpha-1000))}.tree-node--disabled.tree-node--selected{background-color:rgba(var(--color_neutral-4),var(--alpha-1000))}.tree-node--disabled.tree-node--selected .tree-node__selection{color:rgba(var(--color_primary-500),var(--alpha-1000));opacity:1}.tree-node--disabled.tree-node--selected .tree-node__right{background:linear-gradient(90deg,rgba(var(--color_neutral-4),var(--alpha-500)) -95%,rgba(var(--color_neutral-4),var(--alpha-1000)) 70%)}.tree-node--expanded .tree-node__text{font-family:NotoSans,sans-serif;font-weight:500;font-size:11px;line-height:16px}:host-context(.dark-theme) .tree-node{background-color:rgba(var(--color_neutral-1000),var(--alpha-1000))}:host-context(.dark-theme) .tree-node__right{background:linear-gradient(90deg,rgba(var(--color_neutral-1000),var(--alpha-500)) -95%,rgba(var(--color_neutral-1000),var(--alpha-1000)) 70%)}:host-context(.dark-theme) .tree-node__text{color:rgba(var(--color_neutral-1),var(--alpha-1000))}@media (hover: hover){:host-context(.dark-theme) .tree-node:hover{background-color:rgba(var(--color_neutral-600),var(--alpha-1000))}:host-context(.dark-theme) .tree-node:hover .tree-node__right{background:linear-gradient(90deg,rgba(var(--color_neutral-600),var(--alpha-500)) -95%,rgba(var(--color_neutral-600),var(--alpha-1000)) 70%)}}:host-context(.dark-theme) .tree-node:active{background-color:rgba(var(--color_neutral-700),var(--alpha-1000))}:host-context(.dark-theme) .tree-node:active .tree-node__right{background:linear-gradient(90deg,rgba(var(--color_neutral-700),var(--alpha-500)) -95%,rgba(var(--color_neutral-700),var(--alpha-1000)) 70%)}:host-context(.dark-theme) .tree-node--selected{background-color:rgba(var(--color_neutral-500),var(--alpha-1000))}:host-context(.dark-theme) .tree-node--selected .tree-node__selection{color:rgba(var(--color_primary-40),var(--alpha-1000))}:host-context(.dark-theme) .tree-node--selected .tree-node__right{background:linear-gradient(90deg,rgba(var(--color_neutral-500),var(--alpha-500)) -95%,rgba(var(--color_neutral-500),var(--alpha-1000)) 70%)}:host-context(.dark-theme) .tree-node.tree-node--disabled{background-color:rgba(var(--color_neutral-1000),var(--alpha-1000))}:host-context(.dark-theme) .tree-node.tree-node--disabled .tree-node__right{background:linear-gradient(90deg,rgba(var(--color_neutral-1000),var(--alpha-500)) -95%,rgba(var(--color_neutral-1000),var(--alpha-1000)) 70%)}:host-context(.dark-theme) .tree-node.tree-node--disabled .tree-node__text{color:rgba(var(--color_neutral-60),var(--alpha-1000))}:host-context(.dark-theme) .tree-node.tree-node--disabled.tree-node--selected{background-color:rgba(var(--color_neutral-500),var(--alpha-1000))}:host-context(.dark-theme) .tree-node.tree-node--disabled.tree-node--selected .tree-node__right{background:linear-gradient(90deg,rgba(var(--color_neutral-500),var(--alpha-500)) -95%,rgba(var(--color_neutral-500),var(--alpha-1000)) 70%)}:host-context(.dark-theme) .tree-node.tree-node--disabled.tree-node--selected .tree-node__text{color:rgba(var(--color_neutral-60),var(--alpha-1000))}\n"] }] }], propDecorators: { treeNodeProperties: [{ type: Input }], treeNodeActionsTemplate: [{ type: ContentChild, args: [TreeNodeActionsDirective] }] } }); class PupaTreeLayoutModule { } PupaTreeLayoutModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: PupaTreeLayoutModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); PupaTreeLayoutModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.2.12", ngImport: i0, type: PupaTreeLayoutModule, declarations: [TreeNodeComponent, TreeNodeActionsDirective, TreeNodeSkeletonComponent], imports: [CdkTreeModule, CommonModule, PupaButtonsModule, i1$1.PupaIconsModule, PupaCheckboxModule, PupaSpinnerModule], exports: [TreeNodeActionsDirective, TreeNodeComponent, TreeNodeSkeletonComponent] }); PupaTreeLayoutModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: PupaTreeLayoutModule, imports: [CdkTreeModule, CommonModule, PupaButtonsModule, PupaIconsModule.forFeature([appCircle, appChevronDownIcon, appChevronRightIcon]), PupaCheckboxModule, PupaSpinnerModule] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: PupaTreeLayoutModule, decorators: [{ type: NgModule, args: [{ declarations: [TreeNodeComponent, TreeNodeActionsDirective, TreeNodeSkeletonComponent], imports: [ CdkTreeModule, CommonModule, PupaButtonsModule, PupaIconsModule.forFeature([appCircle, appChevronDownIcon, appChevronRightIcon]), PupaCheckboxModule, PupaSpinnerModule, ], exports: [TreeNodeActionsDirective, TreeNodeComponent, TreeNodeSkeletonComponent], }] }] }); class FlatTreeItem { constructor(isExpandable, name, level, id, originalData = null, isElement = false) { this.isExpandable = isExpandable; this.name = name; this.level = level; this.id = id; this.originalData = originalData; this.isElement = isElement; } } class TreeRangedDataSource extends DataSource { constructor(data$) { super(); this.data$ = data$; this.range$ = new BehaviorSubject(null); } setRange(range) { this.range$.next(range); } connect() { return combineLatest([this.data$, this.range$]).pipe(filter(([data, range]) => Array.isArray(data) && !isNil(range)), map(([data, range]) => { const { start, end } = range; return data.slice(start, end); }), shareReplayWithRefCount()); } disconnect() { return; } } var TreeEvents; (function (TreeEvents) { class TreeEventBase extends BusEventBase { constructor(payload = null, fromId = null) { super(); this.payload = payload; this.fromId = fromId; this.scope = null; this.id = getUuid(); this.type = null; } } TreeEvents.TreeEventBase = TreeEventBase; class Click extends TreeEventBase { } TreeEvents.Click = Click; class RemoveItem extends TreeEventBase { } TreeEvents.RemoveItem = RemoveItem; class UpdateItem extends TreeEventBase { } TreeEvents.UpdateItem = UpdateItem; class ScrollById extends TreeEventBase { } TreeEvents.ScrollById = ScrollById; class Drop extends TreeEventBase { } TreeEvents.Drop = Drop; class ScrollByIndex extends TreeEventBase { } TreeEvents.ScrollByIndex = ScrollByIndex; class ScrollViewport extends TreeEventBase { } TreeEvents.ScrollViewport = ScrollViewport; class SetData extends TreeEventBase { } TreeEvents.SetData = SetData; class SetLoading extends TreeEventBase { } TreeEvents.SetLoading = SetLoading; class SetSelected extends TreeEventBase { } TreeEvents.SetSelected = SetSelected; class Collapse extends TreeEventBase { } TreeEvents.Collapse = Collapse; class Expand extends TreeEventBase { } TreeEvents.Expand = Expand; class ExpandWhileDragging extends TreeEventBase { } TreeEvents.ExpandWhileDragging = ExpandWhileDragging; class RemoveChildren extends TreeEventBase { } TreeEvents.RemoveChildren = RemoveChildren; class SetExpanded extends TreeEventBase { } TreeEvents.SetExpanded = SetExpanded; class SetChildren extends TreeEventBase { } TreeEvents.SetChildren = SetChildren; })(TreeEvents || (TreeEvents = {})); const DEFAULT_TREE_ITEM_SIZE_PX = 32; class TreeDataDisplayCollection { constructor() { this.data$ = new BehaviorSubject([]); this.selectedIdsList$ = new BehaviorSubject([]); this.trackBy$ = new BehaviorSubject(TreeDataDisplayCollection.trackBy); this.scrollBehavior$ = new BehaviorSubject('smooth'); this.expandedIdsList$ = new BehaviorSubject([]); this.hasDragAndDrop$ = new BehaviorSubject(false); this.treeItemSizePx$ = new BehaviorSubject(DEFAULT_TREE_ITEM_SIZE_PX); this.isLoading$ = new BehaviorSubject(false); } setExpandedIdsList(value) { this.expandedIdsList$.next(value); } setIsLoading(value) { this.isLoading$.next(value); } setData(data) { this.data$.next(data); return this.data$.pipe(take(1)); } setSelectedIdsList(value) { this.selectedIdsList$.next(value); } } TreeDataDisplayCollection.trackBy = (index, dataItem) => { if (isNil(dataItem)) { return `${index}__null`; } return `${index}__${JSON.stringify(dataItem)}`; }; class DefaultTreeEventHandler { constructor(eventBus, dataDisplayCollection) { this.eventBus = eventBus; this.dataDisplayCollection = dataDisplayCollection; this.subscription = new Subscription(); this.reconnect(); } subscribeToEvents() { this.subscription.add(this.getSubscriptionToSetData()); this.subscription.add(this.getSubscriptionForUpdateItem()); this.subscription.add(this.getSubscriptionForRemoveItem()); this.subscription.add(this.getSubscriptionForScrollTo()); this.subscription.add(this.getSubscriptionForRemoveChildren()); this.subscription.add(this.getSubscriptionForSetChildren()); } getSubscriptionToSetData() { return this.getEvents(TreeEvents.SetData) .pipe(switchMap((event) => this.dataDisplayCollection.setData(event.payload).pipe(mapTo(event)))) .subscribe((event) => this.eventBus.dispatch(new QueueEvents.RemoveFromQueue(event.id))); } getSubscriptionForScrollTo() { return this.getEvents(TreeEvents.ScrollById) .pipe(withLatestFrom(this.dataDisplayCollection.data$)) .subscribe(([event, data]) => { const treeItem = DefaultTreeEventHandler.getTreeItem(event.payload, data); if (isNil(treeItem)) { return this.eventBus.dispatch(new QueueEvents.RemoveFromQueue(event.id)); } const index = data.indexOf(treeItem); this.eventBus.dispatch(new TreeEvents.ScrollByIndex(index)); this.eventBus.dispatch(new QueueEvents.RemoveFromQueue(event.id)); }); } getSubscriptionForRemoveItem() { return this.getEvents(TreeEvents.RemoveItem) .pipe(withLatestFrom(this.dataDisplayCollection.data$, this.dataDisplayCollection.expandedIdsList$)) .subscribe(([event, data, expandedIdsList]) => { this.removeItemWithChildren(event.payload, data, expandedIdsList); this.eventBus.dispatch(new QueueEvents.RemoveFromQueue(event.id)); }); } getSubscriptionForUpdateItem() { return this.getEvents(TreeEvents.UpdateItem) .pipe(withLatestFrom(this.dataDisplayCollection.data$)) .subscribe(([event, data]) => { this.updateItem(event.payload, data); this.eventBus.dispatch(new QueueEvents.RemoveFromQueue(event.id)); }); } updateItem(updatedItem, data) { const treeItemExists = DefaultTreeEventHandler.treeItemExists(updatedItem.id, data); if (!treeItemExists) { return; } const updatedData = data.map((treeItem) => { if (treeItem.id === updatedItem.id) { return new FlatTreeItem(treeItem.isExpandable, updatedItem.name, treeItem.level, treeItem.id, updatedItem.originalData, treeItem.isElement); } return treeItem; }); this.eventBus.dispatch(new TreeEvents.SetData(updatedData)); } removeItem(removeItemId, data) { const treeItemExists = DefaultTreeEventHandler.treeItemExists(removeItemId, data); if (!treeItemExists) { return; } const updatedData = data.filter((treeItem) => treeItem.id !== removeItemId); this.eventBus.dispatch(new TreeEvents.SetData(updatedData)); } reconnect() { this.disconnect(); this.subscribeToEvents(); } disconnect() { this.subscription.unsubscribe(); this.subscription = new Subscription(); } getEvents(eventType) { return this.eventBus .listen() .pipe(filter((event) => event instanceof eventType)); } getSubscriptionForSetChildren() { return this.getEvents(TreeEvents.SetChildren) .pipe(withLatestFrom(this.dataDisplayCollection.data$, this.dataDisplayCollection.expandedIdsList$)) .subscribe(([event, data, expandedIdsList]) => { this.setChildren(event.payload.treeItemId, event.payload.children, data, expandedIdsList); this.eventBus.dispatch(new QueueEvents.RemoveFromQueue(event.id)); }); } getSubscriptionForRemoveChildren() { return this.getEvents(TreeEvents.RemoveChildren) .pipe(withLatestFrom(this.dataDisplayCollection.data$, this.dataDisplayCollection.expandedIdsList$)) .subscribe(([event, data, expandedIdsList]) => { this.removeChildren(event.payload, data, expandedIdsList); this.eventBus.dispatch(new QueueEvents.RemoveFromQueue(event.id)); }); } setChildren(parentId, children, data, expandedIdsList) { if (isNil(parentId)) { const newData = children.map((treeItem) => ({ ...treeItem, level: 0 })); this.eventBus.dispatch(new TreeEvents.SetData(newData)); this.eventBus.dispatch(new TreeEvents.SetExpanded([])); return; } const parentIsExpanded = expandedIdsList.includes(parentId); if (parentIsExpanded) { return; } const parent = DefaultTreeEventHandler.getTreeItem(parentId, data); const isExpanded = expandedIdsList.includes(parentId); if (isNil(parent) || isExpanded) { return; } const childrenIdsSet = new Set(); const childrenWithLevel = children.map((childItem) => { childrenIdsSet.add(childItem.id); return { ...childItem, level: Number(parent.level) + 1, }; }); const parentIndex = data.indexOf(parent); const dataWithChildren = [ ...data.slice(0, parentIndex), parent, ...childrenWithLevel, ...data.slice(parentIndex + 1), ]; const noExpandedChildrenList = expandedIdsList.filter((expandedTreeItemId) => !childrenIdsSet.has(expandedTreeItemId)); const newExpandedList = [...noExpandedChildrenList, parent.id]; this.eventBus.dispatch(new TreeEvents.SetData(dataWithChildren)); this.eventBus.dispatch(new TreeEvents.SetExpanded(newExpandedList)); } removeItemWithChildren(removeItemId, data, expanded) { const treeItemExists = DefaultTreeEventHandler.treeItemExists(removeItemId, data); if (!treeItemExists) { this.eventBus.dispatch(new TreeEvents.SetData(data)); this.eventBus.dispatch(new TreeEvents.SetExpanded(expanded)); return; } const [dataWithoutChildren, expandedWithoutChildren] = this.getRemovedChildren(removeItemId, data, expanded); const dataWithoutRemovedItem = dataWithoutChildren.filter((treeItem) => treeItem.id !== removeItemId); this.eventBus.dispatch(new TreeEvents.SetData(dataWithoutRemovedItem)); this.eventBus.dispatch(new TreeEvents.SetExpanded(expandedWithoutChildren)); } removeChildren(parentId, data, expanded) { const [dataWithoutChildren, expandedWithoutChildren] = this.getRemovedChildren(parentId, data, expanded); this.eventBus.dispatch(new TreeEvents.SetData(dataWithoutChildren)); this.eventBus.dispatch(new TreeEvents.SetExpanded(expandedWithoutChildren)); } getRemovedChildren(parentId, data, expanded) { const parent = DefaultTreeEventHandler.getTreeItem(parentId, data); if (isNil(parent)) { return [data, expanded]; } const parentIndex = data.indexOf(parent); const dataBeforeParent = parentIndex === 0 ? [] : data.slice(0, parentIndex); const dataAfterParent = data.slice(parentIndex + 1); const nextNonChildIndex = dataAfterParent.findIndex((dataItem) => dataItem.level <= parent.level); const isLastParent = nextNonChildIndex === -1; const children = dataAfterParent.slice(0, nextNonChildIndex); const childrenIdsList = children.map((child) => child.id); const expandedWithoutChildren = expanded.filter((expandedItemId) => !childrenIdsList.includes(expandedItemId) && expandedItemId !== parentId); const dataAfterLastChild = isLastParent ? [] : dataAfterParent.slice(nextNonChildIndex); const dataWithoutChildren = [...dataBeforeParent, parent, ...dataAfterLastChild]; return [dataWithoutChildren, expandedWithoutChildren]; } static treeItemExists(treeItemId, data) { const treeItem = DefaultTreeEventHandler.getTreeItem(treeItemId, data); return !isNil(treeItem); } static getTreeItem(treeItemId, data) { return data.find((treeItem) => treeItem.id === treeItemId); } } class TreeController { constructor(options) { this.options = options; this.eventBus = new EventBus(); this.queue = new EventsQueue(this.eventBus); this.dataDisplayCollection = new TreeDataDisplayCollection(); this.handler = new DefaultTreeEventHandler(this.eventBus, this.dataDisplayCollection); this.setScrollBehavior(options?.scrollBehavior); this.setTrackBy(options?.trackBy); this.setHasDragAndDrop(options?.hasDragAndDrop); this.setTreeItemSizePx(options?.treeItemSizePx); } dispatchInQueue(event) { const queueEvent = new QueueEvents.AddToQueue(event); this.eventBus.dispatch(queueEvent); } getOptions() { return this.options; } setData(data) { this.dispatchInQueue(new TreeEvents.SetData(data)); } setSelected(...selectedIds) { this.dispatchInQueue(new TreeEvents.SetSelected(selectedIds)); } setLoading(isLoading) { this.eventBus.dispatch(new TreeEvents.SetLoading(isLoading)); } setHasDragAndDrop(hasDragAndDrop = false) { this.dataDisplayCollection.hasDragAndDrop$.next(hasDragAndDrop); } getEvents(eventType) { return this.queue.getEvents(eventType); } getDataDisplayCollectionRef() { return this.dataDisplayCollection; } expand(treeItemId) { this.eventBus.dispatch(new TreeEvents.Expand(treeItemId)); } setChildren(treeItemId, children) { this.dispatchInQueue(new TreeEvents.SetChildren({ treeItemId, children })); } removeChildren(treeItemId) { this.dispatchInQueue(new TreeEvents.RemoveChildren(treeItemId)); } removeTreeItem(treeItemId) { this.dispatchInQueue(new TreeEvents.RemoveItem(treeItemId)); } setTreeItem(treeItem) { this.dispatchInQueue(new TreeEvents.UpdateItem(treeItem)); } scrollTo(treeItemId) { this.dispatchInQueue(new TreeEvents.ScrollById(treeItemId)); } setScrollBehavior(scrollBehavior = 'smooth') { this.dataDisplayCollection.scrollBehavior$.next(scrollBehavior); } setTrackBy(trackBy = TreeDataDisplayCollection.trackBy) { this.dataDisplayCollection.trackBy$.next(trackBy); } setTreeItemSizePx(treeItemSizePx = DEFAULT_TREE_ITEM_SIZE_PX) { this.dataDisplayCollection.treeItemSizePx$.next(treeItemSizePx); } } class TreeItemTemplateDirective { constructor(templateRef) { this.templateRef = templateRef; } } TreeItemTemplateDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: TreeItemTemplateDirective, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive }); TreeItemTemplateDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.2.12", type: TreeItemTemplateDirective, selector: "[pupaTreeItemTemplate]", ngImport: i0 }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: TreeItemTemplateDirective, decorators: [{ type: Directive, args: [{ selector: '[pupaTreeItemTemplate]', }] }], ctorParameters: function () { return [{ type: i0.TemplateRef }]; } }); const EXPAND_WHILE_DRAGGING_DELAY = 1000; class TreeNewComponent { constructor(renderer, host, changeDetectorRef) { this.renderer = renderer; this.host = host; this.changeDetectorRef = changeDetectorRef; this.treeControl = new FlatTreeControl(TreeNewComponent.getLevel, TreeNewComponent.isExpandable); this.listRange$ = new BehaviorSubject(null); this.dragAndDropMeta$ = new BehaviorSubject(null); this.expandWithDelay$ = new Subject(); this.subscription = new Subscription(); } ngAfterViewInit() { this.subscription.add(this.getSubscriptionToSetLoading()); this.subscription.add(this.getSubscriptionToScrollToIndex()); this.subscription.add(this.getSubscriptionToSetExpanded()); this.subscription.add(this.getSubscriptionToSetSelected()); this.subscription.add(this.getSubscriptionForScrollWithDrag()); this.subscription.add(this.getSubscriptionForRangeChanges()); this.subscription.add(this.getSubscriptionToExpandWhileDragging()); this.eventBus.dispatch(new QueueEvents.StartQueue()); } ngOnChanges(changes) { this.setupController(changes?.controller); } ngOnDestroy() { this.subscription.unsubscribe(); } isExpanded(expandedIdsList, treeItem) { return !isNil(treeItem) && treeItem.isExpandable && !treeItem.isElement && expandedIdsList.includes(treeItem.id); } hasChild(_, treeItem) { return !isNil(treeItem) && treeItem.isExpandable && !treeItem.isElement; } hasNoChild(_, treeItem) { return !isNil(treeItem) && !treeItem.isExpandable && !treeItem.isElement; } isElement(_, treeItem) { return !isNil(treeItem) && !treeItem.isExpandable && treeItem.isElement; } idsIncludesNodeId(idsList, treeItem) { return idsList.includes(treeItem.id); } mouseDown(dragTreeItem, event) { this.hasDragAndDrop$.pipe(take(1), filterTruthy()).subscribe(() => { const mouseDownPosition = { left: event?.screenX, top: event?.screenY }; const target = event.target; const draggableElementBoundingBox = target instanceof HTMLElement ? target.getBoundingClientRect() : null; const dragTreeItemWidth = draggableElementBoundingBox?.width; this.dragAndDropMeta$.next({ mouseDownPosition, dragTreeItem, dropTreeItem: dragTreeItem, draggableElementBoundingBox, dragTreeItemWidth, dragTreeItemIsDisplayed: false, }); }); } mouseEnter(treeItem) { this.dragAndDropMeta$.pipe(take(1), filterNotNil()).subscribe((dragAndDropMeta) => { this.dragAndDropMeta$.next({ ...dragAndDropMeta, dropTreeItem: treeItem }); this.expandWithDelay$.next(treeItem); }); } mouseLeave() { this.dragAndDropMeta$.pipe(take(1), filterNotNil()).subscribe((dragAndDropMeta) => { this.dragAndDropMeta$.next({ ...dragAndDropMeta, dropTreeItem: null }); }); } mouseMove(event) { this.dragAndDropMeta$.pipe(take(1), filterNotNil()).subscribe((dragAndDropMeta) => { this.processDragMoving(dragAndDropMeta, event.screenX, event.screenY); }); } mouseUp() { this.dragAndDropMeta$.pipe(take(1), filterNotNil()).subscribe((dragAndDropMeta) => { if (!dragAndDropMeta.dragTreeItemIsDisplayed) { return; } const dropEventData = { draggedElement: dragAndDropMeta.dragTreeItem, droppedElement: dragAndDropMeta.dropTreeItem, }; this.eventBus.dispatch(new TreeEvents.Drop(dropEventData)); }); this.expandWithDelay$.next(null); this.dragAndDropMeta$.next(null); } click(treeItem) { this.eventBus.dispatch(new TreeEvents.Click(treeItem)); } toggleExpansion(expandedIdsList, treeItem) { this.isExpanded(expandedIdsList, treeItem) ? this.collapseClick(treeItem) : this.expandClick(treeItem); } getTreeNodeProperties(node) { return combineLatest([this.expandedIdsList$, this.selectedIdsList$]).pipe(map(([expandedIdsList, selectedIdsList]) => ({ level: node.level, isDirectory: !node.isElement, hasChildren: node.isExpandable, isLoading: false, isExpanded: this.isExpanded(expandedIdsList, node), isSelected: this.idsIncludesNodeId(selectedIdsList, node), isHighlighted: this.idsIncludesNodeId(selectedIdsList, node), isDisabled: false, expand: () => { this.toggleExpansion(expandedIdsList, node); }, }))); } setupController(change) { const value = change?.currentValue; if (isNil(value)) { return; } this.controller = value; this.dataDisplayCollection = this.controller.getDataDisplayCollectionRef(); this.eventBus = this.controller.eventBus; this.scrollBehavior$ = this.dataDisplayCollection.scrollBehavior$; this.trackBy$ = this.dataDisplayCollection.trackBy$; this.treeItemSizePx$ = this.dataDisplayCollection.treeItemSizePx$; this.data$ = this.dataDisplayCollection.data$; this.isLoading$ = this.dataDisplayCollection.isLoading$; this.selectedIdsList$ = this.dataDisplayCollection.selectedIdsList$; this.expandedIdsList$ = this.dataDisplayCollection.expandedIdsList$; this.hasDragAndDrop$ = this.dataDisplayCollection.hasDragAndDrop$; this.dataSource = new TreeRangedDataSource(this.data$); } expandClick(treeItem) { this.controller.expand(treeItem.id); } collapseClick(treeItem) { this.eventBus.dispatch(new TreeEvents.Collapse(treeItem.id)); } getSubscriptionToExpandWhileDragging() { return this.expandWithDelay$ .pipe(debounce((node) => (isNil(node) ? NEVER : timer(EXPAND_WHILE_DRAGGING_DELAY))), filter((treeItem) => treeItem.isExpandable && !treeItem.isElement)) .subscribe((treeItem) => { this.eventBus.dispatch(new TreeEvents.ExpandWhileDragging(treeItem.id)); }); } getSubscriptionToSetLoading() { return this.getEvents(TreeEvents.SetLoading).subscribe((event) => { this.dataDisplayCollection.setIsLoading(event.payload); this.changeDetectorRef.detectChanges(); this.eventBus.dispatch(new QueueEvents.RemoveFromQueue(event.id)); }); } getSubscriptionToSetExpanded() { return this.getEvents(TreeEvents.SetExpanded).subscribe((event) => { this.setExpandedIdsList(event.payload); this.eventBus.dispatch(new QueueEvents.RemoveFromQueue(event.id)); }); } setExpandedIdsList(list) { this.dataDisplayCollection.setExpandedIdsList(list); this.data$ .pipe(take(1), map((data) => data.filter((treeItem) => list.includes(treeItem.id)))) .subscribe((data) => { data.forEach((treeItem) => this.treeControl.expand(treeItem)); }); this.changeDetectorRef.markForCheck(); } getSubscriptionToSetSelected() { return this.getEvents(TreeEvents.SetSelected).subscribe((event) => { this.setSelectedIdsList(event.payload); this.eventBus.dispatch(new QueueEvents.RemoveFromQueue(event.id)); }); } setSelectedIdsList(list) { this.dataDisplayCollection.setSelectedIdsList(list); this.changeDetectorRef.detectChanges(); } getSubscriptionToScrollToIndex() { return this.getEvents(TreeEvents.ScrollByIndex).subscribe((event) => { this.scrollToIndex(event.payload); this.eventBus.dispatch(new QueueEvents.RemoveFromQueue(event.id)); }); } scrollToIndex(index) { this.scrollBehavior$.pipe(take(1)).subscribe((scrollBehavior) => { this.viewPort.scrollToIndex(index, scrollBehavior); this.skeletonViewPort.scrollToIndex(index, scrollBehavior); }); } getSubscriptionForScrollWithDrag() { return interval(0) .pipe(observeOn(animationFrameScheduler), switchMap(() => this.dragAndDropMeta$.pipe(take(1))), filterNotNil(), map((dragAndDropMeta) => dragAndDropMeta.scrollDirection), filterNotNil(), withLatestFrom(this.scrollBehavior$)) .subscribe(([scrollDirection, scrollBehavior]) => { const scrollingSpeed = 5; const offsetDelta = scrollDirection === 'up' ? -scrollingSpeed : scrollingSpeed; const curren