UNPKG

@siemens/ngx-datatable

Version:

ngx-datatable is an Angular table grid component for presenting large and complex data.

5,521 lines 321 kB
import * as i0 from '@angular/core';
import { Directive, input, contentChild, TemplateRef, computed, output, inject, InjectionToken, Component, ViewContainerRef, Injector, booleanAttribute, numberAttribute, ElementRef, NgZone, signal, DOCUMENT, Injectable, ChangeDetectionStrategy, KeyValueDiffers, HostListener, linkedSignal, ChangeDetectorRef, HostBinding, Renderer2, model, DestroyRef, effect, untracked, ViewChild, Input, ContentChildren, contentChildren, viewChild, IterableDiffers, ContentChild, NgModule } from '@angular/core';
import { NgTemplateOutlet, NgClass, NgStyle } from '@angular/common';
import { __decorate } from 'tslib';
import { startWith } from 'rxjs';

class DatatableGroupHeaderTemplateDirective {
    static ngTemplateContextGuard(directive, context) {
        return true;
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DatatableGroupHeaderTemplateDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
    static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.15", type: DatatableGroupHeaderTemplateDirective, isStandalone: true, selector: "[ngx-datatable-group-header-template]", ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DatatableGroupHeaderTemplateDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[ngx-datatable-group-header-template]'
                }]
        }] });

class DatatableGroupHeaderDirective {
    constructor() {
        /**
         * Row height is required when virtual scroll is enabled.
         */
        this.rowHeight = input(0, ...(ngDevMode ? [{ debugName: "rowHeight" }] : []));
        /**
         * Show checkbox at group header to select all rows of the group.
         */
        this.checkboxable = input(false, ...(ngDevMode ? [{ debugName: "checkboxable" }] : []));
        this._templateInput = input(undefined, ...(ngDevMode ? [{ debugName: "_templateInput", alias: 'template' }] : [{
                alias: 'template'
            }]));
        this._templateQuery = contentChild(DatatableGroupHeaderTemplateDirective, ...(ngDevMode ? [{ debugName: "_templateQuery", read: TemplateRef }] : [{
                read: TemplateRef
            }]));
        this.template = computed(() => this._templateInput() ?? this._templateQuery() ?? null, ...(ngDevMode ? [{ debugName: "template" }] : []));
        /**
         * Track toggling of group visibility
         */
        this.toggle = output();
    }
    /**
     * Toggle the expansion of a group
     */
    toggleExpandGroup(group) {
        this.toggle.emit({
            type: 'group',
            value: group
        });
    }
    /**
     * Expand all groups
     */
    expandAllGroups() {
        this.toggle.emit({
            type: 'all',
            value: true
        });
    }
    /**
     * Collapse all groups
     */
    collapseAllGroups() {
        this.toggle.emit({
            type: 'all',
            value: false
        });
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DatatableGroupHeaderDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
    static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "20.3.15", type: DatatableGroupHeaderDirective, isStandalone: true, selector: "ngx-datatable-group-header", inputs: { rowHeight: { classPropertyName: "rowHeight", publicName: "rowHeight", isSignal: true, isRequired: false, transformFunction: null }, checkboxable: { classPropertyName: "checkboxable", publicName: "checkboxable", isSignal: true, isRequired: false, transformFunction: null }, _templateInput: { classPropertyName: "_templateInput", publicName: "template", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { toggle: "toggle" }, queries: [{ propertyName: "_templateQuery", first: true, predicate: DatatableGroupHeaderTemplateDirective, descendants: true, read: TemplateRef, isSignal: true }], ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DatatableGroupHeaderDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: 'ngx-datatable-group-header'
                }]
        }], propDecorators: { rowHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowHeight", required: false }] }], checkboxable: [{ type: i0.Input, args: [{ isSignal: true, alias: "checkboxable", required: false }] }], _templateInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "template", required: false }] }], _templateQuery: [{ type: i0.ContentChild, args: [i0.forwardRef(() => DatatableGroupHeaderTemplateDirective), { ...{
                            read: TemplateRef
                        }, isSignal: true }] }], toggle: [{ type: i0.Output, args: ["toggle"] }] } });

/**
 * This component is passed as ng-template and rendered by BodyComponent.
 * BodyComponent uses rowDefInternal to first inject actual row template.
 * This component will render that actual row template.
 */
class DatatableRowDefComponent {
    constructor() {
        this.rowDef = inject(ROW_DEF_TOKEN);
        this.rowContext = {
            ...this.rowDef.rowDefInternal(),
            disabled: this.rowDef.rowDefInternalDisabled()
        };
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DatatableRowDefComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DatatableRowDefComponent, isStandalone: true, selector: "datatable-row-def", ngImport: i0, template: `@if (rowDef.rowDefInternal().rowTemplate) {
    <ng-container
      [ngTemplateOutlet]="rowDef.rowDefInternal().rowTemplate"
      [ngTemplateOutletContext]="rowContext"
    />
  }`, isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DatatableRowDefComponent, decorators: [{
            type: Component,
            args: [{
                    selector: 'datatable-row-def',
                    imports: [NgTemplateOutlet],
                    template: `@if (rowDef.rowDefInternal().rowTemplate) {
    <ng-container
      [ngTemplateOutlet]="rowDef.rowDefInternal().rowTemplate"
      [ngTemplateOutletContext]="rowContext"
    />
  }`
                }]
        }] });
class DatatableRowDefDirective {
    static ngTemplateContextGuard(_dir, ctx) {
        return true;
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DatatableRowDefDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
    static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.15", type: DatatableRowDefDirective, isStandalone: true, selector: "[rowDef]", ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DatatableRowDefDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[rowDef]'
                }]
        }] });
/**
 * @internal To be used internally by ngx-datatable.
 */
class DatatableRowDefInternalDirective {
    constructor() {
        this.vc = inject(ViewContainerRef);
        this.rowDefInternal = input.required(...(ngDevMode ? [{ debugName: "rowDefInternal" }] : []));
        this.rowDefInternalDisabled = input(...(ngDevMode ? [undefined, { debugName: "rowDefInternalDisabled" }] : []));
    }
    ngOnInit() {
        this.vc.createEmbeddedView(this.rowDefInternal().template, {
            ...this.rowDefInternal()
        }, {
            injector: Injector.create({
                providers: [
                    {
                        provide: ROW_DEF_TOKEN,
                        useValue: this
                    }
                ]
            })
        });
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DatatableRowDefInternalDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
    static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.3.15", type: DatatableRowDefInternalDirective, isStandalone: true, selector: "[rowDefInternal]", inputs: { rowDefInternal: { classPropertyName: "rowDefInternal", publicName: "rowDefInternal", isSignal: true, isRequired: true, transformFunction: null }, rowDefInternalDisabled: { classPropertyName: "rowDefInternalDisabled", publicName: "rowDefInternalDisabled", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DatatableRowDefInternalDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[rowDefInternal]'
                }]
        }], propDecorators: { rowDefInternal: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowDefInternal", required: true }] }], rowDefInternalDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowDefInternalDisabled", required: false }] }] } });
const ROW_DEF_TOKEN = new InjectionToken('RowDef');

class DataTableColumnCellDirective {
    constructor() {
        this.template = inject(TemplateRef);
    }
    static ngTemplateContextGuard(dir, ctx) {
        return true;
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DataTableColumnCellDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
    static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.15", type: DataTableColumnCellDirective, isStandalone: true, selector: "[ngx-datatable-cell-template]", ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DataTableColumnCellDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[ngx-datatable-cell-template]'
                }]
        }] });

class DataTableColumnGhostCellDirective {
    static ngTemplateContextGuard(directive, context) {
        return true;
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DataTableColumnGhostCellDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
    static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.15", type: DataTableColumnGhostCellDirective, isStandalone: true, selector: "[ngx-datatable-ghost-cell-template]", ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DataTableColumnGhostCellDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[ngx-datatable-ghost-cell-template]'
                }]
        }] });

class DataTableColumnHeaderDirective {
    static ngTemplateContextGuard(directive, context) {
        return true;
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DataTableColumnHeaderDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
    static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.15", type: DataTableColumnHeaderDirective, isStandalone: true, selector: "[ngx-datatable-header-template]", ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DataTableColumnHeaderDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[ngx-datatable-header-template]'
                }]
        }] });

class DataTableColumnCellTreeToggle {
    constructor() {
        this.template = inject(TemplateRef);
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DataTableColumnCellTreeToggle, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
    static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.15", type: DataTableColumnCellTreeToggle, isStandalone: true, selector: "[ngx-datatable-tree-toggle]", ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DataTableColumnCellTreeToggle, decorators: [{
            type: Directive,
            args: [{
                    selector: '[ngx-datatable-tree-toggle]'
                }]
        }] });

class DataTableColumnDirective {
    constructor() {
        this.name = input(...(ngDevMode ? [undefined, { debugName: "name" }] : []));
        this.prop = input(...(ngDevMode ? [undefined, { debugName: "prop" }] : []));
        this.bindAsUnsafeHtml = input(false, ...(ngDevMode ? [{ debugName: "bindAsUnsafeHtml", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
        this.frozenLeft = input(false, ...(ngDevMode ? [{ debugName: "frozenLeft", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
        this.frozenRight = input(false, ...(ngDevMode ? [{ debugName: "frozenRight", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
        this.flexGrow = input(undefined, ...(ngDevMode ? [{ debugName: "flexGrow", transform: numberAttribute }] : [{
                transform: numberAttribute
            }]));
        this.resizeable = input(undefined, ...(ngDevMode ? [{ debugName: "resizeable", transform: booleanAttribute }] : [{
                transform: booleanAttribute
            }]));
        this.comparator = input(...(ngDevMode ? [undefined, { debugName: "comparator" }] : []));
        this.pipe = input(...(ngDevMode ? [undefined, { debugName: "pipe" }] : []));
        this.sortable = input(undefined, ...(ngDevMode ? [{ debugName: "sortable", transform: booleanAttribute }] : [{
                transform: booleanAttribute
            }]));
        this.draggable = input(undefined, ...(ngDevMode ? [{ debugName: "draggable", transform: booleanAttribute }] : [{
                transform: booleanAttribute
            }]));
        this.canAutoResize = input(undefined, ...(ngDevMode ? [{ debugName: "canAutoResize", transform: booleanAttribute }] : [{
                transform: booleanAttribute
            }]));
        this.minWidth = input(undefined, ...(ngDevMode ? [{ debugName: "minWidth", transform: numberAttribute }] : [{
                transform: numberAttribute
            }]));
        this.width = input(undefined, ...(ngDevMode ? [{ debugName: "width", transform: numberAttribute }] : [{
                transform: numberAttribute
            }]));
        this.maxWidth = input(undefined, ...(ngDevMode ? [{ debugName: "maxWidth", transform: numberAttribute }] : [{
                transform: numberAttribute
            }]));
        this.checkboxable = input(false, ...(ngDevMode ? [{ debugName: "checkboxable", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
        this.headerCheckboxable = input(false, ...(ngDevMode ? [{ debugName: "headerCheckboxable", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
        this.headerClass = input(...(ngDevMode ? [undefined, { debugName: "headerClass" }] : []));
        this.cellClass = input(...(ngDevMode ? [undefined, { debugName: "cellClass" }] : []));
        this.isTreeColumn = input(false, ...(ngDevMode ? [{ debugName: "isTreeColumn", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
        this.treeLevelIndent = input(...(ngDevMode ? [undefined, { debugName: "treeLevelIndent" }] : []));
        this.summaryFunc = input(...(ngDevMode ? [undefined, { debugName: "summaryFunc" }] : []));
        this.summaryTemplate = input(...(ngDevMode ? [undefined, { debugName: "summaryTemplate" }] : []));
        this.cellTemplateInput = input(undefined, ...(ngDevMode ? [{ debugName: "cellTemplateInput", alias: 'cellTemplate' }] : [{
                alias: 'cellTemplate'
            }]));
        this.cellTemplateQuery = contentChild(DataTableColumnCellDirective, ...(ngDevMode ? [{ debugName: "cellTemplateQuery", read: TemplateRef }] : [{ read: TemplateRef }]));
        this.headerTemplateInput = input(undefined, ...(ngDevMode ? [{ debugName: "headerTemplateInput", alias: 'headerTemplate' }] : [{
                alias: 'headerTemplate'
            }]));
        this.headerTemplateQuery = contentChild(DataTableColumnHeaderDirective, ...(ngDevMode ? [{ debugName: "headerTemplateQuery", read: TemplateRef }] : [{
                read: TemplateRef
            }]));
        this.treeToggleTemplateInput = input(undefined, ...(ngDevMode ? [{ debugName: "treeToggleTemplateInput", alias: 'treeToggleTemplate' }] : [{
                alias: 'treeToggleTemplate'
            }]));
        this.treeToggleTemplateQuery = contentChild(DataTableColumnCellTreeToggle, ...(ngDevMode ? [{ debugName: "treeToggleTemplateQuery", read: TemplateRef }] : [{
                read: TemplateRef
            }]));
        this.ghostCellTemplateInput = input(undefined, ...(ngDevMode ? [{ debugName: "ghostCellTemplateInput", alias: 'ghostCellTemplate' }] : [{
                alias: 'ghostCellTemplate'
            }]));
        this.ghostCellTemplateQuery = contentChild(DataTableColumnGhostCellDirective, ...(ngDevMode ? [{ debugName: "ghostCellTemplateQuery", read: TemplateRef }] : [{
                read: TemplateRef
            }]));
        /**
         * Computed property that returns the column configuration as a TableColumn object
         */
        this.column = computed(() => ({
            name: this.name(),
            prop: this.prop(),
            bindAsUnsafeHtml: this.bindAsUnsafeHtml(),
            frozenLeft: this.frozenLeft(),
            frozenRight: this.frozenRight(),
            flexGrow: this.flexGrow(),
            resizeable: this.resizeable(),
            comparator: this.comparator(),
            pipe: this.pipe(),
            sortable: this.sortable(),
            draggable: this.draggable(),
            canAutoResize: this.canAutoResize(),
            minWidth: this.minWidth(),
            width: this.width(),
            maxWidth: this.maxWidth(),
            checkboxable: this.checkboxable(),
            headerCheckboxable: this.headerCheckboxable(),
            headerClass: this.headerClass(),
            cellClass: this.cellClass(),
            isTreeColumn: this.isTreeColumn(),
            treeLevelIndent: this.treeLevelIndent(),
            summaryFunc: this.summaryFunc(),
            summaryTemplate: this.summaryTemplate(),
            cellTemplate: this.cellTemplateInput() ?? this.cellTemplateQuery(),
            headerTemplate: this.headerTemplateInput() ?? this.headerTemplateQuery(),
            treeToggleTemplate: this.treeToggleTemplateInput() ?? this.treeToggleTemplateQuery(),
            ghostCellTemplate: this.ghostCellTemplateInput() ?? this.ghostCellTemplateQuery()
        }), ...(ngDevMode ? [{ debugName: "column" }] : []));
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DataTableColumnDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
    static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "20.3.15", type: DataTableColumnDirective, isStandalone: true, selector: "ngx-datatable-column", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, prop: { classPropertyName: "prop", publicName: "prop", isSignal: true, isRequired: false, transformFunction: null }, bindAsUnsafeHtml: { classPropertyName: "bindAsUnsafeHtml", publicName: "bindAsUnsafeHtml", isSignal: true, isRequired: false, transformFunction: null }, frozenLeft: { classPropertyName: "frozenLeft", publicName: "frozenLeft", isSignal: true, isRequired: false, transformFunction: null }, frozenRight: { classPropertyName: "frozenRight", publicName: "frozenRight", isSignal: true, isRequired: false, transformFunction: null }, flexGrow: { classPropertyName: "flexGrow", publicName: "flexGrow", isSignal: true, isRequired: false, transformFunction: null }, resizeable: { classPropertyName: "resizeable", publicName: "resizeable", isSignal: true, isRequired: false, transformFunction: null }, comparator: { classPropertyName: "comparator", publicName: "comparator", isSignal: true, isRequired: false, transformFunction: null }, pipe: { classPropertyName: "pipe", publicName: "pipe", isSignal: true, isRequired: false, transformFunction: null }, sortable: { classPropertyName: "sortable", publicName: "sortable", isSignal: true, isRequired: false, transformFunction: null }, draggable: { classPropertyName: "draggable", publicName: "draggable", isSignal: true, isRequired: false, transformFunction: null }, canAutoResize: { classPropertyName: "canAutoResize", publicName: "canAutoResize", isSignal: true, isRequired: false, transformFunction: null }, minWidth: { classPropertyName: "minWidth", publicName: "minWidth", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, maxWidth: { classPropertyName: "maxWidth", publicName: "maxWidth", isSignal: true, isRequired: false, transformFunction: null }, checkboxable: { classPropertyName: "checkboxable", publicName: "checkboxable", isSignal: true, isRequired: false, transformFunction: null }, headerCheckboxable: { classPropertyName: "headerCheckboxable", publicName: "headerCheckboxable", isSignal: true, isRequired: false, transformFunction: null }, headerClass: { classPropertyName: "headerClass", publicName: "headerClass", isSignal: true, isRequired: false, transformFunction: null }, cellClass: { classPropertyName: "cellClass", publicName: "cellClass", isSignal: true, isRequired: false, transformFunction: null }, isTreeColumn: { classPropertyName: "isTreeColumn", publicName: "isTreeColumn", isSignal: true, isRequired: false, transformFunction: null }, treeLevelIndent: { classPropertyName: "treeLevelIndent", publicName: "treeLevelIndent", isSignal: true, isRequired: false, transformFunction: null }, summaryFunc: { classPropertyName: "summaryFunc", publicName: "summaryFunc", isSignal: true, isRequired: false, transformFunction: null }, summaryTemplate: { classPropertyName: "summaryTemplate", publicName: "summaryTemplate", isSignal: true, isRequired: false, transformFunction: null }, cellTemplateInput: { classPropertyName: "cellTemplateInput", publicName: "cellTemplate", isSignal: true, isRequired: false, transformFunction: null }, headerTemplateInput: { classPropertyName: "headerTemplateInput", publicName: "headerTemplate", isSignal: true, isRequired: false, transformFunction: null }, treeToggleTemplateInput: { classPropertyName: "treeToggleTemplateInput", publicName: "treeToggleTemplate", isSignal: true, isRequired: false, transformFunction: null }, ghostCellTemplateInput: { classPropertyName: "ghostCellTemplateInput", publicName: "ghostCellTemplate", isSignal: true, isRequired: false, transformFunction: null } }, queries: [{ propertyName: "cellTemplateQuery", first: true, predicate: DataTableColumnCellDirective, descendants: true, read: TemplateRef, isSignal: true }, { propertyName: "headerTemplateQuery", first: true, predicate: DataTableColumnHeaderDirective, descendants: true, read: TemplateRef, isSignal: true }, { propertyName: "treeToggleTemplateQuery", first: true, predicate: DataTableColumnCellTreeToggle, descendants: true, read: TemplateRef, isSignal: true }, { propertyName: "ghostCellTemplateQuery", first: true, predicate: DataTableColumnGhostCellDirective, descendants: true, read: TemplateRef, isSignal: true }], ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DataTableColumnDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: 'ngx-datatable-column'
                }]
        }], propDecorators: { name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], prop: [{ type: i0.Input, args: [{ isSignal: true, alias: "prop", required: false }] }], bindAsUnsafeHtml: [{ type: i0.Input, args: [{ isSignal: true, alias: "bindAsUnsafeHtml", required: false }] }], frozenLeft: [{ type: i0.Input, args: [{ isSignal: true, alias: "frozenLeft", required: false }] }], frozenRight: [{ type: i0.Input, args: [{ isSignal: true, alias: "frozenRight", required: false }] }], flexGrow: [{ type: i0.Input, args: [{ isSignal: true, alias: "flexGrow", required: false }] }], resizeable: [{ type: i0.Input, args: [{ isSignal: true, alias: "resizeable", required: false }] }], comparator: [{ type: i0.Input, args: [{ isSignal: true, alias: "comparator", required: false }] }], pipe: [{ type: i0.Input, args: [{ isSignal: true, alias: "pipe", required: false }] }], sortable: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortable", required: false }] }], draggable: [{ type: i0.Input, args: [{ isSignal: true, alias: "draggable", required: false }] }], canAutoResize: [{ type: i0.Input, args: [{ isSignal: true, alias: "canAutoResize", required: false }] }], minWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "minWidth", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], maxWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxWidth", required: false }] }], checkboxable: [{ type: i0.Input, args: [{ isSignal: true, alias: "checkboxable", required: false }] }], headerCheckboxable: [{ type: i0.Input, args: [{ isSignal: true, alias: "headerCheckboxable", required: false }] }], headerClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "headerClass", required: false }] }], cellClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "cellClass", required: false }] }], isTreeColumn: [{ type: i0.Input, args: [{ isSignal: true, alias: "isTreeColumn", required: false }] }], treeLevelIndent: [{ type: i0.Input, args: [{ isSignal: true, alias: "treeLevelIndent", required: false }] }], summaryFunc: [{ type: i0.Input, args: [{ isSignal: true, alias: "summaryFunc", required: false }] }], summaryTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "summaryTemplate", required: false }] }], cellTemplateInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "cellTemplate", required: false }] }], cellTemplateQuery: [{ type: i0.ContentChild, args: [i0.forwardRef(() => DataTableColumnCellDirective), { ...{ read: TemplateRef }, isSignal: true }] }], headerTemplateInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "headerTemplate", required: false }] }], headerTemplateQuery: [{ type: i0.ContentChild, args: [i0.forwardRef(() => DataTableColumnHeaderDirective), { ...{
                            read: TemplateRef
                        }, isSignal: true }] }], treeToggleTemplateInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "treeToggleTemplate", required: false }] }], treeToggleTemplateQuery: [{ type: i0.ContentChild, args: [i0.forwardRef(() => DataTableColumnCellTreeToggle), { ...{
                            read: TemplateRef
                        }, isSignal: true }] }], ghostCellTemplateInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "ghostCellTemplate", required: false }] }], ghostCellTemplateQuery: [{ type: i0.ContentChild, args: [i0.forwardRef(() => DataTableColumnGhostCellDirective), { ...{
                            read: TemplateRef
                        }, isSignal: true }] }] } });

/**
 * Visibility Observer Directive
 *
 * Usage:
 *
 * 		<div
 * 			visibilityObserver
 * 			(visible)="onVisible($event)">
 * 		</div>
 *
 */
class VisibilityDirective {
    constructor() {
        this.element = inject(ElementRef);
        this.zone = inject(NgZone);
        this.isVisible = signal(false, ...(ngDevMode ? [{ debugName: "isVisible" }] : []));
        this.visible = output();
    }
    ngOnInit() {
        this.runCheck();
    }
    ngOnDestroy() {
        clearTimeout(this.timeout);
    }
    onVisibilityChange() {
        // trigger zone recalc for columns
        this.zone.run(() => {
            this.isVisible.set(true);
            this.visible.emit(true);
        });
    }
    runCheck() {
        const check = () => {
            // https://davidwalsh.name/offsetheight-visibility
            const { offsetHeight, offsetWidth } = this.element.nativeElement;
            if (offsetHeight && offsetWidth) {
                clearTimeout(this.timeout);
                this.onVisibilityChange();
            }
            else {
                clearTimeout(this.timeout);
                this.zone.runOutsideAngular(() => {
                    this.timeout = window.setTimeout(() => check(), 50);
                });
            }
        };
        this.timeout = window.setTimeout(() => check());
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: VisibilityDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
    static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.15", type: VisibilityDirective, isStandalone: true, selector: "[visibilityObserver]", outputs: { visible: "visible" }, host: { properties: { "class.visible": "isVisible()" } }, ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: VisibilityDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[visibilityObserver]',
                    host: {
                        '[class.visible]': 'isVisible()'
                    }
                }]
        }], propDecorators: { visible: [{ type: i0.Output, args: ["visible"] }] } });

const NGX_DATATABLE_CONFIG = new InjectionToken('ngx-datatable.config');
/**
 * Provides a global configuration for ngx-datatable.
 *
 * @param overrides The overrides of the table configuration.
 */
const providedNgxDatatableConfig = (overrides) => {
    return {
        provide: NGX_DATATABLE_CONFIG,
        useValue: overrides
    };
};

/**
 * Gets the width of the scrollbar.  Nesc for windows
 * http://stackoverflow.com/a/13382873/888165
 */
class ScrollbarHelper {
    constructor() {
        this.document = inject(DOCUMENT);
        this.width = this.getWidth();
    }
    getWidth() {
        const outer = this.document.createElement('div');
        outer.style.visibility = 'hidden';
        outer.style.width = '100px';
        this.document.body.appendChild(outer);
        const widthNoScroll = outer.offsetWidth;
        outer.style.overflow = 'scroll';
        const inner = this.document.createElement('div');
        inner.style.width = '100%';
        outer.appendChild(inner);
        const widthWithScroll = inner.offsetWidth;
        this.document.body.removeChild(outer);
        return widthNoScroll - widthWithScroll;
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ScrollbarHelper, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ScrollbarHelper, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ScrollbarHelper, decorators: [{
            type: Injectable,
            args: [{ providedIn: 'root' }]
        }] });

/**
 * @deprecated The constant `SortDirection` should no longer be used. Instead use the value directly:
 * ```
 * // old
 * const sortDir: SortDirection = SortDirection.asc;
 * // new
 * const sortDir: SortDirection = 'asc';
 * ```
 */
// eslint-disable-next-line @typescript-eslint/naming-convention
const SortDirection = {
    asc: 'asc',
    desc: 'desc'
};
/**
 * @deprecated The constant `SortType` should no longer be used. Instead use the value directly:
 * ```
 * // old
 * const sortType: SortType = SortType.single;
 * // new
 * const sortType: SortType = 'single';
 * ```
 */
// eslint-disable-next-line @typescript-eslint/naming-convention
const SortType = {
    single: 'single',
    multi: 'multi'
};
/**
 * @deprecated The constant `ColumnMode` should no longer be used. Instead use the value directly:
 * ```
 * // old
 * <ngx-datatable [columnMode]="ColumnMode.force"></ngx-datatable>
 * // new
 * <ngx-datatable [columnMode]="'force'"></ngx-datatable>
 * ```
 */
// eslint-disable-next-line @typescript-eslint/naming-convention
const ColumnMode = {
    standard: 'standard',
    flex: 'flex',
    force: 'force'
};
/**
 * @deprecated The constant `ContextmenuType` should no longer be used. Instead use the value directly:
 * ```
 * // old
 * const contextmenuType: ContextmenuType = ContextmenuType.header;
 * // new
 * const contextmenuType: ContextmenuType = 'header';
 * ```
 */
// eslint-disable-next-line @typescript-eslint/naming-convention
const ContextmenuType = {
    header: 'header',
    body: 'body'
};
/**
 * @deprecated The constant `SelectionType` should no longer be used. Instead use the value directly:
 * ```
 * // old
 * <ngx-datatable [selectionType]="SelectionType.multi"></ngx-datatable>
 * // new
 * <ngx-datatable [selectionType]="'multi'"></ngx-datatable>
 * ```
 */
// eslint-disable-next-line @typescript-eslint/naming-convention
const SelectionType = {
    single: 'single',
    multi: 'multi',
    multiClick: 'multiClick',
    cell: 'cell',
    checkbox: 'checkbox'
};

/**
 * Converts strings from something to camel case
 * http://stackoverflow.com/questions/10425287/convert-dash-separated-string-to-camelcase
 */
const camelCase = (str) => {
    // Replace special characters with a space
    str = str.replace(/[^a-zA-Z0-9 ]/g, ' ');
    // put a space before an uppercase letter
    str = str.replace(/([a-z](?=[A-Z]))/g, '$1 ');
    // Lower case first character and some other stuff
    str = str
        .replace(/([^a-zA-Z0-9 ])|^[0-9]+/g, '')
        .trim()
        .toLowerCase();
    // uppercase characters preceded by a space or number
    str = str.replace(/([ 0-9]+)([a-zA-Z])/g, (a, b, c) => {
        return b.trim() + c.toUpperCase();
    });
    return str;
};
/**
 * Converts strings from camel case to words
 * http://stackoverflow.com/questions/7225407/convert-camelcasetext-to-camel-case-text
 */
const deCamelCase = (str) => {
    return str.replace(/([A-Z])/g, match => ` ${match}`).replace(/^./, match => match.toUpperCase());
};

/**
 * Always returns the empty string ''
 */
const emptyStringGetter = () => {
    return '';
};
/**
 * Returns the appropriate getter function for this kind of prop.
 * If prop == null, returns the emptyStringGetter.
 */
const getterForProp = (prop) => {
    // TODO requires better typing which will also involve adjust TableColum. So postponing it.
    if (prop == null) {
        return emptyStringGetter;
    }
    if (typeof prop === 'number') {
        return numericIndexGetter;
    }
    else {
        // deep or simple
        if (prop.includes('.')) {
            return deepValueGetter;
        }
        else {
            return shallowValueGetter;
        }
    }
};
/**
 * Returns the value at this numeric index.
 * @param row array of values
 * @param index numeric index
 * @returns any or '' if invalid index
 */
const numericIndexGetter = (row, index) => {
    if (row == null) {
        return '';
    }
    // mimic behavior of deepValueGetter
    if (!row || index == null) {
        return row;
    }
    const value = row[index];
    if (value == null) {
        return '';
    }
    return value;
};
/**
 * Returns the value of a field.
 * (more efficient than deepValueGetter)
 * @param obj object containing the field
 * @param fieldName field name string
 */
const shallowValueGetter = (obj, fieldName) => {
    if (obj == null) {
        return '';
    }
    if (!obj || !fieldName) {
        return obj;
    }
    const value = obj[fieldName];
    if (value == null) {
        return '';
    }
    return value;
};
/**
 * Returns a deep object given a string. zoo['animal.type']
 */
const deepValueGetter = (obj, path) => {
    if (obj == null) {
        return '';
    }
    if (!obj || !path) {
        return obj;
    }
    // check if path matches a root-level field
    // { "a.b.c": 123 }
    let current = obj[path];
    if (current !== undefined) {
        return current;
    }
    current = obj;
    const splits = path.split('.');
    if (splits.length) {
        for (const split of splits) {
            current = current[split];
            // if found undefined, return empty string
            if (current === undefined || current === null) {
                return '';
            }
        }
    }
    return current;
};

/**
 * Creates a unique object id.
 * http://stackoverflow.com/questions/6248666/how-to-generate-short-uid-like-ax4j9z-in-js
 */
const id = () => {
    return ('0000' + ((Math.random() * Math.pow(36, 4)) << 0).toString(36)).slice(-4);
};

/**
 * Gets the next sort direction
 */
const nextSortDir = (sortType, current) => {
    if (sortType === SortType.single) {
        if (current === SortDirection.asc) {
            return SortDirection.desc;
        }
        else {
            return SortDirection.asc;
        }
    }
    else {
        if (!current) {
            return SortDirection.asc;
        }
        else if (current === SortDirection.asc) {
            return SortDirection.desc;
        }
        else if (current === SortDirection.desc) {
            return undefined;
        }
        // avoid TS7030: Not all code paths return a value.
        return undefined;
    }
};
/**
 * Adapted from fueld-ui on 6/216
 * https://github.com/FuelInteractive/fuel-ui/tree/master/src/pipes/OrderBy
 */
const orderByComparator = (a, b) => {
    if (a === null || typeof a === 'undefined') {
        a = 0;
    }
    if (b === null || typeof b === 'undefined') {
        b = 0;
    }
    if (a instanceof Date && b instanceof Date) {
        if (a < b) {
            return -1;
        }
        if (a > b) {
            return 1;
        }
    }
    else if (isNaN(parseFloat(a)) || !isFinite(a) || isNaN(parseFloat(b)) || !isFinite(b)) {
        // Convert to string in case of a=0 or b=0
        a = String(a);
        b = String(b);
        // Isn't a number so lowercase the string to properly compare
        if (a.toLowerCase() < b.toLowerCase()) {
            return -1;
        }
        if (a.toLowerCase() > b.toLowerCase()) {
            return 1;
        }
    }
    else {
        // Parse strings as numbers to compare properly
        if (parseFloat(a) < parseFloat(b)) {
            return -1;
        }
        if (parseFloat(a) > parseFloat(b)) {
            return 1;
        }
    }
    // equal each other
    return 0;
};
/**
 * creates a shallow copy of the `rows` input and returns the sorted copy. this function
 * does not sort the `rows` argument in place
 */
const sortRows = (rows, columns, dirs, sortOnGroupHeader) => {
    if (!rows) {
        return [];
    }
    if (!dirs?.length || !columns) {
        return [...rows];
    }
    const temp = [...rows];
    const cols = columns.reduce((obj, col) => {
        if (col.sortable) {
            obj[col.prop] = col.comparator;
        }
        return obj;
    }, {});
    // cache valueGetter and compareFn so that they
    // do not need to be looked-up in the sort function body
    const cachedDirs = dirs.map(dir => {
        // When sorting on group header, override prop to 'key'
        const prop = sortOnGroupHeader?.prop === dir.prop ? 'key' : dir.prop;
        const compareFn = cols[dir.prop];
        return {
            prop,
            dir: dir.dir,
            valueGetter: getterForProp(prop),
            compareFn
        };
    });
    return temp.sort((rowA, rowB) => {
        for (const cachedDir of cachedDirs) {
            // Get property and valuegetters for column to be sorted
            const { prop, valueGetter } = cachedDir;
            // Get A and B cell values from rows based on properties of the columns
            const propA = valueGetter(rowA, prop);
            const propB = valueGetter(rowB, prop);
            // Compare function gets five parameters:
            // Two cell values to be compared as propA and propB
            // Two rows corresponding to the cells as rowA and rowB
            // Direction of the sort for this column as SortDirection
            // Compare can be a standard JS comparison function (a,b) => -1|0|1
            // as additional parameters are silently ignored. The whole row and sort
            // direction enable more complex sort logic.
            const comparison = cachedDir.dir !== SortDirection.desc
                ? cachedDir.compareFn(propA, propB, rowA, rowB)
                : -cachedDir.compareFn(propA, propB, rowA, rowB);
            // Don't return 0 yet in case of needing to sort by next property
            if (comparison !== 0) {
                return comparison;
            }
        }
        return 0;
    });
};
const sortGroupedRows = (groupedRows, columns, dirs, sortOnGroupHeader) => {
    if (sortOnGroupHeader) {
        groupedRows = sortRows(groupedRows, columns, dirs, sortOnGroupHeader);
    }
    return groupedRows.map(group => ({ ...group, value: sortRows(group.value, columns, dirs) }));
};

