UNPKG

@siemens/ngx-datatable

Version:

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

5,832 lines 330 kB
import * as i0 from '@angular/core';
import { Directive, input, contentChild, TemplateRef, computed, output, inject, ElementRef, InjectionToken, booleanAttribute, effect, Component, ViewContainerRef, Injector, numberAttribute, DOCUMENT, Service, signal, ChangeDetectionStrategy, KeyValueDiffers, HostListener, linkedSignal, ChangeDetectorRef, viewChildren, DestroyRef, model, viewChild, untracked, Input, IterableDiffers, contentChildren, afterNextRender, ContentChild, NgModule } from '@angular/core';
import { NgTemplateOutlet } from '@angular/common';

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

class DatatableGroupHeaderDirective {
    /**
     * Row height is required when virtual scroll is enabled.
     */
    rowHeight = input(0, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "rowHeight" }] : /* istanbul ignore next */ []));
    /**
     * Show checkbox at group header to select all rows of the group.
     */
    checkboxable = input(false, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "checkboxable" }] : /* istanbul ignore next */ []));
    _templateInput = input(undefined, { ...(ngDevMode ? { debugName: "_templateInput" } : /* istanbul ignore next */ {}), alias: 'template' });
    _templateQuery = contentChild(DatatableGroupHeaderTemplateDirective, { ...(ngDevMode ? { debugName: "_templateQuery" } : /* istanbul ignore next */ {}), read: TemplateRef });
    template = computed(() => this._templateInput() ?? this._templateQuery() ?? null, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "template" }] : /* istanbul ignore next */ []));
    /**
     * Track toggling of group visibility
     */
    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 ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: DatatableGroupHeaderDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "22.0.8", 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: "22.0.8", 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"] }] } });

/**
 * Renders the datatable's normal row inside a custom row wrapper declared with
 * {@link DatatableRowDefDirective}. Use this as the root content of the
 * `ng-template` and apply row-level directives or classes to it.
 *
 * @example
 * ```html
 * <ngx-datatable>
 *   <ng-template rowDef>
 *     <datatable-row-def appCustomRowDirective class="custom-row" />
 *   </ng-template>
 * </ngx-datatable>
 * ```
 */
