import * as i4 from '@angular/common';
import { CommonModule } from '@angular/common';
import * as i0 from '@angular/core';
import { EventEmitter, Component, ChangeDetectionStrategy, ViewEncapsulation, Self, Optional, ContentChildren, Output, Input, ViewChild, HostBinding, ContentChild, NgModule } from '@angular/core';
import * as i2 from '@angular/forms';
import { FormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatCheckboxModule } from '@angular/material/checkbox';
import * as i7 from '@angular/material/icon';
import { MatIconModule } from '@angular/material/icon';
import * as i9 from '@angular/material/input';
import { MatInputModule } from '@angular/material/input';
import * as i3 from '@deja-js/component/core';
import { KeyCodes, DejaChildValidatorDirective, DejaChildValidatorModule, DejaTextMetricsModule } from '@deja-js/component/core';
import * as i1 from '@deja-js/component/core/item-list';
import { ItemListBase, ViewPortService, DejaItemComponent, DejaItemModule } from '@deja-js/component/core/item-list';
import * as i5 from '@deja-js/component/dragdrop';
import { DejaDragDropModule } from '@deja-js/component/dragdrop';
import * as i6 from '@deja-js/component/loaders';
import { DejaListLoaderModule } from '@deja-js/component/loaders';
import { coerceNumberProperty, coerceBooleanProperty } from '@angular/cdk/coercion';
import { Rect, Position } from '@deja-js/component/core/graphics';
import { Subject, BehaviorSubject, debounceTime, takeUntil, tap, fromEvent, switchMap, combineLatestWith, map, mergeWith, of, take, timer, filter } from 'rxjs';
import * as i8 from '@angular/material/form-field';

/*
 *  @license
 *  Copyright Hôpitaux Universitaires de Genève. All Rights Reserved.
 *
 *  Use of this source code is governed by an Apache-2.0 license that can be
 *  found in the LICENSE file at https://github.com/DSI-HUG/dejajs-components/blob/master/LICENSE
 */