const toInternalColumn = (columns, defaultColumnWidth = 150) => {
    let hasTreeColumn = false;
    // TS fails to infer the type here.
    return columns.map(column => {
        const prop = column.prop ?? (column.name ? camelCase(column.name) : undefined);
        // Only one column should hold the tree view,
        // Thus if multiple columns are provided with
        // isTreeColumn as true, we take only the first one
        const isTreeColumn = !!column.isTreeColumn && !hasTreeColumn;
        hasTreeColumn = hasTreeColumn || isTreeColumn;
        // TODO: add check if prop or name is provided if sorting is enabled.
        return {
            ...column,
            $$id: id(),
            $$valueGetter: getterForProp(prop),
            prop,
            name: column.name ?? (prop ? deCamelCase(String(prop)) : ''),
            resizeable: column.resizeable ?? true,
            sortable: column.sortable ?? true,
            comparator: column.comparator ?? orderByComparator,
            draggable: column.draggable ?? true,
            canAutoResize: column.canAutoResize ?? true,
            width: column.width ?? defaultColumnWidth,
            isTreeColumn,
            // in case of the directive, those are getters, so call them explicitly.
            headerTemplate: column.headerTemplate,
            cellTemplate: column.cellTemplate,
            summaryTemplate: column.summaryTemplate,
            ghostCellTemplate: column.ghostCellTemplate,
            treeToggleTemplate: column.treeToggleTemplate
        }; // TS cannot cast here
    });
};

/**
 * Returns the columns by pin.
 */
const columnsByPin = (cols) => {
    const ret = {
        left: [],
        center: [],
        right: []
    };
    if (cols) {
        for (const col of cols) {
            if (col.frozenLeft) {
                ret.left.push(col);
            }
            else if (col.frozenRight) {
                ret.right.push(col);
            }
            else {
                ret.center.push(col);
            }
        }
    }
    return ret;
};
/**
 * Returns the widths of all group sets of a column
 */
const columnGroupWidths = (groups, all) => {
    return {
        left: columnTotalWidth(groups.left),
        center: columnTotalWidth(groups.center),
        right: columnTotalWidth(groups.right),
        total: Math.floor(columnTotalWidth(all))
    };
};
/**
 * Calculates the total width of all columns
 */
const columnTotalWidth = (columns) => {
    return columns?.reduce((total, column) => total + column.width, 0) ?? 0;
};
const columnsByPinArr = (val) => {
    const colsByPin = columnsByPin(val);
    return [
        { type: 'left', columns: colsByPin.left },
        { type: 'center', columns: colsByPin.center },
        { type: 'right', columns: colsByPin.right }
    ];
};

/**
 * Calculates the Total Flex Grow
 */
const getTotalFlexGrow = (columns) => {
    let totalFlexGrow = 0;
    for (const c of columns) {
        totalFlexGrow += c.flexGrow ?? 0;
    }
    return totalFlexGrow;
};
/**
 * Adjusts the column widths.
 * Inspired by: https://github.com/facebookarchive/fixed-data-table/blob/master/src/FixedDataTableWidthHelper.js
 */
const adjustColumnWidths = (allColumns, expectedWidth) => {
    const columnsWidth = columnTotalWidth(allColumns);
    const totalFlexGrow = getTotalFlexGrow(allColumns);
    const colsByGroup = columnsByPin(allColumns);
    if (columnsWidth !== expectedWidth) {
        scaleColumns(colsByGroup, expectedWidth, totalFlexGrow);
    }
};
/**
 * Resizes columns based on the flexGrow property, while respecting manually set widths
 */
const scaleColumns = (colsByGroup, maxWidth, totalFlexGrow) => {
    const columns = Object.values(colsByGroup).flat();
    let remainingWidth = maxWidth;
    // calculate total width and flexgrow points for columns that can be resized
    for (const column of columns) {
        if (column.$$oldWidth) {
            // when manually resized, switch off auto-resize
            column.canAutoResize = false;
        }
        if (!column.canAutoResize) {
            remainingWidth -= column.width;
            totalFlexGrow -= column.flexGrow ?? 0;
        }
        else {
            column.width = 0;
        }
    }
    const hasMinWidth = {};
    // resize columns until no width is left to be distributed
    do {
        const widthPerFlexPoint = remainingWidth / totalFlexGrow;
        remainingWidth = 0;
        for (const column of columns) {
            // if the column can be resize and it hasn't reached its minimum width yet
            if (column.canAutoResize && !hasMinWidth[column.prop]) {
                const newWidth = column.width + column.flexGrow * widthPerFlexPoint;
                if (column.minWidth !== undefined && newWidth < column.minWidth) {
                    remainingWidth += newWidth - column.minWidth;
                    column.width = column.minWidth;
                    hasMinWidth[column.prop] = true;
                }
                else {
                    column.width = newWidth;
                }
            }
        }
    } while (remainingWidth !== 0);
    // Adjust for any remaining offset in computed widths vs maxWidth
    const totalWidthAchieved = columns.reduce((acc, col) => acc + col.width, 0);
    const delta = maxWidth - totalWidthAchieved;
    if (delta === 0) {
        return;
    }
    // adjust the first column that can be auto-resized respecting the min/max widths
    for (const col of columns.filter(c => c.canAutoResize).sort((a, b) => a.width - b.width)) {
        if ((delta > 0 && (!col.maxWidth || col.width + delta <= col.maxWidth)) ||
            (delta < 0 && (!col.minWidth || col.width + delta >= col.minWidth))) {
            col.width += delta;
            break;
        }
    }
};
/**
 * Forces the width of the columns to
 * distribute equally but overflowing when necessary
 *
 * Rules:
 *
 *  - If combined withs are less than the total width of the grid,
 *    proportion the widths given the min / max / normal widths to fill the width.
 *
 *  - If the combined widths, exceed the total width of the grid,
 *    use the standard widths.
 *
 *  - If a column is resized, it should always use that width
 *
 *  - The proportional widths should never fall below min size if specified.
 *
 *  - If the grid starts off small but then becomes greater than the size ( + / - )
 *    the width should use the original width; not the newly proportioned widths.
 */
const forceFillColumnWidths = (allColumns, expectedWidth, startIdx, allowBleed, defaultColWidth = 150, verticalScrollWidth = 0) => {
    const columnsToResize = allColumns
        .slice(startIdx + 1, allColumns.length)
        .filter(c => c.canAutoResize !== false);
    let additionWidthPerColumn = 0;
    let exceedsWindow = false;
    let contentWidth = getContentWidth(allColumns, defaultColWidth);
    let remainingWidth = expectedWidth - contentWidth;
    const initialRemainingWidth = remainingWidth;
    const columnsProcessed = [];
    const remainingWidthLimit = 1; // when to stop
    // This loop takes care of the
    do {
        additionWidthPerColumn = remainingWidth / columnsToResize.length;
        exceedsWindow = contentWidth >= expectedWidth;
        for (const column of columnsToResize) {
            // don't bleed if the initialRemainingWidth is same as verticalScrollWidth
            if (exceedsWindow && allowBleed && initialRemainingWidth !== -1 * verticalScrollWidth) {
                // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
                column.width = column.width || defaultColWidth;
            }
            else {
                // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
                const newSize = (column.width || defaultColWidth) + additionWidthPerColumn;
                if (column.minWidth && newSize < column.minWidth) {
                    column.width = column.minWidth;
                    columnsProcessed.push(column);
                }
                else if (column.maxWidth && newSize > column.maxWidth) {
                    column.width = column.maxWidth;
                    columnsProcessed.push(column);
                }
                else {
                    column.width = newSize;
                }
            }
            column.width = Math.max(0, column.width);
        }
        contentWidth = getContentWidth(allColumns, defaultColWidth);
        remainingWidth = expectedWidth - contentWidth;
        removeProcessedColumns(columnsToResize, columnsProcessed);
    } while (remainingWidth > remainingWidthLimit && columnsToResize.length !== 0);
};
/**
 * Remove the processed columns from the current active columns.
 */
const removeProcessedColumns = (columnsToResize, columnsProcessed) => {
    for (const column of columnsProcessed) {
        const index = columnsToResize.indexOf(column);
        columnsToResize.splice(index, 1);
    }
};
/**
 * Gets the width of the columns
 */
const getContentWidth = (allColumns, defaultColWidth = 150) => {
    let contentWidth = 0;
    for (const column of allColumns) {
        // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
        contentWidth += column.width || defaultColWidth;
    }
    return contentWidth;
};

/**
 * Same as {@link numberAttribute} but returns `undefined` if the value is `undefined`.
 * {@link numberAttribute} would return `NaN` in that case.
 * @param value
 */
// Must be a function.
// eslint-disable-next-line prefer-arrow/prefer-arrow-functions
function numberOrUndefinedAttribute(value) {
    if (value === undefined) {
        return undefined;
    }
    return numberAttribute(value);
}

/**
 * This token is created to break cycling import error which occurs when we import
 * DatatableComponent in DataTableRowWrapperComponent.
 */
const DATATABLE_COMPONENT_TOKEN = new InjectionToken('DatatableComponentToken');

/**
 * Throttle a function
 */
const throttle = (func, wait, options) => {
    options ??= {};
    let args;
    let result;
    let timeout = null;
    let previous = 0;
    const later = () => {
        previous = options.leading === false ? 0 : +new Date();
        timeout = null;
        result = func(...args);
    };
    return (...argsNew) => {
        const now = +new Date();
        if (!previous && options.leading === false) {
            previous = now;
        }
        const remaining = wait - (now - previous);
        args = argsNew;
        if (remaining <= 0) {
            clearTimeout(timeout);
            timeout = null;
            previous = now;
            result = func(...args);
        }
        else if (!timeout && options.trailing !== false) {
            timeout = setTimeout(later, remaining);
        }
        return result;
    };
};
/**
 * Throttle decorator
 *
 *  class MyClass {
 *    throttleable(10)
 *    myFn() { ... }
 *  }
 */
const throttleable = (duration, options) => {
    return (target, key, descriptor) => {
        return {
            configurable: true,
            enumerable: descriptor.enumerable,
            get: function () {
                Object.defineProperty(this, key, {
                    configurable: true,
                    enumerable: descriptor.enumerable,
                    value: throttle(descriptor.value.bind(this), duration, options)
                });
                return this[key];
            }
        };
    };
};

const optionalGetterForProp = (prop) => {
    return prop ? row => getterForProp(prop)(row, prop) : undefined;
};
/**
 * This functions rearrange items by their parents
 * Also sets the level value to each of the items
 *
 * Note: Expecting each item has a property called parentId
 * Note: This algorithm will fail if a list has two or more items with same ID
 * NOTE: This algorithm will fail if there is a deadlock of relationship
 *
 * For example,
 *
 * Input
 *
 * id -> parent
 * 1  -> 0
 * 2  -> 0
 * 3  -> 1
 * 4  -> 1
 * 5  -> 2
 * 7  -> 8
 * 6  -> 3
 *
 *
 * Output
 * id -> level
 * 1      -> 0
 * --3    -> 1
 * ----6  -> 2
 * --4    -> 1
 * 2      -> 0
 * --5    -> 1
 * 7     -> 8
 *
 *
 * @param rows
 *
 */
const groupRowsByParents = (rows, from, to) => {
    if (from && to) {
        const treeRows = rows.filter(row => !!row).map(row => new TreeNode(row));
        const uniqIDs = new Map(treeRows.map(node => [to(node.row), node]));
        const rootNodes = treeRows.reduce((root, node) => {
            const fromValue = from(node.row);
            const parent = uniqIDs.get(fromValue);
            if (parent) {
                node.row.level = parent.row.level + 1; // TODO: should be reflected by type, that level is defined
                node.parent = parent;
                parent.children.push(node);
            }
            else {
                node.row.level = 0;
                root.push(node);
            }
            return root;
        }, []);
        return rootNodes.flatMap(child => child.flatten());
    }
    else {
        return rows;
    }
};
class TreeNode {
    constructor(row) {
        this.row = row;
        this.children = [];
    }
    flatten() {
        if (this.row.treeStatus === 'expanded') {
            return [this.row, ...this.children.flatMap(child => child.flatten())];
        }
        else {
            return [this.row];
        }
    }
}

const ARROW_UP = 'ArrowUp';
const ARROW_DOWN = 'ArrowDown';
const ENTER = 'Enter';
const ESCAPE = 'Escape';
const ARROW_LEFT = 'ArrowLeft';
const ARROW_RIGHT = 'ArrowRight';

/**
 * This object contains the cache of the various row heights that are present inside
 * the data table.   Its based on Fenwick tree data structure that helps with
 * querying sums that have time complexity of log n.
 *
 * Fenwick Tree Credits: http://petr-mitrichev.blogspot.com/2013/05/fenwick-tree-range-updates.html
 * https://github.com/mikolalysenko/fenwick-tree
 *
 */
class RowHeightCache {
    constructor() {
        /**
         * Tree Array stores the cumulative information of the row heights to perform efficient
         * range queries and updates.  Currently the tree is initialized to the base row
         * height instead of the detail row height.
         */
        this.treeArray = [];
    }
    /**
     * Clear the Tree array.
     */
    clearCache() {
        this.treeArray = [];
    }
    /**
     * Initialize the Fenwick tree with row Heights.
     */
    initCache(details) {
        const { rows, rowHeight, detailRowHeight, externalVirtual, indexOffset, rowCount, rowExpansions } = details;
        const isFn = typeof rowHeight === 'function';
        const isDetailFn = typeof detailRowHeight === 'function';
        if (rowHeight === 'auto' || (!isFn && isNaN(rowHeight))) {
            throw new Error(`Row Height cache initialization failed. Please ensure that 'rowHeight' is a
        valid number or function value: (${rowHeight}) when 'scrollbarV' is enabled.`);
        }
        // Add this additional guard in case detailRowHeight is set to 'auto' as it wont work.
        if (!isDetailFn && isNaN(detailRowHeight)) {
            throw new Error(`Row Height cache initialization failed. Please ensure that 'detailRowHeight' is a
        valid number or function value: (${detailRowHeight}) when 'scrollbarV' is enabled.`);
        }
        const n = externalVirtual ? rowCount : rows.length;
        this.treeArray = new Array(n);
        for (let i = 0; i < n; ++i) {
            this.treeArray[i] = 0;
        }
        for (let i = 0; i < n; ++i) {
            const row = rows[i];
            let currentRowHeight = isFn ? rowHeight(row) : rowHeight;
            // Add the detail row height to the already expanded rows.
            // This is useful for the table that goes through a filter or sort.
            const expanded = rowExpansions.has(row);
            if (row && expanded) {
                currentRowHeight += isDetailFn ? detailRowHeight(row, indexOffset + i) : detailRowHeight;
            }
            this.update(i, currentRowHeight);
        }
    }
    /**
     * Given the ScrollY position i.e. sum, provide the rowIndex
     * that is present in the current view port.  Below handles edge cases.
     */
    getRowIndex(scrollY) {
        if (scrollY === 0) {
            return 0;
        }
        return this.calcRowIndex(scrollY);
    }
    /**
     * When a row is expanded or rowHeight is changed, update the height.  This can
     * be utilized in future when Angular Data table supports dynamic row heights.
     */
    update(atRowIndex, byRowHeight) {
        if (!this.treeArray.length) {
            throw new Error(`Update at index ${atRowIndex} with value ${byRowHeight} failed:
        Row Height cache not initialized.`);
        }
        const n = this.treeArray.length;
        atRowIndex |= 0;
        while (atRowIndex < n) {
            this.treeArray[atRowIndex] += byRowHeight;
            atRowIndex |= atRowIndex + 1;
        }
    }
    /**
     * Range Sum query from 1 to the rowIndex
     */
    query(atIndex) {
        if (!this.treeArray.length) {
            throw new Error(`query at index ${atIndex} failed: Fenwick tree array not initialized.`);
        }
        let sum = 0;
        atIndex |= 0;
        while (atIndex >= 0) {
            sum += this.treeArray[atIndex];
            atIndex = (atIndex & (atIndex + 1)) - 1;
        }
        return sum;
    }
    /**
     * Find the total height between 2 row indexes
     */
    queryBetween(atIndexA, atIndexB) {
        return this.query(atIndexB) - this.query(atIndexA - 1);
    }
    /**
     * Given the ScrollY position i.e. sum, provide the rowIndex
     * that is present in the current view port.
     */
    calcRowIndex(sum) {
        if (!this.treeArray.length) {
            return 0;
        }
        let pos = -1;
        const dataLength = this.treeArray.length;
        // Get the highest bit for the block size.
        const highestBit = Math.pow(2, dataLength.toString(2).length - 1);
        for (let blockSize = highestBit; blockSize !== 0; blockSize >>= 1) {
            const nextPos = pos + blockSize;
            if (nextPos < dataLength && sum >= this.treeArray[nextPos]) {
                sum -= this.treeArray[nextPos];
                pos = nextPos;
            }
        }
        return pos + 1;
    }
}

const selectRows = (selected, row, comparefn) => {
    const selectedIndex = comparefn(row, selected);
    if (selectedIndex > -1) {
        selected.splice(selectedIndex, 1);
    }
    else {
        selected.push(row);
    }
    return selected;
};
const selectRowsBetween = (selected, rows, index, prevIndex) => {
    const reverse = index < prevIndex;
    for (let i = 0; i < rows.length; i++) {
        const row = rows[i];
        const greater = i >= prevIndex && i <= index;
        const lesser = i <= prevIndex && i >= index;
        let range = { start: 0, end: 0 };
        if (reverse) {
            range = {
                start: index,
                end: prevIndex
            };
        }
        else {
            range = {
                start: prevIndex,
                end: index + 1
            };
        }
        if ((reverse && lesser) || (!reverse && greater)) {
            // if in the positive range to be added to `selected`, and
            // not already in the selected array, add it
            if (i >= range.start && i <= range.end && row) {
                selected.push(row);
            }
        }
    }
    return selected;
};

class DataTableGroupWrapperComponent {
    constructor() {
        this.innerWidth = input.required(...(ngDevMode ? [{ debugName: "innerWidth" }] : []));
        this.groupHeader = input.required(...(ngDevMode ? [{ debugName: "groupHeader" }] : []));
        this.groupHeaderRowHeight = input.required(...(ngDevMode ? [{ debugName: "groupHeaderRowHeight" }] : []));
        this.group = input.required(...(ngDevMode ? [{ debugName: "group" }] : []));
        this.groupedRows = input(...(ngDevMode ? [undefined, { debugName: "groupedRows" }] : []));
        this.selected = input.required(...(ngDevMode ? [{ debugName: "selected" }] : []));
        this.disabled = input(...(ngDevMode ? [undefined, { debugName: "disabled" }] : []));
        this.rowIndex = input.required(...(ngDevMode ? [{ debugName: "rowIndex" }] : []));
        this.expanded = input(false, ...(ngDevMode ? [{ debugName: "expanded", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
        this.ariaGroupHeaderCheckboxMessage = input.required(...(ngDevMode ? [{ debugName: "ariaGroupHeaderCheckboxMessage" }] : []));
        this.groupSelectedChange = output();
        this.context = computed(() => {
            return {
                group: this.group(),
                expanded: this.expanded(),
                rowIndex: this.rowIndex()
            };
        }, ...(ngDevMode ? [{ debugName: "context" }] : []));
        this.selectedRowsOfGroup = computed(() => {
            const groupValue = this.group().value;
            return this.selected().filter(row => groupValue.includes(row));
        }, ...(ngDevMode ? [{ debugName: "selectedRowsOfGroup" }] : []));
        this.checked = computed(() => this.selectedRowsOfGroup().length === this.group().value.length, ...(ngDevMode ? [{ debugName: "checked" }] : []));
        this.indeterminate = computed(() => this.selectedRowsOfGroup().length > 0 && !this.checked(), ...(ngDevMode ? [{ debugName: "indeterminate" }] : []));
    }
    onCheckboxChange(groupSelected) {
        this.groupSelectedChange.emit(groupSelected);
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DataTableGroupWrapperComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DataTableGroupWrapperComponent, isStandalone: true, selector: "datatable-group-wrapper", inputs: { innerWidth: { classPropertyName: "innerWidth", publicName: "innerWidth", isSignal: true, isRequired: true, transformFunction: null }, groupHeader: { classPropertyName: "groupHeader", publicName: "groupHeader", isSignal: true, isRequired: true, transformFunction: null }, groupHeaderRowHeight: { classPropertyName: "groupHeaderRowHeight", publicName: "groupHeaderRowHeight", isSignal: true, isRequired: true, transformFunction: null }, group: { classPropertyName: "group", publicName: "group", isSignal: true, isRequired: true, transformFunction: null }, groupedRows: { classPropertyName: "groupedRows", publicName: "groupedRows", isSignal: true, isRequired: false, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "selected", isSignal: true, isRequired: true, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, rowIndex: { classPropertyName: "rowIndex", publicName: "rowIndex", isSignal: true, isRequired: true, transformFunction: null }, expanded: { classPropertyName: "expanded", publicName: "expanded", isSignal: true, isRequired: false, transformFunction: null }, ariaGroupHeaderCheckboxMessage: { classPropertyName: "ariaGroupHeaderCheckboxMessage", publicName: "ariaGroupHeaderCheckboxMessage", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { groupSelectedChange: "groupSelectedChange" }, host: { classAttribute: "datatable-group-wrapper" }, ngImport: i0, template: `
    @let groupHeader = this.groupHeader();
    @if (groupHeader && groupHeader.template()) {
      <div
        class="datatable-group-header"
        [style.height.px]="groupHeaderRowHeight()"
        [style.width.px]="innerWidth()"
      >
        <div class="datatable-group-cell">
          @if (groupHeader.checkboxable()) {
            <div>
              <label class="datatable-checkbox">
                <input
                  #select
                  type="checkbox"
                  [attr.aria-label]="ariaGroupHeaderCheckboxMessage()"
                  [checked]="checked()"
                  [indeterminate]="indeterminate()"
                  (change)="onCheckboxChange(select.checked)"
                />
              </label>
            </div>
          }
          <ng-template
            [ngTemplateOutlet]="groupHeader.template()"
            [ngTemplateOutletContext]="context()"
          />
        </div>
      </div>
    }
    @if (expanded()) {
      <ng-content />
    }
  `, isInline: true, styles: [":host{display:flex;flex-direction:column}.datatable-group-header{inset-inline-start:0;position:sticky}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DataTableGroupWrapperComponent, decorators: [{
            type: Component,
            args: [{ selector: 'datatable-group-wrapper', imports: [NgTemplateOutlet], template: `
    @let groupHeader = this.groupHeader();
    @if (groupHeader && groupHeader.template()) {
      <div
        class="datatable-group-header"
        [style.height.px]="groupHeaderRowHeight()"
        [style.width.px]="innerWidth()"
      >
        <div class="datatable-group-cell">
          @if (groupHeader.checkboxable()) {
            <div>
              <label class="datatable-checkbox">
                <input
                  #select
                  type="checkbox"
                  [attr.aria-label]="ariaGroupHeaderCheckboxMessage()"
                  [checked]="checked()"
                  [indeterminate]="indeterminate()"
                  (change)="onCheckboxChange(select.checked)"
                />
              </label>
            </div>
          }
          <ng-template
            [ngTemplateOutlet]="groupHeader.template()"
            [ngTemplateOutletContext]="context()"
          />
        </div>
      </div>
    }
    @if (expanded()) {
      <ng-content />
    }
  `, changeDetection: ChangeDetectionStrategy.OnPush, host: {
                        class: 'datatable-group-wrapper'
                    }, styles: [":host{display:flex;flex-direction:column}.datatable-group-header{inset-inline-start:0;position:sticky}\n"] }]
        }], propDecorators: { innerWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "innerWidth", required: true }] }], groupHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupHeader", required: true }] }], groupHeaderRowHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupHeaderRowHeight", required: true }] }], group: [{ type: i0.Input, args: [{ isSignal: true, alias: "group", required: true }] }], groupedRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupedRows", required: false }] }], selected: [{ type: i0.Input, args: [{ isSignal: true, alias: "selected", required: true }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], rowIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowIndex", required: true }] }], expanded: [{ type: i0.Input, args: [{ isSignal: true, alias: "expanded", required: false }] }], ariaGroupHeaderCheckboxMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaGroupHeaderCheckboxMessage", required: true }] }], groupSelectedChange: [{ type: i0.Output, args: ["groupSelectedChange"] }] } });

class DataTableRowWrapperComponent {
    constructor() {
        this.innerWidth = input.required(...(ngDevMode ? [{ debugName: "innerWidth" }] : []));
        this.rowDetail = input(...(ngDevMode ? [undefined, { debugName: "rowDetail" }] : []));
        this.detailRowHeightFn = input.required(...(ngDevMode ? [{ debugName: "detailRowHeightFn" }] : []));
        this.row = input.required(...(ngDevMode ? [{ debugName: "row" }] : []));
        this.disabled = input(...(ngDevMode ? [undefined, { debugName: "disabled" }] : []));
        this.rowContextmenu = output();
        this.rowIndex = input.required(...(ngDevMode ? [{ debugName: "rowIndex" }] : []));
        this.expanded = input(false, ...(ngDevMode ? [{ debugName: "expanded", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
        this.ariaGroupHeaderCheckboxMessage = input.required(...(ngDevMode ? [{ debugName: "ariaGroupHeaderCheckboxMessage" }] : []));
        this.detailsRowHeight = computed(() => this.detailRowHeightFn()(this.row(), this.rowIndex()), ...(ngDevMode ? [{ debugName: "detailsRowHeight" }] : []));
        this.context = computed(() => {
            this.rowDiffedCount(); // This allows us to get re-evaluated when the row was mutated internally.
            return {
                row: this.row(),
                expanded: this.expanded(),
                rowIndex: this.rowIndex(),
                disabled: this.disabled()
            };
        }, ...(ngDevMode ? [{ debugName: "context" }] : []));
        // This counter will be incremented every time the row object is mutated.
        this.rowDiffedCount = signal(0, ...(ngDevMode ? [{ debugName: "rowDiffedCount" }] : []));
        this.rowDiffer = inject(KeyValueDiffers).find({}).create();
    }
    ngDoCheck() {
        const row = this.row();
        if (this.rowDiffer.diff(row)) {
            this.rowDiffedCount.update(count => count + 1);
        }
    }
    onContextmenu($event) {
        this.rowContextmenu.emit({ event: $event, row: this.row() });
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DataTableRowWrapperComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DataTableRowWrapperComponent, isStandalone: true, selector: "datatable-row-wrapper", inputs: { innerWidth: { classPropertyName: "innerWidth", publicName: "innerWidth", isSignal: true, isRequired: true, transformFunction: null }, rowDetail: { classPropertyName: "rowDetail", publicName: "rowDetail", isSignal: true, isRequired: false, transformFunction: null }, detailRowHeightFn: { classPropertyName: "detailRowHeightFn", publicName: "detailRowHeightFn", isSignal: true, isRequired: true, transformFunction: null }, row: { classPropertyName: "row", publicName: "row", isSignal: true, isRequired: true, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, rowIndex: { classPropertyName: "rowIndex", publicName: "rowIndex", isSignal: true, isRequired: true, transformFunction: null }, expanded: { classPropertyName: "expanded", publicName: "expanded", isSignal: true, isRequired: false, transformFunction: null }, ariaGroupHeaderCheckboxMessage: { classPropertyName: "ariaGroupHeaderCheckboxMessage", publicName: "ariaGroupHeaderCheckboxMessage", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { rowContextmenu: "rowContextmenu" }, host: { listeners: { "contextmenu": "onContextmenu($event)" }, classAttribute: "datatable-row-wrapper" }, ngImport: i0, template: `
    <ng-content />
    @let rowDetailTemplate = rowDetail()?.template();
    @if (rowDetailTemplate && expanded()) {
      <div class="datatable-row-detail" [style.height.px]="detailsRowHeight()">
        <ng-template [ngTemplateOutlet]="rowDetailTemplate" [ngTemplateOutletContext]="context()" />
      </div>
    }
  `, isInline: true, styles: [":host{display:flex;flex-direction:column}.datatable-row-detail{overflow-y:hidden}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DataTableRowWrapperComponent, decorators: [{
            type: Component,
            args: [{ selector: 'datatable-row-wrapper', imports: [NgTemplateOutlet], template: `
    <ng-content />
    @let rowDetailTemplate = rowDetail()?.template();
    @if (rowDetailTemplate && expanded()) {
      <div class="datatable-row-detail" [style.height.px]="detailsRowHeight()">
        <ng-template [ngTemplateOutlet]="rowDetailTemplate" [ngTemplateOutletContext]="context()" />
      </div>
    }
  `, changeDetection: ChangeDetectionStrategy.OnPush, host: {
                        class: 'datatable-row-wrapper'
                    }, styles: [":host{display:flex;flex-direction:column}.datatable-row-detail{overflow-y:hidden}\n"] }]
        }], propDecorators: { innerWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "innerWidth", required: true }] }], rowDetail: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowDetail", required: false }] }], detailRowHeightFn: [{ type: i0.Input, args: [{ isSignal: true, alias: "detailRowHeightFn", required: true }] }], row: [{ type: i0.Input, args: [{ isSignal: true, alias: "row", required: true }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], rowContextmenu: [{ type: i0.Output, args: ["rowContextmenu"] }], rowIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowIndex", required: true }] }], expanded: [{ type: i0.Input, args: [{ isSignal: true, alias: "expanded", required: false }] }], ariaGroupHeaderCheckboxMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaGroupHeaderCheckboxMessage", required: true }] }], onContextmenu: [{
                type: HostListener,
                args: ['contextmenu', ['$event']]
            }] } });