class DatatableRowDefComponent {
    host = inject(ElementRef).nativeElement;
    rowDef = inject(ROW_DEF_TOKEN);
    rowContext = {
        ...this.rowDef.rowDefInternal(),
        disabled: this.rowDef.rowDefInternalDisabled()
    };
    /**
     * When `true`, clones of this row get the measured column widths stamped onto them.
     * The clone is detached from the table grid, it has no parent tracks to inherit.
     */
    preserveColumnWidthsOnClone = input(false, { ...(ngDevMode ? { debugName: "preserveColumnWidthsOnClone" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
    constructor() {
        effect(onCleanup => {
            if (!this.preserveColumnWidthsOnClone()) {
                return;
            }
            const originalCloneNode = this.host.cloneNode;
            this.host.cloneNode = (deep) => {
                const clone = originalCloneNode.call(this.host, deep);
                const gridTemplateColumns = this.measureGridTemplateColumns();
                if (gridTemplateColumns) {
                    clone.style.gridTemplateColumns = gridTemplateColumns;
                }
                return clone;
            };
            onCleanup(() => (this.host.cloneNode = originalCloneNode));
        });
    }
    measureGridTemplateColumns() {
        const cells = this.host.querySelectorAll('datatable-body-cell');
        return Array.from(cells)
            .map(cell => `${cell.getBoundingClientRect().width}px`)
            .join(' ');
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: DatatableRowDefComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: DatatableRowDefComponent, isStandalone: true, selector: "datatable-row-def", inputs: { preserveColumnWidthsOnClone: { classPropertyName: "preserveColumnWidthsOnClone", publicName: "preserveColumnWidthsOnClone", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `@if (rowDef.rowDefInternal().rowTemplate) {
    <ng-container
      [ngTemplateOutlet]="rowDef.rowDefInternal().rowTemplate"
      [ngTemplateOutletContext]="rowContext"
    />
  }`, isInline: true, styles: [":host{display:grid;grid-template-columns:subgrid;grid-column:1/-1}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", 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"
    />
  }`, styles: [":host{display:grid;grid-template-columns:subgrid;grid-column:1/-1}\n"] }]
        }], ctorParameters: () => [], propDecorators: { preserveColumnWidthsOnClone: [{ type: i0.Input, args: [{ isSignal: true, alias: "preserveColumnWidthsOnClone", required: false }] }] } });
/**
 * Marks an `ng-template` as the custom wrapper for each rendered table row.
 *
 * The template must contain a {@link DatatableRowDefComponent}, which renders
 * the table's regular row inside the wrapper. Apply row-level directives or
 * classes to that component.
 *
 * @example
 * ```html
 * <ngx-datatable>
 *   <ng-template rowDef>
 *     <datatable-row-def appCustomRowDirective class="custom-row" />
 *   </ng-template>
 * </ngx-datatable>
 * ```
 */
class DatatableRowDefDirective {
    static ngTemplateContextGuard(_dir, ctx) {
        return true;
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: DatatableRowDefDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.8", type: DatatableRowDefDirective, isStandalone: true, selector: "[rowDef]", ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: DatatableRowDefDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[rowDef]'
                }]
        }] });
/**
 * @internal To be used internally by ngx-datatable.
 */
class DatatableRowDefInternalDirective {
    vc = inject(ViewContainerRef);
    rowDefInternal = input.required(/* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "rowDefInternal" }] : /* istanbul ignore next */ []));
    rowDefInternalDisabled = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "rowDefInternalDisabled" }] : /* istanbul ignore next */ []));
    ngOnInit() {
        this.vc.createEmbeddedView(this.rowDefInternal().template, {
            ...this.rowDefInternal()
        }, {
            injector: Injector.create({
                providers: [
                    {
                        provide: ROW_DEF_TOKEN,
                        useValue: this
                    }
                ]
            })
        });
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: DatatableRowDefInternalDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.8", 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: "22.0.8", 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');

/**
 * Directive that provides custom content for the summary row.
 * When applied, the summary row renders the provided template instead of
 * computing per-column aggregate values, enabling use cases like summary action bars.
 *
 * The row is rendered with sticky positioning at the top of the datatable body.
 *
 * @example
 * ```html
 * <ngx-datatable [rows]="rows" selectionType="checkbox" [(selected)]="selected">
 *   @if (selected.length) {
 *     <ng-template ngx-datatable-summary-row>
 *       <span>{{ selected.length }} selected</span>
 *       <button (click)="delete()">Delete</button>
 *     </ng-template>
 *   }
 * </ngx-datatable>
 * ```
 */
class DatatableSummaryRowDirective {
    template = inject((TemplateRef));
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: DatatableSummaryRowDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.8", type: DatatableSummaryRowDirective, isStandalone: true, selector: "[ngx-datatable-summary-row]", ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: DatatableSummaryRowDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[ngx-datatable-summary-row]'
                }]
        }] });

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

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

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

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

class DataTableColumnDirective {
    /**
     * Column label. When omitted, the property value is used and decamelized.
     */
    name = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "name" }] : /* istanbul ignore next */ []));
    /**
     * Property used to bind row values. When omitted, the name is converted to camel case.
     */
    prop = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "prop" }] : /* istanbul ignore next */ []));
    bindAsUnsafeHtml = input(false, { ...(ngDevMode ? { debugName: "bindAsUnsafeHtml" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
    /**
     * Whether the column is frozen to the left. Default value: `false`.
     */
    frozenLeft = input(false, { ...(ngDevMode ? { debugName: "frozenLeft" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
    /**
     * Whether the column is frozen to the right. Default value: `false`.
     */
    frozenRight = input(false, { ...(ngDevMode ? { debugName: "frozenRight" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
    /**
     * Grow factor relative to other columns. Available extra width is distributed
     * proportionally according to all columns' `flexGrow` values. Default value: `0`.
     */
    flexGrow = input(undefined, { ...(ngDevMode ? { debugName: "flexGrow" } : /* istanbul ignore next */ {}), transform: numberAttribute });
    /**
     * Whether the user can manually resize the column. Default value: `true`.
     */
    resizeable = input(undefined, { ...(ngDevMode ? { debugName: "resizeable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
    /**
     * Custom client-side sort comparator. It receives cell values and their
     * respective rows; a standard two-argument comparison function is also supported.
     */
    comparator = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "comparator" }] : /* istanbul ignore next */ []));
    /**
     * Custom pipe used to transform cell values.
     */
    pipe = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "pipe" }] : /* istanbul ignore next */ []));
    /**
     * Whether row values can be sorted by this column. Default value: `true`.
     */
    sortable = input(undefined, { ...(ngDevMode ? { debugName: "sortable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
    /**
     * Whether the column can be dragged to reorder it. Default value: `true`.
     */
    draggable = input(undefined, { ...(ngDevMode ? { debugName: "draggable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
    /**
     * Whether the column can automatically resize to fill extra space. Default value: `true`.
     */
    canAutoResize = input(undefined, { ...(ngDevMode ? { debugName: "canAutoResize" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
    /**
     * Minimum column width in pixels.
     */
    minWidth = input(undefined, { ...(ngDevMode ? { debugName: "minWidth" } : /* istanbul ignore next */ {}), transform: numberAttribute });
    /**
     * Default column width in pixels. Default value: `150`.
     */
    width = input(undefined, { ...(ngDevMode ? { debugName: "width" } : /* istanbul ignore next */ {}), transform: numberAttribute });
    /**
     * Maximum column width in pixels.
     */
    maxWidth = input(undefined, { ...(ngDevMode ? { debugName: "maxWidth" } : /* istanbul ignore next */ {}), transform: numberAttribute });
    /**
     * Whether the column displays a selection checkbox. Only applies when selection mode is `checkbox`.
     */
    checkboxable = input(false, { ...(ngDevMode ? { debugName: "checkboxable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
    /**
     * Whether the header displays a selection checkbox. Only applies when selection mode is `checkbox`.
     */
    headerCheckboxable = input(false, { ...(ngDevMode ? { debugName: "headerCheckboxable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
    /**
     * CSS classes to apply to the header cell.
     */
    headerClass = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "headerClass" }] : /* istanbul ignore next */ []));
    /**
     * CSS classes to apply to the body cell.
     */
    cellClass = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "cellClass" }] : /* istanbul ignore next */ []));
    isTreeColumn = input(false, { ...(ngDevMode ? { debugName: "isTreeColumn" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
    treeLevelIndent = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "treeLevelIndent" }] : /* istanbul ignore next */ []));
    summaryFunc = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "summaryFunc" }] : /* istanbul ignore next */ []));
    summaryTemplate = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "summaryTemplate" }] : /* istanbul ignore next */ []));
    /**
     * Template used to render body cells.
     */
    cellTemplateInput = input(undefined, { ...(ngDevMode ? { debugName: "cellTemplateInput" } : /* istanbul ignore next */ {}), alias: 'cellTemplate' });
    cellTemplateQuery = contentChild(DataTableColumnCellDirective, { ...(ngDevMode ? { debugName: "cellTemplateQuery" } : /* istanbul ignore next */ {}), read: TemplateRef });
    /**
     * Template used to render header cells.
     */
    headerTemplateInput = input(undefined, { ...(ngDevMode ? { debugName: "headerTemplateInput" } : /* istanbul ignore next */ {}), alias: 'headerTemplate' });
    headerTemplateQuery = contentChild(DataTableColumnHeaderDirective, { ...(ngDevMode ? { debugName: "headerTemplateQuery" } : /* istanbul ignore next */ {}), read: TemplateRef });
    treeToggleTemplateInput = input(undefined, { ...(ngDevMode ? { debugName: "treeToggleTemplateInput" } : /* istanbul ignore next */ {}), alias: 'treeToggleTemplate' });
    treeToggleTemplateQuery = contentChild(DataTableColumnCellTreeToggle, { ...(ngDevMode ? { debugName: "treeToggleTemplateQuery" } : /* istanbul ignore next */ {}), read: TemplateRef });
    ghostCellTemplateInput = input(undefined, { ...(ngDevMode ? { debugName: "ghostCellTemplateInput" } : /* istanbul ignore next */ {}), alias: 'ghostCellTemplate' });
    ghostCellTemplateQuery = contentChild(DataTableColumnGhostCellDirective, { ...(ngDevMode ? { debugName: "ghostCellTemplateQuery" } : /* istanbul ignore next */ {}), read: TemplateRef });
    /**
     * Computed property that returns the column configuration as a TableColumn object
     */
    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()
    }), /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "column" }] : /* istanbul ignore next */ []));
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: DataTableColumnDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "22.0.8", 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: "22.0.8", 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 }] }] } });

/**
 * Marks the `role="table"` css-grid as the single scroll container that owns
 * both the horizontal and vertical scroll. Descendant components (e.g. the
 * scroller) and the datatable interact with the container through these methods
 * instead of reaching for the native element.
 */
class ScrollContainerDirective {
    element = inject(ElementRef).nativeElement;
    /** Current vertical scroll offset of the container. */
    get scrollTop() {
        return this.element.scrollTop;
    }
    /** Whether the container's content overflows it vertically. */
    get verticalScrollVisible() {
        return this.element.scrollHeight > this.element.clientHeight;
    }
    setScrollTop(value) {
        this.element.scrollTop = value;
    }
    scrollTo(top, options) {
        this.element.scrollTo({ top, behavior: options?.behavior });
    }
    /** Subscribes to scroll events, returning a function that unsubscribes. */
    listenToScroll(listener) {
        this.element.addEventListener('scroll', listener, { passive: true });
        return () => this.element.removeEventListener('scroll', listener);
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: ScrollContainerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.8", type: ScrollContainerDirective, isStandalone: true, selector: "[datatableScrollContainer]", ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: ScrollContainerDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[datatableScrollContainer]'
                }]
        }] });

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 {
    document = inject(DOCUMENT);
    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 ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: ScrollbarHelper, deps: [], target: i0.ɵɵFactoryTarget.Service });
    static ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.0.8", ngImport: i0, type: ScrollbarHelper });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: ScrollbarHelper, decorators: [{
            type: Service
        }] });

/**
 * 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;
};
/**
 * Builds the `grid-template-columns` value for the combined css-grid.
 * Produces one track per column, sized by the column's current width, in the
 * pinned render order (left, center, right). Header and body rows share this
 * single definition so every cell aligns to the same column tracks.
 *
 * `minWidth`/`maxWidth` are baked into the track via `clamp()`/`min()`/`max()`
 * so the constraints are enforced once on the shared grid instead of per cell.
 */
const gridColumnTemplate = (cols) => {
    return cols
        .flatMap(group => group.columns)
        .map(column => gridColumnTrack(column))
        .join(' ');
};
const gridColumnTrack = (column) => {
    const width = `${column.width()}px`;
    const min = column.minWidth ? `${column.minWidth}px` : undefined;
    const max = column.maxWidth ? `${column.maxWidth}px` : undefined;
    if (min && max) {
        return `clamp(${min}, ${width}, ${max})`;
    }
    if (min) {
        return `max(${min}, ${width})`;
    }
    if (max) {
        return `min(${max}, ${width})`;
    }
    return width;
};
const columnsByPinArr = (val) => {
    const colsByPin = columnsByPin(val);
    return [
        { type: 'left', columns: colsByPin.left },
        { type: 'center', columns: colsByPin.center },
        { type: 'right', columns: colsByPin.right }
    ];
};

/**
 * 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 === 'single') {
        if (current === 'asc') {
            return 'desc';
        }
        else {
            return 'asc';
        }
    }
    else {
        if (!current) {
            return 'asc';
        }
        else if (current === 'asc') {
            return 'desc';
        }
        else if (current === '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;
        // SortDirs may contain columns that are not sortable, so compareFn would be undefined. In that case just return a comparator that returns 0.
        const compareFn = cols[dir.prop] ?? (() => 0);
        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 !== '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(),
            $$originalColumn: column,
            $$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: signal(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
    });
};
const toPublicColumn = (column) => {
    return {
        ...column.$$originalColumn,
        checkboxable: column.checkboxable,
        frozenLeft: column.frozenLeft,
        frozenRight: column.frozenRight,
        flexGrow: column.flexGrow,
        minWidth: column.minWidth,
        maxWidth: column.maxWidth,
        width: column.width(),
        resizeable: column.resizeable,
        comparator: column.comparator,
        pipe: column.pipe,
        sortable: column.sortable,
        draggable: column.draggable,
        canAutoResize: column.canAutoResize,
        name: column.name,
        prop: column.prop,
        bindAsUnsafeHtml: column.bindAsUnsafeHtml,
        cellTemplate: column.cellTemplate,
        ghostCellTemplate: column.ghostCellTemplate,
        headerTemplate: column.headerTemplate,
        treeToggleTemplate: column.treeToggleTemplate,
        cellClass: column.cellClass,
        headerClass: column.headerClass,
        headerCheckboxable: column.headerCheckboxable,
        isTreeColumn: column.isTreeColumn,
        treeLevelIndent: column.treeLevelIndent,
        summaryFunc: column.summaryFunc,
        summaryTemplate: column.summaryTemplate
    };
};

/**
 * 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.set(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 ?? 0) * widthPerFlexPoint;
                if (column.minWidth !== undefined && newWidth < column.minWidth) {
                    remainingWidth += newWidth - column.minWidth;
                    column.width.set(column.minWidth);
                    hasMinWidth[column.prop] = true;
                }
                else {
                    column.width.set(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.update(value => value + 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;
    let exceedsWindow;
    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) {
                column.width.update(value => value || defaultColWidth);
            }
            else {
                const newSize = (column.width() || defaultColWidth) + additionWidthPerColumn;
                if (column.minWidth && newSize < column.minWidth) {
                    column.width.set(column.minWidth);
                    columnsProcessed.push(column);
                }
                else if (column.maxWidth && newSize > column.maxWidth) {
                    column.width.set(column.maxWidth);
                    columnsProcessed.push(column);
                }
                else {
                    column.width.set(newSize);
                }
            }
            column.width.update(value => Math.max(0, value));
        }
        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) {
        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');

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: Cyclic relationships are broken by treating one node in the cycle as a root
 *
 * 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 resolved = new Set();
        const resolveLevel = (node, visited) => {
            if (resolved.has(node)) {
                return node.row.level;
            }
            if (visited.has(node)) {
                return Infinity;
            }
            visited.add(node);
            const parent = uniqIDs.get(from(node.row));
            if (parent && parent !== node) {
                const parentLevel = resolveLevel(parent, visited);
                if (parentLevel !== Infinity) {
                    node.row.level = parentLevel + 1;
                }
                else {
                    node.row.level = 0;
                }
            }
            else {
                node.row.level = 0;
            }
            visited.delete(node);
            resolved.add(node);
            return node.row.level;
        };
        for (const node of treeRows) {
            if (!resolved.has(node)) {
                resolveLevel(node, new Set());
            }
        }
        for (const node of treeRows) {
            const parent = uniqIDs.get(from(node.row));
            if (parent && parent !== node && node.row.level > 0) {
                node.parent = parent;
                parent.children.push(node);
            }
        }
        const rootNodes = treeRows.filter(n => !n.parent);
        return rootNodes.flatMap(child => child.flatten());
    }
    else {
        return rows;
    }
};
class TreeNode {
    row;
    parent;
    children;
    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 expandToRow = (targetRow, rows, from, to) => {
    if (from && to) {
        const uniqIDs = new Map(rows.filter(row => !!row).map(node => [to(node), node]));
        const visitedRowIds = new Set();
        let currentRow = targetRow;
        while (currentRow) {
            const currentRowId = to(currentRow);
            if (visitedRowIds.has(currentRowId)) {
                // cycle detected, abort to avoid an infinite loop
                break;
            }
            visitedRowIds.add(currentRowId);
            if (currentRow.treeStatus === 'collapsed') {
                currentRow.treeStatus = 'expanded';
            }
            currentRow = uniqIDs.get(from(currentRow));
        }
    }
};

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 {
    /**
     * 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.
     */
    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 = (rows, index, prevIndex) => {
    const reverse = index < prevIndex;
    const rangeRows = [];
    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;
        if (reverse) {
            range = {
                start: index,
                end: prevIndex
            };
        }
        else {
            range = {
                start: prevIndex,
                end: index + 1
            };
        }
        if ((reverse && lesser) || (!reverse && greater)) {
            if (i >= range.start && i <= range.end && row) {
                rangeRows.push(row);
            }
        }
    }
    return rangeRows;
};

/** @internal */
class DatatableConfiguration {
    datatable;
    globalConfiguration;
    configuration = computed(() => {
        const configuration = this.globalConfiguration;
        return {
            ...configuration,
            defaultColumnWidth: configuration.defaultColumnWidth ?? 150,
            rowHeight: this.datatable.rowHeight(),
            headerHeight: this.datatable.headerHeight(),
            footerHeight: this.datatable.footerHeight() ?? 0,
            cssClasses: {
                sortAscending: 'datatable-icon-up',
                sortDescending: 'datatable-icon-down',
                sortUnset: 'datatable-icon-sort-unset',
                pagerLeftArrow: 'datatable-icon-left',
                pagerRightArrow: 'datatable-icon-right',
                pagerPrevious: 'datatable-icon-prev',
                pagerNext: 'datatable-icon-skip',
                treeStatusLoading: 'icon datatable-icon-collapse',
                treeStatusExpanded: 'icon datatable-icon-down',
                treeStatusCollapsed: 'icon datatable-icon-up',
                ...configuration.cssClasses,
                ...this.datatable.cssClasses()
            },
            messages: {
                emptyMessage: 'No data to display',
                totalMessage: 'total',
                selectedMessage: 'selected',
                ariaFirstPageMessage: 'go to first page',
                ariaPageNMessage: 'page',
                ariaPreviousPageMessage: 'go to previous page',
                ariaNextPageMessage: 'go to next page',
                ariaLastPageMessage: 'go to last page',
                ariaRowCheckboxMessage: 'Select row',
                ariaHeaderCheckboxMessage: 'Select all rows',
                ariaGroupHeaderCheckboxMessage: 'Select row group',
                ariaLoadingMessage: 'Loading',
                ...configuration.messages,
                ...this.datatable.messages()
            }
        };
    }, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "configuration" }] : /* istanbul ignore next */ []));
    constructor(datatable, globalConfiguration) {
        this.datatable = datatable;
        this.globalConfiguration = globalConfiguration;
    }
}

class DataTableGroupWrapperComponent {
    configuration = inject(DatatableConfiguration).configuration;
    groupHeader = input.required(/* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "groupHeader" }] : /* istanbul ignore next */ []));
    groupHeaderRowHeight = input.required(/* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "groupHeaderRowHeight" }] : /* istanbul ignore next */ []));
    group = input.required(/* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "group" }] : /* istanbul ignore next */ []));
    groupedRows = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "groupedRows" }] : /* istanbul ignore next */ []));
    allColumnsColspan = input.required(/* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "allColumnsColspan" }] : /* istanbul ignore next */ []));
    selected = input.required(/* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "selected" }] : /* istanbul ignore next */ []));
    disabled = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "disabled" }] : /* istanbul ignore next */ []));
    rowIndex = input.required(/* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "rowIndex" }] : /* istanbul ignore next */ []));
    expanded = input(false, { ...(ngDevMode ? { debugName: "expanded" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
    groupSelectedChange = output();
    context = computed(() => {
        return {
            group: this.group(),
            expanded: this.expanded(),
            rowIndex: this.rowIndex()
        };
    }, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "context" }] : /* istanbul ignore next */ []));
    selectedRowsOfGroup = computed(() => {
        const groupValue = this.group().value;
        return this.selected().filter(row => groupValue.includes(row));
    }, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "selectedRowsOfGroup" }] : /* istanbul ignore next */ []));
    checked = computed(() => this.selectedRowsOfGroup().length === this.group().value.length, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "checked" }] : /* istanbul ignore next */ []));
    indeterminate = computed(() => this.selectedRowsOfGroup().length > 0 && !this.checked(), /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "indeterminate" }] : /* istanbul ignore next */ []));
    onCheckboxChange(groupSelected) {
        this.groupSelectedChange.emit(groupSelected);
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: DataTableGroupWrapperComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: DataTableGroupWrapperComponent, isStandalone: true, selector: "datatable-group-wrapper", inputs: { 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 }, allColumnsColspan: { classPropertyName: "allColumnsColspan", publicName: "allColumnsColspan", isSignal: true, isRequired: true, 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 } }, outputs: { groupSelectedChange: "groupSelectedChange" }, host: { attributes: { "role": "presentation" }, classAttribute: "datatable-group-wrapper" }, ngImport: i0, template: `
    @let groupHeader = this.groupHeader();
    @if (groupHeader && groupHeader.template()) {
      <div role="row" class="datatable-group-header" [style.height.px]="groupHeaderRowHeight()">
        <div role="cell" class="datatable-group-cell" [attr.aria-colspan]="allColumnsColspan()">
          @if (groupHeader.checkboxable()) {
            <div>
              <label class="datatable-checkbox">
                <input
                  #select
                  type="checkbox"
                  [attr.aria-label]="configuration().messages.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:grid;grid-template-columns:subgrid;grid-column:1/-1}.datatable-group-header{grid-column:1/-1;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: "22.0.8", ngImport: i0, type: DataTableGroupWrapperComponent, decorators: [{
            type: Component,
            args: [{ selector: 'datatable-group-wrapper', imports: [NgTemplateOutlet], template: `
    @let groupHeader = this.groupHeader();
    @if (groupHeader && groupHeader.template()) {
      <div role="row" class="datatable-group-header" [style.height.px]="groupHeaderRowHeight()">
        <div role="cell" class="datatable-group-cell" [attr.aria-colspan]="allColumnsColspan()">
          @if (groupHeader.checkboxable()) {
            <div>
              <label class="datatable-checkbox">
                <input
                  #select
                  type="checkbox"
                  [attr.aria-label]="configuration().messages.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',
                        role: 'presentation'
                    }, styles: [":host{display:grid;grid-template-columns:subgrid;grid-column:1/-1}.datatable-group-header{grid-column:1/-1;inset-inline-start:0;position:sticky}\n"] }]
        }], propDecorators: { 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 }] }], allColumnsColspan: [{ type: i0.Input, args: [{ isSignal: true, alias: "allColumnsColspan", required: true }] }], 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 }] }], groupSelectedChange: [{ type: i0.Output, args: ["groupSelectedChange"] }] } });

class DataTableRowWrapperComponent {
    rowDiffer = inject(KeyValueDiffers).find({}).create();
    elementRef = inject(ElementRef);
    rowDetail = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "rowDetail" }] : /* istanbul ignore next */ []));
    detailRowHeightFn = input.required(/* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "detailRowHeightFn" }] : /* istanbul ignore next */ []));
    row = input.required(/* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "row" }] : /* istanbul ignore next */ []));
    disabled = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "disabled" }] : /* istanbul ignore next */ []));
    rowContextmenu = output();
    rowIndex = input.required(/* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "rowIndex" }] : /* istanbul ignore next */ []));
    expanded = input(false, { ...(ngDevMode ? { debugName: "expanded" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
    checkRowPropertyChanges = input(true, { ...(ngDevMode ? { debugName: "checkRowPropertyChanges" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
    detailsRowHeight = computed(() => this.detailRowHeightFn()(this.row(), this.rowIndex()), /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "detailsRowHeight" }] : /* istanbul ignore next */ []));
    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()
        };
    }, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "context" }] : /* istanbul ignore next */ []));
    // This counter will be incremented every time the row object is mutated.
    rowDiffedCount = signal(0, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "rowDiffedCount" }] : /* istanbul ignore next */ []));
    ngDoCheck() {
        if (!this.checkRowPropertyChanges()) {
            return;
        }
        const row = this.row();
        if (this.rowDiffer.diff(row)) {
            this.rowDiffedCount.update(count => count + 1);
        }
    }
    scrollIntoView(options) {
        this.elementRef.nativeElement.scrollIntoView({
            behavior: options?.behavior,
            block: options?.block ?? 'start'
        });
    }
    onContextmenu($event) {
        this.rowContextmenu.emit({ event: $event, row: this.row() });
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: DataTableRowWrapperComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: DataTableRowWrapperComponent, isStandalone: true, selector: "datatable-row-wrapper", inputs: { 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 }, checkRowPropertyChanges: { classPropertyName: "checkRowPropertyChanges", publicName: "checkRowPropertyChanges", isSignal: true, isRequired: false, 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:grid;grid-template-columns:subgrid;grid-column:1/-1}.datatable-row-detail{grid-column:1/-1;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: "22.0.8", 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:grid;grid-template-columns:subgrid;grid-column:1/-1}.datatable-row-detail{grid-column:1/-1;overflow-y:hidden}\n"] }]
        }], propDecorators: { 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 }] }], checkRowPropertyChanges: [{ type: i0.Input, args: [{ isSignal: true, alias: "checkRowPropertyChanges", required: false }] }], onContextmenu: [{
                type: HostListener,
                args: ['contextmenu', ['$event']]
            }] } });

class DataTableBodyCellComponent {
    _element = inject(ElementRef).nativeElement;
    configuration = inject(DatatableConfiguration).configuration;
    displayCheck = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "displayCheck" }] : /* istanbul ignore next */ []));
    disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
    group = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "group" }] : /* istanbul ignore next */ []));
    rowHeight = input(0, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "rowHeight" }] : /* istanbul ignore next */ []));
    isSelected = input(false, { ...(ngDevMode ? { debugName: "isSelected" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
    rowIndex = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "rowIndex" }] : /* istanbul ignore next */ []));
    column = input.required(/* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "column" }] : /* istanbul ignore next */ []));
    row = input.required(/* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "row" }] : /* istanbul ignore next */ []));
    treeStatus = input('collapsed', /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "treeStatus" }] : /* istanbul ignore next */ []));
    expanded = input(false, { ...(ngDevMode ? { debugName: "expanded" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
    activate = output();
    treeAction = output();
    publicColumn = computed(() => toPublicColumn(this.column()), /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "publicColumn" }] : /* istanbul ignore next */ []));
    columnCssClasses = computed(() => {
        const column = this.column();
        if (!column.cellClass) {
            return [];
        }
        if (typeof column.cellClass === 'string') {
            return column.cellClass;
        }
        return column.cellClass({
            row: this.row(),
            group: this.group(),
            column: this.publicColumn(),
            value: this.value(),
            rowHeight: this.rowHeight()
        });
    }, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "columnCssClasses" }] : /* istanbul ignore next */ []));
    sanitizedValue = computed(() => {
        const value = this.value();
        return value !== null && value !== undefined ? this.stripHtml(value) : value;
    }, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "sanitizedValue" }] : /* istanbul ignore next */ []));
    value = linkedSignal(() => this.getComputedValue(), /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
    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.publicColumn(),
            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()
        };
    }, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "cellContext" }] : /* istanbul ignore next */ []));
    isFocused = signal(false, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "isFocused" }] : /* istanbul ignore next */ []));
    ngDoCheck() {
        const value = this.getComputedValue();
        if (value !== this.value()) {
            this.value.set(value);
        }
    }
    focus() {
        this._element.focus({ preventScroll: true });
    }
    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.publicColumn(),
            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.publicColumn(),
            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.publicColumn(),
                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.publicColumn(),
            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 ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: DataTableBodyCellComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", 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 }, 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()", "class.active": "isFocused() && !disabled()", "class.row-disabled": "disabled()" }, classAttribute: "datatable-body-cell" }, 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, publicColumn(), value()))) {
        <label class="datatable-checkbox">
          <input
            type="checkbox"
            [attr.aria-label]="configuration().messages.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]="configuration().cssClasses.treeStatusLoading"></i>
              }
              @if (treeStatus === 'collapsed') {
                <i [class]="configuration().cssClasses.treeStatusCollapsed"></i>
              }
              @if (treeStatus === 'expanded' || treeStatus === 'disabled') {
                <i [class]="configuration().cssClasses.treeStatusExpanded"></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;min-inline-size:0;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: "22.0.8", 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, publicColumn(), value()))) {
        <label class="datatable-checkbox">
          <input
            type="checkbox"
            [attr.aria-label]="configuration().messages.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]="configuration().cssClasses.treeStatusLoading"></i>
              }
              @if (treeStatus === 'collapsed') {
                <i [class]="configuration().cssClasses.treeStatusCollapsed"></i>
              }
              @if (treeStatus === 'expanded' || treeStatus === 'disabled') {
                <i [class]="configuration().cssClasses.treeStatusExpanded"></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: 'datatable-body-cell',
                        '[class]': 'columnCssClasses()',
                        '[class.active]': 'isFocused() && !disabled()',
                        '[class.row-disabled]': 'disabled()',
                        '(focus)': 'onFocus()',
                        '(blur)': 'onBlur()',
                        '(click)': 'onClick($event)',
                        '(dblclick)': 'onDblClick($event)',
                        '(keydown)': 'onKeyDown($event)'
                    }, styles: [":host{overflow-x:hidden;min-inline-size:0;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 }] }], 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 {
    cd = inject(ChangeDetectorRef);
    _element = inject(ElementRef).nativeElement;
    _rowDiffer = inject(KeyValueDiffers)
        .find({})
        .create();
    columns = input.required(/* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "columns" }] : /* istanbul ignore next */ []));
    expanded = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "expanded" }] : /* istanbul ignore next */ []));
    rowClass = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "rowClass" }] : /* istanbul ignore next */ []));
    row = input.required(/* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "row" }] : /* istanbul ignore next */ []));
    group = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "group" }] : /* istanbul ignore next */ []));
    isSelected = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "isSelected" }] : /* istanbul ignore next */ []));
    rowIndex = input.required(/* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "rowIndex" }] : /* istanbul ignore next */ []));
    displayCheck = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "displayCheck" }] : /* istanbul ignore next */ []));
    treeStatus = input('collapsed', /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "treeStatus" }] : /* istanbul ignore next */ []));
    disabled = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "disabled" }] : /* istanbul ignore next */ []));
    checkRowPropertyChanges = input(true, { ...(ngDevMode ? { debugName: "checkRowPropertyChanges" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
    cssClass = computed(() => {
        const rowClass = this.rowClass();
        return rowClass ? rowClass(this.row()) : [];
    }, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "cssClass" }] : /* istanbul ignore next */ []));
    rowHeight = input.required(/* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "rowHeight" }] : /* istanbul ignore next */ []));
    activate = output();
    treeAction = output();
    _columnGroupWidths = computed(() => {
        const colsByPin = columnsByPin(this.columns());
        return columnGroupWidths(colsByPin, this.columns());
    }, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "_columnGroupWidths" }] : /* istanbul ignore next */ []));
    _columnsByPin = computed(() => {
        return columnsByPinArr(this.columns());
    }, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "_columnsByPin" }] : /* istanbul ignore next */ []));
    cells = viewChildren(DataTableBodyCellComponent, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "cells" }] : /* istanbul ignore next */ []));
    ngDoCheck() {
        if (!this.checkRowPropertyChanges()) {
            return;
        }
        if (this._rowDiffer.diff(this.row())) {
            this.cd.markForCheck();
        }
    }
    onActivate(event, column) {
        this.activate.emit({
            ...event,
            rowElement: this._element,
            cellIndex: this.columns().indexOf(column),
            renderedCellIndex: this.cells().findIndex(cell => cell.column() === column)
        });
    }
    focus() {
        this._element.focus({ preventScroll: true });
    }
    focusCell(index) {
        this.cells()[index]?.focus();
    }
    scrollIntoView() {
        this._element.scrollIntoView({ block: 'nearest' });
    }
    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();
    }
    /** Returns the row index, or if in a group, the index within a group. */
    innerRowIndex = computed(() => {
        const rowIndex = this.rowIndex();
        return rowIndex?.indexInGroup ?? rowIndex?.index ?? 0;
    }, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "innerRowIndex" }] : /* istanbul ignore next */ []));
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: DataTableBodyRowComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", 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 }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, checkRowPropertyChanges: { classPropertyName: "checkRowPropertyChanges", publicName: "checkRowPropertyChanges", isSignal: true, isRequired: false, 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()" }, classAttribute: "datatable-body-row" }, viewQueries: [{ propertyName: "cells", predicate: DataTableBodyCellComponent, descendants: true, isSignal: true }], ngImport: i0, template: `
    @for (colGroup of _columnsByPin(); track colGroup.type) {
      @if (colGroup.columns.length) {
        <div
          class="datatable-row-group"
          [class]="'datatable-row-' + colGroup.type"
          [style.grid-column]="'span ' + colGroup.columns.length"
          [class.row-disabled]="disabled()"
        >
          @for (column of colGroup.columns; track column.$$id) {
            <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()"
              (activate)="onActivate($event, column)"
              (treeAction)="onTreeAction()"
            />
          }
        </div>
      }
    }
  `, isInline: true, styles: [":host{display:grid;grid-template-columns:subgrid;grid-column:1/-1;grid-template-rows:minmax(0,1fr);outline:none}:host-context(ngx-datatable.fixed-row) :host{white-space:nowrap}.datatable-row-group{display:grid;grid-template-columns:subgrid;grid-template-rows:subgrid;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", "expanded"], outputs: ["activate", "treeAction"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", 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-group"
          [class]="'datatable-row-' + colGroup.type"
          [style.grid-column]="'span ' + colGroup.columns.length"
          [class.row-disabled]="disabled()"
        >
          @for (column of colGroup.columns; track column.$$id) {
            <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()"
              (activate)="onActivate($event, column)"
              (treeAction)="onTreeAction()"
            />
          }
        </div>
      }
    }
  `, changeDetection: ChangeDetectionStrategy.OnPush, host: {
                        class: 'datatable-body-row',
                        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:grid;grid-template-columns:subgrid;grid-column:1/-1;grid-template-rows:minmax(0,1fr);outline:none}:host-context(ngx-datatable.fixed-row) :host{white-space:nowrap}.datatable-row-group{display:grid;grid-template-columns:subgrid;grid-template-rows:subgrid;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 }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], checkRowPropertyChanges: [{ type: i0.Input, args: [{ isSignal: true, alias: "checkRowPropertyChanges", required: false }] }], rowHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowHeight", required: true }] }], activate: [{ type: i0.Output, args: ["activate"] }], treeAction: [{ type: i0.Output, args: ["treeAction"] }], cells: [{ type: i0.ViewChildren, args: [i0.forwardRef(() => DataTableBodyCellComponent), { isSignal: true }] }], onKeyDown: [{
                type: HostListener,
                args: ['keydown', ['$event']]
            }], onMouseenter: [{
                type: HostListener,
                args: ['mouseenter', ['$event']]
            }] } });

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

class DataTableGhostLoaderComponent {
    columns = input.required(/* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "columns" }] : /* istanbul ignore next */ []));
    pageSize = input.required({ ...(ngDevMode ? { debugName: "pageSize" } : /* istanbul ignore next */ {}), transform: numberAttribute });
    rowHeight = input.required(/* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "rowHeight" }] : /* istanbul ignore next */ []));
    ghostBodyHeight = input(undefined, { ...(ngDevMode ? { debugName: "ghostBodyHeight" } : /* istanbul ignore next */ {}), transform: numberAttribute });
    ghostRows = computed(() => Array.from({ length: this.pageSize() }, (_, index) => index), /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "ghostRows" }] : /* istanbul ignore next */ []));
    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 ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: DataTableGhostLoaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", 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 ghostRows(); track item) {\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:100vi 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: "22.0.8", 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 ghostRows(); track item) {\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:100vi 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 {
    scrollContainer = inject(ScrollContainerDirective);
    scrollbarV = input(false, { ...(ngDevMode ? { debugName: "scrollbarV" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
    scrollbarH = input(false, { ...(ngDevMode ? { debugName: "scrollbarH" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
    scrollHeight = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "scrollHeight" }] : /* istanbul ignore next */ []));
    scroll = output();
    scrollYPos = 0;
    scrollXPos = 0;
    prevScrollYPos = 0;
    prevScrollXPos = 0;
    _removeScrollListener;
    get scrollTop() {
        return this.scrollContainer.scrollTop;
    }
    ngOnInit() {
        // manual bind so we don't always listen
        if (this.scrollbarV() || this.scrollbarH()) {
            this._removeScrollListener = this.scrollContainer.listenToScroll(this.onScrolled.bind(this));
        }
    }
    ngOnDestroy() {
        this._removeScrollListener?.();
        this._removeScrollListener = undefined;
    }
    setOffset(offsetY) {
        this.scrollContainer.setScrollTop(offsetY);
    }
    scrollTo(top, options) {
        this.scrollContainer.scrollTo(top, options);
    }
    onScrolled(event) {
        const dom = event.currentTarget;
        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 ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: ScrollerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.8", 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 } }, outputs: { scroll: "scroll" }, host: { properties: { "style.height.px": "scrollHeight()" }, classAttribute: "datatable-scroll" }, ngImport: i0, template: ` <ng-content /> `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", 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()'
                    }
                }]
        }], 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 }] }], 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 {
    rows = input.required(/* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "rows" }] : /* istanbul ignore next */ []));
    columns = input.required(/* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "columns" }] : /* istanbul ignore next */ []));
    allColumnsColspan = input.required(/* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "allColumnsColspan" }] : /* istanbul ignore next */ []));
    rowHeight = input.required(/* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "rowHeight" }] : /* istanbul ignore next */ []));
    template = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "template" }] : /* istanbul ignore next */ []));
    _internalColumns = computed(() => {
        return this.columns().map(col => ({
            ...col,
            cellTemplate: col.summaryTemplate
        }));
    }, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "_internalColumns" }] : /* istanbul ignore next */ []));
    summaryRow = computed(() => this.computeSummaryRowValues(), /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "summaryRow" }] : /* istanbul ignore next */ []));
    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 ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: DataTableSummaryRowComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", 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 }, allColumnsColspan: { classPropertyName: "allColumnsColspan", publicName: "allColumnsColspan", isSignal: true, isRequired: true, transformFunction: null }, rowHeight: { classPropertyName: "rowHeight", publicName: "rowHeight", isSignal: true, isRequired: true, transformFunction: null }, template: { classPropertyName: "template", publicName: "template", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "datatable-summary-row" }, ngImport: i0, template: `
    @let template = this.template();
    @if (template) {
      <div class="datatable-body-row" role="row" [style.height.px]="rowHeight()">
        <div class="datatable-body-cell" role="cell" [attr.aria-colspan]="allColumnsColspan()">
          <ng-container [ngTemplateOutlet]="template" />
        </div>
      </div>
    } @else {
      @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 }"
        />
      }
    }
  `, isInline: true, styles: [":host{display:grid;grid-template-columns:subgrid;grid-column:1/-1}:host.sticky{position:sticky;inset-block-start:0;z-index:2}.datatable-body-row{grid-column:1/-1}\n"], dependencies: [{ kind: "component", type: DataTableBodyRowComponent, selector: "datatable-body-row", inputs: ["columns", "expanded", "rowClass", "row", "group", "isSelected", "rowIndex", "displayCheck", "treeStatus", "disabled", "checkRowPropertyChanges", "rowHeight"], outputs: ["activate", "treeAction"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: DataTableSummaryRowComponent, decorators: [{
            type: Component,
            args: [{ selector: 'datatable-summary-row', imports: [DataTableBodyRowComponent, NgTemplateOutlet], template: `
    @let template = this.template();
    @if (template) {
      <div class="datatable-body-row" role="row" [style.height.px]="rowHeight()">
        <div class="datatable-body-cell" role="cell" [attr.aria-colspan]="allColumnsColspan()">
          <ng-container [ngTemplateOutlet]="template" />
        </div>
      </div>
    } @else {
      @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 }"
        />
      }
    }
  `, host: {
                        class: 'datatable-summary-row'
                    }, styles: [":host{display:grid;grid-template-columns:subgrid;grid-column:1/-1}:host.sticky{position:sticky;inset-block-start:0;z-index:2}.datatable-body-row{grid-column:1/-1}\n"] }]
        }], propDecorators: { rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: true }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], allColumnsColspan: [{ type: i0.Input, args: [{ isSignal: true, alias: "allColumnsColspan", required: true }] }], rowHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowHeight", required: true }] }], template: [{ type: i0.Input, args: [{ isSignal: true, alias: "template", required: false }] }] } });

class DataTableBodyComponent {
    cd = inject(ChangeDetectorRef);
    destroyRef = inject(DestroyRef);
    configuration = inject(DatatableConfiguration).configuration;
    rowDefTemplate = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "rowDefTemplate" }] : /* istanbul ignore next */ []));
    scrollbarV = input(false, { ...(ngDevMode ? { debugName: "scrollbarV" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
    scrollbarH = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "scrollbarH" }] : /* istanbul ignore next */ []));
    loadingIndicator = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "loadingIndicator" }] : /* istanbul ignore next */ []));
    ghostLoadingIndicator = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "ghostLoadingIndicator" }] : /* istanbul ignore next */ []));
    externalPaging = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "externalPaging" }] : /* istanbul ignore next */ []));
    offsetX = model.required(/* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "offsetX" }] : /* istanbul ignore next */ []));
    selectionType = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "selectionType" }] : /* istanbul ignore next */ []));
    selected = model([], /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "selected" }] : /* istanbul ignore next */ []));
    rowIdentity = input.required(/* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "rowIdentity" }] : /* istanbul ignore next */ []));
    rowDetail = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "rowDetail" }] : /* istanbul ignore next */ []));
    groupHeader = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "groupHeader" }] : /* istanbul ignore next */ []));
    selectCheck = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "selectCheck" }] : /* istanbul ignore next */ []));
    displayCheck = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "displayCheck" }] : /* istanbul ignore next */ []));
    trackByProp = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "trackByProp" }] : /* istanbul ignore next */ []));
    rowClass = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "rowClass" }] : /* istanbul ignore next */ []));
    groupedRows = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "groupedRows" }] : /* istanbul ignore next */ []));
    // TODO: Find a better way to handle default expansion state with signal input
    // eslint-disable-next-line @angular-eslint/prefer-signals
    groupExpansionDefault;
    virtualization = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "virtualization" }] : /* istanbul ignore next */ []));
    summaryRow = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "summaryRow" }] : /* istanbul ignore next */ []));
    summaryPosition = input.required(/* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "summaryPosition" }] : /* istanbul ignore next */ []));
    summaryHeight = input.required(/* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "summaryHeight" }] : /* istanbul ignore next */ []));
    summaryRowTemplate = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "summaryRowTemplate" }] : /* istanbul ignore next */ []));
    rowDraggable = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "rowDraggable" }] : /* istanbul ignore next */ []));
    rowDragEvents = input.required(/* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "rowDragEvents" }] : /* istanbul ignore next */ []));
    disableRowCheck = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "disableRowCheck" }] : /* istanbul ignore next */ []));
    checkRowPropertyChanges = input(true, { ...(ngDevMode ? { debugName: "checkRowPropertyChanges" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
    pageSize = input.required(/* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "pageSize" }] : /* istanbul ignore next */ []));
    rows = input.required(/* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "rows" }] : /* istanbul ignore next */ []));
    columns = input.required(/* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "columns" }] : /* istanbul ignore next */ []));
    offset = input(0, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "offset" }] : /* istanbul ignore next */ []));
    rowCount = input(0, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "rowCount" }] : /* istanbul ignore next */ []));
    bodyHeight = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "bodyHeight" }] : /* istanbul ignore next */ []));
    verticalScrollVisible = input(false, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "verticalScrollVisible" }] : /* istanbul ignore next */ []));
    scroll = output();
    page = output();
    activate = output();
    rowContextmenu = output();
    treeAction = output();
    scroller = viewChild(ScrollerComponent, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "scroller" }] : /* istanbul ignore next */ []));
    rowWrappers = viewChildren(DataTableRowWrapperComponent, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "rowWrappers" }] : /* istanbul ignore next */ []));
    rowComponents = viewChildren(DataTableBodyRowComponent, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "rowComponents" }] : /* istanbul ignore next */ []));
    /**
     * Returns if selection is enabled.
     */
    get selectEnabled() {
        return !!this.selectionType();
    }
    allColumnsColspan = computed(() => Math.max(1, this.columns().length), /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "allColumnsColspan" }] : /* istanbul ignore next */ []));
    /**
     * 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).
     */
    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;
    }, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "scrollHeight" }] : /* istanbul ignore next */ []));
    detailRowHeightFn = computed(() => {
        const rowDetail = this.rowDetail();
        if (!rowDetail) {
            return () => 0;
        }
        const rowHeight = rowDetail.rowHeight();
        return typeof rowHeight === 'function' ? rowHeight : () => rowHeight;
    }, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "detailRowHeightFn" }] : /* istanbul ignore next */ []));
    rowsToRender = computed(() => {
        return this.updateRows();
    }, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "rowsToRender" }] : /* istanbul ignore next */ []));
    rowHeightsCache = computed(() => this.computeRowHeightsCache(), /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "rowHeightsCache" }] : /* istanbul ignore next */ []));
    offsetY = signal(0, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "offsetY" }] : /* istanbul ignore next */ []));
    indexes = computed(() => this.computeIndexes(), /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "indexes" }] : /* istanbul ignore next */ []));
    pendingFocus = signal(undefined, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "pendingFocus" }] : /* istanbul ignore next */ []));
    rowTrackingFn;
    rowExpansions = signal([], /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "rowExpansions" }] : /* istanbul ignore next */ []));
    groupExpansions = signal([], /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "groupExpansions" }] : /* istanbul ignore next */ []));
    _bodyHeight = computed(() => {
        if (this.scrollbarV()) {
            return this.bodyHeight() + 'px';
        }
        else {
            return 'auto';
        }
    }, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "_bodyHeight" }] : /* istanbul ignore next */ []));
    _offsetEvent = -1;
    _draggedRow;
    _draggedRowElement;
    /**
     * Creates an instance of DataTableBodyComponent.
     */
    constructor() {
        // 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 && this.isRow(row)) {
                return row[trackByProp];
            }
            else if (row && this.isGroup(row)) {
                return row.key ?? index;
            }
            else {
                return row ?? index;
            }
        };
        effect(() => this.defaultGroupExpansionEffect());
        effect(() => this.focusPendingRow());
    }
    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
        const scroller = this.scroller();
        if (!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;
        }
        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();
    }
    focusPendingRow() {
        const pendingFocus = this.pendingFocus();
        if (!pendingFocus) {
            return;
        }
        const row = this.getRenderedRow(pendingFocus.location);
        if (row) {
            this.focusRenderedRow(row, pendingFocus.cellIndex);
            this.pendingFocus.set(undefined);
        }
    }
    /**
     * 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;
    }
    scrollToIndex(index, options) {
        if (this.virtualization()) {
            const scroller = this.scroller();
            if (!scroller) {
                return;
            }
            const cache = this.rowHeightsCache();
            const rowTop = cache.query(index - 1);
            const rowBottom = cache.query(index);
            const rowHeight = rowBottom - rowTop;
            // virtualization always provides a numeric bodyHeight
            const viewportHeight = this.bodyHeight();
            const currentScrollTop = scroller.scrollTop;
            const block = options?.block ?? 'start';
            let top;
            switch (block) {
                case 'center':
                    top = rowTop - Math.max(0, (viewportHeight - rowHeight) / 2);
                    break;
                case 'end':
                    top = rowBottom - viewportHeight;
                    break;
                case 'nearest':
                    if (rowTop < currentScrollTop) {
                        top = rowTop;
                    }
                    else if (rowBottom > currentScrollTop + viewportHeight) {
                        top = rowBottom - viewportHeight;
                    }
                    else {
                        top = currentScrollTop;
                    }
                    break;
                case 'start':
                default:
                    top = rowTop;
                    break;
            }
            scroller.scrollTo(Math.max(0, top), options);
        }
        else {
            this.rowWrappers()[index]?.scrollIntoView(options);
        }
    }
    /**
     * Get the row height
     */
    getRowHeight(row) {
        // if its a function return it
        const rowHeight = this.configuration().rowHeight;
        if (typeof rowHeight === 'function') {
            return rowHeight(row);
        }
        return rowHeight;
    }
    getGroupHeaderRowHeight = (row, index) => {
        const groupHeader = this.groupHeader();
        if (!groupHeader) {
            return 0;
        }
        const rowHeightValue = groupHeader?.rowHeight();
        const rowHeight = rowHeightValue === 0 ? this.configuration().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.
     */
    renderOffset = computed(() => {
        if (this.scrollbarV() && this.virtualization()) {
            return `translateY(${this.rowHeightsCache().query(this.indexes().first - 1)}px)`;
        }
        else {
            return '';
        }
    }, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "renderOffset" }] : /* istanbul ignore next */ []));
    /**
     * 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.configuration().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;
    }
    prevIndex;
    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 && this.prevIndex !== undefined) {
                const rangeSelection = selectRowsBetween(this.rows(), index, this.prevIndex);
                selected = [...this.selected()];
                for (const rangeRow of rangeSelection) {
                    if (this.getRowSelectedIdx(rangeRow, selected) < 0) {
                        selected.push(rangeRow);
                    }
                }
            }
            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, indexInGroup) {
        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, index, indexInGroup);
            }
        }
        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, index, indexInGroup) {
        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 (!isCellSelection) {
                this.focusRow(index, key, indexInGroup);
            }
            else if (isCellSelection && modelObject.renderedCellIndex !== undefined) {
                this.focusCell(index, key, modelObject.renderedCellIndex, indexInGroup);
            }
        }
    }
    focusRow(index, key, indexInGroup) {
        this.moveFocus({ outerIndex: index, innerIndex: indexInGroup }, key);
    }
    focusCell(index, key, cellIndex, indexInGroup) {
        if (key === ARROW_LEFT) {
            this.getRenderedRow({ outerIndex: index, innerIndex: indexInGroup })?.focusCell(cellIndex - 1);
        }
        else if (key === ARROW_RIGHT) {
            this.getRenderedRow({ outerIndex: index, innerIndex: indexInGroup })?.focusCell(cellIndex + 1);
        }
        else if (key === ARROW_UP || key === ARROW_DOWN) {
            this.moveFocus({ outerIndex: index, innerIndex: indexInGroup }, key, cellIndex);
        }
    }
    moveFocus(current, key, cellIndex) {
        if (this.pendingFocus()) {
            return;
        }
        const target = this.getAdjacentRowLocation(current, key);
        if (!target) {
            this.pendingFocus.set(undefined);
            return;
        }
        const row = this.getRenderedRow(target);
        if (row) {
            this.pendingFocus.set(undefined);
            row.scrollIntoView();
            this.focusRenderedRow(row, cellIndex);
            return;
        }
        this.pendingFocus.set({ location: target, cellIndex });
        this.scrollToIndex(target.outerIndex, { block: 'nearest' });
    }
    getAdjacentRowLocation(current, key) {
        if (key !== ARROW_UP && key !== ARROW_DOWN) {
            return undefined;
        }
        const step = key === ARROW_UP ? -1 : 1;
        const groups = this.groupedRows();
        if (!groups) {
            const outerIndex = current.outerIndex + step;
            return outerIndex >= 0 && outerIndex < this.rowCount() ? { outerIndex } : undefined;
        }
        if (current.innerIndex === undefined) {
            return undefined;
        }
        const group = groups[current.outerIndex];
        if (!group) {
            return undefined;
        }
        const innerIndex = current.innerIndex + step;
        if (innerIndex >= 0 && innerIndex < group.value.length) {
            return { outerIndex: current.outerIndex, innerIndex };
        }
        for (let outerIndex = current.outerIndex + step; groups[outerIndex]; outerIndex += step) {
            const adjacentGroup = groups[outerIndex];
            if (adjacentGroup.value.length && this.getGroupExpanded(adjacentGroup)) {
                return {
                    outerIndex,
                    innerIndex: key === ARROW_UP ? adjacentGroup.value.length - 1 : 0
                };
            }
        }
        return undefined;
    }
    getRenderedRow(location) {
        return this.rowComponents().find(row => {
            const rowIndex = row.rowIndex();
            return (rowIndex.index === location.outerIndex && rowIndex.indexInGroup === location.innerIndex);
        });
    }
    focusRenderedRow(row, cellIndex) {
        if (cellIndex === undefined) {
            row.focus();
        }
        else {
            row.focusCell(cellIndex);
        }
    }
    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 ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: DataTableBodyComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", 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 }, 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 }, 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 }, summaryRowTemplate: { classPropertyName: "summaryRowTemplate", publicName: "summaryRowTemplate", isSignal: true, isRequired: false, 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 }, checkRowPropertyChanges: { classPropertyName: "checkRowPropertyChanges", publicName: "checkRowPropertyChanges", isSignal: true, isRequired: false, 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 } }, outputs: { offsetX: "offsetXChange", selected: "selectedChange", scroll: "scroll", page: "page", activate: "activate", rowContextmenu: "rowContextmenu", treeAction: "treeAction" }, host: { classAttribute: "datatable-body" }, viewQueries: [{ propertyName: "scroller", first: true, predicate: ScrollerComponent, descendants: true, isSignal: true }, { propertyName: "rowWrappers", predicate: DataTableRowWrapperComponent, descendants: true, isSignal: true }, { propertyName: "rowComponents", predicate: DataTableBodyRowComponent, descendants: true, isSignal: 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 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]="configuration().rowHeight"
        [ghostBodyHeight]="bodyHeight"
      />
    }
    @if (rows.length) {
      <datatable-scroller
        [scrollbarV]="scrollbarV"
        [scrollbarH]="scrollbarH()"
        [scrollHeight]="scrollHeight()"
        (scroll)="onBodyScroll($event)"
      >
        @if ((summaryRow() || summaryRowTemplate()) && summaryPosition() === 'top') {
          <datatable-summary-row
            [class.sticky]="summaryRowTemplate()"
            [rowHeight]="summaryHeight()"
            [rows]="rows"
            [columns]="columns"
            [allColumnsColspan]="allColumnsColspan()"
            [template]="summaryRowTemplate()"
          />
        }
        <ng-template
          #bodyRow
          let-row="row"
          let-index="index"
          let-indexInGroup="indexInGroup"
          let-groupedRows="groupedRows"
          let-disabled="disabled"
          ngx-datatable-body-row
        >
          @let absoluteIndex = indexes().first + index;
          <datatable-row-wrapper
            [attr.hidden]="
              ghostLoadingIndicator() && (!rowCount || !virtualization() || !scrollbarV)
                ? true
                : null
            "
            [rowDetail]="rowDetail()"
            [detailRowHeightFn]="detailRowHeightFn()"
            [row]="row"
            [disabled]="disabled"
            [expanded]="getRowExpanded(row)"
            [rowIndex]="absoluteIndex"
            [checkRowPropertyChanges]="checkRowPropertyChanges()"
            (rowContextmenu)="rowContextmenu.emit($event)"
          >
            <datatable-body-row
              #rowElement
              [disabled]="disabled"
              [isSelected]="getRowSelected(row)"
              [columns]="columns"
              [rowHeight]="getRowHeight(row)"
              [row]="row"
              [group]="groupedRows"
              [rowIndex]="{ index: absoluteIndex, indexInGroup: indexInGroup }"
              [expanded]="getRowExpanded(row)"
              [rowClass]="rowClass()"
              [displayCheck]="displayCheck()"
              [treeStatus]="row?.treeStatus"
              [draggable]="rowDraggable()"
              [checkRowPropertyChanges]="checkRowPropertyChanges()"
              (treeAction)="onTreeAction(row)"
              (activate)="onActivate($event, absoluteIndex, indexInGroup)"
              (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 class="datatable-row-render-wrapper" [style.transform]="renderOffset()">
          @for (group of rowsToRender(); track rowTrackingFn(i, group); let i = $index) {
            @let absoluteIndex = indexes().first + i;
            @if (!group && ghostLoadingIndicator()) {
              <ghost-loader
                [columns]="columns"
                [pageSize]="1"
                [rowHeight]="configuration().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: i,
                      disabled
                    }"
                  />
                }
              }

              @if (isGroup(group)) {
                <datatable-group-wrapper
                  [group]="group"
                  [attr.hidden]="
                    ghostLoadingIndicator() && (!rowCount || !virtualization() || !scrollbarV)
                      ? true
                      : null
                  "
                  [groupHeader]="groupHeader()"
                  [groupHeaderRowHeight]="getGroupHeaderRowHeight(group, absoluteIndex)"
                  [disabled]="disabled"
                  [expanded]="getGroupExpanded(group)"
                  [rowIndex]="absoluteIndex"
                  [selected]="selected()"
                  [allColumnsColspan]="allColumnsColspan()"
                  (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: i,
                        indexInGroup: $index,
                        disabled
                      }"
                    />
                  }
                </datatable-group-wrapper>
              }
            }
          }
        </div>
      </datatable-scroller>
      @if ((summaryRow() || summaryRowTemplate()) && summaryPosition() === 'bottom') {
        <datatable-summary-row
          [rowHeight]="summaryHeight()"
          [rows]="rows"
          [columns]="columns"
          [allColumnsColspan]="allColumnsColspan()"
          [template]="summaryRowTemplate()"
        />
      }
    }
    @if (!rows?.length && !loadingIndicator() && !ghostLoadingIndicator()) {
      <datatable-scroller
        class="datatable-empty-scroller"
        [scrollbarV]="scrollbarV"
        [scrollbarH]="scrollbarH()"
        [scrollHeight]="scrollHeight()"
        (scroll)="onBodyScroll($event)"
      >
        <div role="row" class="datatable-empty-row">
          <div role="cell" class="datatable-empty-cell" [attr.aria-colspan]="allColumnsColspan()">
            <ng-content select="[empty-content]" />
          </div>
        </div>
      </datatable-scroller>
    }
  `, isInline: true, styles: [":host{position:relative;z-index:10;display:grid;grid-template-columns:subgrid;grid-column:1/-1;grid-row:2;min-block-size:0}datatable-scroller,.datatable-row-render-wrapper{display:grid;grid-template-columns:subgrid;grid-column:1/-1;align-content:start}:host-context(ngx-datatable.fixed-row) datatable-scroller,:host-context(ngx-datatable.fixed-row) .datatable-row-render-wrapper{white-space:nowrap}.datatable-empty-scroller{display:block}.datatable-empty-row,.datatable-empty-cell{block-size:100%}.custom-loading-indicator-wrapper,ghost-loader{grid-column:1/-1}[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"], outputs: ["scroll"] }, { kind: "component", type: DataTableSummaryRowComponent, selector: "datatable-summary-row", inputs: ["rows", "columns", "allColumnsColspan", "rowHeight", "template"] }, { kind: "component", type: DataTableRowWrapperComponent, selector: "datatable-row-wrapper", inputs: ["rowDetail", "detailRowHeightFn", "row", "disabled", "rowIndex", "expanded", "checkRowPropertyChanges"], 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", "disabled", "checkRowPropertyChanges", "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: ["groupHeader", "groupHeaderRowHeight", "group", "groupedRows", "allColumnsColspan", "selected", "disabled", "rowIndex", "expanded"], outputs: ["groupSelectedChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", 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 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]="configuration().rowHeight"
        [ghostBodyHeight]="bodyHeight"
      />
    }
    @if (rows.length) {
      <datatable-scroller
        [scrollbarV]="scrollbarV"
        [scrollbarH]="scrollbarH()"
        [scrollHeight]="scrollHeight()"
        (scroll)="onBodyScroll($event)"
      >
        @if ((summaryRow() || summaryRowTemplate()) && summaryPosition() === 'top') {
          <datatable-summary-row
            [class.sticky]="summaryRowTemplate()"
            [rowHeight]="summaryHeight()"
            [rows]="rows"
            [columns]="columns"
            [allColumnsColspan]="allColumnsColspan()"
            [template]="summaryRowTemplate()"
          />
        }
        <ng-template
          #bodyRow
          let-row="row"
          let-index="index"
          let-indexInGroup="indexInGroup"
          let-groupedRows="groupedRows"
          let-disabled="disabled"
          ngx-datatable-body-row
        >
          @let absoluteIndex = indexes().first + index;
          <datatable-row-wrapper
            [attr.hidden]="
              ghostLoadingIndicator() && (!rowCount || !virtualization() || !scrollbarV)
                ? true
                : null
            "
            [rowDetail]="rowDetail()"
            [detailRowHeightFn]="detailRowHeightFn()"
            [row]="row"
            [disabled]="disabled"
            [expanded]="getRowExpanded(row)"
            [rowIndex]="absoluteIndex"
            [checkRowPropertyChanges]="checkRowPropertyChanges()"
            (rowContextmenu)="rowContextmenu.emit($event)"
          >
            <datatable-body-row
              #rowElement
              [disabled]="disabled"
              [isSelected]="getRowSelected(row)"
              [columns]="columns"
              [rowHeight]="getRowHeight(row)"
              [row]="row"
              [group]="groupedRows"
              [rowIndex]="{ index: absoluteIndex, indexInGroup: indexInGroup }"
              [expanded]="getRowExpanded(row)"
              [rowClass]="rowClass()"
              [displayCheck]="displayCheck()"
              [treeStatus]="row?.treeStatus"
              [draggable]="rowDraggable()"
              [checkRowPropertyChanges]="checkRowPropertyChanges()"
              (treeAction)="onTreeAction(row)"
              (activate)="onActivate($event, absoluteIndex, indexInGroup)"
              (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 class="datatable-row-render-wrapper" [style.transform]="renderOffset()">
          @for (group of rowsToRender(); track rowTrackingFn(i, group); let i = $index) {
            @let absoluteIndex = indexes().first + i;
            @if (!group && ghostLoadingIndicator()) {
              <ghost-loader
                [columns]="columns"
                [pageSize]="1"
                [rowHeight]="configuration().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: i,
                      disabled
                    }"
                  />
                }
              }

              @if (isGroup(group)) {
                <datatable-group-wrapper
                  [group]="group"
                  [attr.hidden]="
                    ghostLoadingIndicator() && (!rowCount || !virtualization() || !scrollbarV)
                      ? true
                      : null
                  "
                  [groupHeader]="groupHeader()"
                  [groupHeaderRowHeight]="getGroupHeaderRowHeight(group, absoluteIndex)"
                  [disabled]="disabled"
                  [expanded]="getGroupExpanded(group)"
                  [rowIndex]="absoluteIndex"
                  [selected]="selected()"
                  [allColumnsColspan]="allColumnsColspan()"
                  (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: i,
                        indexInGroup: $index,
                        disabled
                      }"
                    />
                  }
                </datatable-group-wrapper>
              }
            }
          }
        </div>
      </datatable-scroller>
      @if ((summaryRow() || summaryRowTemplate()) && summaryPosition() === 'bottom') {
        <datatable-summary-row
          [rowHeight]="summaryHeight()"
          [rows]="rows"
          [columns]="columns"
          [allColumnsColspan]="allColumnsColspan()"
          [template]="summaryRowTemplate()"
        />
      }
    }
    @if (!rows?.length && !loadingIndicator() && !ghostLoadingIndicator()) {
      <datatable-scroller
        class="datatable-empty-scroller"
        [scrollbarV]="scrollbarV"
        [scrollbarH]="scrollbarH()"
        [scrollHeight]="scrollHeight()"
        (scroll)="onBodyScroll($event)"
      >
        <div role="row" class="datatable-empty-row">
          <div role="cell" class="datatable-empty-cell" [attr.aria-colspan]="allColumnsColspan()">
            <ng-content select="[empty-content]" />
          </div>
        </div>
      </datatable-scroller>
    }
  `, changeDetection: ChangeDetectionStrategy.OnPush, host: {
                        class: 'datatable-body'
                    }, styles: [":host{position:relative;z-index:10;display:grid;grid-template-columns:subgrid;grid-column:1/-1;grid-row:2;min-block-size:0}datatable-scroller,.datatable-row-render-wrapper{display:grid;grid-template-columns:subgrid;grid-column:1/-1;align-content:start}:host-context(ngx-datatable.fixed-row) datatable-scroller,:host-context(ngx-datatable.fixed-row) .datatable-row-render-wrapper{white-space:nowrap}.datatable-empty-scroller{display:block}.datatable-empty-row,.datatable-empty-cell{block-size:100%}.custom-loading-indicator-wrapper,ghost-loader{grid-column:1/-1}[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 }] }], 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
            }], 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 }] }], summaryRowTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "summaryRowTemplate", required: false }] }], 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 }] }], checkRowPropertyChanges: [{ type: i0.Input, args: [{ isSignal: true, alias: "checkRowPropertyChanges", required: false }] }], 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 }] }], 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: i0.ViewChild, args: [i0.forwardRef(() => ScrollerComponent), { isSignal: true }] }], rowWrappers: [{ type: i0.ViewChildren, args: [i0.forwardRef(() => DataTableRowWrapperComponent), { isSignal: true }] }], rowComponents: [{ type: i0.ViewChildren, args: [i0.forwardRef(() => DataTableBodyRowComponent), { isSignal: true }] }] } });

class ProgressBarComponent {
    configuration = inject(DatatableConfiguration).configuration;
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: ProgressBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.0.8", type: ProgressBarComponent, isStandalone: true, selector: "datatable-progress", ngImport: i0, template: `
    <div
      class="progress-linear"
      role="progressbar"
      [attr.aria-label]="configuration().messages.ariaLoadingMessage"
    >
      <div class="container">
        <div class="bar"></div>
      </div>
    </div>
  `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: ProgressBarComponent, decorators: [{
            type: Component,
            args: [{
                    selector: 'datatable-progress',
                    template: `
    <div
      class="progress-linear"
      role="progressbar"
      [attr.aria-label]="configuration().messages.ariaLoadingMessage"
    >
      <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 {
    // 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.
    datatable = inject(DATATABLE_COMPONENT_TOKEN);
    configuration = inject(DatatableConfiguration).configuration;
    page = computed(() => this.datatable._footerComponent().curPage(), /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "page" }] : /* istanbul ignore next */ []));
    pageSize = computed(() => this.datatable._footerComponent().pageSize(), /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "pageSize" }] : /* istanbul ignore next */ []));
    count = computed(() => this.datatable._footerComponent().groupCount() ??
        this.datatable._footerComponent().rowCount(), /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "count" }] : /* istanbul ignore next */ []));
    pagerNextIcon = computed(() => this.datatable._footerComponent().pagerNextIcon(), /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "pagerNextIcon" }] : /* istanbul ignore next */ []));
    pagerRightArrowIcon = computed(() => this.datatable._footerComponent().pagerRightArrowIcon(), /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "pagerRightArrowIcon" }] : /* istanbul ignore next */ []));
    pagerLeftArrowIcon = computed(() => this.datatable._footerComponent().pagerLeftArrowIcon(), /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "pagerLeftArrowIcon" }] : /* istanbul ignore next */ []));
    pagerPreviousIcon = computed(() => this.datatable._footerComponent().pagerPreviousIcon(), /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "pagerPreviousIcon" }] : /* istanbul ignore next */ []));
    totalPages = computed(() => {
        return Math.max((this.pageSize() < 1 ? 1 : Math.ceil(this.count() / this.pageSize())) || 0, 1);
    }, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "totalPages" }] : /* istanbul ignore next */ []));
    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;
    }, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "pages" }] : /* istanbul ignore next */ []));
    canPrevious = computed(() => this.page() > 1, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "canPrevious" }] : /* istanbul ignore next */ []));
    canNext = computed(() => this.page() < this.totalPages(), /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "canNext" }] : /* istanbul ignore next */ []));
    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 ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: DatatablePagerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", 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]="configuration().messages.ariaFirstPageMessage"
          (click)="selectPage(1)"
        >
          <i [class]="pagerPreviousIcon()"></i>
        </button>
      </li>
      <li>
        <button
          type="button"
          class="page-button"
          [disabled]="!canPrevious()"
          [attr.aria-label]="configuration().messages.ariaPreviousPageMessage"
          (click)="prevPage()"
        >
          <i [class]="pagerLeftArrowIcon()"></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]="configuration().messages.ariaPageNMessage + ' ' + pg.number"
            (click)="selectPage(pg.number)"
          >
            {{ pg.text }}
          </button>
        </li>
      }
      <li>
        <button
          type="button"
          class="page-button"
          [disabled]="!canNext()"
          [attr.aria-label]="configuration().messages.ariaNextPageMessage"
          (click)="nextPage()"
        >
          <i [class]="pagerRightArrowIcon()"></i>
        </button>
      </li>
      <li>
        <button
          type="button"
          class="page-button"
          [disabled]="!canNext()"
          [attr.aria-label]="configuration().messages.ariaLastPageMessage"
          (click)="selectPage(totalPages())"
        >
          <i [class]="pagerNextIcon()"></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: "22.0.8", 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]="configuration().messages.ariaFirstPageMessage"
          (click)="selectPage(1)"
        >
          <i [class]="pagerPreviousIcon()"></i>
        </button>
      </li>
      <li>
        <button
          type="button"
          class="page-button"
          [disabled]="!canPrevious()"
          [attr.aria-label]="configuration().messages.ariaPreviousPageMessage"
          (click)="prevPage()"
        >
          <i [class]="pagerLeftArrowIcon()"></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]="configuration().messages.ariaPageNMessage + ' ' + pg.number"
            (click)="selectPage(pg.number)"
          >
            {{ pg.text }}
          </button>
        </li>
      }
      <li>
        <button
          type="button"
          class="page-button"
          [disabled]="!canNext()"
          [attr.aria-label]="configuration().messages.ariaNextPageMessage"
          (click)="nextPage()"
        >
          <i [class]="pagerRightArrowIcon()"></i>
        </button>
      </li>
      <li>
        <button
          type="button"
          class="page-button"
          [disabled]="!canNext()"
          [attr.aria-label]="configuration().messages.ariaLastPageMessage"
          (click)="selectPage(totalPages())"
        >
          <i [class]="pagerNextIcon()"></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 {
    configuration = inject(DatatableConfiguration).configuration;
    rowCount = input.required(/* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "rowCount" }] : /* istanbul ignore next */ []));
    groupCount = input.required(/* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "groupCount" }] : /* istanbul ignore next */ []));
    pageSize = input.required(/* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "pageSize" }] : /* istanbul ignore next */ []));
    offset = input.required(/* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "offset" }] : /* istanbul ignore next */ []));
    pagerLeftArrowIcon = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "pagerLeftArrowIcon" }] : /* istanbul ignore next */ []));
    pagerRightArrowIcon = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "pagerRightArrowIcon" }] : /* istanbul ignore next */ []));
    pagerPreviousIcon = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "pagerPreviousIcon" }] : /* istanbul ignore next */ []));
    pagerNextIcon = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "pagerNextIcon" }] : /* istanbul ignore next */ []));
    footerTemplate = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "footerTemplate" }] : /* istanbul ignore next */ []));
    selectedCount = input(0, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "selectedCount" }] : /* istanbul ignore next */ []));
    selectedMessage = input(false, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "selectedMessage" }] : /* istanbul ignore next */ []));
    page = output();
    isVisible = computed(() => this.rowCount() / this.pageSize() > 1, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "isVisible" }] : /* istanbul ignore next */ []));
    curPage = computed(() => this.offset() + 1, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "curPage" }] : /* istanbul ignore next */ []));
    templateContext = computed(() => ({
        rowCount: this.rowCount(),
        pageSize: this.pageSize(),
        selectedCount: this.selectedCount(),
        curPage: this.curPage(),
        offset: this.offset()
    }), /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "templateContext" }] : /* istanbul ignore next */ []));
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: DataTableFooterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: DataTableFooterComponent, isStandalone: true, selector: "datatable-footer", inputs: { 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 }, 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"
      [class.selected-count]="selectedMessage()"
      [style.height.px]="configuration().footerHeight"
    >
      @let footerTemplate = this.footerTemplate()?.template();
      @if (footerTemplate) {
        <ng-template
          [ngTemplateOutlet]="footerTemplate"
          [ngTemplateOutletContext]="templateContext()"
        />
      } @else {
        <div class="page-count">
          @if (selectedMessage()) {
            <span>
              {{ selectedCount().toLocaleString() }}
              {{ configuration().messages.selectedMessage }} /
            </span>
          }
          {{ rowCount().toLocaleString() }} {{ configuration().messages.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: 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: "22.0.8", ngImport: i0, type: DataTableFooterComponent, decorators: [{
            type: Component,
            args: [{ selector: 'datatable-footer', imports: [NgTemplateOutlet, DatatablePagerComponent], template: `
    <div
      class="datatable-footer-inner"
      [class.selected-count]="selectedMessage()"
      [style.height.px]="configuration().footerHeight"
    >
      @let footerTemplate = this.footerTemplate()?.template();
      @if (footerTemplate) {
        <ng-template
          [ngTemplateOutlet]="footerTemplate"
          [ngTemplateOutletContext]="templateContext()"
        />
      } @else {
        <div class="page-count">
          @if (selectedMessage()) {
            <span>
              {{ selectedCount().toLocaleString() }}
              {{ configuration().messages.selectedMessage }} /
            </span>
          }
          {{ rowCount().toLocaleString() }} {{ configuration().messages.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: { 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 }] }], 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 ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: DataTableFooterTemplateDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.8", type: DataTableFooterTemplateDirective, isStandalone: true, selector: "[ngx-datatable-footer-template]", ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: DataTableFooterTemplateDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[ngx-datatable-footer-template]'
                }]
        }] });

class DatatableFooterDirective {
    _templateInput = input(undefined, { ...(ngDevMode ? { debugName: "_templateInput" } : /* istanbul ignore next */ {}), alias: 'template' });
    _templateQuery = contentChild(DataTableFooterTemplateDirective, { ...(ngDevMode ? { debugName: "_templateQuery" } : /* istanbul ignore next */ {}), read: TemplateRef });
    template = computed(() => this._templateInput() ?? this._templateQuery(), /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "template" }] : /* istanbul ignore next */ []));
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: DatatableFooterDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "22.0.8", 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: "22.0.8", 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 {
    document = inject(DOCUMENT);
    element = inject(ElementRef).nativeElement;
    dragModel = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "dragModel" }] : /* istanbul ignore next */ []));
    dragStartDelay = input(0, { ...(ngDevMode ? { debugName: "dragStartDelay" } : /* istanbul ignore next */ {}), transform: numberAttribute });
    enabled = input(true, { ...(ngDevMode ? { debugName: "enabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute, alias: 'datatableDraggable' });
    dragMove = output();
    dragEnd = output();
    dragStart = output();
    timeoutId;
    touchId;
    startX = signal(undefined, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "startX" }] : /* istanbul ignore next */ []));
    startY = signal(undefined, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "startY" }] : /* istanbul ignore next */ []));
    currentX;
    currentY;
    isLongPressing = computed(() => this.dragStartDelay() !== 0 && this.isDragging(), /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "isLongPressing" }] : /* istanbul ignore next */ []));
    isDragging = computed(() => this.startX() !== undefined, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "isDragging" }] : /* istanbul ignore next */ []));
    removePointerListeners;
    constructor() {
        effect(() => {
            if (this.enabled()) {
                this.element.addEventListener('mousedown', this.mousedown);
                this.element.addEventListener('touchstart', this.touchstart);
                this.element.addEventListener('contextmenu', this.contextmenu);
                this.removePointerListeners = () => {
                    this.element.removeEventListener('mousedown', this.mousedown);
                    this.element.removeEventListener('touchstart', this.touchstart);
                    this.element.removeEventListener('contextmenu', this.contextmenu);
                };
            }
            else {
                this.removePointerListeners?.();
                this.removePointerListeners = undefined;
            }
        });
    }
    ngOnDestroy() {
        clearTimeout(this.timeoutId);
        this.removePointerListeners?.();
    }
    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);
            this.setDragging(true);
        });
    };
    mousemove = (event) => this.moving(event.clientX, event.clientY);
    // Prevent context menu on long-press drag. Since we don't call preventDefault() on
    // touchstart to allow click events (sorting), the browser would show a context menu
    // after a long press. We prevent this when dragging is active.
    contextmenu = (event) => {
        if (this.isDragging()) {
            event.preventDefault();
        }
    };
    touchstart = (event) => {
        if (!this.enabled()) {
            return;
        }
        event.stopPropagation();
        const touch = event.touches.item(0);
        this.touchId = touch.identifier;
        this.document.addEventListener('touchend', this.ending);
        this.delay(this.dragStartDelay()).then(() => {
            if (this.touchId === touch.identifier) {
                this.document.addEventListener('touchmove', this.touchmove, { passive: false });
                this.starting(touch.clientX, touch.clientY);
                this.setDragging(true);
            }
        });
    };
    touchmove = (event) => {
        const touchMove = this.findTouch(event);
        if (touchMove) {
            // Prevent scrolling and other default touch behaviors during drag
            event.preventDefault();
            this.moving(touchMove.clientX, touchMove.clientY);
        }
    };
    starting(clientX, clientY) {
        this.startX.set(clientX);
        this.startY.set(clientY);
        this.currentX = clientX;
        this.currentY = clientY;
        this.dragStart.emit(this.dragEvent());
    }
    moving(clientX, clientY) {
        this.currentX = clientX;
        this.currentY = clientY;
        this.dragMove.emit(this.dragEvent());
    }
    ending = () => {
        const dragged = this.isDragging();
        const dragEvent = dragged ? this.dragEvent() : undefined;
        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.setDragging(false);
            this.dragEnd.emit(dragEvent);
        }
    };
    dragEvent() {
        return {
            initialX: this.startX(),
            initialY: this.startY(),
            currentX: this.currentX,
            currentY: this.currentY,
            element: this.element,
            model: this.dragModel()
        };
    }
    setDragging(dragging) {
        const model = this.dragModel();
        if (model) {
            model.dragging = dragging;
        }
    }
    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 ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: DatatableDraggableDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.8", 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: { properties: { "class.draggable": "enabled()", "class.dragging": "isDragging()", "class.longpress": "isLongPressing()" } }, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: DatatableDraggableDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[datatableDraggable]',
                    host: {
                        '[class.draggable]': 'enabled()',
                        '[class.dragging]': 'isDragging()',
                        '[class.longpress]': 'isLongPressing()'
                    }
                }]
        }], ctorParameters: () => [], 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 DataTableHeaderCellComponent {
    element = inject(ElementRef).nativeElement;
    configuration = inject(DatatableConfiguration).configuration;
    sortType = input.required(/* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "sortType" }] : /* istanbul ignore next */ []));
    isTarget = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "isTarget" }] : /* istanbul ignore next */ []));
    showResizeHandle = input(true, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "showResizeHandle" }] : /* istanbul ignore next */ []));
    targetMarkerTemplate = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "targetMarkerTemplate" }] : /* istanbul ignore next */ []));
    targetMarkerContext = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "targetMarkerContext" }] : /* istanbul ignore next */ []));
    enableClearingSortState = input(false, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "enableClearingSortState" }] : /* istanbul ignore next */ []));
    allRowsSelected = input(false, { ...(ngDevMode ? { debugName: "allRowsSelected" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
    selectionType = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "selectionType" }] : /* istanbul ignore next */ []));
    column = input.required(/* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "column" }] : /* istanbul ignore next */ []));
    sorts = input([], /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "sorts" }] : /* istanbul ignore next */ []));
    sort = output();
    select = output();
    columnContextmenu = output();
    resize = output();
    resizing = output();
    columnCssClasses = computed(() => {
        const column = this.column();
        if (!column.headerClass) {
            return [];
        }
        if (typeof column.headerClass === 'string') {
            return column.headerClass;
        }
        return column.headerClass({ column: toPublicColumn(column) });
    }, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "columnCssClasses" }] : /* istanbul ignore next */ []));
    name = computed(() => {
        // guaranteed to have a value by setColumnDefaults() in column-helper.ts
        return this.column().headerTemplate === undefined ? this.column().name : undefined;
    }, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
    isCheckboxable = computed(() => this.column().headerCheckboxable, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "isCheckboxable" }] : /* istanbul ignore next */ []));
    sortClass = computed(() => this.calcSortClass(this.sortDir()), /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "sortClass" }] : /* istanbul ignore next */ []));
    sortDir = computed(() => {
        return this.calcSortDir(this.sorts());
    }, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "sortDir" }] : /* istanbul ignore next */ []));
    ariaSort = computed(() => {
        if (!this.column().sortable) {
            return null;
        }
        switch (this.sortDir()) {
            case 'asc':
                return 'ascending';
            case 'desc':
                return 'descending';
            default:
                return 'none';
        }
    }, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "ariaSort" }] : /* istanbul ignore next */ []));
    cellContext = computed(() => {
        return {
            column: toPublicColumn(this.column()),
            sortDir: this.sortDir(),
            sortFn: () => this.onSort(),
            allRowsSelected: this.allRowsSelected(),
            selectFn: () => this.select.emit()
        };
    }, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "cellContext" }] : /* istanbul ignore next */ []));
    initialWidth;
    subscription;
    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;
            }
        }
    }
    // Counter to reset sort once user sort asc and desc.
    totalSortStatesApplied = 0;
    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;
        }
        const base = 'sort-btn';
        switch (sortDir) {
            case 'asc':
                return `${base} sort-asc ${this.configuration().cssClasses.sortAscending}`;
            case 'desc':
                return `${base} sort-desc ${this.configuration().cssClasses.sortDescending}`;
            default:
                return `${base} ${this.configuration().cssClasses.sortUnset}`;
        }
    }
    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 ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: DataTableHeaderCellComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: DataTableHeaderCellComponent, isStandalone: true, selector: "datatable-header-cell", inputs: { sortType: { classPropertyName: "sortType", publicName: "sortType", isSignal: true, isRequired: true, 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 }, 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", "attr.aria-sort": "ariaSort()", "class": "columnCssClasses()", "class.sortable": "column().sortable", "class.resizeable": "showResizeHandle()", "class.sort-active": "sortDir()", "class.sort-asc": "sortDir() === \"asc\"", "class.sort-desc": "sortDir() === \"desc\"" }, classAttribute: "datatable-header-cell" }, 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]="configuration().messages.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 aria-hidden="true" [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;min-inline-size:0;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: "22.0.8", 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]="configuration().messages.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 aria-hidden="true" [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: {
                        class: 'datatable-header-cell',
                        '[attr.resizeable]': 'showResizeHandle()',
                        '[attr.title]': 'name()',
                        '[attr.tabindex]': 'column().sortable ? 0 : -1',
                        '[attr.aria-sort]': 'ariaSort()',
                        '[class]': 'columnCssClasses()',
                        '[class.sortable]': 'column().sortable',
                        '[class.resizeable]': 'showResizeHandle()',
                        '[class.sort-active]': 'sortDir()',
                        '[class.sort-asc]': 'sortDir() === "asc"',
                        '[class.sort-desc]': 'sortDir() === "desc"'
                    }, styles: [":host{overflow-x:hidden;min-inline-size:0;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 }] }], 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 }] }], 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 {
    document = inject(DOCUMENT);
    configuration = inject(DatatableConfiguration).configuration;
    headerCells = viewChildren(DataTableHeaderCellComponent, { ...(ngDevMode ? { debugName: "headerCells" } : /* istanbul ignore next */ {}), read: ElementRef });
    lastColumnId = computed(() => this.columns().at(-1)?.$$id, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "lastColumnId" }] : /* istanbul ignore next */ []));
    scrollbarH = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "scrollbarH" }] : /* istanbul ignore next */ []));
    dealsWithGroup = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "dealsWithGroup" }] : /* istanbul ignore next */ []));
    targetMarkerTemplate = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "targetMarkerTemplate" }] : /* istanbul ignore next */ []));
    enableClearingSortState = input(false, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "enableClearingSortState" }] : /* istanbul ignore next */ []));
    sorts = input.required(/* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "sorts" }] : /* istanbul ignore next */ []));
    sortType = input.required(/* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "sortType" }] : /* istanbul ignore next */ []));
    allRowsSelected = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "allRowsSelected" }] : /* istanbul ignore next */ []));
    selectionType = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "selectionType" }] : /* istanbul ignore next */ []));
    reorderable = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "reorderable" }] : /* istanbul ignore next */ []));
    verticalScrollVisible = input(false, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "verticalScrollVisible" }] : /* istanbul ignore next */ []));
    columns = input.required(/* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "columns" }] : /* istanbul ignore next */ []));
    sort = output();
    reorder = output();
    resize = output();
    resizing = output();
    select = output();
    columnContextmenu = output();
    columnGroups = computed(() => {
        return columnsByPinArr(this.columns());
    }, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "columnGroups" }] : /* istanbul ignore next */ []));
    renderedColumns = computed(() => this.columnGroups().flatMap(group => group.columns), /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "renderedColumns" }] : /* istanbul ignore next */ []));
    dragInitialIndex;
    dragTargetIndex;
    targetColumn = signal(undefined, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "targetColumn" }] : /* istanbul ignore next */ []));
    targetMarkerContext = signal(undefined, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "targetMarkerContext" }] : /* istanbul ignore next */ []));
    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
        };
    }
    onDragStart({ model }) {
        this.dragInitialIndex = model ? this.renderedColumns().indexOf(model) : undefined;
    }
    onDragMove(event) {
        const targetIndex = this.getDragTargetIndex(event);
        if (targetIndex !== this.dragTargetIndex) {
            if (this.dragTargetIndex !== undefined) {
                this.targetColumn.set(undefined);
                this.targetMarkerContext.set(undefined);
            }
            if (targetIndex !== undefined && this.dragInitialIndex !== undefined) {
                this.targetColumn.set(this.renderedColumns()[targetIndex]);
                if (this.dragInitialIndex !== targetIndex) {
                    this.targetMarkerContext.set({
                        class: `targetMarker ${this.dragInitialIndex > targetIndex ? 'dragFromRight' : 'dragFromLeft'}`
                    });
                }
            }
            this.dragTargetIndex = targetIndex;
        }
        event.element.style.transform = `translateX(${event.currentX - event.initialX}px)`;
    }
    onDragEnd(event) {
        event.element.style.transform = '';
        const targetIndex = this.getDragTargetIndex(event);
        if (this.dragTargetIndex !== undefined) {
            this.targetColumn.set(undefined);
            this.targetMarkerContext.set(undefined);
        }
        if (event.model && this.dragInitialIndex !== undefined && targetIndex !== undefined) {
            this.reorder.emit({
                prevValue: this.dragInitialIndex,
                newValue: targetIndex,
                column: event.model
            });
        }
        this.dragInitialIndex = undefined;
        this.dragTargetIndex = undefined;
    }
    getDragTargetIndex({ currentX, currentY, element }) {
        const elementsAtPoint = this.document.elementsFromPoint(currentX, currentY);
        const index = this.headerCells().findIndex(cell => cell.nativeElement !== element && elementsAtPoint.includes(cell.nativeElement));
        return index === -1 ? undefined : index;
    }
    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: toPublicColumn(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() === 'single') {
                sorts.splice(0, this.sorts().length);
            }
            sorts.push({ dir: newValue, prop: column.prop });
        }
        return sorts;
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: DataTableHeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: DataTableHeaderComponent, isStandalone: true, selector: "datatable-header", inputs: { 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 }, 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 }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { sort: "sort", reorder: "reorder", resize: "resize", resizing: "resizing", select: "select", columnContextmenu: "columnContextmenu" }, host: { properties: { "style.height.px": "configuration().headerHeight" }, classAttribute: "datatable-header" }, viewQueries: [{ propertyName: "headerCells", predicate: DataTableHeaderCellComponent, descendants: true, read: ElementRef, isSignal: true }], ngImport: i0, template: `
    <div role="row" class="datatable-header-inner">
      @for (colGroup of columnGroups(); track colGroup.type) {
        @if (colGroup.columns.length) {
          <div
            class="datatable-row-group"
            [class]="'datatable-row-' + colGroup.type"
            [style.grid-column]="'span ' + colGroup.columns.length"
          >
            @for (column of colGroup.columns; track column.$$id) {
              <datatable-header-cell
                role="columnheader"
                dragStartDelay="500"
                [datatableDraggable]="reorderable() && column.draggable"
                [dragModel]="column"
                [isTarget]="targetColumn() === column"
                [targetMarkerTemplate]="targetMarkerTemplate()"
                [targetMarkerContext]="targetMarkerContext()"
                [column]="column"
                [showResizeHandle]="lastColumnId() !== column.$$id && column.resizeable"
                [sortType]="sortType()"
                [sorts]="sorts()"
                [selectionType]="selectionType()"
                [allRowsSelected]="allRowsSelected()"
                [enableClearingSortState]="enableClearingSortState()"
                (dragStart)="onDragStart($event)"
                (dragMove)="onDragMove($event)"
                (dragEnd)="onDragEnd($event)"
                (resize)="onColumnResized($event)"
                (resizing)="onColumnResizing($event)"
                (sort)="onSort($event)"
                (select)="select.emit($event)"
                (columnContextmenu)="columnContextmenu.emit($event)"
              />
            }
          </div>
        }
      }
    </div>
  `, isInline: true, styles: [":host{display:grid;grid-template-columns:subgrid;grid-column:1/-1;grid-row:1;position:sticky;inset-block-start:0;z-index:11}.datatable-header-inner{display:grid;grid-template-columns:subgrid;grid-column:1/-1}:host-context(ngx-datatable.fixed-header) .datatable-header-inner{white-space:nowrap}.datatable-row-group{display:grid;grid-template-columns:subgrid}.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: DataTableHeaderCellComponent, selector: "datatable-header-cell", inputs: ["sortType", "isTarget", "showResizeHandle", "targetMarkerTemplate", "targetMarkerContext", "enableClearingSortState", "allRowsSelected", "selectionType", "column", "sorts"], outputs: ["sort", "select", "columnContextmenu", "resize", "resizing"] }, { 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: "22.0.8", ngImport: i0, type: DataTableHeaderComponent, decorators: [{
            type: Component,
            args: [{ selector: 'datatable-header', imports: [DataTableHeaderCellComponent, DatatableDraggableDirective], template: `
    <div role="row" class="datatable-header-inner">
      @for (colGroup of columnGroups(); track colGroup.type) {
        @if (colGroup.columns.length) {
          <div
            class="datatable-row-group"
            [class]="'datatable-row-' + colGroup.type"
            [style.grid-column]="'span ' + colGroup.columns.length"
          >
            @for (column of colGroup.columns; track column.$$id) {
              <datatable-header-cell
                role="columnheader"
                dragStartDelay="500"
                [datatableDraggable]="reorderable() && column.draggable"
                [dragModel]="column"
                [isTarget]="targetColumn() === column"
                [targetMarkerTemplate]="targetMarkerTemplate()"
                [targetMarkerContext]="targetMarkerContext()"
                [column]="column"
                [showResizeHandle]="lastColumnId() !== column.$$id && column.resizeable"
                [sortType]="sortType()"
                [sorts]="sorts()"
                [selectionType]="selectionType()"
                [allRowsSelected]="allRowsSelected()"
                [enableClearingSortState]="enableClearingSortState()"
                (dragStart)="onDragStart($event)"
                (dragMove)="onDragMove($event)"
                (dragEnd)="onDragEnd($event)"
                (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]': 'configuration().headerHeight'
                    }, styles: [":host{display:grid;grid-template-columns:subgrid;grid-column:1/-1;grid-row:1;position:sticky;inset-block-start:0;z-index:11}.datatable-header-inner{display:grid;grid-template-columns:subgrid;grid-column:1/-1}:host-context(ngx-datatable.fixed-header) .datatable-header-inner{white-space:nowrap}.datatable-row-group{display:grid;grid-template-columns:subgrid}.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: { headerCells: [{ type: i0.ViewChildren, args: [i0.forwardRef(() => DataTableHeaderCellComponent), { ...{ read: ElementRef }, isSignal: true }] }], 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 }] }], 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 }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], 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 ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: DatatableRowDetailTemplateDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.8", type: DatatableRowDetailTemplateDirective, isStandalone: true, selector: "[ngx-datatable-row-detail-template]", ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: DatatableRowDetailTemplateDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[ngx-datatable-row-detail-template]'
                }]
        }] });

class DatatableRowDetailDirective {
    /**
     * The detail row height is required especially
     * when virtual scroll is enabled.
     */
    rowHeight = input(0, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "rowHeight" }] : /* istanbul ignore next */ []));
    /**
     * Template used to render the detail row.
     */
    _templateInput = input(undefined, { ...(ngDevMode ? { debugName: "_templateInput" } : /* istanbul ignore next */ {}), alias: 'template' });
    _templateQuery = contentChild(DatatableRowDetailTemplateDirective, { ...(ngDevMode ? { debugName: "_templateQuery" } : /* istanbul ignore next */ {}), read: TemplateRef });
    template = computed(() => {
        return this._templateInput() ?? this._templateQuery();
    }, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "template" }] : /* istanbul ignore next */ []));
    /**
     * Row detail row visbility was toggled.
     */
    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 ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: DatatableRowDetailDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "22.0.8", 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: "22.0.8", 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 {
    scrollbarHelper = inject(ScrollbarHelper);
    cd = inject(ChangeDetectorRef);
    element = inject(ElementRef).nativeElement;
    rowDiffer = inject(IterableDiffers).find([]).create();
    globalConfiguration = inject(NGX_DATATABLE_CONFIG, { optional: true }) ??
        // This is the old injection token for backward compatibility.
        inject('configuration', { optional: true }) ??
        {};
    datatableConfiguration = new DatatableConfiguration(this, this.globalConfiguration);
    configuration = this.datatableConfiguration.configuration;
    /**
     * Template for the target marker of drag target columns.
     */
    targetMarkerTemplate = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "targetMarkerTemplate" }] : /* istanbul ignore next */ []));
    /**
     * Rows that are displayed in the table.
     */
    rows = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "rows" }] : /* istanbul ignore next */ []));
    /**
     * This attribute allows the user to set the name of the column to group the data with
     */
    groupRowsBy = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "groupRowsBy" }] : /* istanbul ignore next */ []));
    /**
     * 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"}
     *    ]}
     *  ]
     */
    groupedRows = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "groupedRows" }] : /* istanbul ignore next */ []));
    /**
     * Columns to be displayed.
     */
    columns = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "columns" }] : /* istanbul ignore next */ []));
    /**
     * List of row objects that should be
     * represented as selected in the grid.
     * Default value: `[]`
     */
    selected = model([], /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "selected" }] : /* istanbul ignore next */ []));
    /**
     * Enable vertical scrollbars
     */
    scrollbarV = input(false, { ...(ngDevMode ? { debugName: "scrollbarV" } : /* istanbul ignore next */ {}), 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.
     */
    scrollbarVDynamic = input(false, { ...(ngDevMode ? { debugName: "scrollbarVDynamic" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
    /**
     * Enable horz scrollbars
     */
    scrollbarH = input(false, { ...(ngDevMode ? { debugName: "scrollbarH" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
    /**
     * Height of each row. When virtual scrolling is disabled, use `'auto'` for
     * fluid heights. With virtual scrolling enabled, provide a number or a
     * function that calculates each row's height.
     */
    rowHeight = input(this.globalConfiguration.rowHeight ?? 30, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "rowHeight" }] : /* istanbul ignore next */ []));
    /**
     * Column width distribution mode. `standard` uses configured widths, `flex`
     * uses the flex-grow algorithm, and `force` distributes space proportionally.
     */
    columnMode = input('standard', /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "columnMode" }] : /* istanbul ignore next */ []));
    /**
     * The minimum header height in pixels.
     * Pass a falsey for no header
     */
    headerHeight = input(this.globalConfiguration.headerHeight ?? 30, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "headerHeight" }] : /* istanbul ignore next */ []));
    /**
     * The minimum footer height in pixels.
     * Pass falsey for no footer
     */
    footerHeight = input(this.globalConfiguration.footerHeight ?? 0, { ...(ngDevMode ? { debugName: "footerHeight" } : /* istanbul ignore next */ {}), transform: numberAttribute });
    /**
     * If the table should use external paging
     * otherwise its assumed that all data is preloaded.
     */
    externalPaging = input(false, { ...(ngDevMode ? { debugName: "externalPaging" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
    /**
     * If the table should use external sorting or
     * the built-in basic sorting.
     */
    externalSorting = input(false, { ...(ngDevMode ? { debugName: "externalSorting" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
    /**
     * The page size to be shown.
     * Default value: `undefined`
     */
    limit = input(undefined, { ...(ngDevMode ? { debugName: "limit" } : /* istanbul ignore next */ {}), transform: numberOrUndefinedAttribute });
    /**
     * The total count of all rows.
     * Default value: `0`
     */
    count = input(0, { ...(ngDevMode ? { debugName: "count" } : /* istanbul ignore next */ {}), transform: numberAttribute });
    /**
     * The current offset ( page - 1 ) shown.
     * Default value: `0`
     */
    offset = model(0, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "offset" }] : /* istanbul ignore next */ []));
    /**
     * Show the linear loading bar.
     * Default value: `false`
     */
    loadingIndicator = input(false, { ...(ngDevMode ? { debugName: "loadingIndicator" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
    /**
     * Show ghost loaders on each cell.
     * Default value: `false`
     */
    ghostLoadingIndicator = input(false, { ...(ngDevMode ? { debugName: "ghostLoadingIndicator" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
    /**
     * Type of row selection. Options are:
     *
     *  - `single`
     *  - `multi`
     *  - `checkbox`
     *  - `multiClick`
     *  - `cell`
     *
     * For no selection pass a `falsey`.
     * Default value: `undefined`
     */
    selectionType = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "selectionType" }] : /* istanbul ignore next */ []));
    /**
     * Enable/Disable ability to re-order columns
     * by dragging them.
     */
    reorderable = input(true, { ...(ngDevMode ? { debugName: "reorderable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
    /**
     * Swap columns on re-order columns or
     * move them.
     */
    swapColumns = input(true, { ...(ngDevMode ? { debugName: "swapColumns" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
    /**
     * Sorting mode. In `single` mode, sorting a new column replaces existing
     * sorts; in `multi` mode, it adds an additional column sort.
     */
    sortType = input('single', /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "sortType" }] : /* istanbul ignore next */ []));
    /**
     * Array of sorted columns by property and type.
     * Default value: `[]`
     */
    sorts = model([], /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "sorts" }] : /* istanbul ignore next */ []));
    /**
     * CSS class overrides for sort and pager icons.
     */
    cssClasses = input({}, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "cssClasses" }] : /* istanbul ignore next */ []));
    /**
     * 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',
     *   ariaLoadingMessage: 'Loading'
     * }
     * ```
     */
    messages = input({}, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "messages" }] : /* istanbul ignore next */ []));
    /**
     * 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 }`
     */
    rowClass = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "rowClass" }] : /* istanbul ignore next */ []));
    /**
     * 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';
     *    }
     */
    selectCheck = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "selectCheck" }] : /* istanbul ignore next */ []));
    /**
     * 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';
     *    }
     */
    displayCheck = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "displayCheck" }] : /* istanbul ignore next */ []));
    /**
     * 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.
     *
     */
    groupExpansionDefault = input(false, { ...(ngDevMode ? { debugName: "groupExpansionDefault" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
    /**
     * Property to which you can use for custom tracking of rows.
     * Example: 'name'
     */
    trackByProp = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "trackByProp" }] : /* istanbul ignore next */ []));
    /**
     * Property to which you can use for determining select all
     * rows on current page or not.
     */
    selectAllRowsOnPage = input(false, { ...(ngDevMode ? { debugName: "selectAllRowsOnPage" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
    /**
     * A flag for row virtualization on / off
     */
    virtualization = input(true, { ...(ngDevMode ? { debugName: "virtualization" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
    /**
     * Tree from relation
     */
    treeFromRelation = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "treeFromRelation" }] : /* istanbul ignore next */ []));
    /**
     * Tree to relation
     */
    treeToRelation = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "treeToRelation" }] : /* istanbul ignore next */ []));
    /**
     * A flag for switching summary row on / off
     */
    summaryRow = input(false, { ...(ngDevMode ? { debugName: "summaryRow" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
    /**
     * A height of summary row
     */
    summaryHeight = input(30, { ...(ngDevMode ? { debugName: "summaryHeight" } : /* istanbul ignore next */ {}), transform: numberAttribute });
    /**
     * A property holds a summary row position: top/bottom
     */
    summaryPosition = input('top', /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "summaryPosition" }] : /* istanbul ignore next */ []));
    /**
     * A function you can use to check whether you want
     * to disable a row. Example:
     *
     *    (row) => {
     *      return row.name !== 'Ethel Price';
     *    }
     */
    disableRowCheck = input(/* @ts-ignore */
    ...(ngDevMode ? [undefined, { debugName: "disableRowCheck" }] : /* istanbul ignore next */ []));
    /**
     * 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.
     */
    rowDraggable = input(false, { ...(ngDevMode ? { debugName: "rowDraggable" } : /* istanbul ignore next */ {}), 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.
     */
    enableClearingSortState = input(false, { ...(ngDevMode ? { debugName: "enableClearingSortState" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
    /**
     * Controls whether the datatable runs an {@link IterableDiffer} against the
     * `rows` input on every change detection cycle to detect additions, removals
     * and reorderings that happen in-place on the same array reference.
     *
     * Enabled by default. Set to `false` as a performance optimization when you
     * always pass a new `rows` array reference on updates.
     */
    checkRowListChanges = input(true, { ...(ngDevMode ? { debugName: "checkRowListChanges" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
    /**
     * Controls whether each rendered row runs a {@link KeyValueDiffer} against
     * its row object on every change detection cycle to detect in-place property
     * mutations (e.g. `row.name = 'new'` without replacing the row reference).
     *
     * Enabled by default. Set to `false` as a performance optimization when row
     * objects are treated as immutable.
     */
    checkRowPropertyChanges = input(true, { ...(ngDevMode ? { debugName: "checkRowPropertyChanges" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
    /**
     * Body was scrolled typically in a `scrollbarV:true` scenario.
     */
    scroll = output();
    /**
     * A cell or row was focused via keyboard or mouse click.
     */
    activate = output();
    /**
     * The table was paged either triggered by the pager or the body scroll.
     */
    page = output();
    /**
     * Columns were re-ordered.
     */
    reorder = output();
    /**
     * Column was resized.
     */
    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.
     */
    tableContextmenu = output();
    /**
     * A row was expanded ot collapsed for tree
     */
    treeAction = output();
    /**
     * Emits HTML5 native drag events.
     * Only emits dragenter, dragover, drop events by default.
     * Set {@link rowDraggable} to true for dragstart and dragend.
     */
    rowDragEvents = output();
    /**
     * Column templates gathered from `ContentChildren`
     * if described in your markup.
     */
    columnTemplates = contentChildren(DataTableColumnDirective, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "columnTemplates" }] : /* istanbul ignore next */ []));
    /**
     * Row Detail templates gathered from the ContentChild
     */
    rowDetail;
    /**
     * Group Header templates gathered from the ContentChild
     */
    groupHeader;
    /**
     * Custom summary row template gathered from the ContentChild
     */
    summaryRowDirective = contentChild(DatatableSummaryRowDirective, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "summaryRowDirective" }] : /* istanbul ignore next */ []));
    /**
     * Footer template gathered from the ContentChild
     * @internal
     */
    _footer = contentChild(DatatableFooterDirective, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "_footer" }] : /* istanbul ignore next */ []));
    _bodyComponent = viewChild.required(DataTableBodyComponent, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "_bodyComponent" }] : /* istanbul ignore next */ []));
    _headerElement = viewChild(DataTableHeaderComponent, { ...(ngDevMode ? { debugName: "_headerElement" } : /* istanbul ignore next */ {}), read: (ElementRef) });
    /**
     * The `role="table"` element. This is the css-grid that owns both the
     * horizontal and vertical scroll (Option A: single scroll container).
     */
    _scrollContainer = viewChild.required(ScrollContainerDirective, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "_scrollContainer" }] : /* istanbul ignore next */ []));
    /** @internal */
    _rowDefTemplate = contentChild(DatatableRowDefDirective, { ...(ngDevMode ? { debugName: "_rowDefTemplate" } : /* istanbul ignore next */ {}), read: TemplateRef });
    /**
     * Returns if all rows are selected.
     */
    allRowsSelected = computed(() => {
        const selected = this.selected();
        let allRowsSelected = 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);
    }, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "allRowsSelected" }] : /* istanbul ignore next */ []));
    _innerWidth = computed(() => this.dimensions().width, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "_innerWidth" }] : /* istanbul ignore next */ []));
    pageSize = computed(() => this.calcPageSize(), /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "pageSize" }] : /* istanbul ignore next */ []));
    viewportRowCount = computed(() => {
        const size = Math.ceil(this.bodyHeight() / this.rowHeight());
        return Math.max(size, 0);
    }, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "viewportRowCount" }] : /* istanbul ignore next */ []));
    _isFixedHeader = computed(() => {
        const headerHeight = this.headerHeight();
        return typeof headerHeight === 'string' ? headerHeight !== 'auto' : true;
    }, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "_isFixedHeader" }] : /* istanbul ignore next */ []));
    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;
    }, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "bodyHeight" }] : /* istanbul ignore next */ []));
    rowCount = computed(() => this.calcRowCount(), /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "rowCount" }] : /* istanbul ignore next */ []));
    /** This counter is increased, when the rowDiffer detects a change. This will cause an update of _internalRows. */
    _rowDiffCount = signal(0, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "_rowDiffCount" }] : /* istanbul ignore next */ []));
    _offsetX = 0;
    _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()) {
            const ghostRowCount = Math.max(this.viewportRowCount() - rows.length, 1);
            for (let i = 0; i < ghostRowCount; i++) {
                rows.push(undefined);
            }
        }
        return rows;
    }, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "_internalRows" }] : /* istanbul ignore next */ []));
    _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;
    }, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "_internalGroupedRows" }] : /* istanbul ignore next */ []));
    // TODO: consider removing internal modifications of the columns.
    // This requires a different strategy for certain properties like width.
    _internalColumns = linkedSignal(() => toInternalColumn(this.columnTemplates().length
        ? this.columnTemplates().map(c => c.column())
        : (this.columns() ?? []), this._defaultColumnWidth), /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "_internalColumns" }] : /* istanbul ignore next */ []));
    /**
     * The shared `grid-template-columns` definition for the combined css-grid.
     * It is exposed once as a custom property on the scroll container so the
     * header and every body row align to the same column tracks via `var()`,
     * instead of each row binding its own (identical) template string.
     */
    _gridTemplateColumns = computed(() => gridColumnTemplate(columnsByPinArr(this._internalColumns())), /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "_gridTemplateColumns" }] : /* istanbul ignore next */ []));
    /**
     * Computed signal that returns the corrected offset value.
     * It ensures the offset is within valid bounds based on rowCount and pageSize.
     */
    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);
    }, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "correctedOffset" }] : /* istanbul ignore next */ []));
    totalColumnGroupWidths = computed(() => {
        const colsByPin = columnsByPin(this._internalColumns());
        return columnGroupWidths(colsByPin, this._internalColumns()).total;
    }, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "totalColumnGroupWidths" }] : /* istanbul ignore next */ []));
    _subscriptions = [];
    _defaultColumnWidth = this.globalConfiguration.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.
     */
    _footerComponent = viewChild(DataTableFooterComponent, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "_footerComponent" }] : /* istanbul ignore next */ []));
    verticalScrollVisible = false;
    dimensions = signal({ height: 0, width: 0 }, { ...(ngDevMode ? { debugName: "dimensions" } : /* istanbul ignore next */ {}), equal: (a, b) => a.width === b.width && a.height === b.height });
    /** Re-measures the table whenever the host element's size changes. */
    resizeObserver;
    /** Pending debounce timer for the {@link resizeObserver} callback. */
    resizeDebounce;
    constructor() {
        effect(() => this.recalculateColumns());
        afterNextRender(() => {
            this.resizeObserver = new ResizeObserver(entries => {
                const borderBox = entries[entries.length - 1]?.borderBoxSize?.[0];
                if (!borderBox) {
                    return;
                }
                clearTimeout(this.resizeDebounce);
                this.resizeDebounce = setTimeout(() => {
                    this.dimensions.set({ width: borderBox.inlineSize, height: borderBox.blockSize });
                }, 5);
            });
            this.resizeObserver.observe(this.element);
            this.dimensions.set(this.element.getBoundingClientRect());
        });
    }
    /*
     * Lifecycle hook that is called when Angular dirty checks a directive.
     */
    ngDoCheck() {
        const rowDiffers = this.checkRowListChanges() ? this.rowDiffer.diff(this.rows()) : null;
        if (rowDiffers || this.disableRowCheck()) {
            this._rowDiffCount.update(count => count + 1);
            this.cd.markForCheck();
        }
    }
    /**
     * Lifecycle hook that is called after a component's
     * view has been fully initialized.
     */
    ngAfterViewInit() {
        // emit page for virtual server-side kickoff
        if (this.externalPaging() && this.scrollbarV()) {
            queueMicrotask(() => this.page.emit({
                count: this.count(),
                pageSize: this.pageSize(),
                limit: this.limit(),
                offset: 0,
                sorts: this.sorts()
            }));
        }
    }
    /**
     * 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`)
     */
    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;
        }
    }, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "rowIdentity" }] : /* istanbul ignore next */ []));
    /**
     * 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]));
    }
    /**
     * @deprecated No-op. Dimensions are kept current by a `ResizeObserver` on the
     * host element; this will be removed in a future release.
     */
    recalculate() { }
    /**
     * @deprecated No-op. The `window:resize` listener was replaced by a
     * `ResizeObserver`; this will be removed in a future release.
     */
    onWindowResize() { }
    /**
     * Recalulcates the column widths based on column width
     * distribution mode and scrollbar offsets.
     */
    recalculateColumns(forceIdx = -1, allowBleed = this.scrollbarH()) {
        let width = this._innerWidth();
        const columns = this._internalColumns();
        if (!width) {
            return [];
        }
        this.verticalScrollVisible = this._scrollContainer().verticalScrollVisible;
        if (this.scrollbarV() || this.scrollbarVDynamic()) {
            width = width - (this.verticalScrollVisible ? this.scrollbarHelper.width : 0);
        }
        // TODO: this is a temporary workaround to avoid signal writes in a computed.
        // Later, a computed adjustedWidth has to be added to the internal column to avoid this.
        untracked(() => {
            if (this.columnMode() === 'force') {
                forceFillColumnWidths(columns, width, forceIdx, allowBleed, this._defaultColumnWidth, this.scrollbarHelper.width);
            }
            else if (this.columnMode() === 'flex') {
                adjustColumnWidths(columns, width);
            }
        });
        return columns;
    }
    /**
     * @deprecated No-op. Dimensions are kept current by a `ResizeObserver` on the
     * host element; this will be removed in a future release.
     */
    recalculateDims() { }
    /**
     * 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([]);
        }
    }
    /**
     * Recalculates the sizes of the page
     */
    calcPageSize() {
        if (this.scrollbarV() && this.virtualization()) {
            return this.viewportRowCount();
        }
        // if limit is passed, we are paging
        const limit = this.limit();
        if (limit !== undefined) {
            return limit;
        }
        // otherwise use row length
        return this._internalRows().length;
    }
    /**
     * 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: 'header',
            content: toPublicColumn(column)
        });
    }
    /**
     * The body triggered a contextmenu event.
     */
    onRowContextmenu({ event, row }) {
        this.tableContextmenu.emit({ event, type: '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();
        cols[idx].width.set(newValue);
        // set this so we can force the column
        // width distribution to be to this value
        cols[idx].$$oldWidth = newValue;
        this.recalculateColumns(idx);
        this.resize.emit({
            column: toPublicColumn(column),
            newValue,
            prevValue
        });
    }
    onColumnResizing({ column, newValue }) {
        if (column === undefined) {
            return;
        }
        column.width.set(newValue);
        column.$$oldWidth = newValue;
        const idx = this._internalColumns().indexOf(column);
        this.recalculateColumns(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, column: toPublicColumn(event.column) });
    }
    /**
     * The header triggered a column sort event.
     */
    onColumnSort(event) {
        // clean selected rows
        if (this.selectAllRowsOnPage()) {
            this.selected.set([]);
        }
        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()
        });
    }
    /**
     * 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([]);
            }
        }
    }
    /**
     * 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._rowDiffCount.update(v => v + 1);
        this.treeAction.emit({ row, rowIndex });
    }
    ngOnDestroy() {
        this.resizeObserver?.disconnect();
        clearTimeout(this.resizeDebounce);
        this._subscriptions.forEach(subscription => subscription.unsubscribe());
    }
    scrollToRow(row, options) {
        if (!this.scrollbarV()) {
            throw new Error('Vertical scrolling is not enabled.');
        }
        // TODO: We could / should add support for all those cases below.
        if (this._internalGroupedRows()?.length) {
            throw new Error('Scrolling is not supported with grouped rows.');
        }
        if (this.limit()) {
            throw new Error('Scrolling is not supported with limit');
        }
        if (this.treeFromRelation() && this.treeToRelation()) {
            this.scrollToRowTree(row, options);
            return;
        }
        const index = this._internalRows().indexOf(row);
        if (index === -1) {
            throw new Error(`Row not found: ${row}`);
        }
        // Here we have ensured, that we have only one page and the row exists.
        // Now we just need to scroll to that row.
        this._bodyComponent().scrollToIndex(index, options);
    }
    scrollToRowTree(row, options, afterExpand = false) {
        const index = this._internalRows().indexOf(row);
        if (index !== -1) {
            this._bodyComponent().scrollToIndex(index, options);
            return;
        }
        if (afterExpand) {
            throw new Error(`Row not found: ${row}`);
        }
        expandToRow(row, this.rows() ?? [], optionalGetterForProp(this.treeFromRelation()), optionalGetterForProp(this.treeToRelation()));
        this._rowDiffCount.update(v => v + 1);
        // We need a setTimeout to wait until the DOM was updated
        setTimeout(() => this.scrollToRowTree(row, options, true));
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: DatatableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", 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 }, checkRowListChanges: { classPropertyName: "checkRowListChanges", publicName: "checkRowListChanges", isSignal: true, isRequired: false, transformFunction: null }, checkRowPropertyChanges: { classPropertyName: "checkRowPropertyChanges", publicName: "checkRowPropertyChanges", 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", page: "page", reorder: "reorder", resize: "resize", tableContextmenu: "tableContextmenu", treeAction: "treeAction", rowDragEvents: "rowDragEvents" }, host: { 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\"", "class.horizontal-overflow": "_innerWidth() < totalColumnGroupWidths()" }, classAttribute: "ngx-datatable" }, providers: [
            {
                provide: DATATABLE_COMPONENT_TOKEN,
                useExisting: DatatableComponent
            },
            {
                provide: DatatableConfiguration,
                useFactory: () => inject(DatatableComponent).datatableConfiguration
            }
        ], queries: [{ propertyName: "columnTemplates", predicate: DataTableColumnDirective, isSignal: true }, { propertyName: "summaryRowDirective", first: true, predicate: DatatableSummaryRowDirective, descendants: true, 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: "_scrollContainer", first: true, predicate: ScrollContainerDirective, descendants: true, isSignal: true }, { propertyName: "_footerComponent", first: true, predicate: DataTableFooterComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"datatable-wrapper\">\n  <div\n    datatableScrollContainer\n    role=\"table\"\n    class=\"datatable-grid\"\n    [style.--ngx-datatable-grid-template-columns]=\"_gridTemplateColumns()\"\n    [style.scroll-padding-block-start.px]=\"_isFixedHeader() ? headerHeight() : null\"\n  >\n    @if (headerHeight()) {\n      <datatable-header\n        role=\"rowgroup\"\n        [sorts]=\"sorts()\"\n        [sortType]=\"sortType()\"\n        [scrollbarH]=\"scrollbarH()\"\n        [dealsWithGroup]=\"_internalGroupedRows() !== undefined\"\n        [columns]=\"_internalColumns()\"\n        [reorderable]=\"reorderable()\"\n        [targetMarkerTemplate]=\"targetMarkerTemplate()\"\n        [allRowsSelected]=\"allRowsSelected()\"\n        [selectionType]=\"selectionType()\"\n        [verticalScrollVisible]=\"verticalScrollVisible\"\n        [enableClearingSortState]=\"enableClearingSortState()\"\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      [rowCount]=\"rowCount()\"\n      [offset]=\"correctedOffset()\"\n      [trackByProp]=\"trackByProp()\"\n      [columns]=\"_internalColumns()\"\n      [pageSize]=\"pageSize()\"\n      [offsetX]=\"_offsetX\"\n      [rowDetail]=\"rowDetail\"\n      [groupHeader]=\"groupHeader\"\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      [summaryRowTemplate]=\"summaryRowDirective()?.template\"\n      [verticalScrollVisible]=\"verticalScrollVisible\"\n      [disableRowCheck]=\"disableRowCheck()\"\n      [checkRowPropertyChanges]=\"checkRowPropertyChanges()\"\n      [rowDraggable]=\"rowDraggable()\"\n      [rowDragEvents]=\"rowDragEvents\"\n      [rowDefTemplate]=\"_rowDefTemplate()\"\n      [(selected)]=\"selected\"\n      (page)=\"onBodyPage($event)\"\n      (activate)=\"activate.emit($event)\"\n      (rowContextmenu)=\"onRowContextmenu($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 class=\"empty-row\" [innerHTML]=\"configuration().messages.emptyMessage\"></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      [footerTemplate]=\"_footer()\"\n      [pagerLeftArrowIcon]=\"configuration().cssClasses.pagerLeftArrow\"\n      [pagerRightArrowIcon]=\"configuration().cssClasses.pagerRightArrow\"\n      [pagerPreviousIcon]=\"configuration().cssClasses.pagerPrevious\"\n      [selectedCount]=\"selected().length\"\n      [selectedMessage]=\"!!selectionType()\"\n      [pagerNextIcon]=\"configuration().cssClasses.pagerNext\"\n      (page)=\"onFooterPage($event)\"\n    />\n  }\n</div>\n", styles: [":host{display:block;overflow:hidden;position:relative;transform:translateZ(0)}.datatable-wrapper{display:flex;flex-direction:column;block-size:100%;min-block-size:0}.datatable-grid{display:grid;grid-template-columns:var(--ngx-datatable-grid-template-columns, auto);grid-template-rows:auto 1fr;position:relative;max-inline-size:100%;min-block-size:0}:host(.scroll-horz) .datatable-grid{overflow-x:auto;-webkit-overflow-scrolling:touch}:host(.scroll-vertical) .datatable-grid{overflow-y:auto;flex:1 1 0}.datatable-empty-row{grid-column:1/-1}\n"], dependencies: [{ kind: "directive", type: ScrollContainerDirective, selector: "[datatableScrollContainer]" }, { kind: "component", type: DataTableHeaderComponent, selector: "datatable-header", inputs: ["scrollbarH", "dealsWithGroup", "targetMarkerTemplate", "enableClearingSortState", "sorts", "sortType", "allRowsSelected", "selectionType", "reorderable", "verticalScrollVisible", "columns"], outputs: ["sort", "reorder", "resize", "resizing", "select", "columnContextmenu"] }, { kind: "component", type: DataTableBodyComponent, selector: "datatable-body", inputs: ["rowDefTemplate", "scrollbarV", "scrollbarH", "loadingIndicator", "ghostLoadingIndicator", "externalPaging", "offsetX", "selectionType", "selected", "rowIdentity", "rowDetail", "groupHeader", "selectCheck", "displayCheck", "trackByProp", "rowClass", "groupedRows", "groupExpansionDefault", "virtualization", "summaryRow", "summaryPosition", "summaryHeight", "summaryRowTemplate", "rowDraggable", "rowDragEvents", "disableRowCheck", "checkRowPropertyChanges", "pageSize", "rows", "columns", "offset", "rowCount", "bodyHeight", "verticalScrollVisible"], outputs: ["offsetXChange", "selectedChange", "scroll", "page", "activate", "rowContextmenu", "treeAction"] }, { kind: "component", type: DataTableFooterComponent, selector: "datatable-footer", inputs: ["rowCount", "groupCount", "pageSize", "offset", "pagerLeftArrowIcon", "pagerRightArrowIcon", "pagerPreviousIcon", "pagerNextIcon", "footerTemplate", "selectedCount", "selectedMessage"], outputs: ["page"] }, { kind: "component", type: ProgressBarComponent, selector: "datatable-progress" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: DatatableComponent, decorators: [{
            type: Component,
            args: [{ selector: 'ngx-datatable', imports: [
                        ScrollContainerDirective,
                        DataTableHeaderComponent,
                        DataTableBodyComponent,
                        DataTableFooterComponent,
                        ProgressBarComponent
                    ], providers: [
                        {
                            provide: DATATABLE_COMPONENT_TOKEN,
                            useExisting: DatatableComponent
                        },
                        {
                            provide: DatatableConfiguration,
                            useFactory: () => inject(DatatableComponent).datatableConfiguration
                        }
                    ], 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"',
                        '[class.horizontal-overflow]': '_innerWidth() < totalColumnGroupWidths()'
                    }, template: "<div class=\"datatable-wrapper\">\n  <div\n    datatableScrollContainer\n    role=\"table\"\n    class=\"datatable-grid\"\n    [style.--ngx-datatable-grid-template-columns]=\"_gridTemplateColumns()\"\n    [style.scroll-padding-block-start.px]=\"_isFixedHeader() ? headerHeight() : null\"\n  >\n    @if (headerHeight()) {\n      <datatable-header\n        role=\"rowgroup\"\n        [sorts]=\"sorts()\"\n        [sortType]=\"sortType()\"\n        [scrollbarH]=\"scrollbarH()\"\n        [dealsWithGroup]=\"_internalGroupedRows() !== undefined\"\n        [columns]=\"_internalColumns()\"\n        [reorderable]=\"reorderable()\"\n        [targetMarkerTemplate]=\"targetMarkerTemplate()\"\n        [allRowsSelected]=\"allRowsSelected()\"\n        [selectionType]=\"selectionType()\"\n        [verticalScrollVisible]=\"verticalScrollVisible\"\n        [enableClearingSortState]=\"enableClearingSortState()\"\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      [rowCount]=\"rowCount()\"\n      [offset]=\"correctedOffset()\"\n      [trackByProp]=\"trackByProp()\"\n      [columns]=\"_internalColumns()\"\n      [pageSize]=\"pageSize()\"\n      [offsetX]=\"_offsetX\"\n      [rowDetail]=\"rowDetail\"\n      [groupHeader]=\"groupHeader\"\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      [summaryRowTemplate]=\"summaryRowDirective()?.template\"\n      [verticalScrollVisible]=\"verticalScrollVisible\"\n      [disableRowCheck]=\"disableRowCheck()\"\n      [checkRowPropertyChanges]=\"checkRowPropertyChanges()\"\n      [rowDraggable]=\"rowDraggable()\"\n      [rowDragEvents]=\"rowDragEvents\"\n      [rowDefTemplate]=\"_rowDefTemplate()\"\n      [(selected)]=\"selected\"\n      (page)=\"onBodyPage($event)\"\n      (activate)=\"activate.emit($event)\"\n      (rowContextmenu)=\"onRowContextmenu($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 class=\"empty-row\" [innerHTML]=\"configuration().messages.emptyMessage\"></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      [footerTemplate]=\"_footer()\"\n      [pagerLeftArrowIcon]=\"configuration().cssClasses.pagerLeftArrow\"\n      [pagerRightArrowIcon]=\"configuration().cssClasses.pagerRightArrow\"\n      [pagerPreviousIcon]=\"configuration().cssClasses.pagerPrevious\"\n      [selectedCount]=\"selected().length\"\n      [selectedMessage]=\"!!selectionType()\"\n      [pagerNextIcon]=\"configuration().cssClasses.pagerNext\"\n      (page)=\"onFooterPage($event)\"\n    />\n  }\n</div>\n", styles: [":host{display:block;overflow:hidden;position:relative;transform:translateZ(0)}.datatable-wrapper{display:flex;flex-direction:column;block-size:100%;min-block-size:0}.datatable-grid{display:grid;grid-template-columns:var(--ngx-datatable-grid-template-columns, auto);grid-template-rows:auto 1fr;position:relative;max-inline-size:100%;min-block-size:0}:host(.scroll-horz) .datatable-grid{overflow-x:auto;-webkit-overflow-scrolling:touch}:host(.scroll-vertical) .datatable-grid{overflow-y:auto;flex:1 1 0}.datatable-empty-row{grid-column:1/-1}\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 }] }], checkRowListChanges: [{ type: i0.Input, args: [{ isSignal: true, alias: "checkRowListChanges", required: false }] }], checkRowPropertyChanges: [{ type: i0.Input, args: [{ isSignal: true, alias: "checkRowPropertyChanges", required: false }] }], scroll: [{ type: i0.Output, args: ["scroll"] }], activate: [{ type: i0.Output, args: ["activate"] }], 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]
            }], summaryRowDirective: [{ type: i0.ContentChild, args: [i0.forwardRef(() => DatatableSummaryRowDirective), { isSignal: true }] }], _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 }] }], _scrollContainer: [{ type: i0.ViewChild, args: [i0.forwardRef(() => ScrollContainerDirective), { 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 }] }] } });

/**
 * 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 {
    elementRef = inject(ElementRef);
    disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
    constructor() {
        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 ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: DisableRowDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.8", 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: "22.0.8", 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 NgxDatatableConfig
     * @param configuration
     */
    static forRoot(configuration) {
        return {
            ngModule: NgxDatatableModule,
            providers: [providedNgxDatatableConfig(configuration)]
        };
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: NgxDatatableModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
    static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.0.8", ngImport: i0, type: NgxDatatableModule, imports: [DataTableFooterTemplateDirective,
            DatatableComponent,
            DataTableColumnDirective,
            DatatableRowDetailDirective,
            DatatableGroupHeaderDirective,
            DatatableRowDetailTemplateDirective,
            DataTableColumnHeaderDirective,
            DataTableColumnCellDirective,
            DataTableColumnGhostCellDirective,
            DataTableColumnCellTreeToggle,
            DatatableFooterDirective,
            DatatablePagerComponent,
            DatatableGroupHeaderTemplateDirective,
            DisableRowDirective,
            DatatableRowDefComponent,
            DatatableRowDefDirective,
            DatatableSummaryRowDirective], exports: [DatatableComponent,
            DatatableRowDetailDirective,
            DatatableGroupHeaderDirective,
            DatatableRowDetailTemplateDirective,
            DataTableColumnDirective,
            DataTableColumnHeaderDirective,
            DataTableColumnCellDirective,
            DataTableColumnGhostCellDirective,
            DataTableColumnCellTreeToggle,
            DataTableFooterTemplateDirective,
            DatatableFooterDirective,
            DatatablePagerComponent,
            DatatableGroupHeaderTemplateDirective,
            DisableRowDirective,
            DatatableRowDefComponent,
            DatatableRowDefDirective,
            DatatableSummaryRowDirective] });
    static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: NgxDatatableModule });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", 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,
                        DatatableSummaryRowDirective
                    ],
                    exports: [
                        DatatableComponent,
                        DatatableRowDetailDirective,
                        DatatableGroupHeaderDirective,
                        DatatableRowDetailTemplateDirective,
                        DataTableColumnDirective,
                        DataTableColumnHeaderDirective,
                        DataTableColumnCellDirective,
                        DataTableColumnGhostCellDirective,
                        DataTableColumnCellTreeToggle,
                        DataTableFooterTemplateDirective,
                        DatatableFooterDirective,
                        DatatablePagerComponent,
                        DatatableGroupHeaderTemplateDirective,
                        DisableRowDirective,
                        DatatableRowDefComponent,
                        DatatableRowDefDirective,
                        DatatableSummaryRowDirective
                    ]
                }]
        }] });

/**
 * @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'
};

/*
 * 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, DatatableSummaryRowDirective, DisableRowDirective, NgxDatatableModule, SelectionType, SortDirection, SortType, providedNgxDatatableConfig };
//# sourceMappingURL=siemens-ngx-datatable.mjs.map