/** Composant de liste évoluée avec gestion de viewport et templating */
class DejaTreeListComponent extends ItemListBase {
    constructor(changeDetectorRef, viewPort, elementRef, control, clipboardService) {
        super(changeDetectorRef, viewPort);
        this.viewPort = viewPort;
        this.elementRef = elementRef;
        this.control = control;
        this.clipboardService = clipboardService;
        /** Exécuté lorsque la scrollbar change de position. */
        // eslint-disable-next-line @angular-eslint/no-output-native
        this.scroll = new EventEmitter();
        /** Correspond au ngModel du champ de filtrage ou recherche */
        this.query = '';
        /** Largeur des éléments par defaut si différent de 100% */
        this.itemsWidth = null;
        /** Exécuté lorsque le déplacement d'une ligne est terminée. */
        this.itemDragEnd = new EventEmitter();
        /** Exécuté lorsque le déplacement d'une ligne commence. */
        this.itemDragStart = new EventEmitter();
        /** Exécuté lorsque l'utilisateur sélectionne ou désélectionne une ligne. */
        this.selectedChange = new EventEmitter();
        /** Exécuté lorsque le calcul du viewPort est executé. */
        this.viewPortChanged = new EventEmitter();
        this._disabled = null;
        this.setQuery$ = new Subject();
        this._keyboardNavigation = false;
        this.rangeStartIndex = 0;
        this.filterExpression = '';
        this._searchArea = false;
        this._sortable = false;
        this._itemsDraggable = false;
        this.hasCustomService = false;
        this.hasLoadingEvent = false;
        this._modelIsValue = false;
        this.keyboardNavigation$ = new Subject();
        this.clearFilterExpression$ = new BehaviorSubject(null);
        this.writeValue$ = new Subject();
        this.selectItems$ = new Subject();
        this.contentInitialized$ = new Subject();
        // NgModel implementation
        this.onTouchedCallback = () => undefined;
        this.onChangeCallback = (_a) => undefined;
        console.warn('@deja-js/component/deja-tree-list is deprecated, and will be removed in a further version. Please use @deja-js/component/v2/tree-list instead.');
        if (this.control) {
            this.control.valueAccessor = this;
        }
        this.clearFilterExpression$.pipe(debounceTime(400), takeUntil(this.destroyed$)).subscribe(() => this.filterExpression = '');
        this.keyboardNavigation$.pipe(tap(() => this._keyboardNavigation = true), debounceTime(1000), takeUntil(this.destroyed$)).subscribe(() => {
            this._keyboardNavigation = false;
            this.changeDetectorRef.markForCheck();
        });
        fromEvent(window, 'resize').pipe(debounceTime(5), takeUntil(this.destroyed$)).subscribe(() => {
            this.viewPort.deleteSizeCache();
            this.viewPort.refresh();
            this.changeDetectorRef.markForCheck();
        });
        this.setQuery$.pipe(debounceTime(250), switchMap(query => {
            this.query = query;
            this.setCurrentItem(undefined);
            return this.calcViewList$();
        }), takeUntil(this.destroyed$)).subscribe();
        const selectItems$ = this.selectItems$.pipe(combineLatestWith(this.contentInitialized$), map(([value]) => value), 
        // eslint-disable-next-line @typescript-eslint/no-unsafe-return
        map(value => this.getVirtualSelectedEntities(value)), 
        // eslint-disable-next-line @typescript-eslint/no-unsafe-return
        map(value => (value instanceof Array && value) || (value && [value]) || []), 
        // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
        tap(values => super.setSelectedItems(values)));
        const selectModels$ = this.writeValue$.pipe(combineLatestWith(this.contentInitialized$), map(([value]) => {
            if (this.modelIsValue === undefined) {
                if (value instanceof Array) {
                    const av = value || [];
                    const modelType = av.length && typeof av[0];
                    this.modelIsValue = modelType === 'string' || modelType === 'number';
                }
                else {
                    const modelType = typeof value;
                    this.modelIsValue = value === '' || modelType === 'string' || modelType === 'number';
                }
            }
            if (this.modelIsValue) {
                this.query = '';
            }
            return value;
        }), 
        // eslint-disable-next-line @typescript-eslint/no-unsafe-return
        map(value => this.getVirtualSelectedEntities(value)), tap(value => super.setSelectedModels(!value || this._multiSelect || value instanceof Array ? value : [value])));
        selectModels$.pipe(mergeWith(selectItems$), takeUntil(this.destroyed$)).subscribe(() => {
            super.getItemListService().ensureSelection();
            this.changeDetectorRef.markForCheck();
        });
        this._viewPortChanged = this.viewPortChanged;
        this.maxHeight = 0;
    }
    /** Définit la longueur minimale de caractères dans le champ de recherche avant que la recherche ou le filtrage soient effectués */
    // eslint-disable-next-line @angular-eslint/no-input-rename
    set minSearchlength(value) {
        this._minSearchLength = coerceNumberProperty(value);
    }
    get minSearchlength() {
        return this._minSearchLength;
    }
    set listElememtRef(elem) {
        this.listElement = elem.nativeElement;
    }
    keyboardNavigation() {
        return this._keyboardNavigation;
    }
    /** Affiche un barre de recherche au dessus de la liste. */
    set searchArea(value) {
        this._searchArea = coerceBooleanProperty(value);
    }
    get searchArea() {
        return this._searchArea || this.minSearchlength > 0;
    }
    /** Définit une valeur indiquant si en reactive form le model renvoyé doit être un obeject oue une valeur */
    set modelIsValue(value) {
        this._modelIsValue = coerceBooleanProperty(value);
    }
    get modelIsValue() {
        return this._modelIsValue;
    }
    /** Retourne ou définit une valeur indiquant si les lignes de la liste peuvent être déplacées manuelement par l'utilisateur */
    set sortable(value) {
        this._sortable = coerceBooleanProperty(value);
    }
    get sortable() {
        return this._sortable;
    }
    /** Retourne ou définit une valeur indiquant si les lignes peuvent être déplacées vers un autre composant */
    set itemsDraggable(value) {
        this._itemsDraggable = coerceBooleanProperty(value);
    }
    get itemsDraggable() {
        return this._itemsDraggable;
    }
    set pageSize(value) {
        this._pageSize = coerceNumberProperty(value);
    }
    /** Retourne le nombre de lignes à sauter en cas de pression sur les touches PageUp ou PageDown */
    get pageSize() {
        if (this._pageSize === 0) {
            const vpRowHeight = this.getViewPortRowHeight();
            const containerHeight = this.getMaxHeight() || this.listElement.clientHeight;
            return Math.floor(containerHeight / vpRowHeight);
        }
        return this._pageSize;
    }
    /** Définit un texte de conseil en cas d'erreur de validation ou autre */
    set hintLabel(value) {
        this.setHintLabel(value);
    }
    /** Retourne un texte de conseil en cas d'erreur de validation ou autre */
    get hintLabel() {
        return this._hintLabel;
    }
    /** Définit la hauteur d'une ligne pour le calcul du viewport en pixels (la valeur par défaut sera utilisée si aucune valeur n'est setté). */
    set viewPortRowHeight(value) {
        this.setViewPortRowHeight(value);
    }
    /**
     * Les valeurs acceptées en paramètre se trouvent dans l'enum ViewportMode (disabled, constant, variable ou auto)
     * Attention, une désactivation du viewport dégrade considérablement les performances de la liste et ne doit pas être activée si la liste
     * est suceptible de contenir beaucoup d'éléments.
     */
    set viewportMode(mode) {
        this.setViewportMode(mode);
    }
    /** Retourne le champ utilisé pour la liste des enfants d'un parent */
    set childrenField(value) {
        super.setChildrenField(value);
    }
    /** Définit le champ utilisé pour la liste des enfants d'un parent */
    get childrenField() {
        return this._childrenField;
    }
    /** Définit le champ à utiliser comme valeur d'affichage. */
    set textField(value) {
        super.setTextField(value);
    }
    /** Définit le champ à utiliser comme valeur de comparaison. */
    set valueField(value) {
        super.setValueField(value);
    }
    /** Définit le champ à utiliser comme champ de recherche.
     * Ce champ peut indiquer, un champ contenant une valeur, un texte indexé, ou une fonction.
     */
    set searchField(value) {
        super.setSearchField(value);
    }
    /** Retourne le champ à utiliser comme champ de recherche.
     * Ce champ peut indiquer, un champ contenant une valeur, un texte indexé, ou une fonction.
     */
    get searchField() {
        return this._searchField;
    }
    /** Définit la hauteur maximum avant que le composant affiche une scrollbar
     * spécifier une grande valeur pour ne jamais afficher de scrollbar
     * Spécifier 0 pour que le composant determine sa hauteur à partir du container
     */
    set maxHeight(value) {
        super.setMaxHeight(value);
    }
    /** Retourne la hauteur maximum avant que le composant affiche une scrollbar
     * spécifier une grande valeur pour ne jamais afficher de scrollbar
     * Spécifier 0 pour que le composant determine sa hauteur à partir du container
     */
    get maxHeight() {
        return this.getMaxHeight();
    }
    /** Définit la ligne courant ou ligne active */
    set currentItem(item) {
        super.setCurrentItem(item);
        if (item) {
            this.ensureItemVisible(item);
        }
    }
    /** Retourne la ligne courant ou ligne active */
    get currentItem() {
        return super.getCurrentItem();
    }
    /** Retourne le nombre de niveau pour une liste hierarchique */
    get depthMax() {
        return this._depthMax;
    }
    /** Définit une valeur indiquant si plusieurs lignes peuvent être sélectionées. */
    set multiSelect(value) {
        super.setMultiSelect(coerceBooleanProperty(value));
    }
    /** Retourne une valeur indiquant si plusieurs lignes peuvent être sélectionées. */
    get multiSelect() {
        return this._multiSelect;
    }
    /** Définit la liste des éléments selectionés en mode multiselect */
    set selectedItems(value) {
        if (value !== undefined) {
            this.selectItems$.next(value);
        }
    }
    /** Retourne la liste des éléments selectionés en mode multiselect */
    get selectedItems() {
        return super.getSelectedItems();
    }
    /** Définit l'élément selectioné en mode single select */
    set selectedItem(value) {
        if (value !== undefined) {
            this.selectItems$.next(value);
        }
    }
    /** Retourne l'éléments selectioné en mode single select */
    get selectedItem() {
        const selectedItem = super.getSelectedItems();
        return selectedItem?.[0];
    }
    /** Définit le model selectioné en mode single select */
    set selectedModel(value) {
        if (value !== undefined) {
            this.writeValue(value);
        }
    }
    /** Retourne le model selectioné en mode single select */
    get selectedModel() {
        const selectedModel = super.getSelectedModels();
        return selectedModel?.[0];
    }
    /** Définit la liste des models selectionés en mode multiselect */
    set selectedModels(value) {
        if (value !== undefined) {
            this.writeValue(value);
        }
    }
    /** Retourne la liste des models selectionés en mode multiselect */
    get selectedModels() {
        return super.getSelectedModels();
    }
    /** Definit le service de liste utilisé par ce composant. Ce srevice permet de controller dynamiquement la liste, ou de faire du lazyloading. */
    set itemListService(itemListService) {
        if (itemListService !== undefined) {
            this.hasCustomService = true;
            this.setItemListService(itemListService);
            if (itemListService?.lastQuery) {
                this.query = itemListService.lastQuery.toString();
            }
        }
    }
    /** Retourne le service de liste utilisé par ce composant. Ce srevice permet de controller dynamiquement la liste, ou de faire du lazyloading. */
    get itemListService() {
        return this.getItemListService();
    }
    /** Definit le service utilisé pour le tri de la liste */
    set sortingService(value) {
        this.setSortingService(value);
    }
    /** Definit le service utilisé pour le regroupement de la liste */
    set groupingService(value) {
        this.setGroupingService(value);
    }
    /** Définit la liste des éléments */
    // eslint-disable-next-line rxjs/finnish
    set items(items) {
        delete this.hintLabel;
        super.setItems$(items).pipe(switchMap(itms => {
            if (this.minSearchlength > 0 && !this.query) {
                // Waiting for query
                this._itemList = [];
                this.changeDetectorRef.markForCheck();
                return of(itms);
            }
            else {
                return this.calcViewList$().pipe(map(() => itms));
            }
        }), takeUntil(this.destroyed$)).subscribe();
    }
    /**
     * Set a observable called before the list will be displayed
     */
    set loadingItems(fn) {
        this.hasLoadingEvent = !!fn;
        super.setLoadingItems(fn);
    }
    /**
     * Set a promise or an observable called before an item selection
     */
    set selectingItem(fn) {
        super.setSelectingItem(fn);
    }
    /**
     * Set a promise or an observable called before an item deselection
     */
    set unselectingItem(fn) {
        super.setUnselectingItem(fn);
    }
    /**
     * Set a promise or an observable called before an item expand
     */
    set expandingItem(fn) {
        super.setExpandingItem(fn);
    }
    /**
     * Set a promise or an observable called before an item collapse
     */
    set collapsingItem(fn) {
        super.setCollapsingItem(fn);
    }
    /** Définit la liste des éléments (tout type d'objet métier) */
    // eslint-disable-next-line rxjs/finnish
    set models(items) {
        super.setModels$(items).pipe(take(1), switchMap(() => this.calcViewList$()), takeUntil(this.destroyed$)).subscribe();
    }
    /** Permet de désactiver la liste */
    set disabled(value) {
        const disabled = coerceBooleanProperty(value);
        this._disabled = disabled || null;
        this.changeDetectorRef.markForCheck();
    }
    get disabled() {
        return this._disabled;
    }
    /** Definit si le waiter doit être affiché dans la liste. */
    set waiter(value) {
        this._waiter = coerceBooleanProperty(value);
    }
    /** Retourne si le waiter doit être affiché dans la liste. */
    get waiter() {
        return this._waiter;
    }
    set inputValidatorDirective(value) {
        if (value) {
            value.parentControl = this.control;
        }
    }
    set currentItemIndex(value) {
        super.setCurrentItemIndex(value);
        this.changeDetectorRef.markForCheck();
    }
    get currentItemIndex() {
        return this.getCurrentItemIndex();
    }
    get itemTemplate() {
        return this.itemTemplateExternal || this.itemTemplateInternal;
    }
    get parentItemTemplate() {
        return this.parentItemTemplateExternal || this.parentItemTemplateInternal;
    }
    get loaderTemplate() {
        return this.loaderTemplateExternal || this.loaderTemplateInternal;
    }
    get headerTemplate() {
        return this.headerTemplateExternal || this.headerTemplateInternal;
    }
    get searchPrefixTemplate() {
        return this.searchPrefixTemplateExternal || this.searchPrefixTemplateInternal;
    }
    get searchSuffixTemplate() {
        return this.searchSuffixTemplateExternal || this.searchSuffixTemplateInternal;
    }
    // ************* ControlValueAccessor Implementation **************
    get value() {
        return this._multiSelect ? this.selectedItems : this.selectedItem;
    }
    set value(val) {
        this.writeValue(val);
        this.onChangeCallback(val);
        this.onTouchedCallback();
    }
    writeValue(value) {
        this.writeValue$.next(value);
    }
    registerOnChange(fn) {
        this.onChangeCallback = fn;
    }
    registerOnTouched(fn) {
        this.onTouchedCallback = fn;
    }
    setDisabledState(isDisabled) {
        this.disabled = isDisabled;
    }
    // ************* End of ControlValueAccessor Implementation **************
    /** Change l'état d'expansion de toute les lignes parentes */
    toggleAll$(collapsed) {
        return super.toggleAll$(collapsed).pipe(switchMap(items => this.calcViewList$().pipe(take(1), map(() => items))));
    }
    /** Change l'état d'expansion de toute les lignes parentes */
    toggleAll(collapsed) {
        this.toggleAll$(collapsed).pipe(take(1), takeUntil(this.destroyed$)).subscribe();
    }
    /** Positionne a scrollbar pour assurer que l'élément spécifié soit visible */
    ensureItemVisible(item) {
        super.ensureItemVisible(item);
    }
    /** Efface le contenu de la liste */
    clearViewPort() {
        super.clearViewPort();
    }
    ngAfterContentInit() {
        if (!this.items && this.options?.length) {
            const selectedModels = [];
            this.valueField = 'value';
            this.textField = 'text';
            const models = this.options.map(option => {
                const model = {
                    text: option.text,
                    value: option.value
                };
                if (option.selected) {
                    selectedModels.push(model);
                }
                return model;
            });
            this.models = models;
            if (selectedModels.length) {
                this.selectedModels = selectedModels;
            }
            if (models.length > 100) {
                // eslint-disable-next-line no-debugger
                debugger;
                console.error('Select options with more than 100 items can have performance options. Please bind directly the items in code behind with items or models input.');
            }
        }
        this.contentInitialized$.next(true);
    }
    ngAfterViewInit() {
        // FIXME Issue angular/issues/6005
        // see http://stackoverflow.com/questions/34364880/expression-has-changed-after-it-was-checked
        if (this._itemList.length === 0 && (this.hasCustomService || this.hasLoadingEvent)) {
            timer(1).pipe(take(1), switchMap(() => this.calcViewList$()), takeUntil(this.destroyed$)).subscribe();
        }
        fromEvent(this.listElement, 'scroll').pipe(map(event => {
            const target = event.target;
            const e = {
                originalEvent: event,
                scrollLeft: target.scrollLeft,
                scrollTop: target.scrollTop
            };
            this.scroll.emit(e);
            return target.scrollTop;
        }), takeUntil(this.destroyed$)).subscribe(scrollPos => this.viewPort.scrollPosition$.next(scrollPos));
        let keyDown$ = fromEvent(this.listElement, 'keydown');
        if (this.input) {
            const inputKeyDown$ = fromEvent(this.input.nativeElement, 'keydown');
            keyDown$ = keyDown$.pipe(mergeWith(inputKeyDown$));
        }
        keyDown$.pipe(filter(() => !this.disabled), filter(event => {
            const keyCode = event.code;
            return keyCode === KeyCodes.Home ||
                keyCode === KeyCodes.End ||
                keyCode === KeyCodes.PageUp ||
                keyCode === KeyCodes.PageDown ||
                keyCode === KeyCodes.UpArrow ||
                keyCode === KeyCodes.DownArrow ||
                keyCode === KeyCodes.Space ||
                keyCode === KeyCodes.Enter;
        }), switchMap(event => this.ensureListCaches$().pipe(switchMap(() => {
            if (!this.rowsCount) {
                return of(null);
            }
            // Set current item from index for keyboard features only
            const setCurrentIndex = (index) => {
                this.currentItemIndex = index;
                this.ensureItemVisible(this.currentItemIndex);
                this.viewPort.refresh();
            };
            const currentIndex = this.rangeStartIndex >= 0 ? this.rangeStartIndex : this.rangeStartIndex = this.currentItemIndex;
            let upindex;
            let dindex;
            let uaindex;
            let daindex;
            let target;
            let eitem;
            let sitem;
            switch (event.code) {
                case KeyCodes.Home:
                    setCurrentIndex(0);
                    if (event.shiftKey) {
                        return this.selectRange$(currentIndex, 0);
                    }
                    else if (!event.ctrlKey) {
                        this.rangeStartIndex = 0;
                        return this.selectRange$(this.rangeStartIndex);
                    }
                    else {
                        return of(-1);
                    }
                case KeyCodes.End:
                    setCurrentIndex(this.rowsCount - 1);
                    if (event.shiftKey) {
                        return this.selectRange$(currentIndex, this.rowsCount - 1);
                    }
                    else if (!event.ctrlKey) {
                        this.rangeStartIndex = this.rowsCount - 1;
                        return this.selectRange$(this.rangeStartIndex);
                    }
                    else {
                        return of(-1);
                    }
                case KeyCodes.PageUp:
                    upindex = Math.max(0, this.currentItemIndex - this._pageSize);
                    setCurrentIndex(upindex);
                    if (event.shiftKey) {
                        return this.selectRange$(currentIndex, upindex);
                    }
                    else if (!event.ctrlKey) {
                        this.rangeStartIndex = upindex;
                        return this.selectRange$(this.rangeStartIndex);
                    }
                    else {
                        return of(-1);
                    }
                case KeyCodes.PageDown:
                    dindex = Math.min(this.rowsCount - 1, this.currentItemIndex + this._pageSize);
                    setCurrentIndex(dindex);
                    if (event.shiftKey) {
                        return this.selectRange$(currentIndex, dindex);
                    }
                    else if (!event.ctrlKey) {
                        this.rangeStartIndex = dindex;
                        return this.selectRange$(this.rangeStartIndex);
                    }
                    else {
                        return of(-1);
                    }
                case KeyCodes.UpArrow:
                    uaindex = Math.max(0, this.currentItemIndex - 1);
                    if (uaindex !== -1) {
                        setCurrentIndex(uaindex);
                        if (event.shiftKey) {
                            return this.selectRange$(currentIndex, uaindex);
                        }
                        else if (!event.ctrlKey) {
                            this.rangeStartIndex = uaindex;
                            return this.selectRange$(this.rangeStartIndex);
                        }
                    }
                    return of(-1);
                case KeyCodes.DownArrow:
                    daindex = Math.min(this.rowsCount - 1, this.currentItemIndex + 1);
                    if (daindex !== -1) {
                        setCurrentIndex(daindex);
                        if (event.shiftKey) {
                            return this.selectRange$(currentIndex, daindex);
                        }
                        else if (!event.ctrlKey) {
                            this.rangeStartIndex = daindex;
                            return this.selectRange$(this.rangeStartIndex);
                        }
                    }
                    return of(-1);
                case KeyCodes.Space:
                    target = event.target;
                    if (target.tagName === 'INPUT' && !event.ctrlKey && !event.shiftKey) {
                        return of(null);
                    }
                    sitem = this.currentItem;
                    if (sitem) {
                        if (this.isCollapsible(sitem)) {
                            return this.toggleCollapse$(currentIndex, !sitem.collapsed);
                        }
                        else if (sitem.selected) {
                            return this.toggleSelect$([sitem], false);
                        }
                        else if (this.multiSelect && event.ctrlKey) {
                            return this.toggleSelect$([sitem], !sitem.selected);
                        }
                        else {
                            return this.unselectAll$().pipe(switchMap(() => this.toggleSelect$([sitem], true)));
                        }
                    }
                    return of(-1);
                case KeyCodes.Enter:
                    eitem = this.currentItem;
                    if (eitem) {
                        if (this.isCollapsible(eitem)) {
                            return this.toggleCollapse$(currentIndex, !eitem.collapsed);
                        }
                        else if (this.isSelectable(eitem)) {
                            return this.unselectAll$().pipe(switchMap(() => this.toggleSelect$([eitem], true)));
                        }
                    }
                    return of(-1);
                default:
                    return of(null);
            }
        }), map(continuePropagation => {
            if (continuePropagation !== null) {
                this.keyboardNavigation$.next();
                this.changeDetectorRef.markForCheck();
                event.preventDefault();
                return false;
            }
            return undefined;
        }))), takeUntil(this.destroyed$)).subscribe();
        let keyUp$ = fromEvent(this.listElement, 'keyup');
        if (this.input) {
            const inputKeyup$ = fromEvent(this.input.nativeElement, 'keyup');
            const inputDrop$ = fromEvent(this.input.nativeElement, 'drop');
            keyUp$ = keyUp$.pipe(mergeWith(inputKeyup$, inputDrop$));
        }
        // Ensure list cache
        keyUp$.pipe(filter(() => !this.disabled), tap(() => {
            if ((this.query || '').length < this.minSearchlength) {
                this._itemList = [];
                return;
            }
        }), filter(event => {
            const keyCode = event.code;
            return keyCode >= KeyCodes.Key0 ||
                keyCode === KeyCodes.Backspace ||
                keyCode === KeyCodes.Space ||
                keyCode === KeyCodes.Delete;
        }), switchMap(event => {
            if (!this.searchArea) {
                if ((/[a-zA-Z0-9]/).test(event.key)) {
                    // Valid char
                    this.clearFilterExpression$.next(null);
                    // Search next
                    this.filterExpression += event.key;
                    const rg = new RegExp(`^${this.filterExpression}`, 'i');
                    return this.findNextMatch$(item => {
                        if (item && this.isSelectable(item)) {
                            const label = this.getTextValue(item);
                            if (rg.test(label)) {
                                return true;
                            }
                        }
                        event.preventDefault();
                        return false;
                    }, this.currentItemIndex);
                }
            }
            else {
                // Autocomplete, filter the list
                this.keyboardNavigation$.next();
            }
            return of(null);
        }), filter(result => result?.index >= 0), takeUntil(this.destroyed$)).subscribe(result => {
            // Set current item from index for keyboard features only
            this.currentItemIndex = result.index;
            this.ensureItemVisible(this.currentItemIndex);
        });
        this.viewPort.element$.next(this.listElement);
    }
    mousedown(e) {
        if (this.mouseUp$sub) {
            this.mouseUp$sub.unsubscribe();
            this.mouseUp$sub = undefined;
        }
        if (this.disabled) {
            return undefined;
        }
        const target = e.target;
        const itemIndex = this.getItemIndexFromHTMLElement(target);
        if (itemIndex === undefined) {
            return undefined;
        }
        const isExpandButton = (el) => el.id === 'expandbtn' || el.parentElement.id === 'expandbtn';
        const item = this._itemList[itemIndex - this.vpStartRow];
        this.clickedItem = item;
        if ((!isExpandButton(target) || !this.isCollapsible(item)) && this.isSelectable(item) && (!e.ctrlKey || !this.multiSelect) && (e.button === 0 || !item.selected)) {
            if (e.shiftKey && this.multiSelect) {
                // Select all from current to clicked
                this.selectRange$(itemIndex, this.currentItemIndex).pipe(take(1), takeUntil(this.destroyed$)).subscribe(() => this.changeDetectorRef.markForCheck());
                return false;
            }
            else if (!e.ctrlKey) {
                if (!this.multiSelect && item.selected) {
                    return undefined;
                }
                this.unselectAll$().pipe(take(1), switchMap(() => {
                    this.currentItemIndex = itemIndex;
                    return this.toggleSelect$([item], true);
                }), take(1), takeUntil(this.destroyed$)).subscribe(() => this.changeDetectorRef.markForCheck());
            }
        }
        this.mouseUp$sub = fromEvent(this.listElement, 'mouseup').pipe(take(1), filter(() => !this.disabled), switchMap(upevt => {
            // Because .take(1)
            this.mouseUp$sub = undefined;
            const upTarget = upevt.target;
            const upIndex = this.getItemIndexFromHTMLElement(upTarget);
            if (upIndex === undefined) {
                return of(null);
            }
            const upItem = this._itemList[upIndex - this.vpStartRow];
            if (this.clickedItem && upItem !== this.clickedItem) {
                return of(null);
            }
            if (upevt.shiftKey) {
                return of(null);
            }
            if (upevt.button !== 0) {
                // Right click menu
                return of(null);
            }
            if (this.isCollapsible(upItem) && (isExpandButton(upTarget) || !this.isSelectable(upItem))) {
                const treeItem = upItem;
                return this.toggleCollapse$(upIndex, !treeItem.collapsed).pipe(map(() => upIndex));
            }
            else if (upevt.ctrlKey) {
                if (this.multiSelect) {
                    return this.toggleSelect$([upItem], !upItem.selected).pipe(map(() => upIndex));
                }
                else {
                    const o$ = this.selectedItem && this.selectedItem !== upItem ? this.toggleSelect$([this.selectedItem], false).pipe(switchMap(() => this.toggleSelect$([upItem], true))) : this.toggleSelect$([upItem], !upItem.selected);
                    return o$.pipe(map(() => upIndex));
                }
            }
            this.rangeStartIndex = -1;
            return of(null);
        }), filter(currentIndex => currentIndex !== null), takeUntil(this.destroyed$)).subscribe(currentIndex => {
            this.currentItemIndex = currentIndex;
            this.changeDetectorRef.markForCheck();
        });
        return undefined;
    }
    getDragContext(index) {
        if (!this.clipboardService || (!this.sortable && !this.itemsDraggable)) {
            return null;
        }
        return {
            dragendcallback: (event) => {
                this.itemDragEnd.emit(event);
                delete this._ddStartIndex;
                delete this._ddTargetIndex;
                this.calcViewList$().pipe(take(1), takeUntil(this.destroyed$)).subscribe(); // Comment this line to debug dragdrop
            },
            dragstartcallback: (event) => {
                const targetIndex = this.getItemIndexFromHTMLElement(event.target);
                if (targetIndex === undefined) {
                    return;
                }
                this._ddStartIndex = index;
                event.dragObject = this._itemList[targetIndex - this.vpStartRow];
                this.itemDragStart.emit(event);
            },
            object: {
                index: index
            }
        };
    }
    getDropContext() {
        if (!this.clipboardService || !this.sortable) {
            return null;
        }
        const dragcallback = (event) => {
            if (this._ddStartIndex === undefined) {
                return;
            }
            const targetIndex = this.getItemIndexFromHTMLElement(event.target);
            if (targetIndex === undefined) {
                return;
            }
            // Faire calculer le target final en fonction de la hierarchie par le service
            this.calcDragTargetIndex$(this._ddStartIndex, targetIndex).pipe(switchMap(finalTarget => {
                if (finalTarget !== undefined && finalTarget !== this._ddTargetIndex) {
                    this._ddTargetIndex = finalTarget;
                    return this.calcViewList$().pipe(take(1), map(() => finalTarget));
                }
                else {
                    return of(finalTarget);
                }
            }), takeUntil(this.destroyed$)).subscribe();
            event.preventDefault();
            return;
        };
        return {
            dragentercallback: dragcallback,
            dragovercallback: dragcallback,
            dropcallback: (event) => {
                delete this._ddStartIndex;
                delete this._ddTargetIndex;
                this.drop$().pipe(switchMap(() => this.calcViewList$().pipe(take(1))), takeUntil(this.destroyed$)).subscribe();
                event.preventDefault();
            }
        };
    }
    dragLeave(event) {
        const listRect = this.listElement.getBoundingClientRect();
        const listBounds = Rect.fromLTRB(listRect.left, listRect.top, listRect.right, listRect.bottom);
        if (!listBounds.containsPoint(new Position(event.pageX, event.pageY))) {
            this._ddTargetIndex = this._ddStartIndex;
            this.calcViewList$().pipe(take(1), takeUntil(this.destroyed$)).subscribe();
        }
    }
    onSelectionChange() {
        let outputEmitter = null;
        let output = null;
        if (this.multiSelect) {
            const models = this.selectedModels;
            outputEmitter = {
                items: this.selectedItems,
                models: models
            };
            if (this.modelIsValue) {
                const valueField = this.getValueField();
                if (models.find(m => !!m[valueField])) {
                    output = models.map(m => m[valueField] !== undefined ? m[valueField] : m);
                }
            }
            else {
                output = models;
            }
        }
        else {
            const model = this.selectedModel;
            outputEmitter = {
                item: this.selectedItems[0],
                model: model
            };
            if (this.modelIsValue) {
                const valueField = this.getValueField();
                output = model[valueField] !== undefined ? model[valueField] : model;
            }
            else {
                output = model;
            }
        }
        this.onChangeCallback(output);
        this.selectedChange.emit(outputEmitter);
    }
    selectRange$(indexFrom, indexTo) {
        return super.selectRange$(indexFrom, indexTo).pipe(tap(selectedCount => {
            if (selectedCount) {
                // Raise event
                this.onSelectionChange();
            }
            return selectedCount;
        }), tap(() => this.changeDetectorRef.markForCheck()));
    }
    toggleSelect$(items, state) {
        if (!this._multiSelect && !items[0].selected === !state) {
            return of(items);
        }
        else {
            return super.toggleSelect$(items, state).pipe(tap(() => {
                // Raise event
                this.onSelectionChange();
            }));
        }
    }
    calcViewList$() {
        return super.calcViewList$(this.query).pipe(tap(() => this.changeDetectorRef.markForCheck()));
    }
    getItemClass(item) {
        const classNames = ['listitem'];
        if (item.className) {
            classNames.push(item.className);
        }
        if (item.collapsing || item.expanding) {
            classNames.push('hide');
        }
        if (item.depth < this.depthMax) {
            classNames.push('parent');
        }
        if (item.collapsed) {
            classNames.push('collapsed');
        }
        if (item.selected) {
            classNames.push('selected');
        }
        if (!(item.selectable ?? true)) {
            classNames.push('unselectable');
        }
        if (item.depth === this._depthMax && item.odd) {
            classNames.push('odd');
        }
        return classNames.join(' ');
    }
}
DejaTreeListComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.1", ngImport: i0, type: DejaTreeListComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i1.ViewPortService }, { token: i0.ElementRef }, { token: i2.NgControl, optional: true, self: true }, { token: i3.DejaClipboardService, optional: true }], target: i0.ɵɵFactoryTarget.Component });
DejaTreeListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.1.1", type: DejaTreeListComponent, selector: "deja-tree-list", inputs: { placeholder: "placeholder", nodataholder: "nodataholder", query: "query", itemTemplateExternal: "itemTemplateExternal", parentItemTemplateExternal: "parentItemTemplateExternal", loaderTemplateExternal: "loaderTemplateExternal", headerTemplateExternal: "headerTemplateExternal", searchPrefixTemplateExternal: "searchPrefixTemplateExternal", searchSuffixTemplateExternal: "searchSuffixTemplateExternal", itemsWidth: "itemsWidth", minSearchlength: ["min-search-length", "minSearchlength"], searchArea: "searchArea", modelIsValue: "modelIsValue", sortable: "sortable", itemsDraggable: "itemsDraggable", pageSize: "pageSize", hintLabel: "hintLabel", viewPortRowHeight: "viewPortRowHeight", viewportMode: "viewportMode", childrenField: "childrenField", textField: "textField", valueField: "valueField", searchField: "searchField", maxHeight: "maxHeight", currentItem: "currentItem", multiSelect: "multiSelect", selectedItems: "selectedItems", selectedItem: "selectedItem", selectedModel: "selectedModel", selectedModels: "selectedModels", itemListService: "itemListService", sortingService: "sortingService", groupingService: "groupingService", items: "items", loadingItems: "loadingItems", selectingItem: "selectingItem", unselectingItem: "unselectingItem", expandingItem: "expandingItem", collapsingItem: "collapsingItem", models: "models", disabled: "disabled", waiter: "waiter" }, outputs: { scroll: "scroll", itemDragEnd: "itemDragEnd", itemDragStart: "itemDragStart", selectedChange: "selectedChange", viewPortChanged: "viewPortChanged" }, host: { properties: { "attr.disabled": "this._disabled" } }, providers: [ViewPortService], queries: [{ propertyName: "itemTemplateInternal", first: true, predicate: ["itemTemplate"], descendants: true }, { propertyName: "parentItemTemplateInternal", first: true, predicate: ["parentItemTemplate"], descendants: true }, { propertyName: "loaderTemplateInternal", first: true, predicate: ["loaderTemplate"], descendants: true }, { propertyName: "headerTemplateInternal", first: true, predicate: ["headerTemplate"], descendants: true }, { propertyName: "searchPrefixTemplateInternal", first: true, predicate: ["searchPrefixTemplate"], descendants: true }, { propertyName: "searchSuffixTemplateInternal", first: true, predicate: ["searchSuffixTemplate"], descendants: true }, { propertyName: "options", predicate: DejaItemComponent }], viewQueries: [{ propertyName: "input", first: true, predicate: ["inputelement"], descendants: true }, { propertyName: "listElememtRef", first: true, predicate: ["listElement"], descendants: true, static: true }, { propertyName: "inputValidatorDirective", first: true, predicate: DejaChildValidatorDirective, descendants: true }], usesInheritance: true, ngImport: i0, template: "<div id=\"header\" *ngIf=\"searchArea\">\n    <mat-form-field deja-child-validator id=\"input\" *ngIf=\"searchArea\">\n        <input #inputelement type=\"text\" matInput tabindex=\"0\" [ngModel]=\"query\" [placeholder]=\"placeholder\" [disabled]=\"disabled\" (input)=\"setQuery$.next(model && model.value)\" #model=\"ngModel\">\n        <span *ngIf=\"searchPrefixTemplate\" matPrefix>\n\t\t\t<ng-template [ngTemplateOutlet]=\"searchPrefixTemplate\"></ng-template>\n\t\t</span>\n        <span *ngIf=\"searchSuffixTemplate\" matSuffix>\n\t\t\t<ng-template [ngTemplateOutlet]=\"searchSuffixTemplate\"></ng-template>\n\t\t</span>\n    </mat-form-field>\n</div>\n<div id=\"listheader\" *ngIf=\"headerTemplate\">\n    <ng-template [ngTemplateOutlet]=\"headerTemplate\"></ng-template>\n</div>\n<div [id]=\"listElementId\" #listElement class=\"deja-listcontainer\" [attr.itemscount]=\"itemList && itemList.length\" [attr.depth-max]=\"depthMax || null\" [attr.vp-rowheight]=\"getViewPortRowHeight()\" [style.max-height.px]=\"maxHeight || null\" tabindex=\"1\" [class.hasheader]=\"headerTemplate\" [class.dragover]=\"ddStartIndex !== undefined ? ddStartIndex : null\" [attr.keynav]=\"keyboardNavigation()\" (dragleave)=\"sortable ? dragLeave($event): null\" (mousedown)=\"mousedown($event)\" [deja-droppable]=\"getDropContext()\">\n    <div id=\"nodata-holder\" *ngIf=\"(!itemList || itemList.length === 0) && !waiter\">{{ nodataholder }}</div>\n    <div id=\"error-hint\" *ngIf=\"hintLabel\">{{ hintLabel }}</div>\n    <div *ngIf=\"vpBeforeHeight && !waiter\" [style.height.px]=\"vpBeforeHeight\"></div>\n    <ng-container *ngIf=\"!waiter\">\n        <div *ngFor=\"let item of treeItemList; let index = index\" #listitem [attr.class]=\"getItemClass(item)\" [attr.current]=\"(vpStartRow+index === currentItemIndex) || null\" [attr.depth]=\"depthMax ? item.depth : null\" [attr.id]=\"item.id || null\" [attr.flat]=\"vpStartRow + index\" [deja-draggable]=\"getDragContext(vpStartRow + index)\" [style.width.px]=\"itemsWidth\" [style.height.px]=\"getItemHeight(item)\">\n            <span id=\"expandbtn\">\n                <mat-icon *ngIf=\"item.$items?.length\">arrow_drop_down</mat-icon>\n            </span>\n\n            <ng-container *ngIf=\"(!item.$items || !parentItemTemplate) && (item.$items || !itemTemplate)\">{{ getTextValue(item) }}</ng-container>\n            <ng-container *ngIf=\"item.$items && parentItemTemplate\">\n                <ng-template [ngTemplateOutlet]=\"parentItemTemplate\" [ngTemplateOutletContext]=\"{ $implicit: item, query: query, flatindex: vpStartRow+index }\"></ng-template>\n            </ng-container>\n            <ng-container *ngIf=\"!item.$items && itemTemplate\">\n                <ng-template [ngTemplateOutlet]=\"itemTemplate\" [ngTemplateOutletContext]=\"{ $implicit: item, query: query, flatindex: vpStartRow+index }\"></ng-template>\n            </ng-container>\n        </div>\n    </ng-container>\n    <div *ngIf=\"vpAfterHeight && !waiter\" [style.height.px]=\"vpAfterHeight\"></div>\n    <deja-list-loader id=\"loader\" *ngIf=\"waiter && !loaderTemplate\"></deja-list-loader>\n    <ng-container *ngIf=\"waiter && loaderTemplate\">\n        <ng-template [ngTemplateOutlet]=\"loaderTemplate\"></ng-template>\n    </ng-container>\n</div>\n", styles: ["deja-tree-list{display:flex;position:relative;flex-direction:column;align-content:stretch;overflow:hidden}deja-tree-list.ng-invalid #input .mat-form-field-wrapper .mat-form-field-underline .mat-form-field-ripple{opacity:1;transform:scaleY(1)}deja-tree-list #input{outline:none}deja-tree-list #header{flex:0 0 auto;align-items:center;display:flex}deja-tree-list #header #input{flex:1 1 auto}deja-tree-list #header button{flex:0 0 auto;margin:16px .5rem 16px 0}deja-tree-list #listheader{flex:0 0 auto;overflow:hidden;box-sizing:border-box}deja-tree-list .deja-listcontainer{flex:1 1 auto;outline:none;overflow:auto}deja-tree-list .deja-listcontainer.hasheader{border-top:0}deja-tree-list .deja-listcontainer[keynav=false]:not(.dragover) div.listitem:not(.unselectable):hover{cursor:pointer}deja-tree-list .deja-listcontainer[valign=bottom]{border-top:none}deja-tree-list .deja-listcontainer #nodata-holder{margin:.5rem}deja-tree-list .deja-listcontainer #error-hint{margin:.5rem}deja-tree-list #loader{position:absolute;left:0;right:0}deja-tree-list .deja-listcontainer{padding:0;margin:0;position:relative}deja-tree-list .deja-listcontainer[vprowheight=\"0\"]>div.listitem{padding:.35rem .1rem}deja-tree-list .deja-listcontainer>div.listitem{opacity:1;margin:0;transition-timing-function:linear;transition-duration:.3s;transition-property:max-height,opacity;display:flex;align-items:center}deja-tree-list .deja-listcontainer>div.listitem.hide{opacity:0!important;max-height:0!important;transition-timing-function:ease-out}deja-tree-list .deja-listcontainer>div.listitem #expandbtn{width:24px;cursor:pointer}deja-tree-list .deja-listcontainer>div.listitem.parent.collapsed #expandbtn>.mat-icon{transform:rotate(-90deg)}deja-tree-list .deja-listcontainer [depth=\"0\"]{padding-left:0rem}deja-tree-list .deja-listcontainer [depth=\"1\"]{padding-left:1rem}deja-tree-list .deja-listcontainer [depth=\"2\"]{padding-left:2rem}deja-tree-list .deja-listcontainer [depth=\"3\"]{padding-left:3rem}deja-tree-list .deja-listcontainer [depth=\"4\"]{padding-left:4rem}deja-tree-list .deja-listcontainer [depth=\"5\"]{padding-left:5rem}deja-tree-list .deja-listcontainer [depth=\"6\"]{padding-left:6rem}deja-tree-list .deja-listcontainer [depth=\"7\"]{padding-left:7rem}deja-tree-list .deja-listcontainer [depth=\"8\"]{padding-left:8rem}deja-tree-list .deja-listcontainer [depth=\"9\"]{padding-left:9rem}deja-tree-list .deja-listcontainer [depth=\"10\"]{padding-left:10rem}deja-tree-list .deja-listcontainer [depth=\"11\"]{padding-left:11rem}deja-tree-list .deja-listcontainer [depth=\"12\"]{padding-left:12rem}deja-tree-list .deja-listcontainer [depth=\"13\"]{padding-left:13rem}deja-tree-list .deja-listcontainer [depth=\"14\"]{padding-left:14rem}deja-tree-list .deja-listcontainer [depth=\"15\"]{padding-left:15rem}deja-tree-list .deja-listcontainer [depth=\"16\"]{padding-left:16rem}deja-tree-list .deja-listcontainer [depth=\"17\"]{padding-left:17rem}deja-tree-list .deja-listcontainer [depth=\"18\"]{padding-left:18rem}deja-tree-list .deja-listcontainer [depth=\"19\"]{padding-left:19rem}deja-tree-list .deja-listcontainer [depth=\"20\"]{padding-left:20rem}deja-tree-list .deja-listcontainer [depth=\"21\"]{padding-left:21rem}deja-tree-list .deja-listcontainer [depth=\"22\"]{padding-left:22rem}deja-tree-list .deja-listcontainer [depth=\"23\"]{padding-left:23rem}deja-tree-list .deja-listcontainer [depth=\"24\"]{padding-left:24rem}deja-tree-list .deja-listcontainer [depth=\"25\"]{padding-left:25rem}deja-tree-list .deja-listcontainer [depth=\"26\"]{padding-left:26rem}deja-tree-list .deja-listcontainer [depth=\"27\"]{padding-left:27rem}deja-tree-list .deja-listcontainer [depth=\"28\"]{padding-left:28rem}deja-tree-list .deja-listcontainer [depth=\"29\"]{padding-left:29rem}deja-tree-list .deja-listcontainer [depth=\"30\"]{padding-left:30rem}deja-tree-list .deja-listcontainer [depth=\"31\"]{padding-left:31rem}deja-tree-list .deja-listcontainer [depth=\"32\"]{padding-left:32rem}deja-tree-list .deja-listcontainer [depth=\"33\"]{padding-left:33rem}deja-tree-list .deja-listcontainer [depth=\"34\"]{padding-left:34rem}deja-tree-list .deja-listcontainer [depth=\"35\"]{padding-left:35rem}deja-tree-list .deja-listcontainer [depth=\"36\"]{padding-left:36rem}deja-tree-list .deja-listcontainer [depth=\"37\"]{padding-left:37rem}deja-tree-list .deja-listcontainer [depth=\"38\"]{padding-left:38rem}deja-tree-list .deja-listcontainer [depth=\"39\"]{padding-left:39rem}deja-tree-list .deja-listcontainer [depth=\"40\"]{padding-left:40rem}deja-tree-list .deja-listcontainer [depth=\"41\"]{padding-left:41rem}deja-tree-list .deja-listcontainer [depth=\"42\"]{padding-left:42rem}deja-tree-list .deja-listcontainer [depth=\"43\"]{padding-left:43rem}deja-tree-list .deja-listcontainer [depth=\"44\"]{padding-left:44rem}deja-tree-list .deja-listcontainer [depth=\"45\"]{padding-left:45rem}deja-tree-list .deja-listcontainer [depth=\"46\"]{padding-left:46rem}deja-tree-list .deja-listcontainer [depth=\"47\"]{padding-left:47rem}deja-tree-list .deja-listcontainer [depth=\"48\"]{padding-left:48rem}deja-tree-list .deja-listcontainer [depth=\"49\"]{padding-left:49rem}deja-tree-list .deja-listcontainer [depth=\"50\"]{padding-left:50rem}\n"], dependencies: [{ kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i3.DejaChildValidatorDirective, selector: "[deja-child-validator]" }, { kind: "directive", type: i5.DejaDraggableDirective, selector: "[deja-draggable]", inputs: ["deja-draggable"] }, { kind: "directive", type: i5.DejaDroppableDirective, selector: "[deja-droppable]", inputs: ["continous-dragover", "deja-droppable"] }, { kind: "component", type: i6.DejaListLoaderComponent, selector: "deja-list-loader" }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i7.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i8.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i8.MatPrefix, selector: "[matPrefix]" }, { kind: "directive", type: i8.MatSuffix, selector: "[matSuffix]" }, { kind: "directive", type: i9.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl],      input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.1", ngImport: i0, type: DejaTreeListComponent, decorators: [{
            type: Component,
            args: [{ changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [ViewPortService], selector: 'deja-tree-list', template: "<div id=\"header\" *ngIf=\"searchArea\">\n    <mat-form-field deja-child-validator id=\"input\" *ngIf=\"searchArea\">\n        <input #inputelement type=\"text\" matInput tabindex=\"0\" [ngModel]=\"query\" [placeholder]=\"placeholder\" [disabled]=\"disabled\" (input)=\"setQuery$.next(model && model.value)\" #model=\"ngModel\">\n        <span *ngIf=\"searchPrefixTemplate\" matPrefix>\n\t\t\t<ng-template [ngTemplateOutlet]=\"searchPrefixTemplate\"></ng-template>\n\t\t</span>\n        <span *ngIf=\"searchSuffixTemplate\" matSuffix>\n\t\t\t<ng-template [ngTemplateOutlet]=\"searchSuffixTemplate\"></ng-template>\n\t\t</span>\n    </mat-form-field>\n</div>\n<div id=\"listheader\" *ngIf=\"headerTemplate\">\n    <ng-template [ngTemplateOutlet]=\"headerTemplate\"></ng-template>\n</div>\n<div [id]=\"listElementId\" #listElement class=\"deja-listcontainer\" [attr.itemscount]=\"itemList && itemList.length\" [attr.depth-max]=\"depthMax || null\" [attr.vp-rowheight]=\"getViewPortRowHeight()\" [style.max-height.px]=\"maxHeight || null\" tabindex=\"1\" [class.hasheader]=\"headerTemplate\" [class.dragover]=\"ddStartIndex !== undefined ? ddStartIndex : null\" [attr.keynav]=\"keyboardNavigation()\" (dragleave)=\"sortable ? dragLeave($event): null\" (mousedown)=\"mousedown($event)\" [deja-droppable]=\"getDropContext()\">\n    <div id=\"nodata-holder\" *ngIf=\"(!itemList || itemList.length === 0) && !waiter\">{{ nodataholder }}</div>\n    <div id=\"error-hint\" *ngIf=\"hintLabel\">{{ hintLabel }}</div>\n    <div *ngIf=\"vpBeforeHeight && !waiter\" [style.height.px]=\"vpBeforeHeight\"></div>\n    <ng-container *ngIf=\"!waiter\">\n        <div *ngFor=\"let item of treeItemList; let index = index\" #listitem [attr.class]=\"getItemClass(item)\" [attr.current]=\"(vpStartRow+index === currentItemIndex) || null\" [attr.depth]=\"depthMax ? item.depth : null\" [attr.id]=\"item.id || null\" [attr.flat]=\"vpStartRow + index\" [deja-draggable]=\"getDragContext(vpStartRow + index)\" [style.width.px]=\"itemsWidth\" [style.height.px]=\"getItemHeight(item)\">\n            <span id=\"expandbtn\">\n                <mat-icon *ngIf=\"item.$items?.length\">arrow_drop_down</mat-icon>\n            </span>\n\n            <ng-container *ngIf=\"(!item.$items || !parentItemTemplate) && (item.$items || !itemTemplate)\">{{ getTextValue(item) }}</ng-container>\n            <ng-container *ngIf=\"item.$items && parentItemTemplate\">\n                <ng-template [ngTemplateOutlet]=\"parentItemTemplate\" [ngTemplateOutletContext]=\"{ $implicit: item, query: query, flatindex: vpStartRow+index }\"></ng-template>\n            </ng-container>\n            <ng-container *ngIf=\"!item.$items && itemTemplate\">\n                <ng-template [ngTemplateOutlet]=\"itemTemplate\" [ngTemplateOutletContext]=\"{ $implicit: item, query: query, flatindex: vpStartRow+index }\"></ng-template>\n            </ng-container>\n        </div>\n    </ng-container>\n    <div *ngIf=\"vpAfterHeight && !waiter\" [style.height.px]=\"vpAfterHeight\"></div>\n    <deja-list-loader id=\"loader\" *ngIf=\"waiter && !loaderTemplate\"></deja-list-loader>\n    <ng-container *ngIf=\"waiter && loaderTemplate\">\n        <ng-template [ngTemplateOutlet]=\"loaderTemplate\"></ng-template>\n    </ng-container>\n</div>\n", styles: ["deja-tree-list{display:flex;position:relative;flex-direction:column;align-content:stretch;overflow:hidden}deja-tree-list.ng-invalid #input .mat-form-field-wrapper .mat-form-field-underline .mat-form-field-ripple{opacity:1;transform:scaleY(1)}deja-tree-list #input{outline:none}deja-tree-list #header{flex:0 0 auto;align-items:center;display:flex}deja-tree-list #header #input{flex:1 1 auto}deja-tree-list #header button{flex:0 0 auto;margin:16px .5rem 16px 0}deja-tree-list #listheader{flex:0 0 auto;overflow:hidden;box-sizing:border-box}deja-tree-list .deja-listcontainer{flex:1 1 auto;outline:none;overflow:auto}deja-tree-list .deja-listcontainer.hasheader{border-top:0}deja-tree-list .deja-listcontainer[keynav=false]:not(.dragover) div.listitem:not(.unselectable):hover{cursor:pointer}deja-tree-list .deja-listcontainer[valign=bottom]{border-top:none}deja-tree-list .deja-listcontainer #nodata-holder{margin:.5rem}deja-tree-list .deja-listcontainer #error-hint{margin:.5rem}deja-tree-list #loader{position:absolute;left:0;right:0}deja-tree-list .deja-listcontainer{padding:0;margin:0;position:relative}deja-tree-list .deja-listcontainer[vprowheight=\"0\"]>div.listitem{padding:.35rem .1rem}deja-tree-list .deja-listcontainer>div.listitem{opacity:1;margin:0;transition-timing-function:linear;transition-duration:.3s;transition-property:max-height,opacity;display:flex;align-items:center}deja-tree-list .deja-listcontainer>div.listitem.hide{opacity:0!important;max-height:0!important;transition-timing-function:ease-out}deja-tree-list .deja-listcontainer>div.listitem #expandbtn{width:24px;cursor:pointer}deja-tree-list .deja-listcontainer>div.listitem.parent.collapsed #expandbtn>.mat-icon{transform:rotate(-90deg)}deja-tree-list .deja-listcontainer [depth=\"0\"]{padding-left:0rem}deja-tree-list .deja-listcontainer [depth=\"1\"]{padding-left:1rem}deja-tree-list .deja-listcontainer [depth=\"2\"]{padding-left:2rem}deja-tree-list .deja-listcontainer [depth=\"3\"]{padding-left:3rem}deja-tree-list .deja-listcontainer [depth=\"4\"]{padding-left:4rem}deja-tree-list .deja-listcontainer [depth=\"5\"]{padding-left:5rem}deja-tree-list .deja-listcontainer [depth=\"6\"]{padding-left:6rem}deja-tree-list .deja-listcontainer [depth=\"7\"]{padding-left:7rem}deja-tree-list .deja-listcontainer [depth=\"8\"]{padding-left:8rem}deja-tree-list .deja-listcontainer [depth=\"9\"]{padding-left:9rem}deja-tree-list .deja-listcontainer [depth=\"10\"]{padding-left:10rem}deja-tree-list .deja-listcontainer [depth=\"11\"]{padding-left:11rem}deja-tree-list .deja-listcontainer [depth=\"12\"]{padding-left:12rem}deja-tree-list .deja-listcontainer [depth=\"13\"]{padding-left:13rem}deja-tree-list .deja-listcontainer [depth=\"14\"]{padding-left:14rem}deja-tree-list .deja-listcontainer [depth=\"15\"]{padding-left:15rem}deja-tree-list .deja-listcontainer [depth=\"16\"]{padding-left:16rem}deja-tree-list .deja-listcontainer [depth=\"17\"]{padding-left:17rem}deja-tree-list .deja-listcontainer [depth=\"18\"]{padding-left:18rem}deja-tree-list .deja-listcontainer [depth=\"19\"]{padding-left:19rem}deja-tree-list .deja-listcontainer [depth=\"20\"]{padding-left:20rem}deja-tree-list .deja-listcontainer [depth=\"21\"]{padding-left:21rem}deja-tree-list .deja-listcontainer [depth=\"22\"]{padding-left:22rem}deja-tree-list .deja-listcontainer [depth=\"23\"]{padding-left:23rem}deja-tree-list .deja-listcontainer [depth=\"24\"]{padding-left:24rem}deja-tree-list .deja-listcontainer [depth=\"25\"]{padding-left:25rem}deja-tree-list .deja-listcontainer [depth=\"26\"]{padding-left:26rem}deja-tree-list .deja-listcontainer [depth=\"27\"]{padding-left:27rem}deja-tree-list .deja-listcontainer [depth=\"28\"]{padding-left:28rem}deja-tree-list .deja-listcontainer [depth=\"29\"]{padding-left:29rem}deja-tree-list .deja-listcontainer [depth=\"30\"]{padding-left:30rem}deja-tree-list .deja-listcontainer [depth=\"31\"]{padding-left:31rem}deja-tree-list .deja-listcontainer [depth=\"32\"]{padding-left:32rem}deja-tree-list .deja-listcontainer [depth=\"33\"]{padding-left:33rem}deja-tree-list .deja-listcontainer [depth=\"34\"]{padding-left:34rem}deja-tree-list .deja-listcontainer [depth=\"35\"]{padding-left:35rem}deja-tree-list .deja-listcontainer [depth=\"36\"]{padding-left:36rem}deja-tree-list .deja-listcontainer [depth=\"37\"]{padding-left:37rem}deja-tree-list .deja-listcontainer [depth=\"38\"]{padding-left:38rem}deja-tree-list .deja-listcontainer [depth=\"39\"]{padding-left:39rem}deja-tree-list .deja-listcontainer [depth=\"40\"]{padding-left:40rem}deja-tree-list .deja-listcontainer [depth=\"41\"]{padding-left:41rem}deja-tree-list .deja-listcontainer [depth=\"42\"]{padding-left:42rem}deja-tree-list .deja-listcontainer [depth=\"43\"]{padding-left:43rem}deja-tree-list .deja-listcontainer [depth=\"44\"]{padding-left:44rem}deja-tree-list .deja-listcontainer [depth=\"45\"]{padding-left:45rem}deja-tree-list .deja-listcontainer [depth=\"46\"]{padding-left:46rem}deja-tree-list .deja-listcontainer [depth=\"47\"]{padding-left:47rem}deja-tree-list .deja-listcontainer [depth=\"48\"]{padding-left:48rem}deja-tree-list .deja-listcontainer [depth=\"49\"]{padding-left:49rem}deja-tree-list .deja-listcontainer [depth=\"50\"]{padding-left:50rem}\n"] }]
        }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }, { type: i1.ViewPortService }, { type: i0.ElementRef }, { type: i2.NgControl, decorators: [{
                    type: Self
                }, {
                    type: Optional
                }] }, { type: i3.DejaClipboardService, decorators: [{
                    type: Optional
                }] }]; }, propDecorators: { options: [{
                type: ContentChildren,
                args: [DejaItemComponent]
            }], scroll: [{
                type: Output
            }], placeholder: [{
                type: Input
            }], nodataholder: [{
                type: Input
            }], query: [{
                type: Input
            }], itemTemplateExternal: [{
                type: Input
            }], parentItemTemplateExternal: [{
                type: Input
            }], loaderTemplateExternal: [{
                type: Input
            }], headerTemplateExternal: [{
                type: Input
            }], searchPrefixTemplateExternal: [{
                type: Input
            }], searchSuffixTemplateExternal: [{
                type: Input
            }], itemsWidth: [{
                type: Input
            }], itemDragEnd: [{
                type: Output
            }], itemDragStart: [{
                type: Output
            }], selectedChange: [{
                type: Output
            }], viewPortChanged: [{
                type: Output
            }], input: [{
                type: ViewChild,
                args: ['inputelement']
            }], _disabled: [{
                type: HostBinding,
                args: ['attr.disabled']
            }], itemTemplateInternal: [{
                type: ContentChild,
                args: ['itemTemplate']
            }], parentItemTemplateInternal: [{
                type: ContentChild,
                args: ['parentItemTemplate']
            }], loaderTemplateInternal: [{
                type: ContentChild,
                args: ['loaderTemplate']
            }], headerTemplateInternal: [{
                type: ContentChild,
                args: ['headerTemplate']
            }], searchPrefixTemplateInternal: [{
                type: ContentChild,
                args: ['searchPrefixTemplate']
            }], searchSuffixTemplateInternal: [{
                type: ContentChild,
                args: ['searchSuffixTemplate']
            }], minSearchlength: [{
                type: Input,
                args: ['min-search-length']
            }], listElememtRef: [{
                type: ViewChild,
                args: ['listElement', { static: true }]
            }], searchArea: [{
                type: Input
            }], modelIsValue: [{
                type: Input
            }], sortable: [{
                type: Input
            }], itemsDraggable: [{
                type: Input
            }], pageSize: [{
                type: Input
            }], hintLabel: [{
                type: Input
            }], viewPortRowHeight: [{
                type: Input
            }], viewportMode: [{
                type: Input
            }], childrenField: [{
                type: Input
            }], textField: [{
                type: Input
            }], valueField: [{
                type: Input
            }], searchField: [{
                type: Input
            }], maxHeight: [{
                type: Input
            }], currentItem: [{
                type: Input
            }], multiSelect: [{
                type: Input
            }], selectedItems: [{
                type: Input
            }], selectedItem: [{
                type: Input
            }], selectedModel: [{
                type: Input
            }], selectedModels: [{
                type: Input
            }], itemListService: [{
                type: Input
            }], sortingService: [{
                type: Input
            }], groupingService: [{
                type: Input
            }], items: [{
                type: Input
            }], loadingItems: [{
                type: Input
            }], selectingItem: [{
                type: Input
            }], unselectingItem: [{
                type: Input
            }], expandingItem: [{
                type: Input
            }], collapsingItem: [{
                type: Input
            }], models: [{
                type: Input
            }], disabled: [{
                type: Input
            }], waiter: [{
                type: Input
            }], inputValidatorDirective: [{
                type: ViewChild,
                args: [DejaChildValidatorDirective]
            }] } });