class DataTableBodyCellComponent {
    constructor() {
        this.displayCheck = input(...(ngDevMode ? [undefined, { debugName: "displayCheck" }] : []));
        this.disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
        this.group = input(...(ngDevMode ? [undefined, { debugName: "group" }] : []));
        this.rowHeight = input(0, ...(ngDevMode ? [{ debugName: "rowHeight" }] : []));
        this.isSelected = input(false, ...(ngDevMode ? [{ debugName: "isSelected", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
        this.rowIndex = input(...(ngDevMode ? [undefined, { debugName: "rowIndex" }] : []));
        this.column = input.required(...(ngDevMode ? [{ debugName: "column" }] : []));
        this.row = input.required(...(ngDevMode ? [{ debugName: "row" }] : []));
        this.treeStatus = input('collapsed', ...(ngDevMode ? [{ debugName: "treeStatus" }] : []));
        this.ariaRowCheckboxMessage = input.required(...(ngDevMode ? [{ debugName: "ariaRowCheckboxMessage" }] : []));
        this.cssClasses = input.required(...(ngDevMode ? [{ debugName: "cssClasses" }] : []));
        this.expanded = input(false, ...(ngDevMode ? [{ debugName: "expanded", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
        this.activate = output();
        this.treeAction = output();
        this.columnCssClasses = computed(() => {
            let cls = 'datatable-body-cell';
            const column = this.column();
            if (column.cellClass) {
                if (typeof column.cellClass === 'string') {
                    cls += ' ' + column.cellClass;
                }
                else if (typeof column.cellClass === 'function') {
                    const res = column.cellClass({
                        row: this.row,
                        group: this.group(),
                        column: column,
                        value: this.value(),
                        rowHeight: this.rowHeight()
                    });
                    if (typeof res === 'string') {
                        cls += ' ' + res;
                    }
                    else if (typeof res === 'object') {
                        const keys = Object.keys(res);
                        for (const k of keys) {
                            if (res[k] === true) {
                                cls += ` ${k}`;
                            }
                        }
                    }
                }
            }
            if (this.isFocused() && !this.disabled()) {
                cls += ' active';
            }
            if (this.disabled()) {
                cls += ' row-disabled';
            }
            return cls;
        }, ...(ngDevMode ? [{ debugName: "columnCssClasses" }] : []));
        this.height = computed(() => {
            const height = this.rowHeight();
            if (isNaN(height)) {
                return height;
            }
            return height + 'px';
        }, ...(ngDevMode ? [{ debugName: "height" }] : []));
        this.sanitizedValue = computed(() => {
            const value = this.value();
            return value !== null && value !== undefined ? this.stripHtml(value) : value;
        }, ...(ngDevMode ? [{ debugName: "sanitizedValue" }] : []));
        this.value = linkedSignal(() => this.getComputedValue(), ...(ngDevMode ? [{ debugName: "value" }] : []));
        this.cellContext = computed(() => {
            return {
                onCheckboxChangeFn: (event) => this.onCheckboxChange(event),
                activateFn: (event) => this.activate.emit(event),
                row: this.row(),
                group: this.group(),
                value: this.value(),
                column: this.column(),
                rowHeight: this.rowHeight(),
                isSelected: this.isSelected(),
                rowIndex: this.rowIndex()?.index ?? 0,
                rowInGroupIndex: this.rowIndex()?.indexInGroup,
                treeStatus: this.treeStatus() ?? 'collapsed',
                disabled: this.disabled(),
                expanded: this.expanded(),
                onTreeAction: () => this.onTreeAction()
            };
        }, ...(ngDevMode ? [{ debugName: "cellContext" }] : []));
        this.isFocused = signal(false, ...(ngDevMode ? [{ debugName: "isFocused" }] : []));
        this._element = inject(ElementRef).nativeElement;
    }
    ngDoCheck() {
        const value = this.getComputedValue();
        if (value !== this.value()) {
            this.value.set(value);
        }
    }
    getComputedValue() {
        let value = '';
        const column = this.column();
        const row = this.row();
        if (!row || column.prop == undefined) {
            value = '';
        }
        else {
            const val = column.$$valueGetter(row, column.prop);
            const userPipe = column.pipe;
            if (userPipe) {
                value = userPipe.transform(val);
            }
            else if (value !== undefined) {
                value = val;
            }
        }
        return value;
    }
    onFocus() {
        this.isFocused.set(true);
    }
    onBlur() {
        this.isFocused.set(false);
    }
    onClick(event) {
        this.activate.emit({
            type: 'click',
            event,
            row: this.row(),
            group: this.group(),
            rowHeight: this.rowHeight(),
            column: this.column(),
            value: this.value(),
            cellElement: this._element
        });
    }
    onDblClick(event) {
        this.activate.emit({
            type: 'dblclick',
            event,
            row: this.row(),
            group: this.group(),
            rowHeight: this.rowHeight(),
            column: this.column(),
            value: this.value(),
            cellElement: this._element
        });
    }
    onKeyDown(event) {
        const key = event.key;
        const isTargetCell = event.target === this._element;
        const isAction = key === ENTER ||
            key === ARROW_DOWN ||
            key === ARROW_UP ||
            key === ARROW_LEFT ||
            key === ARROW_RIGHT;
        if (isAction && isTargetCell) {
            event.preventDefault();
            event.stopPropagation();
            this.activate.emit({
                type: 'keydown',
                event,
                row: this.row(),
                group: this.group(),
                rowHeight: this.rowHeight(),
                column: this.column(),
                value: this.value(),
                cellElement: this._element
            });
        }
    }
    onCheckboxChange(event) {
        this.activate.emit({
            type: 'checkbox',
            event,
            row: this.row(),
            group: this.group(),
            rowHeight: this.rowHeight(),
            column: this.column(),
            value: this.value(),
            cellElement: this._element,
            treeStatus: 'collapsed'
        });
    }
    stripHtml(html) {
        if (!html.replace) {
            return html;
        }
        return html.replace(/<\/?[^>]+(>|$)/g, '');
    }
    onTreeAction() {
        this.treeAction.emit(this.row());
    }
    calcLeftMargin(column, row) {
        const levelIndent = column.treeLevelIndent ?? 50;
        return column.isTreeColumn ? row.level * levelIndent : 0;
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DataTableBodyCellComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DataTableBodyCellComponent, isStandalone: true, selector: "datatable-body-cell", inputs: { displayCheck: { classPropertyName: "displayCheck", publicName: "displayCheck", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, group: { classPropertyName: "group", publicName: "group", isSignal: true, isRequired: false, transformFunction: null }, rowHeight: { classPropertyName: "rowHeight", publicName: "rowHeight", isSignal: true, isRequired: false, transformFunction: null }, isSelected: { classPropertyName: "isSelected", publicName: "isSelected", isSignal: true, isRequired: false, transformFunction: null }, rowIndex: { classPropertyName: "rowIndex", publicName: "rowIndex", isSignal: true, isRequired: false, transformFunction: null }, column: { classPropertyName: "column", publicName: "column", isSignal: true, isRequired: true, transformFunction: null }, row: { classPropertyName: "row", publicName: "row", isSignal: true, isRequired: true, transformFunction: null }, treeStatus: { classPropertyName: "treeStatus", publicName: "treeStatus", isSignal: true, isRequired: false, transformFunction: null }, ariaRowCheckboxMessage: { classPropertyName: "ariaRowCheckboxMessage", publicName: "ariaRowCheckboxMessage", isSignal: true, isRequired: true, transformFunction: null }, cssClasses: { classPropertyName: "cssClasses", publicName: "cssClasses", isSignal: true, isRequired: true, transformFunction: null }, expanded: { classPropertyName: "expanded", publicName: "expanded", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { activate: "activate", treeAction: "treeAction" }, host: { listeners: { "focus": "onFocus()", "blur": "onBlur()", "click": "onClick($event)", "dblclick": "onDblClick($event)", "keydown": "onKeyDown($event)" }, properties: { "class": "columnCssClasses()", "style.width.px": "column().width", "style.minWidth.px": "column().minWidth", "style.maxWidth.px": "column().maxWidth", "style.height": "height()" } }, ngImport: i0, template: `
    @let column = this.column();
    @let row = this.row();
    <div class="datatable-body-cell-label" [style.margin-left.px]="calcLeftMargin(column, row)">
      @let displayCheck = this.displayCheck();
      @if (column.checkboxable && (!displayCheck || displayCheck(row, column, value()))) {
        <label class="datatable-checkbox">
          <input
            type="checkbox"
            [attr.aria-label]="ariaRowCheckboxMessage()"
            [disabled]="disabled()"
            [checked]="isSelected()"
            (click)="onCheckboxChange($event)"
          />
        </label>
      }
      @if (column.isTreeColumn) {
        @if (!column.treeToggleTemplate) {
          @let treeStatus = this.treeStatus() ?? 'collapsed';
          <button
            class="datatable-tree-button"
            type="button"
            [disabled]="treeStatus === 'disabled'"
            [attr.aria-label]="treeStatus"
            (click)="onTreeAction()"
          >
            <span>
              @if (treeStatus === 'loading') {
                <i [class]="cssClasses().treeStatusLoading ?? 'icon datatable-icon-collapse'"></i>
              }
              @if (treeStatus === 'collapsed') {
                <i [class]="cssClasses().treeStatusCollapsed ?? 'icon datatable-icon-up'"></i>
              }
              @if (treeStatus === 'expanded' || treeStatus === 'disabled') {
                <i [class]="cssClasses().treeStatusExpanded ?? 'icon datatable-icon-down'"></i>
              }
            </span>
          </button>
        } @else {
          <ng-template
            [ngTemplateOutlet]="column.treeToggleTemplate"
            [ngTemplateOutletContext]="{ cellContext: cellContext() }"
          />
        }
      }

      @if (!column.cellTemplate) {
        @if (column.bindAsUnsafeHtml) {
          <span [title]="sanitizedValue()" [innerHTML]="value()"> </span>
        } @else {
          <span [title]="sanitizedValue()">{{ value() }}</span>
        }
      } @else {
        <ng-template
          [ngTemplateOutlet]="column.cellTemplate"
          [ngTemplateOutletContext]="cellContext()"
        />
      }
    </div>
  `, isInline: true, styles: [":host{overflow-x:hidden;vertical-align:top;display:inline-block;line-height:1.625}:host:focus{outline:none}:host-context(ngx-datatable.fixed-row) :host{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DataTableBodyCellComponent, decorators: [{
            type: Component,
            args: [{ selector: 'datatable-body-cell', imports: [NgTemplateOutlet], template: `
    @let column = this.column();
    @let row = this.row();
    <div class="datatable-body-cell-label" [style.margin-left.px]="calcLeftMargin(column, row)">
      @let displayCheck = this.displayCheck();
      @if (column.checkboxable && (!displayCheck || displayCheck(row, column, value()))) {
        <label class="datatable-checkbox">
          <input
            type="checkbox"
            [attr.aria-label]="ariaRowCheckboxMessage()"
            [disabled]="disabled()"
            [checked]="isSelected()"
            (click)="onCheckboxChange($event)"
          />
        </label>
      }
      @if (column.isTreeColumn) {
        @if (!column.treeToggleTemplate) {
          @let treeStatus = this.treeStatus() ?? 'collapsed';
          <button
            class="datatable-tree-button"
            type="button"
            [disabled]="treeStatus === 'disabled'"
            [attr.aria-label]="treeStatus"
            (click)="onTreeAction()"
          >
            <span>
              @if (treeStatus === 'loading') {
                <i [class]="cssClasses().treeStatusLoading ?? 'icon datatable-icon-collapse'"></i>
              }
              @if (treeStatus === 'collapsed') {
                <i [class]="cssClasses().treeStatusCollapsed ?? 'icon datatable-icon-up'"></i>
              }
              @if (treeStatus === 'expanded' || treeStatus === 'disabled') {
                <i [class]="cssClasses().treeStatusExpanded ?? 'icon datatable-icon-down'"></i>
              }
            </span>
          </button>
        } @else {
          <ng-template
            [ngTemplateOutlet]="column.treeToggleTemplate"
            [ngTemplateOutletContext]="{ cellContext: cellContext() }"
          />
        }
      }

      @if (!column.cellTemplate) {
        @if (column.bindAsUnsafeHtml) {
          <span [title]="sanitizedValue()" [innerHTML]="value()"> </span>
        } @else {
          <span [title]="sanitizedValue()">{{ value() }}</span>
        }
      } @else {
        <ng-template
          [ngTemplateOutlet]="column.cellTemplate"
          [ngTemplateOutletContext]="cellContext()"
        />
      }
    </div>
  `, changeDetection: ChangeDetectionStrategy.OnPush, host: {
                        '[class]': 'columnCssClasses()',
                        '[style.width.px]': 'column().width',
                        '[style.minWidth.px]': 'column().minWidth',
                        '[style.maxWidth.px]': 'column().maxWidth',
                        '[style.height]': 'height()',
                        '(focus)': 'onFocus()',
                        '(blur)': 'onBlur()',
                        '(click)': 'onClick($event)',
                        '(dblclick)': 'onDblClick($event)',
                        '(keydown)': 'onKeyDown($event)'
                    }, styles: [":host{overflow-x:hidden;vertical-align:top;display:inline-block;line-height:1.625}:host:focus{outline:none}:host-context(ngx-datatable.fixed-row) :host{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}\n"] }]
        }], propDecorators: { displayCheck: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayCheck", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], group: [{ type: i0.Input, args: [{ isSignal: true, alias: "group", required: false }] }], rowHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowHeight", required: false }] }], isSelected: [{ type: i0.Input, args: [{ isSignal: true, alias: "isSelected", required: false }] }], rowIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowIndex", required: false }] }], column: [{ type: i0.Input, args: [{ isSignal: true, alias: "column", required: true }] }], row: [{ type: i0.Input, args: [{ isSignal: true, alias: "row", required: true }] }], treeStatus: [{ type: i0.Input, args: [{ isSignal: true, alias: "treeStatus", required: false }] }], ariaRowCheckboxMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaRowCheckboxMessage", required: true }] }], cssClasses: [{ type: i0.Input, args: [{ isSignal: true, alias: "cssClasses", required: true }] }], expanded: [{ type: i0.Input, args: [{ isSignal: true, alias: "expanded", required: false }] }], activate: [{ type: i0.Output, args: ["activate"] }], treeAction: [{ type: i0.Output, args: ["treeAction"] }] } });

class DataTableBodyRowComponent {
    constructor() {
        this.cd = inject(ChangeDetectorRef);
        this.columns = input.required(...(ngDevMode ? [{ debugName: "columns" }] : []));
        this.expanded = input(...(ngDevMode ? [undefined, { debugName: "expanded" }] : []));
        this.rowClass = input(...(ngDevMode ? [undefined, { debugName: "rowClass" }] : []));
        this.row = input.required(...(ngDevMode ? [{ debugName: "row" }] : []));
        this.group = input(...(ngDevMode ? [undefined, { debugName: "group" }] : []));
        this.isSelected = input(...(ngDevMode ? [undefined, { debugName: "isSelected" }] : []));
        this.rowIndex = input.required(...(ngDevMode ? [{ debugName: "rowIndex" }] : []));
        this.displayCheck = input(...(ngDevMode ? [undefined, { debugName: "displayCheck" }] : []));
        this.treeStatus = input('collapsed', ...(ngDevMode ? [{ debugName: "treeStatus" }] : []));
        this.ariaRowCheckboxMessage = input.required(...(ngDevMode ? [{ debugName: "ariaRowCheckboxMessage" }] : []));
        this.disabled = input(...(ngDevMode ? [undefined, { debugName: "disabled" }] : []));
        this.cssClasses = input.required(...(ngDevMode ? [{ debugName: "cssClasses" }] : []));
        this.cssClass = computed(() => {
            let cls = 'datatable-body-row';
            const rowClass = this.rowClass();
            if (rowClass) {
                const res = rowClass(this.row());
                if (typeof res === 'string') {
                    cls += ` ${res}`;
                }
                else if (typeof res === 'object') {
                    const keys = Object.keys(res);
                    for (const k of keys) {
                        if (res[k] === true) {
                            cls += ` ${k}`;
                        }
                    }
                }
            }
            return cls;
        }, ...(ngDevMode ? [{ debugName: "cssClass" }] : []));
        this.rowHeight = input.required(...(ngDevMode ? [{ debugName: "rowHeight" }] : []));
        this.activate = output();
        this.treeAction = output();
        this._element = inject(ElementRef).nativeElement;
        this._columnGroupWidths = computed(() => {
            const colsByPin = columnsByPin(this.columns());
            return columnGroupWidths(colsByPin, this.columns());
        }, ...(ngDevMode ? [{ debugName: "_columnGroupWidths" }] : []));
        this._columnsByPin = computed(() => {
            return columnsByPinArr(this.columns());
        }, ...(ngDevMode ? [{ debugName: "_columnsByPin" }] : []));
        this._rowDiffer = inject(KeyValueDiffers)
            .find({})
            .create();
        /** Returns the row index, or if in a group, the index within a group. */
        this.innerRowIndex = computed(() => {
            const rowIndex = this.rowIndex();
            return rowIndex?.indexInGroup ?? rowIndex?.index ?? 0;
        }, ...(ngDevMode ? [{ debugName: "innerRowIndex" }] : []));
    }
    get columnsTotalWidths() {
        return this._columnGroupWidths().total;
    }
    ngDoCheck() {
        if (this._rowDiffer.diff(this.row())) {
            this.cd.markForCheck();
        }
    }
    onActivate(event, index) {
        this.activate.emit({ ...event, rowElement: this._element, cellIndex: index });
    }
    onKeyDown(event) {
        const key = event.key;
        const isTargetRow = event.target === this._element;
        const isAction = key === ENTER ||
            key === ARROW_DOWN ||
            key === ARROW_UP ||
            key === ARROW_LEFT ||
            key === ARROW_RIGHT;
        const isCtrlA = event.key === 'a' && (event.ctrlKey || event.metaKey);
        if ((isAction && isTargetRow) || isCtrlA) {
            event.preventDefault();
            event.stopPropagation();
            this.activate.emit({
                type: 'keydown',
                event,
                row: this.row(),
                rowElement: this._element
            });
        }
    }
    onMouseenter(event) {
        this.activate.emit({
            type: 'mouseenter',
            event,
            row: this.row(),
            rowElement: this._element
        });
    }
    onTreeAction() {
        this.treeAction.emit();
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DataTableBodyRowComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DataTableBodyRowComponent, isStandalone: true, selector: "datatable-body-row", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, expanded: { classPropertyName: "expanded", publicName: "expanded", isSignal: true, isRequired: false, transformFunction: null }, rowClass: { classPropertyName: "rowClass", publicName: "rowClass", isSignal: true, isRequired: false, transformFunction: null }, row: { classPropertyName: "row", publicName: "row", isSignal: true, isRequired: true, transformFunction: null }, group: { classPropertyName: "group", publicName: "group", isSignal: true, isRequired: false, transformFunction: null }, isSelected: { classPropertyName: "isSelected", publicName: "isSelected", isSignal: true, isRequired: false, transformFunction: null }, rowIndex: { classPropertyName: "rowIndex", publicName: "rowIndex", isSignal: true, isRequired: true, transformFunction: null }, displayCheck: { classPropertyName: "displayCheck", publicName: "displayCheck", isSignal: true, isRequired: false, transformFunction: null }, treeStatus: { classPropertyName: "treeStatus", publicName: "treeStatus", isSignal: true, isRequired: false, transformFunction: null }, ariaRowCheckboxMessage: { classPropertyName: "ariaRowCheckboxMessage", publicName: "ariaRowCheckboxMessage", isSignal: true, isRequired: true, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, cssClasses: { classPropertyName: "cssClasses", publicName: "cssClasses", isSignal: true, isRequired: true, transformFunction: null }, rowHeight: { classPropertyName: "rowHeight", publicName: "rowHeight", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { activate: "activate", treeAction: "treeAction" }, host: { attributes: { "role": "row", "tabindex": "-1" }, listeners: { "keydown": "onKeyDown($event)", "mouseenter": "onMouseenter($event)" }, properties: { "class": "cssClass()", "class.active": "isSelected()", "class.datatable-row-odd": "innerRowIndex() % 2 !== 0", "class.datatable-row-even": "innerRowIndex() % 2 === 0", "class.row-disabled": "disabled()", "style.height.px": "rowHeight()", "style.width.px": "this.columnsTotalWidths" } }, ngImport: i0, template: `
    @for (colGroup of _columnsByPin(); track colGroup.type) {
      @if (colGroup.columns.length) {
        <div
          [class]="'datatable-row-' + colGroup.type + ' datatable-row-group'"
          [style.width.px]="_columnGroupWidths()[colGroup.type]"
          [class.row-disabled]="disabled()"
        >
          @for (column of colGroup.columns; track column.$$id; let ii = $index) {
            <datatable-body-cell
              role="cell"
              tabindex="-1"
              [row]="row()"
              [group]="group()"
              [expanded]="expanded()"
              [isSelected]="isSelected()"
              [rowIndex]="rowIndex()"
              [column]="column"
              [rowHeight]="rowHeight()"
              [displayCheck]="displayCheck()"
              [disabled]="disabled()"
              [treeStatus]="treeStatus()"
              [ariaRowCheckboxMessage]="ariaRowCheckboxMessage()"
              [cssClasses]="cssClasses()"
              (activate)="onActivate($event, ii)"
              (treeAction)="onTreeAction()"
            />
          }
        </div>
      }
    }
  `, isInline: true, styles: [":host{display:flex;outline:none}:host-context(ngx-datatable.fixed-row) :host{white-space:nowrap}.datatable-row-group{display:flex;position:relative}.datatable-row-left,.datatable-row-right{position:sticky;z-index:9}.datatable-row-left{inset-inline-start:0}.datatable-row-right{inset-inline-end:0}\n"], dependencies: [{ kind: "component", type: DataTableBodyCellComponent, selector: "datatable-body-cell", inputs: ["displayCheck", "disabled", "group", "rowHeight", "isSelected", "rowIndex", "column", "row", "treeStatus", "ariaRowCheckboxMessage", "cssClasses", "expanded"], outputs: ["activate", "treeAction"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DataTableBodyRowComponent, decorators: [{
            type: Component,
            args: [{ selector: 'datatable-body-row', imports: [DataTableBodyCellComponent], template: `
    @for (colGroup of _columnsByPin(); track colGroup.type) {
      @if (colGroup.columns.length) {
        <div
          [class]="'datatable-row-' + colGroup.type + ' datatable-row-group'"
          [style.width.px]="_columnGroupWidths()[colGroup.type]"
          [class.row-disabled]="disabled()"
        >
          @for (column of colGroup.columns; track column.$$id; let ii = $index) {
            <datatable-body-cell
              role="cell"
              tabindex="-1"
              [row]="row()"
              [group]="group()"
              [expanded]="expanded()"
              [isSelected]="isSelected()"
              [rowIndex]="rowIndex()"
              [column]="column"
              [rowHeight]="rowHeight()"
              [displayCheck]="displayCheck()"
              [disabled]="disabled()"
              [treeStatus]="treeStatus()"
              [ariaRowCheckboxMessage]="ariaRowCheckboxMessage()"
              [cssClasses]="cssClasses()"
              (activate)="onActivate($event, ii)"
              (treeAction)="onTreeAction()"
            />
          }
        </div>
      }
    }
  `, changeDetection: ChangeDetectionStrategy.OnPush, host: {
                        role: 'row',
                        tabindex: '-1',
                        '[class]': 'cssClass()',
                        '[class.active]': 'isSelected()',
                        '[class.datatable-row-odd]': 'innerRowIndex() % 2 !== 0',
                        '[class.datatable-row-even]': 'innerRowIndex() % 2 === 0',
                        '[class.row-disabled]': 'disabled()',
                        '[style.height.px]': 'rowHeight()'
                    }, styles: [":host{display:flex;outline:none}:host-context(ngx-datatable.fixed-row) :host{white-space:nowrap}.datatable-row-group{display:flex;position:relative}.datatable-row-left,.datatable-row-right{position:sticky;z-index:9}.datatable-row-left{inset-inline-start:0}.datatable-row-right{inset-inline-end:0}\n"] }]
        }], propDecorators: { columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], expanded: [{ type: i0.Input, args: [{ isSignal: true, alias: "expanded", required: false }] }], rowClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowClass", required: false }] }], row: [{ type: i0.Input, args: [{ isSignal: true, alias: "row", required: true }] }], group: [{ type: i0.Input, args: [{ isSignal: true, alias: "group", required: false }] }], isSelected: [{ type: i0.Input, args: [{ isSignal: true, alias: "isSelected", required: false }] }], rowIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowIndex", required: true }] }], displayCheck: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayCheck", required: false }] }], treeStatus: [{ type: i0.Input, args: [{ isSignal: true, alias: "treeStatus", required: false }] }], ariaRowCheckboxMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaRowCheckboxMessage", required: true }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], cssClasses: [{ type: i0.Input, args: [{ isSignal: true, alias: "cssClasses", required: true }] }], rowHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowHeight", required: true }] }], columnsTotalWidths: [{
                type: HostBinding,
                args: ['style.width.px']
            }], activate: [{ type: i0.Output, args: ["activate"] }], treeAction: [{ type: i0.Output, args: ["treeAction"] }], onKeyDown: [{
                type: HostListener,
                args: ['keydown', ['$event']]
            }], onMouseenter: [{
                type: HostListener,
                args: ['mouseenter', ['$event']]
            }] } });

class DatatableBodyRowDirective {
    static ngTemplateContextGuard(directive, context) {
        return true;
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DatatableBodyRowDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
    static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.15", type: DatatableBodyRowDirective, isStandalone: true, selector: "[ngx-datatable-body-row]", ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DatatableBodyRowDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[ngx-datatable-body-row]'
                }]
        }] });

class DataTableGhostLoaderComponent {
    constructor() {
        this.columns = input.required(...(ngDevMode ? [{ debugName: "columns" }] : []));
        this.pageSize = input.required(...(ngDevMode ? [{ debugName: "pageSize", transform: numberAttribute }] : [{ transform: numberAttribute }]));
        this.rowHeight = input.required(...(ngDevMode ? [{ debugName: "rowHeight" }] : []));
        this.ghostBodyHeight = input(undefined, ...(ngDevMode ? [{ debugName: "ghostBodyHeight", transform: numberAttribute }] : [{ transform: numberAttribute }]));
        this.rowHeightComputed = () => {
            const rowHeight = this.rowHeight();
            if (typeof rowHeight === 'function') {
                // If rowHeight is a function, we cannot determine a fixed height here.
                return 'auto';
            }
            return rowHeight === 'auto' ? 'auto' : rowHeight + 'px';
        };
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DataTableGhostLoaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DataTableGhostLoaderComponent, isStandalone: true, selector: "ghost-loader", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: true, transformFunction: null }, rowHeight: { classPropertyName: "rowHeight", publicName: "rowHeight", isSignal: true, isRequired: true, transformFunction: null }, ghostBodyHeight: { classPropertyName: "ghostBodyHeight", publicName: "ghostBodyHeight", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"ghost-loader ghost-cell-container\" [style.height]=\"ghostBodyHeight()\">\n  @for (item of [].constructor(pageSize()); track $index) {\n    <div class=\"ghost-element datatable-body-row\" [style.height]=\"rowHeightComputed()\">\n      @for (col of columns(); track col) {\n        <div class=\"ghost-cell datatable-body-cell\" [style.width.px]=\"col.width\">\n          @if (!col.ghostCellTemplate) {\n            <div class=\"line ghost-cell-strip\"></div>\n          } @else {\n            <ng-template [ngTemplateOutlet]=\"col.ghostCellTemplate\" />\n          }\n        </div>\n      }\n    </div>\n  }\n</div>\n", styles: ["@keyframes ghost{0%{background-position:0 0}to{background-position:100vw 0}}.ghost-loader{overflow:hidden}.ghost-loader .line{inline-size:100%;block-size:12px;animation-name:ghost;animation-iteration-count:infinite;animation-timing-function:linear}.ghost-loader .ghost-element{display:flex;align-items:center}:host.ghost-overlay{position:sticky;inset-block-start:20px}:host.ghost-overlay .ghost-cell{padding-inline:1.2rem}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DataTableGhostLoaderComponent, decorators: [{
            type: Component,
            args: [{ selector: 'ghost-loader', imports: [NgTemplateOutlet], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"ghost-loader ghost-cell-container\" [style.height]=\"ghostBodyHeight()\">\n  @for (item of [].constructor(pageSize()); track $index) {\n    <div class=\"ghost-element datatable-body-row\" [style.height]=\"rowHeightComputed()\">\n      @for (col of columns(); track col) {\n        <div class=\"ghost-cell datatable-body-cell\" [style.width.px]=\"col.width\">\n          @if (!col.ghostCellTemplate) {\n            <div class=\"line ghost-cell-strip\"></div>\n          } @else {\n            <ng-template [ngTemplateOutlet]=\"col.ghostCellTemplate\" />\n          }\n        </div>\n      }\n    </div>\n  }\n</div>\n", styles: ["@keyframes ghost{0%{background-position:0 0}to{background-position:100vw 0}}.ghost-loader{overflow:hidden}.ghost-loader .line{inline-size:100%;block-size:12px;animation-name:ghost;animation-iteration-count:infinite;animation-timing-function:linear}.ghost-loader .ghost-element{display:flex;align-items:center}:host.ghost-overlay{position:sticky;inset-block-start:20px}:host.ghost-overlay .ghost-cell{padding-inline:1.2rem}\n"] }]
        }], propDecorators: { columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: true }] }], rowHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowHeight", required: true }] }], ghostBodyHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "ghostBodyHeight", required: false }] }] } });

class ScrollerComponent {
    constructor() {
        this.renderer = inject(Renderer2);
        this.scrollbarV = input(false, ...(ngDevMode ? [{ debugName: "scrollbarV", transform: booleanAttribute }] : [{
                transform: booleanAttribute
            }]));
        this.scrollbarH = input(false, ...(ngDevMode ? [{ debugName: "scrollbarH", transform: booleanAttribute }] : [{
                transform: booleanAttribute
            }]));
        this.scrollHeight = input(...(ngDevMode ? [undefined, { debugName: "scrollHeight" }] : []));
        this.scrollWidth = input(...(ngDevMode ? [undefined, { debugName: "scrollWidth" }] : []));
        this.scroll = output();
        this.scrollYPos = 0;
        this.scrollXPos = 0;
        this.prevScrollYPos = 0;
        this.prevScrollXPos = 0;
        this.element = inject(ElementRef).nativeElement;
        this._scrollEventListener = null;
    }
    ngOnInit() {
        // manual bind so we don't always listen
        if (this.scrollbarV() || this.scrollbarH()) {
            const renderer = this.renderer;
            this.parentElement = renderer.parentNode(this.element);
            this._scrollEventListener = this.onScrolled.bind(this);
            this.parentElement?.addEventListener('scroll', this._scrollEventListener);
        }
    }
    ngOnDestroy() {
        if (this._scrollEventListener) {
            this.parentElement?.removeEventListener('scroll', this._scrollEventListener);
            this._scrollEventListener = null;
        }
    }
    setOffset(offsetY) {
        if (this.parentElement) {
            this.parentElement.scrollTop = offsetY;
        }
    }
    onScrolled(event) {
        const dom = event.currentTarget;
        requestAnimationFrame(() => {
            this.scrollYPos = dom.scrollTop;
            this.scrollXPos = dom.scrollLeft;
            this.updateOffset();
        });
    }
    updateOffset() {
        let direction;
        if (this.scrollYPos < this.prevScrollYPos) {
            direction = 'down';
        }
        else {
            direction = 'up';
        }
        this.scroll.emit({
            direction,
            scrollYPos: this.scrollYPos,
            scrollXPos: this.scrollXPos
        });
        this.prevScrollYPos = this.scrollYPos;
        this.prevScrollXPos = this.scrollXPos;
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ScrollerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.15", type: ScrollerComponent, isStandalone: true, selector: "datatable-scroller", inputs: { scrollbarV: { classPropertyName: "scrollbarV", publicName: "scrollbarV", isSignal: true, isRequired: false, transformFunction: null }, scrollbarH: { classPropertyName: "scrollbarH", publicName: "scrollbarH", isSignal: true, isRequired: false, transformFunction: null }, scrollHeight: { classPropertyName: "scrollHeight", publicName: "scrollHeight", isSignal: true, isRequired: false, transformFunction: null }, scrollWidth: { classPropertyName: "scrollWidth", publicName: "scrollWidth", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { scroll: "scroll" }, host: { properties: { "style.height.px": "scrollHeight()", "style.width.px": "scrollWidth()" }, classAttribute: "datatable-scroll" }, ngImport: i0, template: ` <ng-content /> `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ScrollerComponent, decorators: [{
            type: Component,
            args: [{
                    selector: 'datatable-scroller',
                    template: ` <ng-content /> `,
                    changeDetection: ChangeDetectionStrategy.OnPush,
                    host: {
                        class: 'datatable-scroll',
                        '[style.height.px]': 'scrollHeight()',
                        '[style.width.px]': 'scrollWidth()'
                    }
                }]
        }], propDecorators: { scrollbarV: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollbarV", required: false }] }], scrollbarH: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollbarH", required: false }] }], scrollHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollHeight", required: false }] }], scrollWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollWidth", required: false }] }], scroll: [{ type: i0.Output, args: ["scroll"] }] } });

const defaultSumFunc = (cells) => {
    const cellsWithValues = cells.filter(cell => !!cell);
    if (!cellsWithValues.length) {
        return null;
    }
    if (cellsWithValues.some(cell => typeof cell !== 'number')) {
        return null;
    }
    return cellsWithValues.reduce((res, cell) => res + cell);
};
const noopSumFunc = (cells) => {
    return;
};
class DataTableSummaryRowComponent {
    constructor() {
        this.rows = input.required(...(ngDevMode ? [{ debugName: "rows" }] : []));
        this.columns = input.required(...(ngDevMode ? [{ debugName: "columns" }] : []));
        this.rowHeight = input.required(...(ngDevMode ? [{ debugName: "rowHeight" }] : []));
        this.innerWidth = input.required(...(ngDevMode ? [{ debugName: "innerWidth" }] : []));
        this._internalColumns = computed(() => {
            return this.columns().map(col => ({
                ...col,
                cellTemplate: col.summaryTemplate
            }));
        }, ...(ngDevMode ? [{ debugName: "_internalColumns" }] : []));
        this.summaryRow = computed(() => this.computeSummaryRowValues(), ...(ngDevMode ? [{ debugName: "summaryRow" }] : []));
    }
    computeSummaryRowValues() {
        if (!this.columns().length || !this.rows().length) {
            return undefined;
        }
        const summaryRow = {};
        this.columns()
            .filter(col => !col.summaryTemplate && col.prop)
            .forEach(col => {
            const cellsFromSingleColumn = this.rows().map(row => row[col.prop]);
            const sumFunc = this.getSummaryFunction(col);
            summaryRow[col.prop] = col.pipe
                ? col.pipe.transform(sumFunc(cellsFromSingleColumn))
                : sumFunc(cellsFromSingleColumn);
        });
        return summaryRow;
    }
    getSummaryFunction(column) {
        if (column.summaryFunc === undefined) {
            return defaultSumFunc;
        }
        else if (column.summaryFunc === null) {
            return noopSumFunc;
        }
        else {
            return column.summaryFunc;
        }
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DataTableSummaryRowComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DataTableSummaryRowComponent, isStandalone: true, selector: "datatable-summary-row", inputs: { rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: true, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, rowHeight: { classPropertyName: "rowHeight", publicName: "rowHeight", isSignal: true, isRequired: true, transformFunction: null }, innerWidth: { classPropertyName: "innerWidth", publicName: "innerWidth", isSignal: true, isRequired: true, transformFunction: null } }, host: { classAttribute: "datatable-summary-row" }, ngImport: i0, template: `
    @let summaryRow = this.summaryRow();
    @let _internalColumns = this._internalColumns();
    @if (summaryRow && _internalColumns.length) {
      <datatable-body-row
        ariaRowCheckboxMessage=""
        [columns]="_internalColumns"
        [rowHeight]="rowHeight()"
        [row]="summaryRow"
        [rowIndex]="{ index: -1 }"
        [cssClasses]="{}"
      />
    }
  `, isInline: true, dependencies: [{ kind: "component", type: DataTableBodyRowComponent, selector: "datatable-body-row", inputs: ["columns", "expanded", "rowClass", "row", "group", "isSelected", "rowIndex", "displayCheck", "treeStatus", "ariaRowCheckboxMessage", "disabled", "cssClasses", "rowHeight"], outputs: ["activate", "treeAction"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DataTableSummaryRowComponent, decorators: [{
            type: Component,
            args: [{
                    selector: 'datatable-summary-row',
                    imports: [DataTableBodyRowComponent],
                    template: `
    @let summaryRow = this.summaryRow();
    @let _internalColumns = this._internalColumns();
    @if (summaryRow && _internalColumns.length) {
      <datatable-body-row
        ariaRowCheckboxMessage=""
        [columns]="_internalColumns"
        [rowHeight]="rowHeight()"
        [row]="summaryRow"
        [rowIndex]="{ index: -1 }"
        [cssClasses]="{}"
      />
    }
  `,
                    host: {
                        class: 'datatable-summary-row'
                    }
                }]
        }], propDecorators: { rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: true }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], rowHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowHeight", required: true }] }], innerWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "innerWidth", required: true }] }] } });

class DataTableBodyComponent {
    /**
     * Returns if selection is enabled.
     */
    get selectEnabled() {
        return !!this.selectionType();
    }
    /**
     * Creates an instance of DataTableBodyComponent.
     */
    constructor() {
        this.cd = inject(ChangeDetectorRef);
        this.rowDefTemplate = input(...(ngDevMode ? [undefined, { debugName: "rowDefTemplate" }] : []));
        this.scrollbarV = input(false, ...(ngDevMode ? [{ debugName: "scrollbarV", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
        this.scrollbarH = input(...(ngDevMode ? [undefined, { debugName: "scrollbarH" }] : []));
        this.loadingIndicator = input(...(ngDevMode ? [undefined, { debugName: "loadingIndicator" }] : []));
        this.ghostLoadingIndicator = input(...(ngDevMode ? [undefined, { debugName: "ghostLoadingIndicator" }] : []));
        this.externalPaging = input(...(ngDevMode ? [undefined, { debugName: "externalPaging" }] : []));
        this.rowHeight = input.required(...(ngDevMode ? [{ debugName: "rowHeight" }] : []));
        this.offsetX = model.required(...(ngDevMode ? [{ debugName: "offsetX" }] : []));
        this.selectionType = input(...(ngDevMode ? [undefined, { debugName: "selectionType" }] : []));
        this.selected = model([], ...(ngDevMode ? [{ debugName: "selected" }] : []));
        this.rowIdentity = input.required(...(ngDevMode ? [{ debugName: "rowIdentity" }] : []));
        this.rowDetail = input(...(ngDevMode ? [undefined, { debugName: "rowDetail" }] : []));
        this.groupHeader = input(...(ngDevMode ? [undefined, { debugName: "groupHeader" }] : []));
        this.selectCheck = input(...(ngDevMode ? [undefined, { debugName: "selectCheck" }] : []));
        this.displayCheck = input(...(ngDevMode ? [undefined, { debugName: "displayCheck" }] : []));
        this.trackByProp = input(...(ngDevMode ? [undefined, { debugName: "trackByProp" }] : []));
        this.rowClass = input(...(ngDevMode ? [undefined, { debugName: "rowClass" }] : []));
        this.groupedRows = input(...(ngDevMode ? [undefined, { debugName: "groupedRows" }] : []));
        this.innerWidth = input.required(...(ngDevMode ? [{ debugName: "innerWidth" }] : []));
        this.virtualization = input(...(ngDevMode ? [undefined, { debugName: "virtualization" }] : []));
        this.summaryRow = input(...(ngDevMode ? [undefined, { debugName: "summaryRow" }] : []));
        this.summaryPosition = input.required(...(ngDevMode ? [{ debugName: "summaryPosition" }] : []));
        this.summaryHeight = input.required(...(ngDevMode ? [{ debugName: "summaryHeight" }] : []));
        this.rowDraggable = input(...(ngDevMode ? [undefined, { debugName: "rowDraggable" }] : []));
        this.rowDragEvents = input.required(...(ngDevMode ? [{ debugName: "rowDragEvents" }] : []));
        this.disableRowCheck = input(...(ngDevMode ? [undefined, { debugName: "disableRowCheck" }] : []));
        this.ariaGroupHeaderCheckboxMessage = input.required(...(ngDevMode ? [{ debugName: "ariaGroupHeaderCheckboxMessage" }] : []));
        this.pageSize = input.required(...(ngDevMode ? [{ debugName: "pageSize" }] : []));
        this.rows = input.required(...(ngDevMode ? [{ debugName: "rows" }] : []));
        this.columns = input.required(...(ngDevMode ? [{ debugName: "columns" }] : []));
        this.offset = input(0, ...(ngDevMode ? [{ debugName: "offset" }] : []));
        this.rowCount = input(0, ...(ngDevMode ? [{ debugName: "rowCount" }] : []));
        this.bodyHeight = input(...(ngDevMode ? [undefined, { debugName: "bodyHeight" }] : []));
        this.verticalScrollVisible = input(false, ...(ngDevMode ? [{ debugName: "verticalScrollVisible" }] : []));
        this.ariaRowCheckboxMessage = input.required(...(ngDevMode ? [{ debugName: "ariaRowCheckboxMessage" }] : []));
        this.cssClasses = input.required(...(ngDevMode ? [{ debugName: "cssClasses" }] : []));
        this.scroll = output();
        this.page = output();
        this.activate = output();
        this.rowContextmenu = output();
        this.treeAction = output();
        /**
         * Property that would calculate the height of scroll bar
         * based on the row heights cache for virtual scroll and virtualization. Other scenarios
         * calculate scroll height automatically (as height will be undefined).
         */
        this.scrollHeight = computed(() => {
            if (this.rowHeightsCache() && this.scrollbarV() && this.virtualization() && this.rowCount()) {
                return this.rowHeightsCache().query(this.rowCount() - 1);
            }
            // avoid TS7030: Not all code paths return a value.
            return undefined;
        }, ...(ngDevMode ? [{ debugName: "scrollHeight" }] : []));
        this.detailRowHeightFn = computed(() => {
            const rowDetail = this.rowDetail();
            if (!rowDetail) {
                return () => 0;
            }
            const rowHeight = rowDetail.rowHeight();
            return typeof rowHeight === 'function' ? rowHeight : () => rowHeight;
        }, ...(ngDevMode ? [{ debugName: "detailRowHeightFn" }] : []));
        this.rowsToRender = computed(() => {
            return this.updateRows();
        }, ...(ngDevMode ? [{ debugName: "rowsToRender" }] : []));
        this.rowHeightsCache = computed(() => this.computeRowHeightsCache(), ...(ngDevMode ? [{ debugName: "rowHeightsCache" }] : []));
        this.offsetY = signal(0, ...(ngDevMode ? [{ debugName: "offsetY" }] : []));
        this.indexes = computed(() => this.computeIndexes(), ...(ngDevMode ? [{ debugName: "indexes" }] : []));
        this.columnGroupWidths = computed(() => {
            const colsByPin = columnsByPin(this.columns());
            return columnGroupWidths(colsByPin, this.columns());
        }, ...(ngDevMode ? [{ debugName: "columnGroupWidths" }] : []));
        this.destroyRef = inject(DestroyRef);
        this.rowExpansions = signal([], ...(ngDevMode ? [{ debugName: "rowExpansions" }] : []));
        this.groupExpansions = signal([], ...(ngDevMode ? [{ debugName: "groupExpansions" }] : []));
        this._bodyWidth = computed(() => {
            if (this.scrollbarH()) {
                return this.innerWidth() + 'px';
            }
            else {
                return '100%';
            }
        }, ...(ngDevMode ? [{ debugName: "_bodyWidth" }] : []));
        this._bodyHeight = computed(() => {
            if (this.scrollbarV()) {
                return this.bodyHeight() + 'px';
            }
            else {
                return 'auto';
            }
        }, ...(ngDevMode ? [{ debugName: "_bodyHeight" }] : []));
        this._offsetEvent = -1;
        this.getGroupHeaderRowHeight = (row, index) => {
            const groupHeader = this.groupHeader();
            if (!groupHeader) {
                return 0;
            }
            const rowHeightValue = groupHeader?.rowHeight();
            const rowHeight = rowHeightValue === 0 ? this.rowHeight() : rowHeightValue;
            return typeof rowHeight === 'function' ? rowHeight(row, index) : rowHeight;
        };
        /**
         * Calculates the offset of the rendered rows.
         * As virtual rows are not shown, we have to move all rendered rows
         * by the total size of previous non-rendered rows.
         * If each row has a size of 10px and the first 10 rows are not rendered due to scroll,
         * then we have a renderOffset of 100px.
         */
        this.renderOffset = computed(() => {
            if (this.scrollbarV() && this.virtualization()) {
                return `translateY(${this.rowHeightsCache().query(this.indexes().first - 1)}px)`;
            }
            else {
                return '';
            }
        }, ...(ngDevMode ? [{ debugName: "renderOffset" }] : []));
        // declare fn here so we can get access to the `this` property
        this.rowTrackingFn = (index, row) => {
            if (this.ghostLoadingIndicator()) {
                return index;
            }
            const trackByProp = this.trackByProp();
            if (trackByProp && row) {
                return row[trackByProp];
            }
            else if (row && this.isGroup(row)) {
                return row.key ?? index;
            }
            else {
                return row ?? index;
            }
        };
        effect(() => this.defaultGroupExpansionEffect());
    }
    ngOnChanges(changes) {
        if (changes.bodyHeight || changes.rows || changes.rowCount || changes.pageSize) {
            if (changes.pageSize) {
                this._offsetEvent = -1;
                this.updatePage('up');
                this.updatePage('down');
            }
        }
    }
    /**
     * Called after the constructor, initializing input properties
     */
    ngOnInit() {
        const rowDetail = this.rowDetail();
        if (rowDetail) {
            const listener = rowDetail.toggle.subscribe(event => this.rowToggleStateChange(event));
            this.destroyRef.onDestroy(() => listener.unsubscribe());
        }
        const groupHeader = this.groupHeader();
        if (groupHeader) {
            const listener = groupHeader.toggle.subscribe(event => {
                // Remove default expansion state once user starts manual toggle.
                this.groupExpansionDefault = false;
                this.groupToggleStateChange(event);
            });
            this.destroyRef.onDestroy(() => listener.unsubscribe());
        }
    }
    defaultGroupExpansionEffect() {
        if (this.groupedRows() &&
            untracked(() => this.groupExpansions().length) === 0 &&
            this.groupExpansionDefault) {
            this.groupExpansions.set([...(this.groupedRows() ?? [])]);
        }
    }
    groupToggleStateChange({ type, value }) {
        if (type === 'group') {
            this.toggleGroupExpansion(value);
        }
        if (type === 'all') {
            this.toggleAllGroups(value);
        }
        // Refresh rows after toggle
        this.cd.markForCheck();
    }
    rowToggleStateChange({ type, value }) {
        if (type === 'row') {
            this.toggleRowExpansion(value);
        }
        if (type === 'all') {
            this.toggleAllRows(value);
        }
        // Refresh rows after toggle
        this.cd.markForCheck();
    }
    /**
     * Updates the Y offset given a new offset.
     */
    updateOffsetY(offset) {
        // scroller is missing on empty table
        if (!this.scroller) {
            return;
        }
        const virtualization = this.virtualization();
        if (this.scrollbarV() && virtualization && offset) {
            // First get the row Index that we need to move to.
            const rowIndex = this.pageSize() * offset;
            offset = this.rowHeightsCache().query(rowIndex - 1);
        }
        else if (this.scrollbarV() && !virtualization) {
            offset = 0;
        }
        this.scroller.setOffset(offset ?? 0);
    }
    /**
     * Body was scrolled, this is mainly useful for
     * when a user is server-side pagination via virtual scroll.
     */
    onBodyScroll(event) {
        const scrollYPos = event.scrollYPos;
        const scrollXPos = event.scrollXPos;
        // if scroll change, trigger update
        // this is mainly used for header cell positions
        if (this.offsetY() !== scrollYPos || this.offsetX() !== scrollXPos) {
            this.scroll.emit({
                offsetY: scrollYPos,
                offsetX: scrollXPos
            });
        }
        this.offsetY.set(scrollYPos);
        this.offsetX.set(scrollXPos);
        this.updatePage(event.direction);
        this.cd.detectChanges();
    }
    /**
     * Updates the page given a direction.
     */
    updatePage(direction) {
        let offset = this.indexes().first / this.pageSize();
        const scrollInBetween = !Number.isInteger(offset);
        if (direction === 'up') {
            offset = Math.ceil(offset);
        }
        else if (direction === 'down') {
            offset = Math.floor(offset);
        }
        if (direction !== undefined && !isNaN(offset) && offset !== this._offsetEvent) {
            this._offsetEvent = offset;
            // if scroll was done by mouse drag make sure previous row and next row data is also fetched if its not fetched
            if (scrollInBetween && this.scrollbarV() && this.virtualization() && this.externalPaging()) {
                const upRow = this.rows()[this.indexes().first - 1];
                if (!upRow && direction === 'up') {
                    this.page.emit(offset - 1);
                }
                const downRow = this.rows()[this.indexes().first + this.pageSize()];
                if (!downRow && direction === 'down') {
                    this.page.emit(offset + 1);
                }
            }
            this.page.emit(offset);
        }
    }
    /**
     * Updates the rows in the view port
     */
    updateRows() {
        const { first, last } = this.indexes();
        // if grouprowsby has been specified treat row paging
        // parameters as group paging parameters ie if limit 10 has been
        // specified treat it as 10 groups rather than 10 rows
        const groupedRows = this.groupedRows();
        const rows = groupedRows
            ? groupedRows.slice(first, Math.min(last, groupedRows.length))
            : this.rows().slice(first, Math.min(last, this.rowCount()));
        rows.length = last - first;
        return rows;
    }
    /**
     * Get the row height
     */
    getRowHeight(row) {
        // if its a function return it
        const rowHeight = this.rowHeight();
        if (typeof rowHeight === 'function') {
            return rowHeight(row);
        }
        return rowHeight;
    }
    /**
     * Updates the index of the rows in the viewport
     */
    computeIndexes() {
        let first = 0;
        let last = this.rowCount();
        if (this.scrollbarV()) {
            if (this.virtualization()) {
                // Calculation of the first and last indexes will be based on where the
                // scrollY position would be at.  The last index would be the one
                // that shows up inside the view port the last.
                const height = parseInt(this._bodyHeight(), 10);
                first = this.rowHeightsCache().getRowIndex(this.offsetY());
                last = this.rowHeightsCache().getRowIndex(height + this.offsetY()) + 1;
            }
        }
        else {
            // The server is handling paging and will pass an array that begins with the
            // element at a specified offset.  first should always be 0 with external paging.
            if (!this.externalPaging()) {
                first = Math.max(this.offset() * this.pageSize(), 0);
            }
            last = Math.min(first + this.pageSize(), this.rowCount());
        }
        return { first, last };
    }
    /**
     * Refreshes the full Row Height cache.  Should be used
     * when the entire row array state has changed.
     */
    computeRowHeightsCache() {
        const cache = new RowHeightCache();
        if (!this.scrollbarV() || (this.scrollbarV() && !this.virtualization())) {
            return cache;
        }
        // Initialize the tree only if there are rows inside the tree.
        if (this.rows().length) {
            cache.initCache({
                rows: this.rows(), // TODO: RowHeightCache does not support grouping
                rowHeight: this.rowHeight(),
                detailRowHeight: this.detailRowHeightFn(),
                externalVirtual: this.scrollbarV() && this.externalPaging(),
                indexOffset: this.externalPaging() ? this.offset() * this.pageSize() : 0,
                rowCount: this.rowCount(),
                rowExpansions: new Set(this.rowDetail() ? this.rowExpansions() : [])
            });
        }
        return cache;
    }
    /**
     * Toggle the Expansion of the row i.e. if the row is expanded then it will
     * collapse and vice versa.   Note that the expanded status is stored as
     * a part of the row object itself as we have to preserve the expanded row
     * status in case of sorting and filtering of the row set.
     */
    toggleRowExpansion(row) {
        const rowExpandedIdx = this.getExpandedIdx(row, this.rowExpansions());
        const expanded = rowExpandedIdx > -1;
        // Update the toggled row and update thive nevere heights in the cache.
        if (expanded) {
            this.rowExpansions.update(expansions => {
                expansions.splice(rowExpandedIdx, 1);
                return [...expansions];
            });
        }
        else {
            this.rowExpansions.update(expansions => [...expansions, row]);
        }
    }
    toggleGroupExpansion(row) {
        const groupExpandedIdx = this.getExpandedIdx(row, this.groupExpansions());
        const expanded = groupExpandedIdx > -1;
        // Update the toggled row and update thive nevere heights in the cache.
        if (expanded) {
            this.groupExpansions.update(expansions => {
                expansions.splice(groupExpandedIdx, 1);
                return [...expansions];
            });
        }
        else {
            this.groupExpansions.update(expansions => [...expansions, row]);
        }
    }
    /**
     * Expand/Collapse all the rows no matter what their state is.
     */
    toggleAllRows(expanded) {
        // TODO requires fixing. This still does not work with groups.
        this.rowExpansions.set(expanded ? [...this.rows()] : []);
    }
    /**
     * Expand/Collapse all the groups no matter what their state is.
     */
    toggleAllGroups(expanded) {
        this.groupExpansions.set(expanded ? [...this.groupedRows()] : []);
    }
    /**
     * Returns if the row was expanded and set default row expansion when row expansion is empty
     */
    getRowExpanded(row) {
        return this.getExpandedIdx(row, this.rowExpansions()) > -1;
    }
    getGroupExpanded(group) {
        return this.getExpandedIdx(group, this.groupExpansions()) > -1;
    }
    getExpandedIdx(row, expanded) {
        if (!expanded?.length) {
            return -1;
        }
        const rowId = this.rowIdentity()(row);
        return expanded.findIndex(r => {
            const id = this.rowIdentity()(r);
            return id === rowId;
        });
    }
    onTreeAction(row) {
        this.treeAction.emit({ row });
    }
    dragOver(event, dropRow) {
        event.preventDefault();
        this.rowDragEvents().emit({
            event,
            srcElement: this._draggedRowElement,
            eventType: 'dragover',
            dragRow: this._draggedRow,
            dropRow
        });
    }
    drag(event, dragRow, rowComponent) {
        this._draggedRow = dragRow;
        this._draggedRowElement = rowComponent._element;
        this.rowDragEvents().emit({
            event,
            srcElement: this._draggedRowElement,
            eventType: 'dragstart',
            dragRow
        });
    }
    drop(event, dropRow, rowComponent) {
        event.preventDefault();
        this.rowDragEvents().emit({
            event,
            srcElement: this._draggedRowElement,
            targetElement: rowComponent._element,
            eventType: 'drop',
            dragRow: this._draggedRow,
            dropRow
        });
    }
    dragEnter(event, dropRow, rowComponent) {
        event.preventDefault();
        this.rowDragEvents().emit({
            event,
            srcElement: this._draggedRowElement,
            targetElement: rowComponent._element,
            eventType: 'dragenter',
            dragRow: this._draggedRow,
            dropRow
        });
    }
    dragLeave(event, dropRow, rowComponent) {
        event.preventDefault();
        this.rowDragEvents().emit({
            event,
            srcElement: this._draggedRowElement,
            targetElement: rowComponent._element,
            eventType: 'dragleave',
            dragRow: this._draggedRow,
            dropRow
        });
    }
    dragEnd(event, dragRow) {
        event.preventDefault();
        this.rowDragEvents().emit({
            event,
            srcElement: this._draggedRowElement,
            eventType: 'dragend',
            dragRow
        });
        this._draggedRow = undefined;
        this._draggedRowElement = undefined;
    }
    selectRow(event, index, row) {
        if (!this.selectEnabled) {
            return;
        }
        const chkbox = this.selectionType() === 'checkbox';
        const multi = this.selectionType() === 'multi';
        const multiClick = this.selectionType() === 'multiClick';
        let selected = [];
        // TODO: this code needs cleanup. Casting it to KeyboardEvent is not correct as it could also be other types.
        if (multi || chkbox || multiClick) {
            if (event.shiftKey) {
                selected = selectRowsBetween([], this.rows(), index, this.prevIndex);
            }
            else if (event.key === 'a' &&
                (event.ctrlKey || event.metaKey)) {
                // select all rows except dummy rows which are added for ghostloader in case of virtual scroll
                selected = this.rows().filter(rowItem => !!rowItem);
            }
            else if (event.ctrlKey ||
                event.metaKey ||
                multiClick ||
                chkbox) {
                selected = selectRows([...this.selected()], row, this.getRowSelectedIdx.bind(this));
            }
            else {
                selected = selectRows([], row, this.getRowSelectedIdx.bind(this));
            }
        }
        else {
            selected = selectRows([], row, this.getRowSelectedIdx.bind(this));
        }
        const selectCheck = this.selectCheck();
        if (typeof selectCheck === 'function') {
            selected = selected.filter(selectCheck.bind(this));
        }
        if (typeof this.disableRowCheck() === 'function') {
            selected = selected.filter(rowData => !this.disableRowCheck()(rowData));
        }
        this.selected.set(selected);
        this.prevIndex = index;
    }
    onActivate(modelObject, index) {
        const { type, event, row } = modelObject;
        const chkbox = this.selectionType() === 'checkbox';
        const select = (!chkbox && (type === 'click' || type === 'dblclick')) || (chkbox && type === 'checkbox');
        if (select) {
            this.selectRow(event, index, row);
        }
        else if (type === 'keydown') {
            if (event.key === ENTER) {
                this.selectRow(event, index, row);
            }
            else if (event.key === 'a' &&
                (event.ctrlKey || event.metaKey)) {
                this.selectRow(event, 0, row); // The row property is ignored in this case. So we can pass anything.
            }
            else {
                this.onKeyboardFocus(modelObject);
            }
        }
        this.activate.emit(modelObject);
    }
    groupSelectedChange(selected, group) {
        const selectedSet = new Set(this.selected());
        if (selected) {
            group.value.forEach(row => selectedSet.add(row));
        }
        else {
            group.value.forEach(row => selectedSet.delete(row));
        }
        this.selected.set(Array.from(selectedSet));
    }
    onKeyboardFocus(modelObject) {
        const { key } = modelObject.event;
        const shouldFocus = key === ARROW_UP || key === ARROW_DOWN || key === ARROW_RIGHT || key === ARROW_LEFT;
        if (shouldFocus) {
            const isCellSelection = this.selectionType() === 'cell';
            const disableRowCheck = this.disableRowCheck();
            if (typeof disableRowCheck === 'function') {
                const isRowDisabled = disableRowCheck(modelObject.row);
                if (isRowDisabled) {
                    return;
                }
            }
            if (!modelObject.cellElement || !isCellSelection) {
                this.focusRow(modelObject.rowElement, key);
            }
            else if (isCellSelection && modelObject.cellIndex !== undefined) {
                this.focusCell(modelObject.cellElement, modelObject.rowElement, key, modelObject.cellIndex);
            }
        }
    }
    focusRow(rowElement, key) {
        const nextRowElement = this.getPrevNextRow(rowElement, key);
        if (nextRowElement) {
            nextRowElement.focus();
        }
    }
    getPrevNextRow(rowElement, key) {
        const parentElement = rowElement.parentElement;
        if (parentElement) {
            let focusElement = null;
            if (key === ARROW_UP) {
                focusElement = parentElement.previousElementSibling;
            }
            else if (key === ARROW_DOWN) {
                focusElement = parentElement.nextElementSibling;
            }
            if (focusElement?.children.length) {
                return focusElement.children[0];
            }
        }
    }
    focusCell(cellElement, rowElement, key, cellIndex) {
        let nextCellElement = null;
        if (key === ARROW_LEFT) {
            nextCellElement = cellElement.previousElementSibling;
        }
        else if (key === ARROW_RIGHT) {
            nextCellElement = cellElement.nextElementSibling;
        }
        else if (key === ARROW_UP || key === ARROW_DOWN) {
            const nextRowElement = this.getPrevNextRow(rowElement, key);
            if (nextRowElement) {
                const children = nextRowElement.getElementsByClassName('datatable-body-cell');
                if (children.length) {
                    nextCellElement = children[cellIndex];
                }
            }
        }
        if (nextCellElement &&
            'focus' in nextCellElement &&
            typeof nextCellElement.focus === 'function') {
            nextCellElement.focus();
        }
    }
    getRowSelected(row) {
        return this.getRowSelectedIdx(row, this.selected()) > -1;
    }
    getRowSelectedIdx(row, selected) {
        if (!selected?.length) {
            return -1;
        }
        const rowId = this.rowIdentity()(row);
        return selected.findIndex(r => {
            const id = this.rowIdentity()(r);
            return id === rowId;
        });
    }
    isGroup(row) {
        return !!this.groupedRows();
    }
    isRow(row) {
        return !this.groupedRows();
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DataTableBodyComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DataTableBodyComponent, isStandalone: true, selector: "datatable-body", inputs: { rowDefTemplate: { classPropertyName: "rowDefTemplate", publicName: "rowDefTemplate", isSignal: true, isRequired: false, transformFunction: null }, scrollbarV: { classPropertyName: "scrollbarV", publicName: "scrollbarV", isSignal: true, isRequired: false, transformFunction: null }, scrollbarH: { classPropertyName: "scrollbarH", publicName: "scrollbarH", isSignal: true, isRequired: false, transformFunction: null }, loadingIndicator: { classPropertyName: "loadingIndicator", publicName: "loadingIndicator", isSignal: true, isRequired: false, transformFunction: null }, ghostLoadingIndicator: { classPropertyName: "ghostLoadingIndicator", publicName: "ghostLoadingIndicator", isSignal: true, isRequired: false, transformFunction: null }, externalPaging: { classPropertyName: "externalPaging", publicName: "externalPaging", isSignal: true, isRequired: false, transformFunction: null }, rowHeight: { classPropertyName: "rowHeight", publicName: "rowHeight", isSignal: true, isRequired: true, transformFunction: null }, offsetX: { classPropertyName: "offsetX", publicName: "offsetX", isSignal: true, isRequired: true, transformFunction: null }, selectionType: { classPropertyName: "selectionType", publicName: "selectionType", isSignal: true, isRequired: false, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "selected", isSignal: true, isRequired: false, transformFunction: null }, rowIdentity: { classPropertyName: "rowIdentity", publicName: "rowIdentity", isSignal: true, isRequired: true, transformFunction: null }, rowDetail: { classPropertyName: "rowDetail", publicName: "rowDetail", isSignal: true, isRequired: false, transformFunction: null }, groupHeader: { classPropertyName: "groupHeader", publicName: "groupHeader", isSignal: true, isRequired: false, transformFunction: null }, selectCheck: { classPropertyName: "selectCheck", publicName: "selectCheck", isSignal: true, isRequired: false, transformFunction: null }, displayCheck: { classPropertyName: "displayCheck", publicName: "displayCheck", isSignal: true, isRequired: false, transformFunction: null }, trackByProp: { classPropertyName: "trackByProp", publicName: "trackByProp", isSignal: true, isRequired: false, transformFunction: null }, rowClass: { classPropertyName: "rowClass", publicName: "rowClass", isSignal: true, isRequired: false, transformFunction: null }, groupedRows: { classPropertyName: "groupedRows", publicName: "groupedRows", isSignal: true, isRequired: false, transformFunction: null }, groupExpansionDefault: { classPropertyName: "groupExpansionDefault", publicName: "groupExpansionDefault", isSignal: false, isRequired: false, transformFunction: null }, innerWidth: { classPropertyName: "innerWidth", publicName: "innerWidth", isSignal: true, isRequired: true, transformFunction: null }, virtualization: { classPropertyName: "virtualization", publicName: "virtualization", isSignal: true, isRequired: false, transformFunction: null }, summaryRow: { classPropertyName: "summaryRow", publicName: "summaryRow", isSignal: true, isRequired: false, transformFunction: null }, summaryPosition: { classPropertyName: "summaryPosition", publicName: "summaryPosition", isSignal: true, isRequired: true, transformFunction: null }, summaryHeight: { classPropertyName: "summaryHeight", publicName: "summaryHeight", isSignal: true, isRequired: true, transformFunction: null }, rowDraggable: { classPropertyName: "rowDraggable", publicName: "rowDraggable", isSignal: true, isRequired: false, transformFunction: null }, rowDragEvents: { classPropertyName: "rowDragEvents", publicName: "rowDragEvents", isSignal: true, isRequired: true, transformFunction: null }, disableRowCheck: { classPropertyName: "disableRowCheck", publicName: "disableRowCheck", isSignal: true, isRequired: false, transformFunction: null }, ariaGroupHeaderCheckboxMessage: { classPropertyName: "ariaGroupHeaderCheckboxMessage", publicName: "ariaGroupHeaderCheckboxMessage", isSignal: true, isRequired: true, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: true, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: true, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, offset: { classPropertyName: "offset", publicName: "offset", isSignal: true, isRequired: false, transformFunction: null }, rowCount: { classPropertyName: "rowCount", publicName: "rowCount", isSignal: true, isRequired: false, transformFunction: null }, bodyHeight: { classPropertyName: "bodyHeight", publicName: "bodyHeight", isSignal: true, isRequired: false, transformFunction: null }, verticalScrollVisible: { classPropertyName: "verticalScrollVisible", publicName: "verticalScrollVisible", isSignal: true, isRequired: false, transformFunction: null }, ariaRowCheckboxMessage: { classPropertyName: "ariaRowCheckboxMessage", publicName: "ariaRowCheckboxMessage", isSignal: true, isRequired: true, transformFunction: null }, cssClasses: { classPropertyName: "cssClasses", publicName: "cssClasses", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { offsetX: "offsetXChange", selected: "selectedChange", scroll: "scroll", page: "page", activate: "activate", rowContextmenu: "rowContextmenu", treeAction: "treeAction" }, host: { properties: { "style.height": "_bodyHeight()", "style.width": "_bodyWidth()" }, classAttribute: "datatable-body" }, viewQueries: [{ propertyName: "scroller", first: true, predicate: ScrollerComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: `
    @if (loadingIndicator()) {
      <div class="custom-loading-indicator-wrapper">
        <div class="custom-loading-content">
          <ng-content select="[loading-indicator]" />
        </div>
      </div>
    }
    @let scrollbarV = this.scrollbarV();
    @let columns = this.columns();
    @let columnGroupWidths = this.columnGroupWidths();
    @let bodyHeight = this._bodyHeight();
    @let rows = this.rows();
    @let rowCount = this.rowCount();
    @if (ghostLoadingIndicator() && (!rowCount || !virtualization() || !scrollbarV)) {
      <ghost-loader
        class="ghost-overlay"
        [columns]="columns"
        [pageSize]="pageSize()"
        [rowHeight]="rowHeight()"
        [ghostBodyHeight]="bodyHeight"
      />
    }
    @if (rows.length) {
      <datatable-scroller
        [scrollbarV]="scrollbarV"
        [scrollbarH]="scrollbarH()"
        [scrollHeight]="scrollHeight()"
        [scrollWidth]="columnGroupWidths?.total"
        [class.horizontal-overflow]="innerWidth() < (columnGroupWidths?.total ?? 0)"
        (scroll)="onBodyScroll($event)"
      >
        @if (summaryRow() && summaryPosition() === 'top') {
          <datatable-summary-row
            [rowHeight]="summaryHeight()"
            [innerWidth]="innerWidth()"
            [rows]="rows"
            [columns]="columns"
          />
        }
        <ng-template
          #bodyRow
          let-row="row"
          let-index="index"
          let-indexInGroup="indexInGroup"
          let-groupedRows="groupedRows"
          let-disabled="disabled"
          ngx-datatable-body-row
        >
          <datatable-row-wrapper
            [attr.hidden]="
              ghostLoadingIndicator() && (!rowCount || !virtualization() || !scrollbarV)
                ? true
                : null
            "
            [innerWidth]="innerWidth()"
            [rowDetail]="rowDetail()"
            [detailRowHeightFn]="detailRowHeightFn()"
            [row]="row"
            [disabled]="disabled"
            [expanded]="getRowExpanded(row)"
            [rowIndex]="indexes().first + index"
            [ariaGroupHeaderCheckboxMessage]="ariaGroupHeaderCheckboxMessage()"
            (rowContextmenu)="rowContextmenu.emit($event)"
          >
            <datatable-body-row
              #rowElement
              [disabled]="disabled"
              [isSelected]="getRowSelected(row)"
              [columns]="columns"
              [rowHeight]="getRowHeight(row)"
              [row]="row"
              [group]="groupedRows"
              [rowIndex]="{ index: index, indexInGroup: indexInGroup }"
              [expanded]="getRowExpanded(row)"
              [rowClass]="rowClass()"
              [displayCheck]="displayCheck()"
              [treeStatus]="row?.treeStatus"
              [draggable]="rowDraggable()"
              [ariaRowCheckboxMessage]="ariaRowCheckboxMessage()"
              [cssClasses]="cssClasses()"
              (treeAction)="onTreeAction(row)"
              (activate)="onActivate($event, index)"
              (drop)="drop($event, row, rowElement)"
              (dragover)="dragOver($event, row)"
              (dragenter)="dragEnter($event, row, rowElement)"
              (dragleave)="dragLeave($event, row, rowElement)"
              (dragstart)="drag($event, row, rowElement)"
              (dragend)="dragEnd($event, row)"
            />
          </datatable-row-wrapper>
        </ng-template>

        <div [style.transform]="renderOffset()">
          @for (group of rowsToRender(); track rowTrackingFn(i, group); let i = $index) {
            @if (!group && ghostLoadingIndicator()) {
              <ghost-loader [columns]="columns" [pageSize]="1" [rowHeight]="rowHeight()" />
            } @else if (group) {
              @let disableRowCheck = this.disableRowCheck();
              @let disabled = isRow(group) && disableRowCheck && disableRowCheck(group);
              @let rowDefTemplate = this.rowDefTemplate();
              @if (rowDefTemplate) {
                <ng-container
                  *rowDefInternal="
                    {
                      template: rowDefTemplate,
                      rowTemplate: bodyRow,
                      row: group,
                      index: i
                    };
                    disabled: disabled
                  "
                />
              } @else {
                @if (isRow(group)) {
                  <ng-container
                    [ngTemplateOutlet]="bodyRow"
                    [ngTemplateOutletContext]="{
                      row: group,
                      index: indexes().first + i,
                      disabled
                    }"
                  />
                }
              }

              @if (isGroup(group)) {
                <datatable-group-wrapper
                  [group]="group"
                  [attr.hidden]="
                    ghostLoadingIndicator() && (!rowCount || !virtualization() || !scrollbarV)
                      ? true
                      : null
                  "
                  [innerWidth]="innerWidth()"
                  [style.width]="groupedRows() ? columnGroupWidths.total : undefined"
                  [groupHeader]="groupHeader()"
                  [groupHeaderRowHeight]="getGroupHeaderRowHeight(group, i)"
                  [disabled]="disabled"
                  [expanded]="getGroupExpanded(group)"
                  [rowIndex]="indexes().first + i"
                  [selected]="selected()"
                  [ariaGroupHeaderCheckboxMessage]="ariaGroupHeaderCheckboxMessage()"
                  (groupSelectedChange)="groupSelectedChange($event, group)"
                >
                  @for (row of group.value; track rowTrackingFn($index, row)) {
                    @let disabled = disableRowCheck && disableRowCheck(row);
                    <ng-container
                      [ngTemplateOutlet]="bodyRow"
                      [ngTemplateOutletContext]="{
                        row,
                        groupedRows: group?.value,
                        index: indexes().first + i,
                        indexInGroup: $index,
                        disabled
                      }"
                    />
                  }
                </datatable-group-wrapper>
              }
            }
          }
        </div>
      </datatable-scroller>
      @if (summaryRow() && summaryPosition() === 'bottom') {
        <datatable-summary-row
          [rowHeight]="summaryHeight()"
          [innerWidth]="innerWidth()"
          [rows]="rows"
          [columns]="columns"
        />
      }
    }
    @if (!rows?.length && !loadingIndicator() && !ghostLoadingIndicator()) {
      <datatable-scroller
        [scrollbarV]="scrollbarV"
        [scrollbarH]="scrollbarH()"
        [scrollHeight]="scrollHeight()"
        [style.width]="scrollbarH() ? columnGroupWidths?.total + 'px' : '100%'"
        (scroll)="onBodyScroll($event)"
      >
        <ng-content select="[empty-content]" />
      </datatable-scroller>
    }
  `, isInline: true, styles: [":host{position:relative;z-index:10;display:block;overflow:hidden}:host-context(ngx-datatable.scroll-horz) :host{overflow-x:auto;-webkit-overflow-scrolling:touch}datatable-scroller{display:block}:host-context(ngx-datatable.fixed-row) datatable-scroller{white-space:nowrap}:host-context(ngx-datatable.scroll-vertical) :host{overflow-y:auto}[hidden]{display:none!important}\n"], dependencies: [{ kind: "component", type: DataTableGhostLoaderComponent, selector: "ghost-loader", inputs: ["columns", "pageSize", "rowHeight", "ghostBodyHeight"] }, { kind: "component", type: ScrollerComponent, selector: "datatable-scroller", inputs: ["scrollbarV", "scrollbarH", "scrollHeight", "scrollWidth"], outputs: ["scroll"] }, { kind: "component", type: DataTableSummaryRowComponent, selector: "datatable-summary-row", inputs: ["rows", "columns", "rowHeight", "innerWidth"] }, { kind: "component", type: DataTableRowWrapperComponent, selector: "datatable-row-wrapper", inputs: ["innerWidth", "rowDetail", "detailRowHeightFn", "row", "disabled", "rowIndex", "expanded", "ariaGroupHeaderCheckboxMessage"], outputs: ["rowContextmenu"] }, { kind: "directive", type: DatatableRowDefInternalDirective, selector: "[rowDefInternal]", inputs: ["rowDefInternal", "rowDefInternalDisabled"] }, { kind: "component", type: DataTableBodyRowComponent, selector: "datatable-body-row", inputs: ["columns", "expanded", "rowClass", "row", "group", "isSelected", "rowIndex", "displayCheck", "treeStatus", "ariaRowCheckboxMessage", "disabled", "cssClasses", "rowHeight"], outputs: ["activate", "treeAction"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: DatatableBodyRowDirective, selector: "[ngx-datatable-body-row]" }, { kind: "component", type: DataTableGroupWrapperComponent, selector: "datatable-group-wrapper", inputs: ["innerWidth", "groupHeader", "groupHeaderRowHeight", "group", "groupedRows", "selected", "disabled", "rowIndex", "expanded", "ariaGroupHeaderCheckboxMessage"], outputs: ["groupSelectedChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DataTableBodyComponent, decorators: [{
            type: Component,
            args: [{ selector: 'datatable-body', imports: [
                        DataTableGhostLoaderComponent,
                        ScrollerComponent,
                        DataTableSummaryRowComponent,
                        DataTableRowWrapperComponent,
                        DatatableRowDefInternalDirective,
                        DataTableBodyRowComponent,
                        NgTemplateOutlet,
                        DatatableBodyRowDirective,
                        DataTableGroupWrapperComponent
                    ], template: `
    @if (loadingIndicator()) {
      <div class="custom-loading-indicator-wrapper">
        <div class="custom-loading-content">
          <ng-content select="[loading-indicator]" />
        </div>
      </div>
    }
    @let scrollbarV = this.scrollbarV();
    @let columns = this.columns();
    @let columnGroupWidths = this.columnGroupWidths();
    @let bodyHeight = this._bodyHeight();
    @let rows = this.rows();
    @let rowCount = this.rowCount();
    @if (ghostLoadingIndicator() && (!rowCount || !virtualization() || !scrollbarV)) {
      <ghost-loader
        class="ghost-overlay"
        [columns]="columns"
        [pageSize]="pageSize()"
        [rowHeight]="rowHeight()"
        [ghostBodyHeight]="bodyHeight"
      />
    }
    @if (rows.length) {
      <datatable-scroller
        [scrollbarV]="scrollbarV"
        [scrollbarH]="scrollbarH()"
        [scrollHeight]="scrollHeight()"
        [scrollWidth]="columnGroupWidths?.total"
        [class.horizontal-overflow]="innerWidth() < (columnGroupWidths?.total ?? 0)"
        (scroll)="onBodyScroll($event)"
      >
        @if (summaryRow() && summaryPosition() === 'top') {
          <datatable-summary-row
            [rowHeight]="summaryHeight()"
            [innerWidth]="innerWidth()"
            [rows]="rows"
            [columns]="columns"
          />
        }
        <ng-template
          #bodyRow
          let-row="row"
          let-index="index"
          let-indexInGroup="indexInGroup"
          let-groupedRows="groupedRows"
          let-disabled="disabled"
          ngx-datatable-body-row
        >
          <datatable-row-wrapper
            [attr.hidden]="
              ghostLoadingIndicator() && (!rowCount || !virtualization() || !scrollbarV)
                ? true
                : null
            "
            [innerWidth]="innerWidth()"
            [rowDetail]="rowDetail()"
            [detailRowHeightFn]="detailRowHeightFn()"
            [row]="row"
            [disabled]="disabled"
            [expanded]="getRowExpanded(row)"
            [rowIndex]="indexes().first + index"
            [ariaGroupHeaderCheckboxMessage]="ariaGroupHeaderCheckboxMessage()"
            (rowContextmenu)="rowContextmenu.emit($event)"
          >
            <datatable-body-row
              #rowElement
              [disabled]="disabled"
              [isSelected]="getRowSelected(row)"
              [columns]="columns"
              [rowHeight]="getRowHeight(row)"
              [row]="row"
              [group]="groupedRows"
              [rowIndex]="{ index: index, indexInGroup: indexInGroup }"
              [expanded]="getRowExpanded(row)"
              [rowClass]="rowClass()"
              [displayCheck]="displayCheck()"
              [treeStatus]="row?.treeStatus"
              [draggable]="rowDraggable()"
              [ariaRowCheckboxMessage]="ariaRowCheckboxMessage()"
              [cssClasses]="cssClasses()"
              (treeAction)="onTreeAction(row)"
              (activate)="onActivate($event, index)"
              (drop)="drop($event, row, rowElement)"
              (dragover)="dragOver($event, row)"
              (dragenter)="dragEnter($event, row, rowElement)"
              (dragleave)="dragLeave($event, row, rowElement)"
              (dragstart)="drag($event, row, rowElement)"
              (dragend)="dragEnd($event, row)"
            />
          </datatable-row-wrapper>
        </ng-template>

        <div [style.transform]="renderOffset()">
          @for (group of rowsToRender(); track rowTrackingFn(i, group); let i = $index) {
            @if (!group && ghostLoadingIndicator()) {
              <ghost-loader [columns]="columns" [pageSize]="1" [rowHeight]="rowHeight()" />
            } @else if (group) {
              @let disableRowCheck = this.disableRowCheck();
              @let disabled = isRow(group) && disableRowCheck && disableRowCheck(group);
              @let rowDefTemplate = this.rowDefTemplate();
              @if (rowDefTemplate) {
                <ng-container
                  *rowDefInternal="
                    {
                      template: rowDefTemplate,
                      rowTemplate: bodyRow,
                      row: group,
                      index: i
                    };
                    disabled: disabled
                  "
                />
              } @else {
                @if (isRow(group)) {
                  <ng-container
                    [ngTemplateOutlet]="bodyRow"
                    [ngTemplateOutletContext]="{
                      row: group,
                      index: indexes().first + i,
                      disabled
                    }"
                  />
                }
              }

              @if (isGroup(group)) {
                <datatable-group-wrapper
                  [group]="group"
                  [attr.hidden]="
                    ghostLoadingIndicator() && (!rowCount || !virtualization() || !scrollbarV)
                      ? true
                      : null
                  "
                  [innerWidth]="innerWidth()"
                  [style.width]="groupedRows() ? columnGroupWidths.total : undefined"
                  [groupHeader]="groupHeader()"
                  [groupHeaderRowHeight]="getGroupHeaderRowHeight(group, i)"
                  [disabled]="disabled"
                  [expanded]="getGroupExpanded(group)"
                  [rowIndex]="indexes().first + i"
                  [selected]="selected()"
                  [ariaGroupHeaderCheckboxMessage]="ariaGroupHeaderCheckboxMessage()"
                  (groupSelectedChange)="groupSelectedChange($event, group)"
                >
                  @for (row of group.value; track rowTrackingFn($index, row)) {
                    @let disabled = disableRowCheck && disableRowCheck(row);
                    <ng-container
                      [ngTemplateOutlet]="bodyRow"
                      [ngTemplateOutletContext]="{
                        row,
                        groupedRows: group?.value,
                        index: indexes().first + i,
                        indexInGroup: $index,
                        disabled
                      }"
                    />
                  }
                </datatable-group-wrapper>
              }
            }
          }
        </div>
      </datatable-scroller>
      @if (summaryRow() && summaryPosition() === 'bottom') {
        <datatable-summary-row
          [rowHeight]="summaryHeight()"
          [innerWidth]="innerWidth()"
          [rows]="rows"
          [columns]="columns"
        />
      }
    }
    @if (!rows?.length && !loadingIndicator() && !ghostLoadingIndicator()) {
      <datatable-scroller
        [scrollbarV]="scrollbarV"
        [scrollbarH]="scrollbarH()"
        [scrollHeight]="scrollHeight()"
        [style.width]="scrollbarH() ? columnGroupWidths?.total + 'px' : '100%'"
        (scroll)="onBodyScroll($event)"
      >
        <ng-content select="[empty-content]" />
      </datatable-scroller>
    }
  `, changeDetection: ChangeDetectionStrategy.OnPush, host: {
                        class: 'datatable-body',
                        '[style.height]': '_bodyHeight()',
                        '[style.width]': '_bodyWidth()'
                    }, styles: [":host{position:relative;z-index:10;display:block;overflow:hidden}:host-context(ngx-datatable.scroll-horz) :host{overflow-x:auto;-webkit-overflow-scrolling:touch}datatable-scroller{display:block}:host-context(ngx-datatable.fixed-row) datatable-scroller{white-space:nowrap}:host-context(ngx-datatable.scroll-vertical) :host{overflow-y:auto}[hidden]{display:none!important}\n"] }]
        }], ctorParameters: () => [], propDecorators: { rowDefTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowDefTemplate", required: false }] }], scrollbarV: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollbarV", required: false }] }], scrollbarH: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollbarH", required: false }] }], loadingIndicator: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadingIndicator", required: false }] }], ghostLoadingIndicator: [{ type: i0.Input, args: [{ isSignal: true, alias: "ghostLoadingIndicator", required: false }] }], externalPaging: [{ type: i0.Input, args: [{ isSignal: true, alias: "externalPaging", required: false }] }], rowHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowHeight", required: true }] }], offsetX: [{ type: i0.Input, args: [{ isSignal: true, alias: "offsetX", required: true }] }, { type: i0.Output, args: ["offsetXChange"] }], selectionType: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectionType", required: false }] }], selected: [{ type: i0.Input, args: [{ isSignal: true, alias: "selected", required: false }] }, { type: i0.Output, args: ["selectedChange"] }], rowIdentity: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowIdentity", required: true }] }], rowDetail: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowDetail", required: false }] }], groupHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupHeader", required: false }] }], selectCheck: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectCheck", required: false }] }], displayCheck: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayCheck", required: false }] }], trackByProp: [{ type: i0.Input, args: [{ isSignal: true, alias: "trackByProp", required: false }] }], rowClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowClass", required: false }] }], groupedRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupedRows", required: false }] }], groupExpansionDefault: [{
                type: Input
            }], innerWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "innerWidth", required: true }] }], virtualization: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualization", required: false }] }], summaryRow: [{ type: i0.Input, args: [{ isSignal: true, alias: "summaryRow", required: false }] }], summaryPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "summaryPosition", required: true }] }], summaryHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "summaryHeight", required: true }] }], rowDraggable: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowDraggable", required: false }] }], rowDragEvents: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowDragEvents", required: true }] }], disableRowCheck: [{ type: i0.Input, args: [{ isSignal: true, alias: "disableRowCheck", required: false }] }], ariaGroupHeaderCheckboxMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaGroupHeaderCheckboxMessage", required: true }] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: true }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: true }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], offset: [{ type: i0.Input, args: [{ isSignal: true, alias: "offset", required: false }] }], rowCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowCount", required: false }] }], bodyHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "bodyHeight", required: false }] }], verticalScrollVisible: [{ type: i0.Input, args: [{ isSignal: true, alias: "verticalScrollVisible", required: false }] }], ariaRowCheckboxMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaRowCheckboxMessage", required: true }] }], cssClasses: [{ type: i0.Input, args: [{ isSignal: true, alias: "cssClasses", required: true }] }], scroll: [{ type: i0.Output, args: ["scroll"] }], page: [{ type: i0.Output, args: ["page"] }], activate: [{ type: i0.Output, args: ["activate"] }], rowContextmenu: [{ type: i0.Output, args: ["rowContextmenu"] }], treeAction: [{ type: i0.Output, args: ["treeAction"] }], scroller: [{
                type: ViewChild,
                args: [ScrollerComponent]
            }] } });