/*
 *  @license
 *  Copyright Hôpitaux Universitaires de Genève. All Rights Reserved.
 *
 *  Use of this source code is governed by an Apache-2.0 license that can be
 *  found in the LICENSE file at https://github.com/DSI-HUG/dejajs-components/blob/master/LICENSE
 */
class DejaTreeListScrollEvent {
}

/*
 *  @license
 *  Copyright Hôpitaux Universitaires de Genève. All Rights Reserved.
 *
 *  Use of this source code is governed by an Apache-2.0 license that can be
 *  found in the LICENSE file at https://github.com/DSI-HUG/dejajs-components/blob/master/LICENSE
 */
class DejaTreeListModule {
}
DejaTreeListModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.1", ngImport: i0, type: DejaTreeListModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
DejaTreeListModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.1.1", ngImport: i0, type: DejaTreeListModule, declarations: [DejaTreeListComponent], imports: [CommonModule,
        DejaChildValidatorModule,
        DejaDragDropModule,
        DejaItemModule,
        DejaListLoaderModule,
        DejaTextMetricsModule,
        FormsModule,
        MatButtonModule,
        MatCheckboxModule,
        MatIconModule,
        MatInputModule], exports: [DejaTreeListComponent] });
DejaTreeListModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.1.1", ngImport: i0, type: DejaTreeListModule, imports: [CommonModule,
        DejaChildValidatorModule,
        DejaDragDropModule,
        DejaItemModule,
        DejaListLoaderModule,
        DejaTextMetricsModule,
        FormsModule,
        MatButtonModule,
        MatCheckboxModule,
        MatIconModule,
        MatInputModule] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.1", ngImport: i0, type: DejaTreeListModule, decorators: [{
            type: NgModule,
            args: [{
                    declarations: [
                        DejaTreeListComponent
                    ],
                    exports: [
                        DejaTreeListComponent
                    ],
                    imports: [
                        CommonModule,
                        DejaChildValidatorModule,
                        DejaDragDropModule,
                        DejaItemModule,
                        DejaListLoaderModule,
                        DejaTextMetricsModule,
                        FormsModule,
                        MatButtonModule,
                        MatCheckboxModule,
                        MatIconModule,
                        MatInputModule
                    ]
                }]
        }] });

/**
 * Generated bundle index. Do not edit.
 */

export { DejaTreeListComponent, DejaTreeListModule, DejaTreeListScrollEvent };
//# sourceMappingURL=deja-js-component-tree-list.mjs.map