class ProgressBarComponent {
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ProgressBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: ProgressBarComponent, isStandalone: true, selector: "datatable-progress", ngImport: i0, template: `
    <div class="progress-linear" role="progressbar">
      <div class="container">
        <div class="bar"></div>
      </div>
    </div>
  `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ProgressBarComponent, decorators: [{
            type: Component,
            args: [{
                    selector: 'datatable-progress',
                    template: `
    <div class="progress-linear" role="progressbar">
      <div class="container">
        <div class="bar"></div>
      </div>
    </div>
  `,
                    changeDetection: ChangeDetectionStrategy.OnPush
                }]
        }] });

/**
 * Use this component to construct custom table footer with standard pagination.
 *
 * It must be used inside the `ngx-datatable-footer`
 *
 * @example
 * ```html
 *
 * <ngx-datatable>
 *   ...
 *   <ngx-datatable-footer>
 *     <ng-template>
 *        <app-custom-content />
 *        <ngx-datatable-pager />
 *     </ng-template>
 *   </ngx-datatable-footer>
 * </ngx-datatable>
 * ```
 */
class DatatablePagerComponent {
    constructor() {
        // We cannot inject the footer directly as it is not part of the injector when used in a template.
        // But the table always is.
        // Ideally we can one day fetch those attributes from a global state, but for now this is fine.
        this.datatable = inject(DATATABLE_COMPONENT_TOKEN);
        this.page = computed(() => this.datatable._footerComponent().curPage(), ...(ngDevMode ? [{ debugName: "page" }] : []));
        this.pageSize = computed(() => this.datatable._footerComponent().pageSize(), ...(ngDevMode ? [{ debugName: "pageSize" }] : []));
        this.count = computed(() => this.datatable._footerComponent().groupCount() ??
            this.datatable._footerComponent().rowCount(), ...(ngDevMode ? [{ debugName: "count" }] : []));
        this.pagerNextIcon = computed(() => this.datatable._footerComponent().pagerNextIcon(), ...(ngDevMode ? [{ debugName: "pagerNextIcon" }] : []));
        this.pagerRightArrowIcon = computed(() => this.datatable._footerComponent().pagerRightArrowIcon(), ...(ngDevMode ? [{ debugName: "pagerRightArrowIcon" }] : []));
        this.pagerLeftArrowIcon = computed(() => this.datatable._footerComponent().pagerLeftArrowIcon(), ...(ngDevMode ? [{ debugName: "pagerLeftArrowIcon" }] : []));
        this.pagerPreviousIcon = computed(() => this.datatable._footerComponent().pagerPreviousIcon(), ...(ngDevMode ? [{ debugName: "pagerPreviousIcon" }] : []));
        this.totalPages = computed(() => {
            return Math.max((this.pageSize() < 1 ? 1 : Math.ceil(this.count() / this.pageSize())) || 0, 1);
        }, ...(ngDevMode ? [{ debugName: "totalPages" }] : []));
        this.pages = computed(() => {
            const pages = [];
            let startPage = 1;
            let endPage = this.totalPages();
            const maxSize = 5;
            const isMaxSized = maxSize < this.totalPages();
            const page = this.page();
            if (isMaxSized) {
                startPage = page - Math.floor(maxSize / 2);
                endPage = page + Math.floor(maxSize / 2);
                if (startPage < 1) {
                    startPage = 1;
                    endPage = Math.min(startPage + maxSize - 1, this.totalPages());
                }
                else if (endPage > this.totalPages()) {
                    startPage = Math.max(this.totalPages() - maxSize + 1, 1);
                    endPage = this.totalPages();
                }
            }
            for (let num = startPage; num <= endPage; num++) {
                pages.push({
                    number: num,
                    text: num.toString()
                });
            }
            return pages;
        }, ...(ngDevMode ? [{ debugName: "pages" }] : []));
        this.canPrevious = computed(() => this.page() > 1, ...(ngDevMode ? [{ debugName: "canPrevious" }] : []));
        this.canNext = computed(() => this.page() < this.totalPages(), ...(ngDevMode ? [{ debugName: "canNext" }] : []));
    }
    get messages() {
        return this.datatable?.messages() ?? {};
    }
    prevPage() {
        this.selectPage(this.page() - 1);
    }
    nextPage() {
        this.selectPage(this.page() + 1);
    }
    selectPage(page) {
        if (page > 0 && page <= this.totalPages() && page !== this.page()) {
            this.datatable._footerComponent().page.emit({ page });
        }
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DatatablePagerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DatatablePagerComponent, isStandalone: true, selector: "ngx-datatable-pager", host: { classAttribute: "datatable-pager" }, ngImport: i0, template: `
    <ul class="pager">
      <li>
        <button
          type="button"
          class="page-button"
          [disabled]="!canPrevious()"
          [attr.aria-label]="messages.ariaFirstPageMessage ?? 'go to first page'"
          (click)="selectPage(1)"
        >
          <i [class]="pagerPreviousIcon() ?? 'datatable-icon-prev'"></i>
        </button>
      </li>
      <li>
        <button
          type="button"
          class="page-button"
          [disabled]="!canPrevious()"
          [attr.aria-label]="messages.ariaPreviousPageMessage ?? 'go to previous page'"
          (click)="prevPage()"
        >
          <i [class]="pagerLeftArrowIcon() ?? 'datatable-icon-left'"></i>
        </button>
      </li>
      @for (pg of pages(); track pg.number) {
        <li class="pages">
          <button
            type="button"
            class="page-button"
            [class.active]="pg.number === page()"
            [attr.aria-label]="(messages.ariaPageNMessage ?? 'page') + ' ' + pg.number"
            (click)="selectPage(pg.number)"
          >
            {{ pg.text }}
          </button>
        </li>
      }
      <li>
        <button
          type="button"
          class="page-button"
          [disabled]="!canNext()"
          [attr.aria-label]="messages.ariaNextPageMessage ?? 'go to next page'"
          (click)="nextPage()"
        >
          <i [class]="pagerRightArrowIcon() ?? 'datatable-icon-right'"></i>
        </button>
      </li>
      <li>
        <button
          type="button"
          class="page-button"
          [disabled]="!canNext()"
          [attr.aria-label]="messages.ariaLastPageMessage ?? 'go to last page'"
          (click)="selectPage(totalPages())"
        >
          <i [class]="pagerNextIcon() ?? 'datatable-icon-skip'"></i>
        </button>
      </li>
    </ul>
  `, isInline: true, styles: [":host-context(datatable-footer .selected-count) .datatable-pager{flex:1 1 60%}:host{flex:1 1 80%;text-align:end}.pager,.pager li{padding:0;margin:0;display:inline-block;list-style:none}.page-button{cursor:pointer;display:inline-block}.page-button:disabled{cursor:not-allowed}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DatatablePagerComponent, decorators: [{
            type: Component,
            args: [{ selector: 'ngx-datatable-pager', template: `
    <ul class="pager">
      <li>
        <button
          type="button"
          class="page-button"
          [disabled]="!canPrevious()"
          [attr.aria-label]="messages.ariaFirstPageMessage ?? 'go to first page'"
          (click)="selectPage(1)"
        >
          <i [class]="pagerPreviousIcon() ?? 'datatable-icon-prev'"></i>
        </button>
      </li>
      <li>
        <button
          type="button"
          class="page-button"
          [disabled]="!canPrevious()"
          [attr.aria-label]="messages.ariaPreviousPageMessage ?? 'go to previous page'"
          (click)="prevPage()"
        >
          <i [class]="pagerLeftArrowIcon() ?? 'datatable-icon-left'"></i>
        </button>
      </li>
      @for (pg of pages(); track pg.number) {
        <li class="pages">
          <button
            type="button"
            class="page-button"
            [class.active]="pg.number === page()"
            [attr.aria-label]="(messages.ariaPageNMessage ?? 'page') + ' ' + pg.number"
            (click)="selectPage(pg.number)"
          >
            {{ pg.text }}
          </button>
        </li>
      }
      <li>
        <button
          type="button"
          class="page-button"
          [disabled]="!canNext()"
          [attr.aria-label]="messages.ariaNextPageMessage ?? 'go to next page'"
          (click)="nextPage()"
        >
          <i [class]="pagerRightArrowIcon() ?? 'datatable-icon-right'"></i>
        </button>
      </li>
      <li>
        <button
          type="button"
          class="page-button"
          [disabled]="!canNext()"
          [attr.aria-label]="messages.ariaLastPageMessage ?? 'go to last page'"
          (click)="selectPage(totalPages())"
        >
          <i [class]="pagerNextIcon() ?? 'datatable-icon-skip'"></i>
        </button>
      </li>
    </ul>
  `, changeDetection: ChangeDetectionStrategy.OnPush, host: {
                        class: 'datatable-pager'
                    }, styles: [":host-context(datatable-footer .selected-count) .datatable-pager{flex:1 1 60%}:host{flex:1 1 80%;text-align:end}.pager,.pager li{padding:0;margin:0;display:inline-block;list-style:none}.page-button{cursor:pointer;display:inline-block}.page-button:disabled{cursor:not-allowed}\n"] }]
        }] });

class DataTableFooterComponent {
    constructor() {
        this.footerHeight = input.required(...(ngDevMode ? [{ debugName: "footerHeight" }] : []));
        this.rowCount = input.required(...(ngDevMode ? [{ debugName: "rowCount" }] : []));
        this.groupCount = input.required(...(ngDevMode ? [{ debugName: "groupCount" }] : []));
        this.pageSize = input.required(...(ngDevMode ? [{ debugName: "pageSize" }] : []));
        this.offset = input.required(...(ngDevMode ? [{ debugName: "offset" }] : []));
        this.pagerLeftArrowIcon = input(...(ngDevMode ? [undefined, { debugName: "pagerLeftArrowIcon" }] : []));
        this.pagerRightArrowIcon = input(...(ngDevMode ? [undefined, { debugName: "pagerRightArrowIcon" }] : []));
        this.pagerPreviousIcon = input(...(ngDevMode ? [undefined, { debugName: "pagerPreviousIcon" }] : []));
        this.pagerNextIcon = input(...(ngDevMode ? [undefined, { debugName: "pagerNextIcon" }] : []));
        this.totalMessage = input.required(...(ngDevMode ? [{ debugName: "totalMessage" }] : []));
        this.footerTemplate = input(...(ngDevMode ? [undefined, { debugName: "footerTemplate" }] : []));
        this.selectedCount = input(0, ...(ngDevMode ? [{ debugName: "selectedCount" }] : []));
        this.selectedMessage = input(undefined, ...(ngDevMode ? [{ debugName: "selectedMessage" }] : []));
        this.page = output();
        this.isVisible = computed(() => this.rowCount() / this.pageSize() > 1, ...(ngDevMode ? [{ debugName: "isVisible" }] : []));
        this.curPage = computed(() => this.offset() + 1, ...(ngDevMode ? [{ debugName: "curPage" }] : []));
        this.templateContext = computed(() => ({
            rowCount: this.rowCount(),
            pageSize: this.pageSize(),
            selectedCount: this.selectedCount(),
            curPage: this.curPage(),
            offset: this.offset()
        }), ...(ngDevMode ? [{ debugName: "templateContext" }] : []));
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DataTableFooterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DataTableFooterComponent, isStandalone: true, selector: "datatable-footer", inputs: { footerHeight: { classPropertyName: "footerHeight", publicName: "footerHeight", isSignal: true, isRequired: true, transformFunction: null }, rowCount: { classPropertyName: "rowCount", publicName: "rowCount", isSignal: true, isRequired: true, transformFunction: null }, groupCount: { classPropertyName: "groupCount", publicName: "groupCount", isSignal: true, isRequired: true, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: true, transformFunction: null }, offset: { classPropertyName: "offset", publicName: "offset", isSignal: true, isRequired: true, transformFunction: null }, pagerLeftArrowIcon: { classPropertyName: "pagerLeftArrowIcon", publicName: "pagerLeftArrowIcon", isSignal: true, isRequired: false, transformFunction: null }, pagerRightArrowIcon: { classPropertyName: "pagerRightArrowIcon", publicName: "pagerRightArrowIcon", isSignal: true, isRequired: false, transformFunction: null }, pagerPreviousIcon: { classPropertyName: "pagerPreviousIcon", publicName: "pagerPreviousIcon", isSignal: true, isRequired: false, transformFunction: null }, pagerNextIcon: { classPropertyName: "pagerNextIcon", publicName: "pagerNextIcon", isSignal: true, isRequired: false, transformFunction: null }, totalMessage: { classPropertyName: "totalMessage", publicName: "totalMessage", isSignal: true, isRequired: true, transformFunction: null }, footerTemplate: { classPropertyName: "footerTemplate", publicName: "footerTemplate", isSignal: true, isRequired: false, transformFunction: null }, selectedCount: { classPropertyName: "selectedCount", publicName: "selectedCount", isSignal: true, isRequired: false, transformFunction: null }, selectedMessage: { classPropertyName: "selectedMessage", publicName: "selectedMessage", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { page: "page" }, host: { classAttribute: "datatable-footer" }, ngImport: i0, template: `
    <div
      class="datatable-footer-inner"
      [ngClass]="{ 'selected-count': selectedMessage() }"
      [style.height.px]="footerHeight()"
    >
      @let footerTemplate = this.footerTemplate()?.template();
      @if (footerTemplate) {
        <ng-template
          [ngTemplateOutlet]="footerTemplate"
          [ngTemplateOutletContext]="templateContext()"
        />
      } @else {
        <div class="page-count">
          @if (selectedMessage()) {
            <span> {{ selectedCount()?.toLocaleString() }} {{ selectedMessage() }} / </span>
          }
          {{ rowCount()?.toLocaleString() }} {{ totalMessage() }}
        </div>
        @if (isVisible()) {
          <ngx-datatable-pager />
        }
      }
    </div>
  `, isInline: true, styles: [":host{display:block;inline-size:100%;overflow:auto}.datatable-footer-inner{display:flex;align-items:center;inline-size:100%}.page-count{flex:1 1 20%}.selected-count .page-count{flex:1 1 40%}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: DatatablePagerComponent, selector: "ngx-datatable-pager" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DataTableFooterComponent, decorators: [{
            type: Component,
            args: [{ selector: 'datatable-footer', imports: [NgClass, NgTemplateOutlet, DatatablePagerComponent], template: `
    <div
      class="datatable-footer-inner"
      [ngClass]="{ 'selected-count': selectedMessage() }"
      [style.height.px]="footerHeight()"
    >
      @let footerTemplate = this.footerTemplate()?.template();
      @if (footerTemplate) {
        <ng-template
          [ngTemplateOutlet]="footerTemplate"
          [ngTemplateOutletContext]="templateContext()"
        />
      } @else {
        <div class="page-count">
          @if (selectedMessage()) {
            <span> {{ selectedCount()?.toLocaleString() }} {{ selectedMessage() }} / </span>
          }
          {{ rowCount()?.toLocaleString() }} {{ totalMessage() }}
        </div>
        @if (isVisible()) {
          <ngx-datatable-pager />
        }
      }
    </div>
  `, changeDetection: ChangeDetectionStrategy.OnPush, host: {
                        class: 'datatable-footer'
                    }, styles: [":host{display:block;inline-size:100%;overflow:auto}.datatable-footer-inner{display:flex;align-items:center;inline-size:100%}.page-count{flex:1 1 20%}.selected-count .page-count{flex:1 1 40%}\n"] }]
        }], propDecorators: { footerHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "footerHeight", required: true }] }], rowCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowCount", required: true }] }], groupCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupCount", required: true }] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: true }] }], offset: [{ type: i0.Input, args: [{ isSignal: true, alias: "offset", required: true }] }], pagerLeftArrowIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "pagerLeftArrowIcon", required: false }] }], pagerRightArrowIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "pagerRightArrowIcon", required: false }] }], pagerPreviousIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "pagerPreviousIcon", required: false }] }], pagerNextIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "pagerNextIcon", required: false }] }], totalMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "totalMessage", required: true }] }], footerTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "footerTemplate", required: false }] }], selectedCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedCount", required: false }] }], selectedMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedMessage", required: false }] }], page: [{ type: i0.Output, args: ["page"] }] } });

class DataTableFooterTemplateDirective {
    static ngTemplateContextGuard(directive, context) {
        return true;
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DataTableFooterTemplateDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
    static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.15", type: DataTableFooterTemplateDirective, isStandalone: true, selector: "[ngx-datatable-footer-template]", ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DataTableFooterTemplateDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[ngx-datatable-footer-template]'
                }]
        }] });

class DatatableFooterDirective {
    constructor() {
        this._templateInput = input(undefined, ...(ngDevMode ? [{ debugName: "_templateInput", alias: 'template' }] : [{ alias: 'template' }]));
        this._templateQuery = contentChild(DataTableFooterTemplateDirective, ...(ngDevMode ? [{ debugName: "_templateQuery", read: TemplateRef }] : [{
                read: TemplateRef
            }]));
        this.template = computed(() => this._templateInput() ?? this._templateQuery(), ...(ngDevMode ? [{ debugName: "template" }] : []));
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DatatableFooterDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
    static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "20.3.15", type: DatatableFooterDirective, isStandalone: true, selector: "ngx-datatable-footer", inputs: { _templateInput: { classPropertyName: "_templateInput", publicName: "template", isSignal: true, isRequired: false, transformFunction: null } }, queries: [{ propertyName: "_templateQuery", first: true, predicate: DataTableFooterTemplateDirective, descendants: true, read: TemplateRef, isSignal: true }], ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DatatableFooterDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: 'ngx-datatable-footer'
                }]
        }], propDecorators: { _templateInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "template", required: false }] }], _templateQuery: [{ type: i0.ContentChild, args: [i0.forwardRef(() => DataTableFooterTemplateDirective), { ...{
                            read: TemplateRef
                        }, isSignal: true }] }] } });

class DatatableDraggableDirective {
    constructor() {
        this.document = inject(DOCUMENT);
        this.element = inject(ElementRef).nativeElement;
        this.dragModel = input(...(ngDevMode ? [undefined, { debugName: "dragModel" }] : []));
        this.dragStartDelay = input(0, ...(ngDevMode ? [{ debugName: "dragStartDelay", transform: numberAttribute }] : [{ transform: numberAttribute }]));
        this.enabled = input(true, ...(ngDevMode ? [{ debugName: "enabled", transform: booleanAttribute, alias: 'datatableDraggable' }] : [{ transform: booleanAttribute, alias: 'datatableDraggable' }]));
        this.dragMove = output();
        this.dragEnd = output();
        this.dragStart = output();
        this.startX = signal(undefined, ...(ngDevMode ? [{ debugName: "startX" }] : []));
        this.startY = signal(undefined, ...(ngDevMode ? [{ debugName: "startY" }] : []));
        this.isLongPressing = computed(() => this.dragStartDelay() !== 0 && this.isDragging(), ...(ngDevMode ? [{ debugName: "isLongPressing" }] : []));
        this.isDragging = computed(() => this.startX() !== undefined, ...(ngDevMode ? [{ debugName: "isDragging" }] : []));
        this.mousemove = (event) => this.moving(event.clientX, event.clientY);
        this.touchmove = (event) => {
            const touchMove = this.findTouch(event);
            if (touchMove) {
                this.moving(touchMove.clientX, touchMove.clientY);
            }
        };
        this.ending = () => {
            const dragged = this.isDragging();
            this.document.removeEventListener('mousemove', this.mousemove);
            this.document.removeEventListener('touchmove', this.touchmove);
            this.document.removeEventListener('mouseup', this.ending);
            this.document.removeEventListener('touchend', this.ending);
            this.touchId = undefined;
            this.startX.set(undefined);
            this.startY.set(undefined);
            clearTimeout(this.timeoutId);
            // This function is also called if the long press was aborted before the delay.
            // In that case, we don't want to emit dragEnd.
            if (dragged) {
                this.dragEnd.emit();
            }
        };
    }
    ngOnDestroy() {
        clearTimeout(this.timeoutId);
    }
    mousedown(event) {
        if (!this.enabled()) {
            return;
        }
        event.stopPropagation();
        event.preventDefault();
        this.document.addEventListener('mouseup', this.ending);
        this.delay(this.dragStartDelay()).then(() => {
            this.document.addEventListener('mousemove', this.mousemove);
            this.starting(event.clientX, event.clientY);
        });
    }
    touchstart(event) {
        if (!this.enabled()) {
            return;
        }
        event.stopPropagation();
        event.preventDefault();
        const touch = event.touches.item(0);
        this.touchId = touch.identifier;
        this.document.addEventListener('touchend', this.ending);
        this.delay(this.dragStartDelay()).then(() => {
            this.document.addEventListener('touchmove', this.touchmove);
            this.starting(touch.clientX, touch.clientY);
        });
    }
    starting(clientX, clientY) {
        this.startX.set(clientX);
        this.startY.set(clientY);
        this.dragStart.emit();
    }
    moving(clientX, clientY) {
        this.dragMove.emit({
            initialX: this.startX(),
            initialY: this.startY(),
            currentX: clientX,
            currentY: clientY
        });
    }
    findTouch(event) {
        return Array.from(event.touches).find(touch => touch.identifier === this.touchId);
    }
    delay(ms) {
        return new Promise(resolve => (this.timeoutId = window.setTimeout(() => resolve(), ms)));
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DatatableDraggableDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
    static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.3.15", type: DatatableDraggableDirective, isStandalone: true, selector: "[datatableDraggable]", inputs: { dragModel: { classPropertyName: "dragModel", publicName: "dragModel", isSignal: true, isRequired: false, transformFunction: null }, dragStartDelay: { classPropertyName: "dragStartDelay", publicName: "dragStartDelay", isSignal: true, isRequired: false, transformFunction: null }, enabled: { classPropertyName: "enabled", publicName: "datatableDraggable", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dragMove: "dragMove", dragEnd: "dragEnd", dragStart: "dragStart" }, host: { listeners: { "mousedown": "mousedown($event)", "touchstart": "touchstart($event)" }, properties: { "class.draggable": "enabled()", "class.dragging": "isDragging()", "class.longpress": "isLongPressing()" } }, ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DatatableDraggableDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[datatableDraggable]',
                    host: {
                        '[class.draggable]': 'enabled()',
                        '[class.dragging]': 'isDragging()',
                        '[class.longpress]': 'isLongPressing()',
                        '(mousedown)': 'mousedown($event)',
                        '(touchstart)': 'touchstart($event)'
                    }
                }]
        }], propDecorators: { dragModel: [{ type: i0.Input, args: [{ isSignal: true, alias: "dragModel", required: false }] }], dragStartDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "dragStartDelay", required: false }] }], enabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "datatableDraggable", required: false }] }], dragMove: [{ type: i0.Output, args: ["dragMove"] }], dragEnd: [{ type: i0.Output, args: ["dragEnd"] }], dragStart: [{ type: i0.Output, args: ["dragStart"] }] } });

class OrderableDirective {
    constructor() {
        this.document = inject(DOCUMENT);
        this.reorder = output();
        this.targetChanged = output();
        this.draggables = signal([], ...(ngDevMode ? [{ debugName: "draggables" }] : []));
        this.subscriptions = new Map();
        this.differ = inject(KeyValueDiffers)
            .find({})
            .create();
        this.subscribeToDraggable = (record) => {
            this.unsubscribeFromDraggable(record);
            const { key, currentValue } = record;
            if (!currentValue) {
                return;
            }
            const subs = this.subscriptions.get(key) ?? [];
            let currentEvent;
            subs.push(currentValue.dragStart.subscribe(() => this.onDragStart()), currentValue.dragMove.subscribe(e => {
                currentEvent = e;
                this.onDragging(e, currentValue.dragModel(), currentValue.element);
            }), currentValue.dragEnd.subscribe(() => this.onDragEnd(currentEvent, currentValue.dragModel(), currentValue.element)));
            this.subscriptions.set(key, subs);
        };
        this.unsubscribeFromDraggable = (record) => {
            const { key, previousValue } = record;
            if (!previousValue) {
                return;
            }
            const subs = this.subscriptions.get(key);
            if (!subs) {
                return;
            }
            subs.forEach(sub => sub.unsubscribe());
            this.subscriptions.delete(key);
        };
        effect(() => {
            const diffMap = this.draggables().reduce((acc, curr) => {
                acc[curr.dragModel().$$id] = curr;
                return acc;
            }, {});
            this.updateSubscriptions(diffMap);
        });
    }
    ngAfterContentInit() {
        this.draggablesQueryList.changes.pipe(startWith(this.draggablesQueryList)).subscribe(() => {
            this.draggables.set(this.draggablesQueryList.toArray());
        });
    }
    ngOnDestroy() {
        this.subscriptions.forEach(subList => subList.forEach(sub => sub.unsubscribe()));
    }
    updateSubscriptions(diffMap) {
        const differResult = this.differ.diff(diffMap);
        if (!differResult) {
            return;
        }
        differResult.forEachAddedItem(record => this.subscribeToDraggable(record));
        differResult.forEachRemovedItem(record => this.unsubscribeFromDraggable(record));
    }
    onDragStart() {
        const positions = {};
        this.draggables().forEach((draggable, idx) => {
            const elm = draggable.element;
            const left = parseInt(elm.offsetLeft.toString(), 10);
            positions[draggable.dragModel().$$id] = {
                left,
                right: left + parseInt(elm.offsetWidth.toString(), 10),
                index: idx,
                element: elm
            };
        });
        this.positions = positions;
    }
    onDragging({ currentX, currentY, initialX }, model, element) {
        if (!this.positions) {
            return;
        }
        const prevPos = this.positions[model.$$id];
        const target = this.isTarget(model, currentX, currentY);
        if (target) {
            if (this.lastDraggingIndex !== target.index) {
                this.targetChanged.emit({
                    prevIndex: this.lastDraggingIndex,
                    newIndex: target.index,
                    initialIndex: prevPos.index
                });
                this.lastDraggingIndex = target.index;
            }
        }
        else if (this.lastDraggingIndex !== prevPos.index) {
            this.targetChanged.emit({
                prevIndex: this.lastDraggingIndex,
                initialIndex: prevPos.index
            });
            this.lastDraggingIndex = prevPos.index;
        }
        requestAnimationFrame(() => (element.style.left = `${currentX - initialX}px`));
    }
    onDragEnd({ currentX, currentY }, model, element) {
        if (!this.positions) {
            return;
        }
        const prevPos = this.positions[model.$$id];
        const target = this.isTarget(model, currentX, currentY);
        if (target) {
            this.reorder.emit({
                prevValue: prevPos.index,
                newValue: target.index,
                column: model
            });
        }
        this.lastDraggingIndex = undefined;
        element.style.left = 'auto';
    }
    isTarget(model, clientX, clientY) {
        if (!this.positions) {
            return undefined;
        }
        const elementsAtPoint = this.document.elementsFromPoint(clientX, clientY);
        return Object.entries(this.positions).reduce((acc, [id, pos], idx) => {
            // since we drag the inner span, we need to find it in the elements at the cursor
            if (!acc && model.$$id !== id && elementsAtPoint.some(el => el === pos.element)) {
                return { pos, index: idx };
            }
            return acc;
        }, undefined);
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: OrderableDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
    static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.15", type: OrderableDirective, isStandalone: true, selector: "[orderable]", outputs: { reorder: "reorder", targetChanged: "targetChanged" }, queries: [{ propertyName: "draggablesQueryList", predicate: DatatableDraggableDirective, descendants: true }], ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: OrderableDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[orderable]'
                }]
        }], ctorParameters: () => [], propDecorators: { reorder: [{ type: i0.Output, args: ["reorder"] }], targetChanged: [{ type: i0.Output, args: ["targetChanged"] }], draggablesQueryList: [{
                type: ContentChildren,
                args: [DatatableDraggableDirective, { descendants: true }]
            }] } });

class DataTableHeaderCellComponent {
    constructor() {
        this.sortType = input.required(...(ngDevMode ? [{ debugName: "sortType" }] : []));
        this.sortAscendingIcon = input(...(ngDevMode ? [undefined, { debugName: "sortAscendingIcon" }] : []));
        this.sortDescendingIcon = input(...(ngDevMode ? [undefined, { debugName: "sortDescendingIcon" }] : []));
        this.sortUnsetIcon = input(...(ngDevMode ? [undefined, { debugName: "sortUnsetIcon" }] : []));
        this.isTarget = input(...(ngDevMode ? [undefined, { debugName: "isTarget" }] : []));
        this.showResizeHandle = input(true, ...(ngDevMode ? [{ debugName: "showResizeHandle" }] : []));
        this.targetMarkerTemplate = input(...(ngDevMode ? [undefined, { debugName: "targetMarkerTemplate" }] : []));
        this.targetMarkerContext = input(...(ngDevMode ? [undefined, { debugName: "targetMarkerContext" }] : []));
        this.enableClearingSortState = input(false, ...(ngDevMode ? [{ debugName: "enableClearingSortState" }] : []));
        this.ariaHeaderCheckboxMessage = input.required(...(ngDevMode ? [{ debugName: "ariaHeaderCheckboxMessage" }] : []));
        this.allRowsSelected = input(false, ...(ngDevMode ? [{ debugName: "allRowsSelected", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
        this.selectionType = input(...(ngDevMode ? [undefined, { debugName: "selectionType" }] : []));
        this.column = input.required(...(ngDevMode ? [{ debugName: "column" }] : []));
        this.sorts = input([], ...(ngDevMode ? [{ debugName: "sorts" }] : []));
        this.sort = output();
        this.select = output();
        this.columnContextmenu = output();
        this.resize = output();
        this.resizing = output();
        this.columnCssClasses = computed(() => {
            let cls = 'datatable-header-cell';
            const column = this.column();
            if (column.sortable) {
                cls += ' sortable';
            }
            if (this.showResizeHandle()) {
                cls += ' resizeable';
            }
            if (column.headerClass) {
                if (typeof column.headerClass === 'string') {
                    cls += ' ' + column.headerClass;
                }
                else if (typeof column.headerClass === 'function') {
                    const res = column.headerClass({
                        column
                    });
                    if (typeof res === 'string') {
                        cls += ' ' + res;
                    }
                    else if (typeof res === 'object') {
                        const keys = Object.keys(res);
                        for (const k of keys) {
                            if (res[k] === true) {
                                cls += ` ${k}`;
                            }
                        }
                    }
                }
            }
            const sortDir = this.sortDir();
            if (sortDir) {
                cls += ` sort-active sort-${sortDir}`;
            }
            return cls;
        }, ...(ngDevMode ? [{ debugName: "columnCssClasses" }] : []));
        this.name = computed(() => {
            // guaranteed to have a value by setColumnDefaults() in column-helper.ts
            return this.column().headerTemplate === undefined ? this.column().name : undefined;
        }, ...(ngDevMode ? [{ debugName: "name" }] : []));
        this.isCheckboxable = computed(() => this.column().headerCheckboxable, ...(ngDevMode ? [{ debugName: "isCheckboxable" }] : []));
        this.sortClass = computed(() => {
            return this.calcSortClass(this.sortDir());
        }, ...(ngDevMode ? [{ debugName: "sortClass" }] : []));
        this.sortDir = computed(() => {
            return this.calcSortDir(this.sorts());
        }, ...(ngDevMode ? [{ debugName: "sortDir" }] : []));
        this.cellContext = computed(() => {
            return {
                column: this.column(),
                sortDir: this.sortDir(),
                sortFn: () => this.onSort(),
                allRowsSelected: this.allRowsSelected(),
                selectFn: () => this.select.emit()
            };
        }, ...(ngDevMode ? [{ debugName: "cellContext" }] : []));
        this.element = inject(ElementRef).nativeElement;
        // Counter to reset sort once user sort asc and desc.
        this.totalSortStatesApplied = 0;
    }
    onContextmenu($event) {
        this.columnContextmenu.emit({ event: $event, column: this.column() });
        if (this.column().draggable) {
            $event.preventDefault();
        }
    }
    enter() {
        this.onSort();
    }
    ngOnInit() {
        // If there is already a default sort then start the counter with 1.
        if (this.sortDir()) {
            this.totalSortStatesApplied = 1;
        }
    }
    ngOnDestroy() {
        this.destroySubscription();
    }
    calcSortDir(sorts) {
        if (sorts && this.column()) {
            const sort = sorts.find((s) => s.prop === this.column().prop);
            if (sort) {
                return sort.dir;
            }
        }
    }
    onSort() {
        if (!this.column().sortable) {
            return;
        }
        this.totalSortStatesApplied++;
        let newValue = nextSortDir(this.sortType(), this.sortDir());
        // User has done both direction sort so we reset the next sort.
        if (this.enableClearingSortState() && this.totalSortStatesApplied === 3) {
            newValue = undefined;
            this.totalSortStatesApplied = 0;
        }
        this.sort.emit({
            column: this.column(),
            prevValue: this.sortDir(),
            newValue
        });
    }
    calcSortClass(sortDir) {
        if (!this.cellContext().column.sortable) {
            return undefined;
        }
        if (sortDir === SortDirection.asc) {
            return `sort-btn sort-asc ${this.sortAscendingIcon() ?? 'datatable-icon-up'}`;
        }
        else if (sortDir === SortDirection.desc) {
            return `sort-btn sort-desc ${this.sortDescendingIcon() ?? 'datatable-icon-down'}`;
        }
        else {
            return `sort-btn ${this.sortUnsetIcon() ?? 'datatable-icon-sort-unset'}`;
        }
    }
    onMousedown() {
        this.initialWidth = this.element.clientWidth;
    }
    onMouseup() {
        this.resize.emit({ width: this.element.clientWidth, column: this.column() });
    }
    move({ currentX, initialX }) {
        this.resizing.emit({
            width: this.initialWidth + (currentX - initialX),
            column: this.column()
        });
    }
    destroySubscription() {
        if (this.subscription) {
            this.subscription.unsubscribe();
            this.subscription = undefined;
        }
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DataTableHeaderCellComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DataTableHeaderCellComponent, isStandalone: true, selector: "datatable-header-cell", inputs: { sortType: { classPropertyName: "sortType", publicName: "sortType", isSignal: true, isRequired: true, transformFunction: null }, sortAscendingIcon: { classPropertyName: "sortAscendingIcon", publicName: "sortAscendingIcon", isSignal: true, isRequired: false, transformFunction: null }, sortDescendingIcon: { classPropertyName: "sortDescendingIcon", publicName: "sortDescendingIcon", isSignal: true, isRequired: false, transformFunction: null }, sortUnsetIcon: { classPropertyName: "sortUnsetIcon", publicName: "sortUnsetIcon", isSignal: true, isRequired: false, transformFunction: null }, isTarget: { classPropertyName: "isTarget", publicName: "isTarget", isSignal: true, isRequired: false, transformFunction: null }, showResizeHandle: { classPropertyName: "showResizeHandle", publicName: "showResizeHandle", isSignal: true, isRequired: false, transformFunction: null }, targetMarkerTemplate: { classPropertyName: "targetMarkerTemplate", publicName: "targetMarkerTemplate", isSignal: true, isRequired: false, transformFunction: null }, targetMarkerContext: { classPropertyName: "targetMarkerContext", publicName: "targetMarkerContext", isSignal: true, isRequired: false, transformFunction: null }, enableClearingSortState: { classPropertyName: "enableClearingSortState", publicName: "enableClearingSortState", isSignal: true, isRequired: false, transformFunction: null }, ariaHeaderCheckboxMessage: { classPropertyName: "ariaHeaderCheckboxMessage", publicName: "ariaHeaderCheckboxMessage", isSignal: true, isRequired: true, transformFunction: null }, allRowsSelected: { classPropertyName: "allRowsSelected", publicName: "allRowsSelected", isSignal: true, isRequired: false, transformFunction: null }, selectionType: { classPropertyName: "selectionType", publicName: "selectionType", isSignal: true, isRequired: false, transformFunction: null }, column: { classPropertyName: "column", publicName: "column", isSignal: true, isRequired: true, transformFunction: null }, sorts: { classPropertyName: "sorts", publicName: "sorts", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { sort: "sort", select: "select", columnContextmenu: "columnContextmenu", resize: "resize", resizing: "resizing" }, host: { listeners: { "contextmenu": "onContextmenu($event)", "keydown.enter": "enter()" }, properties: { "attr.resizeable": "showResizeHandle()", "attr.title": "name()", "attr.tabindex": "column().sortable ? 0 : -1", "class": "columnCssClasses()", "style.minWidth.px": "column().minWidth", "style.maxWidth.px": "column().maxWidth", "style.width.px": "column().width" } }, ngImport: i0, template: `
    <div class="datatable-header-cell-template-wrap">
      @if (isTarget()) {
        <ng-template
          [ngTemplateOutlet]="targetMarkerTemplate()!"
          [ngTemplateOutletContext]="targetMarkerContext()"
        />
      }
      @if (isCheckboxable()) {
        <label class="datatable-checkbox">
          <input
            type="checkbox"
            [attr.aria-label]="ariaHeaderCheckboxMessage()"
            [checked]="allRowsSelected()"
            (change)="select.emit()"
          />
        </label>
      }
      @let column = this.column();
      @if (column.headerTemplate) {
        <ng-template
          [ngTemplateOutlet]="column.headerTemplate"
          [ngTemplateOutletContext]="cellContext()"
        />
      } @else {
        <span class="datatable-header-cell-wrapper">
          <span class="datatable-header-cell-label draggable" (click)="onSort()">
            {{ name() }}
          </span>
        </span>
      }
      <span [class]="sortClass()" (click)="onSort()"> </span>
    </div>
    @if (showResizeHandle()) {
      <span
        class="resize-handle"
        datatableDraggable
        (dragStart)="onMousedown()"
        (dragMove)="move($event)"
        (dragEnd)="onMouseup()"
      ></span>
    }
  `, isInline: true, styles: [":host{overflow-x:hidden;vertical-align:top;display:inline-block;line-height:1.625}:host:focus{outline:none}:host{position:relative;display:inline-block}:host.dragging{pointer-events:none}:host-context(ngx-datatable.fixed-header) :host{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}:host.sortable .datatable-header-cell-wrapper{cursor:pointer}:host.longpress .datatable-header-cell-wrapper{cursor:move}.datatable-header-cell-template-wrap{block-size:inherit}.sort-btn{line-height:100%;vertical-align:middle;display:inline-block;cursor:pointer}.resize-handle,.resize-handle--not-resizable{display:inline-block;position:absolute;inset-inline-end:0;inset-block:0;inline-size:5px;padding-block:0;padding-inline:4px;visibility:hidden}.resize-handle{cursor:ew-resize}:host(.resizeable:hover) .resize-handle{visibility:visible}@media (hover: none){:host{touch-action:none}:host .resize-handle{visibility:visible}:host .datatable-header-cell-label.draggable{-webkit-user-select:none;user-select:none}}.resize-handle--not-resizable :host(:hover){visibility:visible}:host::ng-deep .targetMarker{position:absolute;inset-block:0}:host::ng-deep .targetMarker.dragFromLeft{inset-inline-end:0}:host::ng-deep .targetMarker.dragFromRight{inset-inline-start:0}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: DatatableDraggableDirective, selector: "[datatableDraggable]", inputs: ["dragModel", "dragStartDelay", "datatableDraggable"], outputs: ["dragMove", "dragEnd", "dragStart"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DataTableHeaderCellComponent, decorators: [{
            type: Component,
            args: [{ selector: 'datatable-header-cell', imports: [NgTemplateOutlet, DatatableDraggableDirective], template: `
    <div class="datatable-header-cell-template-wrap">
      @if (isTarget()) {
        <ng-template
          [ngTemplateOutlet]="targetMarkerTemplate()!"
          [ngTemplateOutletContext]="targetMarkerContext()"
        />
      }
      @if (isCheckboxable()) {
        <label class="datatable-checkbox">
          <input
            type="checkbox"
            [attr.aria-label]="ariaHeaderCheckboxMessage()"
            [checked]="allRowsSelected()"
            (change)="select.emit()"
          />
        </label>
      }
      @let column = this.column();
      @if (column.headerTemplate) {
        <ng-template
          [ngTemplateOutlet]="column.headerTemplate"
          [ngTemplateOutletContext]="cellContext()"
        />
      } @else {
        <span class="datatable-header-cell-wrapper">
          <span class="datatable-header-cell-label draggable" (click)="onSort()">
            {{ name() }}
          </span>
        </span>
      }
      <span [class]="sortClass()" (click)="onSort()"> </span>
    </div>
    @if (showResizeHandle()) {
      <span
        class="resize-handle"
        datatableDraggable
        (dragStart)="onMousedown()"
        (dragMove)="move($event)"
        (dragEnd)="onMouseup()"
      ></span>
    }
  `, changeDetection: ChangeDetectionStrategy.OnPush, host: {
                        '[attr.resizeable]': 'showResizeHandle()',
                        '[attr.title]': 'name()',
                        '[attr.tabindex]': 'column().sortable ? 0 : -1',
                        '[class]': 'columnCssClasses()',
                        '[style.minWidth.px]': 'column().minWidth',
                        '[style.maxWidth.px]': 'column().maxWidth',
                        '[style.width.px]': 'column().width'
                    }, styles: [":host{overflow-x:hidden;vertical-align:top;display:inline-block;line-height:1.625}:host:focus{outline:none}:host{position:relative;display:inline-block}:host.dragging{pointer-events:none}:host-context(ngx-datatable.fixed-header) :host{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}:host.sortable .datatable-header-cell-wrapper{cursor:pointer}:host.longpress .datatable-header-cell-wrapper{cursor:move}.datatable-header-cell-template-wrap{block-size:inherit}.sort-btn{line-height:100%;vertical-align:middle;display:inline-block;cursor:pointer}.resize-handle,.resize-handle--not-resizable{display:inline-block;position:absolute;inset-inline-end:0;inset-block:0;inline-size:5px;padding-block:0;padding-inline:4px;visibility:hidden}.resize-handle{cursor:ew-resize}:host(.resizeable:hover) .resize-handle{visibility:visible}@media (hover: none){:host{touch-action:none}:host .resize-handle{visibility:visible}:host .datatable-header-cell-label.draggable{-webkit-user-select:none;user-select:none}}.resize-handle--not-resizable :host(:hover){visibility:visible}:host::ng-deep .targetMarker{position:absolute;inset-block:0}:host::ng-deep .targetMarker.dragFromLeft{inset-inline-end:0}:host::ng-deep .targetMarker.dragFromRight{inset-inline-start:0}\n"] }]
        }], propDecorators: { sortType: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortType", required: true }] }], sortAscendingIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortAscendingIcon", required: false }] }], sortDescendingIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortDescendingIcon", required: false }] }], sortUnsetIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortUnsetIcon", required: false }] }], isTarget: [{ type: i0.Input, args: [{ isSignal: true, alias: "isTarget", required: false }] }], showResizeHandle: [{ type: i0.Input, args: [{ isSignal: true, alias: "showResizeHandle", required: false }] }], targetMarkerTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "targetMarkerTemplate", required: false }] }], targetMarkerContext: [{ type: i0.Input, args: [{ isSignal: true, alias: "targetMarkerContext", required: false }] }], enableClearingSortState: [{ type: i0.Input, args: [{ isSignal: true, alias: "enableClearingSortState", required: false }] }], ariaHeaderCheckboxMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaHeaderCheckboxMessage", required: true }] }], allRowsSelected: [{ type: i0.Input, args: [{ isSignal: true, alias: "allRowsSelected", required: false }] }], selectionType: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectionType", required: false }] }], column: [{ type: i0.Input, args: [{ isSignal: true, alias: "column", required: true }] }], sorts: [{ type: i0.Input, args: [{ isSignal: true, alias: "sorts", required: false }] }], sort: [{ type: i0.Output, args: ["sort"] }], select: [{ type: i0.Output, args: ["select"] }], columnContextmenu: [{ type: i0.Output, args: ["columnContextmenu"] }], resize: [{ type: i0.Output, args: ["resize"] }], resizing: [{ type: i0.Output, args: ["resizing"] }], onContextmenu: [{
                type: HostListener,
                args: ['contextmenu', ['$event']]
            }], enter: [{
                type: HostListener,
                args: ['keydown.enter']
            }] } });

class DataTableHeaderComponent {
    constructor() {
        this.scrollbarHelper = inject(ScrollbarHelper);
        this.lastColumnId = computed(() => this.columns().at(-1)?.$$id, ...(ngDevMode ? [{ debugName: "lastColumnId" }] : []));
        this.sortAscendingIcon = input(...(ngDevMode ? [undefined, { debugName: "sortAscendingIcon" }] : []));
        this.sortDescendingIcon = input(...(ngDevMode ? [undefined, { debugName: "sortDescendingIcon" }] : []));
        this.sortUnsetIcon = input(...(ngDevMode ? [undefined, { debugName: "sortUnsetIcon" }] : []));
        this.scrollbarH = input(...(ngDevMode ? [undefined, { debugName: "scrollbarH" }] : []));
        this.dealsWithGroup = input(...(ngDevMode ? [undefined, { debugName: "dealsWithGroup" }] : []));
        this.targetMarkerTemplate = input(...(ngDevMode ? [undefined, { debugName: "targetMarkerTemplate" }] : []));
        this.enableClearingSortState = input(false, ...(ngDevMode ? [{ debugName: "enableClearingSortState" }] : []));
        this.innerWidth = input.required(...(ngDevMode ? [{ debugName: "innerWidth" }] : []));
        this.sorts = input.required(...(ngDevMode ? [{ debugName: "sorts" }] : []));
        this.sortType = input.required(...(ngDevMode ? [{ debugName: "sortType" }] : []));
        this.allRowsSelected = input(...(ngDevMode ? [undefined, { debugName: "allRowsSelected" }] : []));
        this.selectionType = input(...(ngDevMode ? [undefined, { debugName: "selectionType" }] : []));
        this.reorderable = input(...(ngDevMode ? [undefined, { debugName: "reorderable" }] : []));
        this.verticalScrollVisible = input(false, ...(ngDevMode ? [{ debugName: "verticalScrollVisible" }] : []));
        this.ariaHeaderCheckboxMessage = input.required(...(ngDevMode ? [{ debugName: "ariaHeaderCheckboxMessage" }] : []));
        this.headerHeight = input.required(...(ngDevMode ? [{ debugName: "headerHeight" }] : []));
        this.columns = input.required(...(ngDevMode ? [{ debugName: "columns" }] : []));
        this.offsetX = input(...(ngDevMode ? [undefined, { debugName: "offsetX" }] : []));
        this.sort = output();
        this.reorder = output();
        this.resize = output();
        this.resizing = output();
        this.select = output();
        this.columnContextmenu = output();
        this._columnsByPin = computed(() => {
            return columnsByPinArr(this.columns());
        }, ...(ngDevMode ? [{ debugName: "_columnsByPin" }] : []));
        this._columnGroupWidths = computed(() => {
            const colsByPin = columnsByPin(this.columns());
            return columnGroupWidths(colsByPin, this.columns());
        }, ...(ngDevMode ? [{ debugName: "_columnGroupWidths" }] : []));
        this._styleByGroup = computed(() => {
            return {
                left: this.calcStylesByGroup('left'),
                center: this.calcStylesByGroup('center'),
                right: this.calcStylesByGroup('right')
            };
        }, ...(ngDevMode ? [{ debugName: "_styleByGroup" }] : []));
        this.headerWidth = computed(() => {
            if (this.scrollbarH()) {
                const width = this.verticalScrollVisible()
                    ? this.innerWidth() - this.scrollbarHelper.width
                    : this.innerWidth();
                return width + 'px';
            }
            return '100%';
        }, ...(ngDevMode ? [{ debugName: "headerWidth" }] : []));
    }
    onColumnResized({ width, column }) {
        this.resize.emit(this.makeResizeEvent(width, column));
    }
    onColumnResizing({ width, column }) {
        this.resizing.emit(this.makeResizeEvent(width, column));
    }
    makeResizeEvent(width, column) {
        if (column.minWidth && width <= column.minWidth) {
            width = column.minWidth;
        }
        else if (column.maxWidth && width >= column.maxWidth) {
            width = column.maxWidth;
        }
        return {
            column,
            prevValue: column.width,
            newValue: width
        };
    }
    onColumnReordered(event) {
        const column = this.getColumn(event.newValue);
        column.isTarget = false;
        column.targetMarkerContext = undefined;
        this.reorder.emit(event);
    }
    onTargetChanged({ prevIndex, newIndex, initialIndex }) {
        if (prevIndex || prevIndex === 0) {
            const oldColumn = this.getColumn(prevIndex);
            oldColumn.isTarget = false;
            oldColumn.targetMarkerContext = undefined;
        }
        if (newIndex || newIndex === 0) {
            const newColumn = this.getColumn(newIndex);
            newColumn.isTarget = true;
            if (initialIndex !== newIndex) {
                newColumn.targetMarkerContext = {
                    class: 'targetMarker '.concat(initialIndex > newIndex ? 'dragFromRight' : 'dragFromLeft')
                };
            }
        }
    }
    getColumn(index) {
        const _columnsByPin = this._columnsByPin();
        const leftColumnCount = _columnsByPin[0].columns.length;
        if (index < leftColumnCount) {
            return _columnsByPin[0].columns[index];
        }
        const centerColumnCount = _columnsByPin[1].columns.length;
        if (index < leftColumnCount + centerColumnCount) {
            return _columnsByPin[1].columns[index - leftColumnCount];
        }
        return _columnsByPin[2].columns[index - leftColumnCount - centerColumnCount];
    }
    onSort({ column, prevValue, newValue }) {
        // if we are dragging don't sort!
        if (column.dragging) {
            return;
        }
        const sorts = this.calcNewSorts(column, prevValue, newValue);
        this.sort.emit({
            sorts,
            column,
            prevValue,
            newValue
        });
    }
    calcNewSorts(column, prevValue, newValue) {
        let idx = 0;
        const sorts = this.sorts().map((s, i) => {
            s = { ...s };
            if (s.prop === column.prop) {
                idx = i;
            }
            return s;
        });
        if (newValue === undefined) {
            sorts.splice(idx, 1);
        }
        else if (prevValue) {
            sorts[idx].dir = newValue;
        }
        else {
            if (this.sortType() === SortType.single) {
                sorts.splice(0, this.sorts().length);
            }
            sorts.push({ dir: newValue, prop: column.prop });
        }
        return sorts;
    }
    calcStylesByGroup(group) {
        const widths = this._columnGroupWidths();
        if (group === 'center') {
            return {
                transform: `translateX(${(this.offsetX() ?? 0) * -1}px)`,
                width: `${widths[group]}px`,
                willChange: 'transform'
            };
        }
        return {
            width: `${widths[group]}px`
        };
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DataTableHeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DataTableHeaderComponent, isStandalone: true, selector: "datatable-header", inputs: { sortAscendingIcon: { classPropertyName: "sortAscendingIcon", publicName: "sortAscendingIcon", isSignal: true, isRequired: false, transformFunction: null }, sortDescendingIcon: { classPropertyName: "sortDescendingIcon", publicName: "sortDescendingIcon", isSignal: true, isRequired: false, transformFunction: null }, sortUnsetIcon: { classPropertyName: "sortUnsetIcon", publicName: "sortUnsetIcon", isSignal: true, isRequired: false, transformFunction: null }, scrollbarH: { classPropertyName: "scrollbarH", publicName: "scrollbarH", isSignal: true, isRequired: false, transformFunction: null }, dealsWithGroup: { classPropertyName: "dealsWithGroup", publicName: "dealsWithGroup", isSignal: true, isRequired: false, transformFunction: null }, targetMarkerTemplate: { classPropertyName: "targetMarkerTemplate", publicName: "targetMarkerTemplate", isSignal: true, isRequired: false, transformFunction: null }, enableClearingSortState: { classPropertyName: "enableClearingSortState", publicName: "enableClearingSortState", isSignal: true, isRequired: false, transformFunction: null }, innerWidth: { classPropertyName: "innerWidth", publicName: "innerWidth", isSignal: true, isRequired: true, transformFunction: null }, sorts: { classPropertyName: "sorts", publicName: "sorts", isSignal: true, isRequired: true, transformFunction: null }, sortType: { classPropertyName: "sortType", publicName: "sortType", isSignal: true, isRequired: true, transformFunction: null }, allRowsSelected: { classPropertyName: "allRowsSelected", publicName: "allRowsSelected", isSignal: true, isRequired: false, transformFunction: null }, selectionType: { classPropertyName: "selectionType", publicName: "selectionType", isSignal: true, isRequired: false, transformFunction: null }, reorderable: { classPropertyName: "reorderable", publicName: "reorderable", isSignal: true, isRequired: false, transformFunction: null }, verticalScrollVisible: { classPropertyName: "verticalScrollVisible", publicName: "verticalScrollVisible", isSignal: true, isRequired: false, transformFunction: null }, ariaHeaderCheckboxMessage: { classPropertyName: "ariaHeaderCheckboxMessage", publicName: "ariaHeaderCheckboxMessage", isSignal: true, isRequired: true, transformFunction: null }, headerHeight: { classPropertyName: "headerHeight", publicName: "headerHeight", isSignal: true, isRequired: true, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, offsetX: { classPropertyName: "offsetX", publicName: "offsetX", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { sort: "sort", reorder: "reorder", resize: "resize", resizing: "resizing", select: "select", columnContextmenu: "columnContextmenu" }, host: { properties: { "style.height.px": "headerHeight()", "style.width": "headerWidth()" }, classAttribute: "datatable-header" }, ngImport: i0, template: `
    @let _columnGroupWidths = this._columnGroupWidths();
    <div
      role="row"
      orderable
      class="datatable-header-inner"
      [class.horizontal-overflow]="innerWidth() < _columnGroupWidths.total"
      [style.width.px]="_columnGroupWidths.total"
      (reorder)="onColumnReordered($event)"
      (targetChanged)="onTargetChanged($event)"
    >
      @for (colGroup of _columnsByPin(); track colGroup.type) {
        @if (colGroup.columns.length) {
          <div
            class="datatable-row-group"
            [ngClass]="'datatable-row-' + colGroup.type"
            [ngStyle]="_styleByGroup()[colGroup.type]"
          >
            @for (column of colGroup.columns; track column.$$id) {
              <datatable-header-cell
                role="columnheader"
                dragStartDelay="500"
                [datatableDraggable]="reorderable() && column.draggable"
                [dragModel]="column"
                [isTarget]="column.isTarget"
                [targetMarkerTemplate]="targetMarkerTemplate()"
                [targetMarkerContext]="column.targetMarkerContext"
                [column]="column"
                [showResizeHandle]="lastColumnId() !== column.$$id && column.resizeable"
                [sortType]="sortType()"
                [sorts]="sorts()"
                [selectionType]="selectionType()"
                [sortAscendingIcon]="sortAscendingIcon()"
                [sortDescendingIcon]="sortDescendingIcon()"
                [sortUnsetIcon]="sortUnsetIcon()"
                [allRowsSelected]="allRowsSelected()"
                [enableClearingSortState]="enableClearingSortState()"
                [ariaHeaderCheckboxMessage]="ariaHeaderCheckboxMessage()"
                (resize)="onColumnResized($event)"
                (resizing)="onColumnResizing($event)"
                (sort)="onSort($event)"
                (select)="select.emit($event)"
                (columnContextmenu)="columnContextmenu.emit($event)"
              />
            }
          </div>
        }
      }
    </div>
  `, isInline: true, styles: [":host{display:block;overflow:hidden}.datatable-header-inner{display:flex}:host-context(ngx-datatable.fixed-header) .datatable-header-inner{white-space:nowrap}.datatable-row-group{display:flex}.datatable-row-left,.datatable-row-right{position:sticky;z-index:9}.datatable-row-left{inset-inline-start:0}.datatable-row-right{inset-inline-end:0}\n"], dependencies: [{ kind: "directive", type: OrderableDirective, selector: "[orderable]", outputs: ["reorder", "targetChanged"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: DataTableHeaderCellComponent, selector: "datatable-header-cell", inputs: ["sortType", "sortAscendingIcon", "sortDescendingIcon", "sortUnsetIcon", "isTarget", "showResizeHandle", "targetMarkerTemplate", "targetMarkerContext", "enableClearingSortState", "ariaHeaderCheckboxMessage", "allRowsSelected", "selectionType", "column", "sorts"], outputs: ["sort", "select", "columnContextmenu", "resize", "resizing"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: DatatableDraggableDirective, selector: "[datatableDraggable]", inputs: ["dragModel", "dragStartDelay", "datatableDraggable"], outputs: ["dragMove", "dragEnd", "dragStart"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DataTableHeaderComponent, decorators: [{
            type: Component,
            args: [{ selector: 'datatable-header', imports: [
                        OrderableDirective,
                        NgStyle,
                        DataTableHeaderCellComponent,
                        NgClass,
                        DatatableDraggableDirective
                    ], template: `
    @let _columnGroupWidths = this._columnGroupWidths();
    <div
      role="row"
      orderable
      class="datatable-header-inner"
      [class.horizontal-overflow]="innerWidth() < _columnGroupWidths.total"
      [style.width.px]="_columnGroupWidths.total"
      (reorder)="onColumnReordered($event)"
      (targetChanged)="onTargetChanged($event)"
    >
      @for (colGroup of _columnsByPin(); track colGroup.type) {
        @if (colGroup.columns.length) {
          <div
            class="datatable-row-group"
            [ngClass]="'datatable-row-' + colGroup.type"
            [ngStyle]="_styleByGroup()[colGroup.type]"
          >
            @for (column of colGroup.columns; track column.$$id) {
              <datatable-header-cell
                role="columnheader"
                dragStartDelay="500"
                [datatableDraggable]="reorderable() && column.draggable"
                [dragModel]="column"
                [isTarget]="column.isTarget"
                [targetMarkerTemplate]="targetMarkerTemplate()"
                [targetMarkerContext]="column.targetMarkerContext"
                [column]="column"
                [showResizeHandle]="lastColumnId() !== column.$$id && column.resizeable"
                [sortType]="sortType()"
                [sorts]="sorts()"
                [selectionType]="selectionType()"
                [sortAscendingIcon]="sortAscendingIcon()"
                [sortDescendingIcon]="sortDescendingIcon()"
                [sortUnsetIcon]="sortUnsetIcon()"
                [allRowsSelected]="allRowsSelected()"
                [enableClearingSortState]="enableClearingSortState()"
                [ariaHeaderCheckboxMessage]="ariaHeaderCheckboxMessage()"
                (resize)="onColumnResized($event)"
                (resizing)="onColumnResizing($event)"
                (sort)="onSort($event)"
                (select)="select.emit($event)"
                (columnContextmenu)="columnContextmenu.emit($event)"
              />
            }
          </div>
        }
      }
    </div>
  `, changeDetection: ChangeDetectionStrategy.OnPush, host: {
                        class: 'datatable-header',
                        '[style.height.px]': 'headerHeight()',
                        '[style.width]': 'headerWidth()'
                    }, styles: [":host{display:block;overflow:hidden}.datatable-header-inner{display:flex}:host-context(ngx-datatable.fixed-header) .datatable-header-inner{white-space:nowrap}.datatable-row-group{display:flex}.datatable-row-left,.datatable-row-right{position:sticky;z-index:9}.datatable-row-left{inset-inline-start:0}.datatable-row-right{inset-inline-end:0}\n"] }]
        }], propDecorators: { sortAscendingIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortAscendingIcon", required: false }] }], sortDescendingIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortDescendingIcon", required: false }] }], sortUnsetIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortUnsetIcon", required: false }] }], scrollbarH: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollbarH", required: false }] }], dealsWithGroup: [{ type: i0.Input, args: [{ isSignal: true, alias: "dealsWithGroup", required: false }] }], targetMarkerTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "targetMarkerTemplate", required: false }] }], enableClearingSortState: [{ type: i0.Input, args: [{ isSignal: true, alias: "enableClearingSortState", required: false }] }], innerWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "innerWidth", required: true }] }], sorts: [{ type: i0.Input, args: [{ isSignal: true, alias: "sorts", required: true }] }], sortType: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortType", required: true }] }], allRowsSelected: [{ type: i0.Input, args: [{ isSignal: true, alias: "allRowsSelected", required: false }] }], selectionType: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectionType", required: false }] }], reorderable: [{ type: i0.Input, args: [{ isSignal: true, alias: "reorderable", required: false }] }], verticalScrollVisible: [{ type: i0.Input, args: [{ isSignal: true, alias: "verticalScrollVisible", required: false }] }], ariaHeaderCheckboxMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaHeaderCheckboxMessage", required: true }] }], headerHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "headerHeight", required: true }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], offsetX: [{ type: i0.Input, args: [{ isSignal: true, alias: "offsetX", required: false }] }], sort: [{ type: i0.Output, args: ["sort"] }], reorder: [{ type: i0.Output, args: ["reorder"] }], resize: [{ type: i0.Output, args: ["resize"] }], resizing: [{ type: i0.Output, args: ["resizing"] }], select: [{ type: i0.Output, args: ["select"] }], columnContextmenu: [{ type: i0.Output, args: ["columnContextmenu"] }] } });

class DatatableRowDetailTemplateDirective {
    static ngTemplateContextGuard(directive, context) {
        return true;
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DatatableRowDetailTemplateDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
    static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.15", type: DatatableRowDetailTemplateDirective, isStandalone: true, selector: "[ngx-datatable-row-detail-template]", ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DatatableRowDetailTemplateDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[ngx-datatable-row-detail-template]'
                }]
        }] });

class DatatableRowDetailDirective {
    constructor() {
        /**
         * The detail row height is required especially
         * when virtual scroll is enabled.
         */
        this.rowHeight = input(0, ...(ngDevMode ? [{ debugName: "rowHeight" }] : []));
        this._templateInput = input(undefined, ...(ngDevMode ? [{ debugName: "_templateInput", alias: 'template' }] : [{
                alias: 'template'
            }]));
        this._templateQuery = contentChild(DatatableRowDetailTemplateDirective, ...(ngDevMode ? [{ debugName: "_templateQuery", read: TemplateRef }] : [{
                read: TemplateRef
            }]));
        this.template = computed(() => {
            return this._templateInput() ?? this._templateQuery();
        }, ...(ngDevMode ? [{ debugName: "template" }] : []));
        /**
         * Row detail row visbility was toggled.
         */
        this.toggle = output();
    }
    /**
     * Toggle the expansion of the row
     */
    toggleExpandRow(row) {
        this.toggle.emit({
            type: 'row',
            value: row
        });
    }
    /**
     * API method to expand all the rows.
     */
    expandAllRows() {
        this.toggle.emit({
            type: 'all',
            value: true
        });
    }
    /**
     * API method to collapse all the rows.
     */
    collapseAllRows() {
        this.toggle.emit({
            type: 'all',
            value: false
        });
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DatatableRowDetailDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
    static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "20.3.15", type: DatatableRowDetailDirective, isStandalone: true, selector: "ngx-datatable-row-detail", inputs: { rowHeight: { classPropertyName: "rowHeight", publicName: "rowHeight", isSignal: true, isRequired: false, transformFunction: null }, _templateInput: { classPropertyName: "_templateInput", publicName: "template", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { toggle: "toggle" }, queries: [{ propertyName: "_templateQuery", first: true, predicate: DatatableRowDetailTemplateDirective, descendants: true, read: TemplateRef, isSignal: true }], ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DatatableRowDetailDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: 'ngx-datatable-row-detail'
                }]
        }], propDecorators: { rowHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowHeight", required: false }] }], _templateInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "template", required: false }] }], _templateQuery: [{ type: i0.ContentChild, args: [i0.forwardRef(() => DatatableRowDetailTemplateDirective), { ...{
                            read: TemplateRef
                        }, isSignal: true }] }], toggle: [{ type: i0.Output, args: ["toggle"] }] } });

class DatatableComponent {
    constructor() {
        this.scrollbarHelper = inject(ScrollbarHelper);
        this.cd = inject(ChangeDetectorRef);
        this.configuration = inject(NGX_DATATABLE_CONFIG, { optional: true }) ??
            // This is the old injection token for backward compatibility.
            inject('configuration', { optional: true });
        /**
         * Template for the target marker of drag target columns.
         */
        this.targetMarkerTemplate = input(...(ngDevMode ? [undefined, { debugName: "targetMarkerTemplate" }] : []));
        /**
         * Rows that are displayed in the table.
         */
        this.rows = input(...(ngDevMode ? [undefined, { debugName: "rows" }] : []));
        /**
         * This attribute allows the user to set the name of the column to group the data with
         */
        this.groupRowsBy = input(...(ngDevMode ? [undefined, { debugName: "groupRowsBy" }] : []));
        /**
         * This attribute allows the user to set a grouped array in the following format:
         *  [
         *    {groupid=1} [
         *      {id=1 name="test1"},
         *      {id=2 name="test2"},
         *      {id=3 name="test3"}
         *    ]},
         *    {groupid=2>[
         *      {id=4 name="test4"},
         *      {id=5 name="test5"},
         *      {id=6 name="test6"}
         *    ]}
         *  ]
         */
        this.groupedRows = input(...(ngDevMode ? [undefined, { debugName: "groupedRows" }] : []));
        /**
         * Columns to be displayed.
         */
        this.columns = input(...(ngDevMode ? [undefined, { debugName: "columns" }] : []));
        /**
         * List of row objects that should be
         * represented as selected in the grid.
         * Default value: `[]`
         */
        this.selected = model([], ...(ngDevMode ? [{ debugName: "selected" }] : []));
        /**
         * Enable vertical scrollbars
         */
        this.scrollbarV = input(false, ...(ngDevMode ? [{ debugName: "scrollbarV", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
        /**
         * Enable vertical scrollbars dynamically on demand.
         * Property `scrollbarV` needs to be set `true` too.
         * Width that is gained when no scrollbar is needed
         * is added to the inner table width.
         */
        this.scrollbarVDynamic = input(false, ...(ngDevMode ? [{ debugName: "scrollbarVDynamic", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
        /**
         * Enable horz scrollbars
         */
        this.scrollbarH = input(false, ...(ngDevMode ? [{ debugName: "scrollbarH", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
        /**
         * The row height; which is necessary
         * to calculate the height for the lazy rendering.
         */
        this.rowHeight = input(this.configuration?.rowHeight ?? 30, ...(ngDevMode ? [{ debugName: "rowHeight" }] : []));
        /**
         * Type of column width distribution formula.
         * Example: flex, force, standard
         */
        this.columnMode = input(ColumnMode.standard, ...(ngDevMode ? [{ debugName: "columnMode" }] : []));
        /**
         * The minimum header height in pixels.
         * Pass a falsey for no header
         */
        this.headerHeight = input(this.configuration?.headerHeight ?? 30, ...(ngDevMode ? [{ debugName: "headerHeight" }] : []));
        /**
         * The minimum footer height in pixels.
         * Pass falsey for no footer
         */
        this.footerHeight = input(this.configuration?.footerHeight ?? 0, ...(ngDevMode ? [{ debugName: "footerHeight", transform: numberAttribute }] : [{
                transform: numberAttribute
            }]));
        /**
         * If the table should use external paging
         * otherwise its assumed that all data is preloaded.
         */
        this.externalPaging = input(false, ...(ngDevMode ? [{ debugName: "externalPaging", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
        /**
         * If the table should use external sorting or
         * the built-in basic sorting.
         */
        this.externalSorting = input(false, ...(ngDevMode ? [{ debugName: "externalSorting", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
        /**
         * The page size to be shown.
         * Default value: `undefined`
         */
        this.limit = input(undefined, ...(ngDevMode ? [{ debugName: "limit", transform: numberOrUndefinedAttribute }] : [{
                transform: numberOrUndefinedAttribute
            }]));
        /**
         * The total count of all rows.
         * Default value: `0`
         */
        this.count = input(0, ...(ngDevMode ? [{ debugName: "count", transform: numberAttribute }] : [{ transform: numberAttribute }]));
        /**
         * The current offset ( page - 1 ) shown.
         * Default value: `0`
         */
        this.offset = model(0, ...(ngDevMode ? [{ debugName: "offset" }] : []));
        /**
         * Show the linear loading bar.
         * Default value: `false`
         */
        this.loadingIndicator = input(false, ...(ngDevMode ? [{ debugName: "loadingIndicator", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
        /**
         * Show ghost loaders on each cell.
         * Default value: `false`
         */
        this.ghostLoadingIndicator = input(false, ...(ngDevMode ? [{ debugName: "ghostLoadingIndicator", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
        /**
         * Type of row selection. Options are:
         *
         *  - `single`
         *  - `multi`
         *  - `checkbox`
         *  - `multiClick`
         *  - `cell`
         *
         * For no selection pass a `falsey`.
         * Default value: `undefined`
         */
        this.selectionType = input(...(ngDevMode ? [undefined, { debugName: "selectionType" }] : []));
        /**
         * Enable/Disable ability to re-order columns
         * by dragging them.
         */
        this.reorderable = input(true, ...(ngDevMode ? [{ debugName: "reorderable", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
        /**
         * Swap columns on re-order columns or
         * move them.
         */
        this.swapColumns = input(true, ...(ngDevMode ? [{ debugName: "swapColumns", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
        /**
         * The type of sorting
         */
        this.sortType = input('single', ...(ngDevMode ? [{ debugName: "sortType" }] : []));
        /**
         * Array of sorted columns by property and type.
         * Default value: `[]`
         */
        this.sorts = model([], ...(ngDevMode ? [{ debugName: "sorts" }] : []));
        /**
         * Css class overrides
         */
        this.cssClasses = input(this.configuration?.cssClasses ?? {}, ...(ngDevMode ? [{ debugName: "cssClasses" }] : []));
        /**
         * Message overrides for localization
         *
         * @defaultValue
         * ```
         * {
         *   emptyMessage: 'No data to display',
         *   totalMessage: 'total',
         *   selectedMessage: 'selected',
         *   ariaFirstPageMessage: 'go to first page',
         *   ariaPreviousPageMessage: 'go to previous page',
         *   ariaPageNMessage: 'page',
         *   ariaNextPageMessage: 'go to next page',
         *   ariaLastPageMessage: 'go to last page',
         *   ariaRowCheckboxMessage: 'Select row',
         *   ariaHeaderCheckboxMessage: 'Select all rows',
         *   ariaGroupHeaderCheckboxMessage: 'Select row group'
         * }
         * ```
         */
        this.messages = input(this.configuration?.messages ?? {}, ...(ngDevMode ? [{ debugName: "messages" }] : []));
        /**
         * A function which is called with the row and should return either:
         * - a string: `"class-1 class-2`
         * - a Record<string, boolean>: `{ 'class-1': true, 'class-2': false }`
         */
        this.rowClass = input(...(ngDevMode ? [undefined, { debugName: "rowClass" }] : []));
        /**
         * A boolean/function you can use to check whether you want
         * to select a particular row based on a criteria. Example:
         *
         *    (selection) => {
         *      return selection !== 'Ethel Price';
         *    }
         */
        this.selectCheck = input(...(ngDevMode ? [undefined, { debugName: "selectCheck" }] : []));
        /**
         * A function you can use to check whether you want
         * to show the checkbox for a particular row based on a criteria. Example:
         *
         *    (row, column, value) => {
         *      return row.name !== 'Ethel Price';
         *    }
         */
        this.displayCheck = input(...(ngDevMode ? [undefined, { debugName: "displayCheck" }] : []));
        /**
         * A boolean you can use to set the detault behaviour of rows and groups
         * whether they will start expanded or not. If ommited the default is NOT expanded.
         *
         */
        this.groupExpansionDefault = input(false, ...(ngDevMode ? [{ debugName: "groupExpansionDefault", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
        /**
         * Property to which you can use for custom tracking of rows.
         * Example: 'name'
         */
        this.trackByProp = input(...(ngDevMode ? [undefined, { debugName: "trackByProp" }] : []));
        /**
         * Property to which you can use for determining select all
         * rows on current page or not.
         */
        this.selectAllRowsOnPage = input(false, ...(ngDevMode ? [{ debugName: "selectAllRowsOnPage", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
        /**
         * A flag for row virtualization on / off
         */
        this.virtualization = input(true, ...(ngDevMode ? [{ debugName: "virtualization", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
        /**
         * Tree from relation
         */
        this.treeFromRelation = input(...(ngDevMode ? [undefined, { debugName: "treeFromRelation" }] : []));
        /**
         * Tree to relation
         */
        this.treeToRelation = input(...(ngDevMode ? [undefined, { debugName: "treeToRelation" }] : []));
        /**
         * A flag for switching summary row on / off
         */
        this.summaryRow = input(false, ...(ngDevMode ? [{ debugName: "summaryRow", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
        /**
         * A height of summary row
         */
        this.summaryHeight = input(30, ...(ngDevMode ? [{ debugName: "summaryHeight", transform: numberAttribute }] : [{ transform: numberAttribute }]));
        /**
         * A property holds a summary row position: top/bottom
         */
        this.summaryPosition = input('top', ...(ngDevMode ? [{ debugName: "summaryPosition" }] : []));
        /**
         * A function you can use to check whether you want
         * to disable a row. Example:
         *
         *    (row) => {
         *      return row.name !== 'Ethel Price';
         *    }
         */
        this.disableRowCheck = input(...(ngDevMode ? [undefined, { debugName: "disableRowCheck" }] : []));
        /**
         * A flag to enable drag behavior of native HTML5 drag and drop API on rows.
         * If set to true, {@link rowDragEvents} will emit dragstart and dragend events.
         */
        this.rowDraggable = input(false, ...(ngDevMode ? [{ debugName: "rowDraggable", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
        /**
         * A flag to controll behavior of sort states.
         * By default sort on column toggles between ascending and descending without getting removed.
         * Set true to clear sorting of column after performing ascending and descending sort on that column.
         */
        this.enableClearingSortState = input(false, ...(ngDevMode ? [{ debugName: "enableClearingSortState", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
        /**
         * Body was scrolled typically in a `scrollbarV:true` scenario.
         */
        this.scroll = output();
        /**
         * A cell or row was focused via keyboard or mouse click.
         */
        this.activate = output();
        /**
         * A cell or row was selected.
         * @deprecated Use two-way binding on `selected` instead.
         *
         * Before:
         * ```html
         * <ngx-datatable [selected]="mySelection" (select)="onSelect($event)"></ngx-datatable>
         * ```
         *
         * After:
         * ```html
         * <ngx-datatable [selected]="mySelection" (selectedChange)="onSelect({selected: $event})"></ngx-datatable>
         * <!-- or -->
         * <ngx-datatable [(selected)]="mySelection"></ngx-datatable>
         * ```
         */
        this.select = output();
        /**
         * Column sort was invoked.
         * @deprecated Use two-way binding on `sorts` instead.
         *
         * Before:
         * ```html
         * <ngx-datatable [sorts]="mySorts" (sort)="onSort($event)"></ngx-datatable>
         * ```
         *
         * After:
         * ```html
         * <ngx-datatable [sorts]="mySorts" (sortsChange)="onSort({sorts: $event})"></ngx-datatable>
         * <!-- or -->
         * <ngx-datatable [(sorts)]="mySorts"></ngx-datatable>
         */
        this.sort = output();
        /**
         * The table was paged either triggered by the pager or the body scroll.
         */
        this.page = output();
        /**
         * Columns were re-ordered.
         */
        this.reorder = output();
        /**
         * Column was resized.
         */
        this.resize = output();
        /**
         * The context menu was invoked on the table.
         * type indicates whether the header or the body was clicked.
         * content contains either the column or the row that was clicked.
         */
        this.tableContextmenu = output();
        /**
         * A row was expanded ot collapsed for tree
         */
        this.treeAction = output();
        /**
         * Emits HTML5 native drag events.
         * Only emits dragenter, dragover, drop events by default.
         * Set {@link rowDraggable} to true for dragstart and dragend.
         */
        this.rowDragEvents = output();
        /**
         * Column templates gathered from `ContentChildren`
         * if described in your markup.
         */
        this.columnTemplates = contentChildren(DataTableColumnDirective, ...(ngDevMode ? [{ debugName: "columnTemplates" }] : []));
        /**
         * Footer template gathered from the ContentChild
         * @internal
         */
        this._footer = contentChild(DatatableFooterDirective, ...(ngDevMode ? [{ debugName: "_footer" }] : []));
        this._bodyComponent = viewChild.required(DataTableBodyComponent);
        this._headerElement = viewChild(DataTableHeaderComponent, ...(ngDevMode ? [{ debugName: "_headerElement", read: (ElementRef) }] : [{
                read: (ElementRef)
            }]));
        this._bodyElement = viewChild.required(DataTableBodyComponent, {
            read: (ElementRef)
        });
        /** @internal */
        this._rowDefTemplate = contentChild(DatatableRowDefDirective, ...(ngDevMode ? [{ debugName: "_rowDefTemplate", read: TemplateRef }] : [{
                read: TemplateRef
            }]));
        /**
         * Returns if all rows are selected.
         */
        this.allRowsSelected = computed(() => {
            const selected = this.selected();
            let allRowsSelected = this.rows() && selected && selected.length === this.rows().length;
            if (this.selectAllRowsOnPage()) {
                const { first, last } = this._bodyComponent().indexes();
                const rowsOnPage = last - first;
                allRowsSelected = selected.length === rowsOnPage;
            }
            return !!(selected && this.rows()?.length !== 0 && allRowsSelected);
        }, ...(ngDevMode ? [{ debugName: "allRowsSelected" }] : []));
        this.element = inject(ElementRef).nativeElement;
        this._innerWidth = computed(() => this.dimensions().width, ...(ngDevMode ? [{ debugName: "_innerWidth" }] : []));
        this.pageSize = computed(() => this.calcPageSize(), ...(ngDevMode ? [{ debugName: "pageSize" }] : []));
        this._isFixedHeader = computed(() => {
            const headerHeight = this.headerHeight();
            return typeof headerHeight === 'string' ? headerHeight !== 'auto' : true;
        }, ...(ngDevMode ? [{ debugName: "_isFixedHeader" }] : []));
        this.bodyHeight = computed(() => {
            if (this.scrollbarV()) {
                let height = this.dimensions().height;
                const headerElement = this._headerElement();
                if (headerElement) {
                    height = height - headerElement.nativeElement.getBoundingClientRect().height;
                }
                return height - this.footerHeight();
            }
            return 0;
        }, ...(ngDevMode ? [{ debugName: "bodyHeight" }] : []));
        this.rowCount = computed(() => this.calcRowCount(), ...(ngDevMode ? [{ debugName: "rowCount" }] : []));
        this.rowDiffer = inject(IterableDiffers).find([]).create();
        /** This counter is increased, when the rowDiffer detects a change. This will cause an update of _internalRows. */
        this._rowDiffCount = signal(0, ...(ngDevMode ? [{ debugName: "_rowDiffCount" }] : []));
        this._offsetX = 0;
        this._internalRows = computed(() => {
            this._rowDiffCount(); // to trigger recalculation when row differ detects a change
            let rows = this.rows()?.slice() ?? [];
            const sorts = this.sorts();
            if (sorts.length && !this.externalSorting()) {
                rows = sortRows(rows, this._internalColumns(), this.sorts());
            }
            if (this.treeFromRelation() && this.treeToRelation()) {
                rows = groupRowsByParents(rows, optionalGetterForProp(this.treeFromRelation()), optionalGetterForProp(this.treeToRelation()));
            }
            if (this.ghostLoadingIndicator() && this.scrollbarV() && !this.externalPaging()) {
                // in case where we don't have predefined total page length
                rows.push(undefined); // undefined row will render ghost cell row at the end of the page
            }
            return rows;
        }, ...(ngDevMode ? [{ debugName: "_internalRows" }] : []));
        this._internalGroupedRows = computed(() => {
            let groupedRows = this.groupedRows();
            const groupRowsBy = this.groupRowsBy();
            if (!groupedRows && groupRowsBy) {
                this._rowDiffCount(); // to trigger recalculation when row differ detects a change
                groupedRows = this.groupArrayBy(this.rows() ?? [], groupRowsBy);
            }
            if (!groupedRows) {
                // return here to prevent subscription to sorts when no grouping
                return undefined;
            }
            const sorts = this.sorts();
            if (sorts.length && !this.externalSorting()) {
                if (groupedRows?.length) {
                    groupedRows = sortGroupedRows(groupedRows, this._internalColumns(), sorts, sorts.find(sortColumns => sortColumns.prop === groupRowsBy));
                }
            }
            return groupedRows;
        }, ...(ngDevMode ? [{ debugName: "_internalGroupedRows" }] : []));
        // TODO: consider removing internal modifications of the columns.
        // This requires a different strategy for certain properties like width.
        this._internalColumns = linkedSignal(() => this.recalculateColumns(toInternalColumn(this.columnTemplates().length
            ? this.columnTemplates().map(c => c.column())
            : (this.columns() ?? []), this._defaultColumnWidth)), ...(ngDevMode ? [{ debugName: "_internalColumns" }] : []));
        /**
         * Computed signal that returns the corrected offset value.
         * It ensures the offset is within valid bounds based on rowCount and pageSize.
         */
        this.correctedOffset = computed(() => {
            const offset = this.offset();
            const rowCount = this.rowCount();
            const pageSize = this.pageSize();
            return Math.max(Math.min(offset, Math.ceil(rowCount / pageSize) - 1), 0);
        }, ...(ngDevMode ? [{ debugName: "correctedOffset" }] : []));
        this._subscriptions = [];
        this._defaultColumnWidth = this.configuration?.defaultColumnWidth ?? 150;
        /**
         * To have this available for all components.
         * The Footer itself is not available in the injection context in templates,
         * so we need to get if from here until we have a state service.
         */
        this._footerComponent = viewChild(DataTableFooterComponent, ...(ngDevMode ? [{ debugName: "_footerComponent" }] : []));
        this.verticalScrollVisible = false;
        // In case horizontal scroll is enabled
        // the column widths are initially calculated without vertical scroll offset
        // this makes horizontal scroll to appear on load even if columns can fit in view
        // this will be set to true once rows are available and rendered on UI
        this._rowInitDone = signal(false, ...(ngDevMode ? [{ debugName: "_rowInitDone" }] : []));
        this.dimensions = signal({ height: 0, width: 0 }, ...(ngDevMode ? [{ debugName: "dimensions" }] : []));
        /**
         * This will be used when displaying or selecting rows.
         * when tracking/comparing them, we'll use the value of this fn,
         *
         * (`fn(x) === fn(y)` instead of `x === y`)
         */
        this.rowIdentity = input(x => {
            if (this.groupRowsBy()) {
                // each group in groupedRows are stored as {key, value: [rows]},
                // where key is the groupRowsBy index
                return x.key ?? x;
            }
            else {
                return x;
            }
        }, ...(ngDevMode ? [{ debugName: "rowIdentity" }] : []));
        // TODO: This should be a computed signal.
        // Effect to handle recalculate when limit or count changes
        effect(() => {
            // Track limit and count changes
            this.limit();
            this.count();
            // Recalculate without tracking other signals
            untracked(() => this.recalculateDims());
        });
    }
    /**
     * Lifecycle hook that is called after data-bound
     * properties of a directive are initialized.
     */
    ngOnInit() {
        // need to call this immediatly to size
        // if the table is hidden the visibility
        // listener will invoke this itself upon show
        this.recalculate();
    }
    /*
     * Lifecycle hook that is called when Angular dirty checks a directive.
     */
    ngDoCheck() {
        const rowDiffers = this.rowDiffer.diff(this.rows());
        if (rowDiffers || this.disableRowCheck()) {
            this._rowDiffCount.update(count => count + 1);
            if (rowDiffers) {
                queueMicrotask(() => {
                    this._rowInitDone.set(true);
                    this.recalculate();
                    this.cd.markForCheck();
                });
            }
            this.cd.markForCheck();
        }
    }
    /**
     * Lifecycle hook that is called after a component's
     * view has been fully initialized.
     */
    ngAfterViewInit() {
        // this has to be done to prevent the change detection
        // tree from freaking out because we are readjusting
        if (typeof requestAnimationFrame === 'undefined') {
            return;
        }
        requestAnimationFrame(() => {
            this.recalculate();
            // emit page for virtual server-side kickoff
            if (this.externalPaging() && this.scrollbarV()) {
                this.page.emit({
                    count: this.count(),
                    pageSize: this.pageSize(),
                    limit: this.limit(),
                    offset: 0,
                    sorts: this.sorts()
                });
            }
        });
    }
    /**
     * Creates a map with the data grouped by the user choice of grouping index
     *
     * @param originalArray the original array passed via parameter
     * @param groupBy the key of the column to group the data by
     */
    groupArrayBy(originalArray, groupBy) {
        // create a map to hold groups with their corresponding results
        const map = new Map();
        let i = 0;
        originalArray.forEach(item => {
            if (!item) {
                // skip undefined items
                return;
            }
            const key = item[groupBy];
            const value = map.get(key);
            if (!value) {
                map.set(key, [item]);
            }
            else {
                value.push(item);
            }
            i++;
        });
        const addGroup = (key, value) => ({ key, value });
        // convert map back to a simple array of objects
        return Array.from(map, x => addGroup(x[0], x[1]));
    }
    /**
     * Recalc's the sizes of the grid.
     *
     * Updated automatically on changes to:
     *
     *  - Columns
     *  - Rows
     *  - Paging related
     *
     * Also can be manually invoked or upon window resize.
     */
    recalculate() {
        this.recalculateDims();
        this._internalColumns.set(this.recalculateColumns(this._internalColumns().slice()));
        this.cd.markForCheck();
    }
    /**
     * Window resize handler to update sizes.
     */
    onWindowResize() {
        this.recalculate();
    }
    /**
     * Recalulcates the column widths based on column width
     * distribution mode and scrollbar offsets.
     */
    recalculateColumns(columns, forceIdx = -1, allowBleed = this.scrollbarH()) {
        let width = this._innerWidth();
        if (!width) {
            return [];
        }
        const { scrollHeight, clientHeight } = this._bodyElement().nativeElement;
        this.verticalScrollVisible = scrollHeight > clientHeight;
        if (this.scrollbarV() || this.scrollbarVDynamic()) {
            width =
                width -
                    (this.verticalScrollVisible || !this._rowInitDone() ? this.scrollbarHelper.width : 0);
        }
        if (this.columnMode() === ColumnMode.force) {
            forceFillColumnWidths(columns, width, forceIdx, allowBleed, this._defaultColumnWidth, this.scrollbarHelper.width);
        }
        else if (this.columnMode() === ColumnMode.flex) {
            adjustColumnWidths(columns, width);
        }
        return columns;
    }
    /**
     * Recalculates the dimensions of the table size.
     * Internally calls the page size and row count calcs too.
     *
     */
    recalculateDims() {
        const dims = this.element.getBoundingClientRect();
        this.dimensions.set(dims);
    }
    /**
     * Body triggered a page event.
     */
    onBodyPage(offset) {
        // Avoid pagination caming from body events like scroll when the table
        // has no virtualization and the external paging is enable.
        // This means, let's the developer handle pagination by my him(her) self
        if (this.externalPaging() && !this.virtualization()) {
            return;
        }
        this.offset.set(offset);
        if (!isNaN(this.correctedOffset())) {
            this.page.emit({
                count: this.count(),
                pageSize: this.pageSize(),
                limit: this.limit(),
                offset: this.correctedOffset(),
                sorts: this.sorts()
            });
        }
    }
    /**
     * The body triggered a scroll event.
     */
    onBodyScroll(event) {
        this._offsetX = event.offsetX;
        this.scroll.emit(event);
    }
    /**
     * The footer triggered a page event.
     */
    onFooterPage(event) {
        this.offset.set(event.page - 1);
        this._bodyComponent().updateOffsetY(this.correctedOffset());
        this.page.emit({
            count: this.count(),
            pageSize: this.pageSize(),
            limit: this.limit(),
            offset: this.correctedOffset(),
            sorts: this.sorts()
        });
        if (this.selectAllRowsOnPage()) {
            this.selected.set([]);
            this.select.emit({
                selected: this.selected()
            });
        }
    }
    /**
     * Recalculates the sizes of the page
     */
    calcPageSize() {
        // Keep the page size constant even if the row has been expanded.
        // This is because an expanded row is still considered to be a child of
        // the original row.  Hence calculation would use rowHeight only.
        if (this.scrollbarV() && this.virtualization()) {
            const size = Math.ceil(this.bodyHeight() / this.rowHeight());
            return Math.max(size, 0);
        }
        // if limit is passed, we are paging
        const limit = this.limit();
        if (limit !== undefined) {
            return limit;
        }
        // otherwise use row length
        return this.rows()?.length ?? 0;
    }
    /**
     * Calculates the row count.
     */
    calcRowCount() {
        if (!this.externalPaging()) {
            const groupedRows = this._internalGroupedRows();
            if (groupedRows) {
                return groupedRows.length;
            }
            else {
                return this._internalRows().length;
            }
        }
        return this.count();
    }
    /**
     * The header triggered a contextmenu event.
     */
    onColumnContextmenu({ event, column }) {
        this.tableContextmenu.emit({ event, type: ContextmenuType.header, content: column });
    }
    /**
     * The body triggered a contextmenu event.
     */
    onRowContextmenu({ event, row }) {
        this.tableContextmenu.emit({ event, type: ContextmenuType.body, content: row });
    }
    /**
     * The header triggered a column resize event.
     */
    onColumnResize({ column, newValue, prevValue }) {
        /* Safari/iOS 10.2 workaround */
        if (column === undefined) {
            return;
        }
        const idx = this._internalColumns().indexOf(column);
        const cols = this._internalColumns().map(col => ({ ...col }));
        cols[idx].width = newValue;
        // set this so we can force the column
        // width distribution to be to this value
        cols[idx].$$oldWidth = newValue;
        this._internalColumns.set(this.recalculateColumns(cols, idx));
        this.resize.emit({
            column,
            newValue,
            prevValue
        });
    }
    onColumnResizing({ column, newValue }) {
        if (column === undefined) {
            return;
        }
        column.width = newValue;
        column.$$oldWidth = newValue;
        const idx = this._internalColumns().indexOf(column);
        this._internalColumns.set(this.recalculateColumns(this._internalColumns().slice(), idx));
    }
    /**
     * The header triggered a column re-order event.
     */
    onColumnReorder(event) {
        const { column, newValue, prevValue } = event;
        const cols = this._internalColumns().map(c => ({ ...c }));
        const prevCol = cols[newValue];
        if (column.frozenLeft !== prevCol.frozenLeft || column.frozenRight !== prevCol.frozenRight) {
            return;
        }
        if (this.swapColumns()) {
            cols[newValue] = column;
            cols[prevValue] = prevCol;
        }
        else {
            if (newValue > prevValue) {
                const movedCol = cols[prevValue];
                for (let i = prevValue; i < newValue; i++) {
                    cols[i] = cols[i + 1];
                }
                cols[newValue] = movedCol;
            }
            else {
                const movedCol = cols[prevValue];
                for (let i = prevValue; i > newValue; i--) {
                    cols[i] = cols[i - 1];
                }
                cols[newValue] = movedCol;
            }
        }
        this._internalColumns.set(cols);
        this.reorder.emit(event);
    }
    /**
     * The header triggered a column sort event.
     */
    onColumnSort(event) {
        // clean selected rows
        if (this.selectAllRowsOnPage()) {
            this.selected.set([]);
            this.select.emit({
                selected: this.selected()
            });
        }
        this.sorts.set(event.sorts);
        // Always go to first page when sorting to see the newly sorted data
        this.offset.set(0);
        this._bodyComponent().updateOffsetY(this.correctedOffset());
        // Emit the page object with updated offset value
        this.page.emit({
            count: this.count(),
            pageSize: this.pageSize(),
            limit: this.limit(),
            offset: this.correctedOffset(),
            sorts: this.sorts()
        });
        this.sort.emit(event);
    }
    /**
     * Toggle all row selection
     */
    onHeaderSelect() {
        if (this.selectAllRowsOnPage()) {
            // before we splice, chk if we currently have all selected
            const { first, last } = this._bodyComponent().indexes();
            const allSelected = this.selected().length === last - first;
            // do the opposite here
            if (!allSelected) {
                this.selected.set(this._internalRows()
                    .slice(first, last)
                    .filter(row => !!row));
            }
            else {
                this.selected.set([]);
            }
        }
        else {
            let relevantRows;
            const disableRowCheckFn = this.disableRowCheck();
            if (disableRowCheckFn) {
                relevantRows = (this.rows() ?? []).filter((row => row && !disableRowCheckFn(row)));
            }
            else {
                relevantRows = (this.rows() ?? []).filter(row => !!row);
            }
            // before we splice, chk if we currently have all selected
            const allSelected = this.selected().length === relevantRows.length;
            // do the opposite here
            if (!allSelected) {
                this.selected.set(relevantRows);
            }
            else {
                this.selected.set([]);
            }
        }
        this.select.emit({
            selected: this.selected()
        });
    }
    /**
     * A row was selected from body
     */
    onBodySelect(selected) {
        this.select.emit({ selected });
    }
    /**
     * A row was expanded or collapsed for tree
     */
    onTreeAction(event) {
        const row = event.row;
        // TODO: For duplicated items this will not work
        const treeToRel = this.treeToRelation();
        const rowIndex = (this.rows() ?? []).findIndex(r => r && r[treeToRel] === event.row[treeToRel]);
        this.treeAction.emit({ row, rowIndex });
    }
    ngOnDestroy() {
        this._subscriptions.forEach(subscription => subscription.unsubscribe());
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DatatableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DatatableComponent, isStandalone: true, selector: "ngx-datatable", inputs: { targetMarkerTemplate: { classPropertyName: "targetMarkerTemplate", publicName: "targetMarkerTemplate", isSignal: true, isRequired: false, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, groupRowsBy: { classPropertyName: "groupRowsBy", publicName: "groupRowsBy", isSignal: true, isRequired: false, transformFunction: null }, groupedRows: { classPropertyName: "groupedRows", publicName: "groupedRows", isSignal: true, isRequired: false, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "selected", isSignal: true, isRequired: false, transformFunction: null }, scrollbarV: { classPropertyName: "scrollbarV", publicName: "scrollbarV", isSignal: true, isRequired: false, transformFunction: null }, scrollbarVDynamic: { classPropertyName: "scrollbarVDynamic", publicName: "scrollbarVDynamic", isSignal: true, isRequired: false, transformFunction: null }, scrollbarH: { classPropertyName: "scrollbarH", publicName: "scrollbarH", isSignal: true, isRequired: false, transformFunction: null }, rowHeight: { classPropertyName: "rowHeight", publicName: "rowHeight", isSignal: true, isRequired: false, transformFunction: null }, columnMode: { classPropertyName: "columnMode", publicName: "columnMode", isSignal: true, isRequired: false, transformFunction: null }, headerHeight: { classPropertyName: "headerHeight", publicName: "headerHeight", isSignal: true, isRequired: false, transformFunction: null }, footerHeight: { classPropertyName: "footerHeight", publicName: "footerHeight", isSignal: true, isRequired: false, transformFunction: null }, externalPaging: { classPropertyName: "externalPaging", publicName: "externalPaging", isSignal: true, isRequired: false, transformFunction: null }, externalSorting: { classPropertyName: "externalSorting", publicName: "externalSorting", isSignal: true, isRequired: false, transformFunction: null }, limit: { classPropertyName: "limit", publicName: "limit", isSignal: true, isRequired: false, transformFunction: null }, count: { classPropertyName: "count", publicName: "count", isSignal: true, isRequired: false, transformFunction: null }, offset: { classPropertyName: "offset", publicName: "offset", isSignal: true, isRequired: false, transformFunction: null }, loadingIndicator: { classPropertyName: "loadingIndicator", publicName: "loadingIndicator", isSignal: true, isRequired: false, transformFunction: null }, ghostLoadingIndicator: { classPropertyName: "ghostLoadingIndicator", publicName: "ghostLoadingIndicator", isSignal: true, isRequired: false, transformFunction: null }, selectionType: { classPropertyName: "selectionType", publicName: "selectionType", isSignal: true, isRequired: false, transformFunction: null }, reorderable: { classPropertyName: "reorderable", publicName: "reorderable", isSignal: true, isRequired: false, transformFunction: null }, swapColumns: { classPropertyName: "swapColumns", publicName: "swapColumns", isSignal: true, isRequired: false, transformFunction: null }, sortType: { classPropertyName: "sortType", publicName: "sortType", isSignal: true, isRequired: false, transformFunction: null }, sorts: { classPropertyName: "sorts", publicName: "sorts", isSignal: true, isRequired: false, transformFunction: null }, cssClasses: { classPropertyName: "cssClasses", publicName: "cssClasses", isSignal: true, isRequired: false, transformFunction: null }, messages: { classPropertyName: "messages", publicName: "messages", isSignal: true, isRequired: false, transformFunction: null }, rowClass: { classPropertyName: "rowClass", publicName: "rowClass", isSignal: true, isRequired: false, transformFunction: null }, selectCheck: { classPropertyName: "selectCheck", publicName: "selectCheck", isSignal: true, isRequired: false, transformFunction: null }, displayCheck: { classPropertyName: "displayCheck", publicName: "displayCheck", isSignal: true, isRequired: false, transformFunction: null }, groupExpansionDefault: { classPropertyName: "groupExpansionDefault", publicName: "groupExpansionDefault", isSignal: true, isRequired: false, transformFunction: null }, trackByProp: { classPropertyName: "trackByProp", publicName: "trackByProp", isSignal: true, isRequired: false, transformFunction: null }, selectAllRowsOnPage: { classPropertyName: "selectAllRowsOnPage", publicName: "selectAllRowsOnPage", isSignal: true, isRequired: false, transformFunction: null }, virtualization: { classPropertyName: "virtualization", publicName: "virtualization", isSignal: true, isRequired: false, transformFunction: null }, treeFromRelation: { classPropertyName: "treeFromRelation", publicName: "treeFromRelation", isSignal: true, isRequired: false, transformFunction: null }, treeToRelation: { classPropertyName: "treeToRelation", publicName: "treeToRelation", isSignal: true, isRequired: false, transformFunction: null }, summaryRow: { classPropertyName: "summaryRow", publicName: "summaryRow", isSignal: true, isRequired: false, transformFunction: null }, summaryHeight: { classPropertyName: "summaryHeight", publicName: "summaryHeight", isSignal: true, isRequired: false, transformFunction: null }, summaryPosition: { classPropertyName: "summaryPosition", publicName: "summaryPosition", isSignal: true, isRequired: false, transformFunction: null }, disableRowCheck: { classPropertyName: "disableRowCheck", publicName: "disableRowCheck", isSignal: true, isRequired: false, transformFunction: null }, rowDraggable: { classPropertyName: "rowDraggable", publicName: "rowDraggable", isSignal: true, isRequired: false, transformFunction: null }, enableClearingSortState: { classPropertyName: "enableClearingSortState", publicName: "enableClearingSortState", isSignal: true, isRequired: false, transformFunction: null }, rowIdentity: { classPropertyName: "rowIdentity", publicName: "rowIdentity", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selected: "selectedChange", offset: "offsetChange", sorts: "sortsChange", scroll: "scroll", activate: "activate", select: "select", sort: "sort", page: "page", reorder: "reorder", resize: "resize", tableContextmenu: "tableContextmenu", treeAction: "treeAction", rowDragEvents: "rowDragEvents" }, host: { listeners: { "window:resize": "onWindowResize()" }, properties: { "class.fixed-header": "_isFixedHeader()", "class.fixed-row": "rowHeight() !== \"auto\"", "class.scroll-vertical": "scrollbarV()", "class.virtualized": "virtualization()", "class.scroll-horz": "scrollbarH()", "class.selectable": "selectionType() !== undefined", "class.checkbox-selection": "selectionType() === \"checkbox\"", "class.cell-selection": "selectionType() === \"cell\"", "class.single-selection": "selectionType() === \"single\"", "class.multi-selection": "selectionType() === \"multi\"", "class.multi-click-selection": "selectionType() === \"multiClick\"" }, classAttribute: "ngx-datatable" }, providers: [
            {
                provide: DATATABLE_COMPONENT_TOKEN,
                useExisting: DatatableComponent
            }
        ], queries: [{ propertyName: "columnTemplates", predicate: DataTableColumnDirective, isSignal: true }, { propertyName: "_footer", first: true, predicate: DatatableFooterDirective, descendants: true, isSignal: true }, { propertyName: "_rowDefTemplate", first: true, predicate: DatatableRowDefDirective, descendants: true, read: TemplateRef, isSignal: true }, { propertyName: "rowDetail", first: true, predicate: DatatableRowDetailDirective, descendants: true }, { propertyName: "groupHeader", first: true, predicate: DatatableGroupHeaderDirective, descendants: true }], viewQueries: [{ propertyName: "_bodyComponent", first: true, predicate: DataTableBodyComponent, descendants: true, isSignal: true }, { propertyName: "_headerElement", first: true, predicate: DataTableHeaderComponent, descendants: true, read: ElementRef, isSignal: true }, { propertyName: "_bodyElement", first: true, predicate: DataTableBodyComponent, descendants: true, read: ElementRef, isSignal: true }, { propertyName: "_footerComponent", first: true, predicate: DataTableFooterComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<div visibilityObserver (visible)=\"recalculate()\">\n  <div role=\"table\">\n    @if (headerHeight()) {\n      <datatable-header\n        role=\"rowgroup\"\n        [sorts]=\"sorts()\"\n        [sortType]=\"sortType()\"\n        [scrollbarH]=\"scrollbarH()\"\n        [innerWidth]=\"_innerWidth()\"\n        [offsetX]=\"_offsetX\"\n        [dealsWithGroup]=\"_internalGroupedRows() !== undefined\"\n        [columns]=\"_internalColumns()\"\n        [headerHeight]=\"headerHeight()\"\n        [reorderable]=\"reorderable()\"\n        [targetMarkerTemplate]=\"targetMarkerTemplate()\"\n        [sortAscendingIcon]=\"cssClasses().sortAscending\"\n        [sortDescendingIcon]=\"cssClasses().sortDescending\"\n        [sortUnsetIcon]=\"cssClasses().sortUnset\"\n        [allRowsSelected]=\"allRowsSelected()\"\n        [selectionType]=\"selectionType()\"\n        [verticalScrollVisible]=\"verticalScrollVisible\"\n        [enableClearingSortState]=\"enableClearingSortState()\"\n        [ariaHeaderCheckboxMessage]=\"messages().ariaHeaderCheckboxMessage ?? 'Select all rows'\"\n        (sort)=\"onColumnSort($event)\"\n        (resize)=\"onColumnResize($event)\"\n        (resizing)=\"onColumnResizing($event)\"\n        (reorder)=\"onColumnReorder($event)\"\n        (select)=\"onHeaderSelect()\"\n        (columnContextmenu)=\"onColumnContextmenu($event)\"\n      />\n    }\n    <datatable-body\n      tabindex=\"0\"\n      role=\"rowgroup\"\n      [groupedRows]=\"_internalGroupedRows()\"\n      [rows]=\"_internalRows()\"\n      [groupExpansionDefault]=\"groupExpansionDefault()\"\n      [scrollbarV]=\"scrollbarV()\"\n      [scrollbarH]=\"scrollbarH()\"\n      [virtualization]=\"virtualization()\"\n      [loadingIndicator]=\"loadingIndicator()\"\n      [ghostLoadingIndicator]=\"ghostLoadingIndicator()\"\n      [externalPaging]=\"externalPaging()\"\n      [rowHeight]=\"rowHeight()\"\n      [rowCount]=\"rowCount()\"\n      [offset]=\"correctedOffset()\"\n      [trackByProp]=\"trackByProp()\"\n      [columns]=\"_internalColumns()\"\n      [pageSize]=\"pageSize()\"\n      [offsetX]=\"_offsetX\"\n      [rowDetail]=\"rowDetail\"\n      [groupHeader]=\"groupHeader\"\n      [innerWidth]=\"_innerWidth()\"\n      [bodyHeight]=\"bodyHeight()\"\n      [selectionType]=\"selectionType()\"\n      [rowIdentity]=\"rowIdentity()\"\n      [rowClass]=\"rowClass()\"\n      [selectCheck]=\"selectCheck()\"\n      [displayCheck]=\"displayCheck()\"\n      [summaryRow]=\"summaryRow()\"\n      [summaryHeight]=\"summaryHeight()\"\n      [summaryPosition]=\"summaryPosition()\"\n      [verticalScrollVisible]=\"verticalScrollVisible\"\n      [ariaRowCheckboxMessage]=\"messages().ariaRowCheckboxMessage ?? 'Select row'\"\n      [ariaGroupHeaderCheckboxMessage]=\"\n        messages().ariaGroupHeaderCheckboxMessage ?? 'Select row group'\n      \"\n      [disableRowCheck]=\"disableRowCheck()\"\n      [rowDraggable]=\"rowDraggable()\"\n      [rowDragEvents]=\"rowDragEvents\"\n      [rowDefTemplate]=\"_rowDefTemplate()\"\n      [cssClasses]=\"cssClasses()\"\n      [(selected)]=\"selected\"\n      (page)=\"onBodyPage($event)\"\n      (activate)=\"activate.emit($event)\"\n      (rowContextmenu)=\"onRowContextmenu($event)\"\n      (selectedChange)=\"onBodySelect($event)\"\n      (scroll)=\"onBodyScroll($event)\"\n      (treeAction)=\"onTreeAction($event)\"\n    >\n      <ng-content select=\"[loading-indicator]\" ngProjectAs=\"[loading-indicator]\">\n        <datatable-progress />\n      </ng-content>\n      <ng-content select=\"[empty-content]\" ngProjectAs=\"[empty-content]\">\n        <div role=\"row\">\n          <div\n            role=\"cell\"\n            class=\"empty-row\"\n            [innerHTML]=\"messages().emptyMessage ?? 'No data to display'\"\n          ></div>\n        </div>\n      </ng-content>\n    </datatable-body>\n  </div>\n  @if (footerHeight()) {\n    <datatable-footer\n      [rowCount]=\"_internalGroupedRows() !== undefined ? _internalRows().length : rowCount()\"\n      [groupCount]=\"_internalGroupedRows() !== undefined ? rowCount() : undefined\"\n      [pageSize]=\"pageSize()\"\n      [offset]=\"correctedOffset()\"\n      [footerHeight]=\"footerHeight()\"\n      [footerTemplate]=\"_footer()\"\n      [totalMessage]=\"messages().totalMessage ?? 'total'\"\n      [pagerLeftArrowIcon]=\"cssClasses().pagerLeftArrow\"\n      [pagerRightArrowIcon]=\"cssClasses().pagerRightArrow\"\n      [pagerPreviousIcon]=\"cssClasses().pagerPrevious\"\n      [selectedCount]=\"selected().length\"\n      [selectedMessage]=\"!!selectionType() && (messages().selectedMessage ?? 'selected')\"\n      [pagerNextIcon]=\"cssClasses().pagerNext\"\n      (page)=\"onFooterPage($event)\"\n    />\n  }\n</div>\n", styles: [":host{display:block;overflow:hidden;justify-content:center;position:relative;transform:translateZ(0)}\n"], dependencies: [{ kind: "directive", type: VisibilityDirective, selector: "[visibilityObserver]", outputs: ["visible"] }, { kind: "component", type: DataTableHeaderComponent, selector: "datatable-header", inputs: ["sortAscendingIcon", "sortDescendingIcon", "sortUnsetIcon", "scrollbarH", "dealsWithGroup", "targetMarkerTemplate", "enableClearingSortState", "innerWidth", "sorts", "sortType", "allRowsSelected", "selectionType", "reorderable", "verticalScrollVisible", "ariaHeaderCheckboxMessage", "headerHeight", "columns", "offsetX"], outputs: ["sort", "reorder", "resize", "resizing", "select", "columnContextmenu"] }, { kind: "component", type: DataTableBodyComponent, selector: "datatable-body", inputs: ["rowDefTemplate", "scrollbarV", "scrollbarH", "loadingIndicator", "ghostLoadingIndicator", "externalPaging", "rowHeight", "offsetX", "selectionType", "selected", "rowIdentity", "rowDetail", "groupHeader", "selectCheck", "displayCheck", "trackByProp", "rowClass", "groupedRows", "groupExpansionDefault", "innerWidth", "virtualization", "summaryRow", "summaryPosition", "summaryHeight", "rowDraggable", "rowDragEvents", "disableRowCheck", "ariaGroupHeaderCheckboxMessage", "pageSize", "rows", "columns", "offset", "rowCount", "bodyHeight", "verticalScrollVisible", "ariaRowCheckboxMessage", "cssClasses"], outputs: ["offsetXChange", "selectedChange", "scroll", "page", "activate", "rowContextmenu", "treeAction"] }, { kind: "component", type: DataTableFooterComponent, selector: "datatable-footer", inputs: ["footerHeight", "rowCount", "groupCount", "pageSize", "offset", "pagerLeftArrowIcon", "pagerRightArrowIcon", "pagerPreviousIcon", "pagerNextIcon", "totalMessage", "footerTemplate", "selectedCount", "selectedMessage"], outputs: ["page"] }, { kind: "component", type: ProgressBarComponent, selector: "datatable-progress" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
__decorate([
    throttleable(5)
], DatatableComponent.prototype, "onWindowResize", null);
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DatatableComponent, decorators: [{
            type: Component,
            args: [{ selector: 'ngx-datatable', imports: [
                        VisibilityDirective,
                        DataTableHeaderComponent,
                        DataTableBodyComponent,
                        DataTableFooterComponent,
                        ProgressBarComponent
                    ], providers: [
                        {
                            provide: DATATABLE_COMPONENT_TOKEN,
                            useExisting: DatatableComponent
                        }
                    ], changeDetection: ChangeDetectionStrategy.OnPush, host: {
                        class: 'ngx-datatable',
                        '[class.fixed-header]': '_isFixedHeader()',
                        '[class.fixed-row]': 'rowHeight() !== "auto"',
                        '[class.scroll-vertical]': 'scrollbarV()',
                        '[class.virtualized]': 'virtualization()',
                        '[class.scroll-horz]': 'scrollbarH()',
                        '[class.selectable]': 'selectionType() !== undefined',
                        '[class.checkbox-selection]': 'selectionType() === "checkbox"',
                        '[class.cell-selection]': 'selectionType() === "cell"',
                        '[class.single-selection]': 'selectionType() === "single"',
                        '[class.multi-selection]': 'selectionType() === "multi"',
                        '[class.multi-click-selection]': 'selectionType() === "multiClick"'
                    }, template: "<div visibilityObserver (visible)=\"recalculate()\">\n  <div role=\"table\">\n    @if (headerHeight()) {\n      <datatable-header\n        role=\"rowgroup\"\n        [sorts]=\"sorts()\"\n        [sortType]=\"sortType()\"\n        [scrollbarH]=\"scrollbarH()\"\n        [innerWidth]=\"_innerWidth()\"\n        [offsetX]=\"_offsetX\"\n        [dealsWithGroup]=\"_internalGroupedRows() !== undefined\"\n        [columns]=\"_internalColumns()\"\n        [headerHeight]=\"headerHeight()\"\n        [reorderable]=\"reorderable()\"\n        [targetMarkerTemplate]=\"targetMarkerTemplate()\"\n        [sortAscendingIcon]=\"cssClasses().sortAscending\"\n        [sortDescendingIcon]=\"cssClasses().sortDescending\"\n        [sortUnsetIcon]=\"cssClasses().sortUnset\"\n        [allRowsSelected]=\"allRowsSelected()\"\n        [selectionType]=\"selectionType()\"\n        [verticalScrollVisible]=\"verticalScrollVisible\"\n        [enableClearingSortState]=\"enableClearingSortState()\"\n        [ariaHeaderCheckboxMessage]=\"messages().ariaHeaderCheckboxMessage ?? 'Select all rows'\"\n        (sort)=\"onColumnSort($event)\"\n        (resize)=\"onColumnResize($event)\"\n        (resizing)=\"onColumnResizing($event)\"\n        (reorder)=\"onColumnReorder($event)\"\n        (select)=\"onHeaderSelect()\"\n        (columnContextmenu)=\"onColumnContextmenu($event)\"\n      />\n    }\n    <datatable-body\n      tabindex=\"0\"\n      role=\"rowgroup\"\n      [groupedRows]=\"_internalGroupedRows()\"\n      [rows]=\"_internalRows()\"\n      [groupExpansionDefault]=\"groupExpansionDefault()\"\n      [scrollbarV]=\"scrollbarV()\"\n      [scrollbarH]=\"scrollbarH()\"\n      [virtualization]=\"virtualization()\"\n      [loadingIndicator]=\"loadingIndicator()\"\n      [ghostLoadingIndicator]=\"ghostLoadingIndicator()\"\n      [externalPaging]=\"externalPaging()\"\n      [rowHeight]=\"rowHeight()\"\n      [rowCount]=\"rowCount()\"\n      [offset]=\"correctedOffset()\"\n      [trackByProp]=\"trackByProp()\"\n      [columns]=\"_internalColumns()\"\n      [pageSize]=\"pageSize()\"\n      [offsetX]=\"_offsetX\"\n      [rowDetail]=\"rowDetail\"\n      [groupHeader]=\"groupHeader\"\n      [innerWidth]=\"_innerWidth()\"\n      [bodyHeight]=\"bodyHeight()\"\n      [selectionType]=\"selectionType()\"\n      [rowIdentity]=\"rowIdentity()\"\n      [rowClass]=\"rowClass()\"\n      [selectCheck]=\"selectCheck()\"\n      [displayCheck]=\"displayCheck()\"\n      [summaryRow]=\"summaryRow()\"\n      [summaryHeight]=\"summaryHeight()\"\n      [summaryPosition]=\"summaryPosition()\"\n      [verticalScrollVisible]=\"verticalScrollVisible\"\n      [ariaRowCheckboxMessage]=\"messages().ariaRowCheckboxMessage ?? 'Select row'\"\n      [ariaGroupHeaderCheckboxMessage]=\"\n        messages().ariaGroupHeaderCheckboxMessage ?? 'Select row group'\n      \"\n      [disableRowCheck]=\"disableRowCheck()\"\n      [rowDraggable]=\"rowDraggable()\"\n      [rowDragEvents]=\"rowDragEvents\"\n      [rowDefTemplate]=\"_rowDefTemplate()\"\n      [cssClasses]=\"cssClasses()\"\n      [(selected)]=\"selected\"\n      (page)=\"onBodyPage($event)\"\n      (activate)=\"activate.emit($event)\"\n      (rowContextmenu)=\"onRowContextmenu($event)\"\n      (selectedChange)=\"onBodySelect($event)\"\n      (scroll)=\"onBodyScroll($event)\"\n      (treeAction)=\"onTreeAction($event)\"\n    >\n      <ng-content select=\"[loading-indicator]\" ngProjectAs=\"[loading-indicator]\">\n        <datatable-progress />\n      </ng-content>\n      <ng-content select=\"[empty-content]\" ngProjectAs=\"[empty-content]\">\n        <div role=\"row\">\n          <div\n            role=\"cell\"\n            class=\"empty-row\"\n            [innerHTML]=\"messages().emptyMessage ?? 'No data to display'\"\n          ></div>\n        </div>\n      </ng-content>\n    </datatable-body>\n  </div>\n  @if (footerHeight()) {\n    <datatable-footer\n      [rowCount]=\"_internalGroupedRows() !== undefined ? _internalRows().length : rowCount()\"\n      [groupCount]=\"_internalGroupedRows() !== undefined ? rowCount() : undefined\"\n      [pageSize]=\"pageSize()\"\n      [offset]=\"correctedOffset()\"\n      [footerHeight]=\"footerHeight()\"\n      [footerTemplate]=\"_footer()\"\n      [totalMessage]=\"messages().totalMessage ?? 'total'\"\n      [pagerLeftArrowIcon]=\"cssClasses().pagerLeftArrow\"\n      [pagerRightArrowIcon]=\"cssClasses().pagerRightArrow\"\n      [pagerPreviousIcon]=\"cssClasses().pagerPrevious\"\n      [selectedCount]=\"selected().length\"\n      [selectedMessage]=\"!!selectionType() && (messages().selectedMessage ?? 'selected')\"\n      [pagerNextIcon]=\"cssClasses().pagerNext\"\n      (page)=\"onFooterPage($event)\"\n    />\n  }\n</div>\n", styles: [":host{display:block;overflow:hidden;justify-content:center;position:relative;transform:translateZ(0)}\n"] }]
        }], ctorParameters: () => [], propDecorators: { targetMarkerTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "targetMarkerTemplate", required: false }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }], groupRowsBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupRowsBy", required: false }] }], groupedRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupedRows", required: false }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }], selected: [{ type: i0.Input, args: [{ isSignal: true, alias: "selected", required: false }] }, { type: i0.Output, args: ["selectedChange"] }], scrollbarV: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollbarV", required: false }] }], scrollbarVDynamic: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollbarVDynamic", required: false }] }], scrollbarH: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollbarH", required: false }] }], rowHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowHeight", required: false }] }], columnMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "columnMode", required: false }] }], headerHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "headerHeight", required: false }] }], footerHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "footerHeight", required: false }] }], externalPaging: [{ type: i0.Input, args: [{ isSignal: true, alias: "externalPaging", required: false }] }], externalSorting: [{ type: i0.Input, args: [{ isSignal: true, alias: "externalSorting", required: false }] }], limit: [{ type: i0.Input, args: [{ isSignal: true, alias: "limit", required: false }] }], count: [{ type: i0.Input, args: [{ isSignal: true, alias: "count", required: false }] }], offset: [{ type: i0.Input, args: [{ isSignal: true, alias: "offset", required: false }] }, { type: i0.Output, args: ["offsetChange"] }], loadingIndicator: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadingIndicator", required: false }] }], ghostLoadingIndicator: [{ type: i0.Input, args: [{ isSignal: true, alias: "ghostLoadingIndicator", required: false }] }], selectionType: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectionType", required: false }] }], reorderable: [{ type: i0.Input, args: [{ isSignal: true, alias: "reorderable", required: false }] }], swapColumns: [{ type: i0.Input, args: [{ isSignal: true, alias: "swapColumns", required: false }] }], sortType: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortType", required: false }] }], sorts: [{ type: i0.Input, args: [{ isSignal: true, alias: "sorts", required: false }] }, { type: i0.Output, args: ["sortsChange"] }], cssClasses: [{ type: i0.Input, args: [{ isSignal: true, alias: "cssClasses", required: false }] }], messages: [{ type: i0.Input, args: [{ isSignal: true, alias: "messages", required: false }] }], rowClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowClass", required: false }] }], selectCheck: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectCheck", required: false }] }], displayCheck: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayCheck", required: false }] }], groupExpansionDefault: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupExpansionDefault", required: false }] }], trackByProp: [{ type: i0.Input, args: [{ isSignal: true, alias: "trackByProp", required: false }] }], selectAllRowsOnPage: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectAllRowsOnPage", required: false }] }], virtualization: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualization", required: false }] }], treeFromRelation: [{ type: i0.Input, args: [{ isSignal: true, alias: "treeFromRelation", required: false }] }], treeToRelation: [{ type: i0.Input, args: [{ isSignal: true, alias: "treeToRelation", required: false }] }], summaryRow: [{ type: i0.Input, args: [{ isSignal: true, alias: "summaryRow", required: false }] }], summaryHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "summaryHeight", required: false }] }], summaryPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "summaryPosition", required: false }] }], disableRowCheck: [{ type: i0.Input, args: [{ isSignal: true, alias: "disableRowCheck", required: false }] }], rowDraggable: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowDraggable", required: false }] }], enableClearingSortState: [{ type: i0.Input, args: [{ isSignal: true, alias: "enableClearingSortState", required: false }] }], scroll: [{ type: i0.Output, args: ["scroll"] }], activate: [{ type: i0.Output, args: ["activate"] }], select: [{ type: i0.Output, args: ["select"] }], sort: [{ type: i0.Output, args: ["sort"] }], page: [{ type: i0.Output, args: ["page"] }], reorder: [{ type: i0.Output, args: ["reorder"] }], resize: [{ type: i0.Output, args: ["resize"] }], tableContextmenu: [{ type: i0.Output, args: ["tableContextmenu"] }], treeAction: [{ type: i0.Output, args: ["treeAction"] }], rowDragEvents: [{ type: i0.Output, args: ["rowDragEvents"] }], columnTemplates: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => DataTableColumnDirective), { isSignal: true }] }], rowDetail: [{
                type: ContentChild,
                args: [DatatableRowDetailDirective]
            }], groupHeader: [{
                type: ContentChild,
                args: [DatatableGroupHeaderDirective]
            }], _footer: [{ type: i0.ContentChild, args: [i0.forwardRef(() => DatatableFooterDirective), { isSignal: true }] }], _bodyComponent: [{ type: i0.ViewChild, args: [i0.forwardRef(() => DataTableBodyComponent), { isSignal: true }] }], _headerElement: [{ type: i0.ViewChild, args: [i0.forwardRef(() => DataTableHeaderComponent), { ...{
                            read: (ElementRef)
                        }, isSignal: true }] }], _bodyElement: [{ type: i0.ViewChild, args: [i0.forwardRef(() => DataTableBodyComponent), { ...{
                            read: (ElementRef)
                        }, isSignal: true }] }], _rowDefTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => DatatableRowDefDirective), { ...{
                            read: TemplateRef
                        }, isSignal: true }] }], _footerComponent: [{ type: i0.ViewChild, args: [i0.forwardRef(() => DataTableFooterComponent), { isSignal: true }] }], rowIdentity: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowIdentity", required: false }] }], onWindowResize: [{
                type: HostListener,
                args: ['window:resize']
            }] } });

/**
 * Row Disable Directive
 * Use this to disable/enable all children elements
 * Usage:
 *  To disable
 * 		<div [disabled]="true" disable-row >
 * 		</div>
 *  To enable
 *  	<div [disabled]="false" disable-row >
 * 		</div>
 */
class DisableRowDirective {
    constructor() {
        this.elementRef = inject(ElementRef);
        this.disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled", transform: booleanAttribute }] : [{
                transform: booleanAttribute
            }]));
        effect(() => {
            if (this.disabled()) {
                this.disableAllElements();
            }
        });
    }
    disableAllElements() {
        const hostElement = this.elementRef?.nativeElement;
        if (!hostElement) {
            return;
        }
        Array.from(hostElement.querySelectorAll('*')).forEach(child => {
            child.setAttribute('disabled', '');
        });
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DisableRowDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
    static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.3.15", type: DisableRowDirective, isStandalone: true, selector: "[disable-row]", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DisableRowDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[disable-row]'
                }]
        }], ctorParameters: () => [], propDecorators: { disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }] } });

class NgxDatatableModule {
    /**
     * Configure global configuration via INgxDatatableConfig
     * @param configuration
     */
    static forRoot(configuration) {
        return {
            ngModule: NgxDatatableModule,
            providers: [providedNgxDatatableConfig(configuration)]
        };
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NgxDatatableModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
    static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.15", ngImport: i0, type: NgxDatatableModule, imports: [DataTableFooterTemplateDirective,
            DatatableComponent,
            DataTableColumnDirective,
            DatatableRowDetailDirective,
            DatatableGroupHeaderDirective,
            DatatableRowDetailTemplateDirective,
            DataTableColumnHeaderDirective,
            DataTableColumnCellDirective,
            DataTableColumnGhostCellDirective,
            DataTableColumnCellTreeToggle,
            DatatableFooterDirective,
            DatatablePagerComponent,
            DatatableGroupHeaderTemplateDirective,
            DisableRowDirective,
            DatatableRowDefComponent,
            DatatableRowDefDirective], exports: [DatatableComponent,
            DatatableRowDetailDirective,
            DatatableGroupHeaderDirective,
            DatatableRowDetailTemplateDirective,
            DataTableColumnDirective,
            DataTableColumnHeaderDirective,
            DataTableColumnCellDirective,
            DataTableColumnGhostCellDirective,
            DataTableColumnCellTreeToggle,
            DataTableFooterTemplateDirective,
            DatatableFooterDirective,
            DatatablePagerComponent,
            DatatableGroupHeaderTemplateDirective,
            DisableRowDirective,
            DatatableRowDefComponent,
            DatatableRowDefDirective] }); }
    static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NgxDatatableModule }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NgxDatatableModule, decorators: [{
            type: NgModule,
            args: [{
                    imports: [
                        DataTableFooterTemplateDirective,
                        DatatableComponent,
                        DataTableColumnDirective,
                        DatatableRowDetailDirective,
                        DatatableGroupHeaderDirective,
                        DatatableRowDetailTemplateDirective,
                        DataTableColumnHeaderDirective,
                        DataTableColumnCellDirective,
                        DataTableColumnGhostCellDirective,
                        DataTableColumnCellTreeToggle,
                        DatatableFooterDirective,
                        DatatablePagerComponent,
                        DatatableGroupHeaderTemplateDirective,
                        DisableRowDirective,
                        DatatableRowDefComponent,
                        DatatableRowDefDirective
                    ],
                    exports: [
                        DatatableComponent,
                        DatatableRowDetailDirective,
                        DatatableGroupHeaderDirective,
                        DatatableRowDetailTemplateDirective,
                        DataTableColumnDirective,
                        DataTableColumnHeaderDirective,
                        DataTableColumnCellDirective,
                        DataTableColumnGhostCellDirective,
                        DataTableColumnCellTreeToggle,
                        DataTableFooterTemplateDirective,
                        DatatableFooterDirective,
                        DatatablePagerComponent,
                        DatatableGroupHeaderTemplateDirective,
                        DisableRowDirective,
                        DatatableRowDefComponent,
                        DatatableRowDefDirective
                    ]
                }]
        }] });

/*
 * Public API Surface of ngx-datatable
 */
// components

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

export { ColumnMode, ContextmenuType, DataTableColumnCellDirective, DataTableColumnCellTreeToggle, DataTableColumnDirective, DataTableColumnGhostCellDirective, DataTableColumnHeaderDirective, DataTableFooterTemplateDirective, DatatableComponent, DatatableFooterDirective, DatatableGroupHeaderDirective, DatatableGroupHeaderTemplateDirective, DatatablePagerComponent, DatatableRowDefComponent, DatatableRowDefDirective, DatatableRowDefInternalDirective, DatatableRowDetailDirective, DatatableRowDetailTemplateDirective, DisableRowDirective, NgxDatatableModule, SelectionType, SortDirection, SortType, providedNgxDatatableConfig };
//# sourceMappingURL=siemens-ngx-datatable.mjs.map