import * as _angular_core from '@angular/core';
import { TemplateRef, Signal, WritableSignal } from '@angular/core';
import { MTIcon } from '@masterteam/icons';
import { ConfirmationConfig, ConfirmationService } from '@masterteam/components/confirmation';
import * as primeng_api from 'primeng/api';
import { TreeNode, MenuItem } from 'primeng/api';
import { TranslocoService } from '@jsverse/transloco';
import { TablePageEvent } from 'primeng/table';
import { EntityData } from '@masterteam/components/entities';
import { ControlValueAccessor } from '@angular/forms';
import { Popover } from 'primeng/popover';
import { TieredMenu } from 'primeng/tieredmenu';

/**
 * Table action confirmation config with optional event
 */
type TableActionConfirmationConfig = Omit<ConfirmationConfig, 'event'> & {
    event?: Event;
    confirmationType?: 'delete';
};
/**
 * Defines the options for a select filter.
 */
interface FilterOption {
    label: string;
    value: any;
}
/**
 * Configuration for filtering on a specific column.
 */
interface FilterConfig {
    type: 'text' | 'select' | 'userSelect' | 'treeSelect' | 'date' | 'boolean' | 'user' | 'numberRange';
    label?: string;
    options?: FilterOption[];
    treeOptions?: TreeNode[];
    /**
     * Controls multi-select behaviour for `select` / `userSelect` filters.
     * Defaults to `true` — opt out with `multiple: false` for a single-select.
     * The stored filter value is an array; rows match if the cell value matches
     * *any* selected entry.
     */
    multiple?: boolean;
    [key: string]: unknown;
}
/**
 * Filter value for date range, numeric range, or simple value
 */
interface FilterValue {
    value?: any;
    from?: Date | number | null;
    to?: Date | number | null;
}
interface TableStatusMapValue {
    display?: string;
    color?: string;
    description?: string;
}
/**
 * Table filters map
 */
type TableFilters = Record<string, FilterValue | any>;
/**
 * Column type definition
 */
type ColumnType = 'text' | 'number' | 'boolean' | 'date' | 'dateTime' | 'user' | 'status' | 'entity' | 'custom';
/**
 * Event emitted when a cell value changes
 */
interface CellChangeEvent {
    row: any;
    column: string;
    value: any;
    type: ColumnTypeForActionCell;
}
type ColumnTypeForActionCell = 'boolean';
type TableActionShape = 'flat' | 'popover';
/**
 * Filter UX mode for a table.
 *
 * - `popover`: single top-right funnel button opening a form with every filter.
 * - `column`:  per-column funnel icon next to each filterable header.
 *
 * Add new modes here + a matching branch in the table header template.
 */
type TableFilterMode = 'popover' | 'column';
/**
 * Injected value resolver for export/print — caller decides how a cell value
 * becomes a scalar for Excel/PDF output. Keeps TableExportService
 * schema-agnostic (open/closed for new column types).
 */
type TableExportValueResolver = (row: unknown, column: ColumnDef) => string | number | boolean | null;
interface TableExportConfig {
    rows: any[];
    columns: ColumnDef[];
    filename: string;
    resolveValue: TableExportValueResolver;
}
interface TablePrintConfig extends TableExportConfig {
    title?: string;
}
interface ColumnDef {
    key: string;
    label: string;
    type?: ColumnType;
    customCellTpl?: TemplateRef<any>;
    filterConfig?: FilterConfig;
    statusMap?: Record<string, TableStatusMapValue>;
    sortable?: boolean;
    readonly?: boolean;
    width?: string;
    filterOnly?: boolean;
}
interface TableAction {
    icon?: MTIcon | undefined;
    color?: 'info' | 'success' | 'warn' | 'danger' | 'secondary' | 'contrast' | 'help' | 'primary';
    variant?: 'text' | 'outlined' | undefined;
    label?: string;
    tooltip?: string;
    hidden?: (row: any) => boolean;
    action: (row: any) => void;
    loading?: (row: any) => boolean;
    confirmation?: TableActionConfirmationConfig;
}

/**
 * Pure controller owning all row-grouping concerns. Table instantiates one and
 * binds its signals — keeps grouping logic out of table.ts.
 *
 * PrimeNG's subheader grouping renders only when `sortField === groupRowsBy`.
 * `setGroup` therefore also pins the sort to the grouped column; clearing the
 * group leaves the user's sort untouched.
 */
declare class TableGroupingController {
    private readonly columns;
    private readonly rows;
    private readonly groupBy;
    private readonly sortField;
    private readonly sortDirection;
    private readonly transloco?;
    constructor(columns: Signal<ColumnDef[]>, rows: Signal<unknown[]>, groupBy: WritableSignal<string | null>, sortField: WritableSignal<string | null>, sortDirection: WritableSignal<'asc' | 'desc' | null>, transloco?: TranslocoService | undefined);
    private translate;
    readonly groupableColumns: Signal<ColumnDef[]>;
    /**
     * Row counts per group key — consumed by the group header template so each
     * subheader can show "Status: Active (12)".
     */
    readonly groupCounts: Signal<Map<string, number>>;
    getGroupCount(row: unknown): number;
    readonly activeGroupColumn: Signal<ColumnDef | null>;
    readonly groupingActive: Signal<boolean>;
    /**
     * Returns true when the given column is the active group column and
     * therefore cannot have its sort cleared (PrimeNG requirement).
     */
    isGroupLockedSort(columnKey: string): boolean;
    setGroup(key: string | null): void;
    /**
     * Display label for a row's grouped value — used by the `#groupheader`
     * template. Leverages the same resolver pipeline the cells use, so status
     * maps / user display names render consistently.
     */
    getGroupLabel(row: unknown): string;
    /**
     * Accent color for status/entity-Status group headers. Reused from the
     * cell renderer's status-map pipeline so tint is consistent with the cell.
     */
    getGroupAccentColor(row: unknown): string | null;
    /** Stable key used to bucket rows into groups — normalised to string. */
    private getGroupKey;
}

declare class Table {
    private static readonly LOADING_COLUMN_COUNT;
    selectionChange: _angular_core.OutputEmitterRef<any[]>;
    cellChange: _angular_core.OutputEmitterRef<CellChangeEvent>;
    lazyLoad: _angular_core.OutputEmitterRef<any>;
    columnReorder: _angular_core.OutputEmitterRef<any>;
    rowReorder: _angular_core.OutputEmitterRef<any>;
    rowClick: _angular_core.OutputEmitterRef<any>;
    /**
     * Fires when the per-row actions popover is opened (3-dots click) so the
     * parent can lazy-load row-specific actions instead of fetching for every
     * visible row up front. Only emitted when `actionShape` is `popover`.
     */
    rowActionsRequested: _angular_core.OutputEmitterRef<any>;
    filters: _angular_core.ModelSignal<TableFilters>;
    data: _angular_core.InputSignal<any[]>;
    columns: _angular_core.InputSignal<ColumnDef[]>;
    rowActions: _angular_core.InputSignal<TableAction[]>;
    size: _angular_core.InputSignal<"small" | "large" | undefined>;
    showGridlines: _angular_core.InputSignalWithTransform<boolean, unknown>;
    stripedRows: _angular_core.InputSignalWithTransform<boolean, unknown>;
    selectableRows: _angular_core.InputSignalWithTransform<boolean, unknown>;
    clickableRows: _angular_core.InputSignalWithTransform<boolean, unknown>;
    generalSearch: _angular_core.InputSignalWithTransform<boolean, unknown>;
    lazyLocalSearch: _angular_core.InputSignalWithTransform<boolean, unknown>;
    showFilters: _angular_core.InputSignalWithTransform<boolean, unknown>;
    filterMode: _angular_core.InputSignal<TableFilterMode>;
    loading: _angular_core.InputSignalWithTransform<boolean, unknown>;
    updating: _angular_core.InputSignalWithTransform<boolean, unknown>;
    lazy: _angular_core.InputSignalWithTransform<boolean, unknown>;
    lazyLocalSort: _angular_core.InputSignalWithTransform<boolean, unknown>;
    lazyTotalRecords: _angular_core.InputSignal<number | undefined>;
    reorderableColumns: _angular_core.InputSignalWithTransform<boolean, unknown>;
    reorderableRows: _angular_core.InputSignalWithTransform<boolean, unknown>;
    dataKey: _angular_core.InputSignal<string | undefined>;
    storageKey: _angular_core.InputSignal<string | null>;
    storageMode: _angular_core.InputSignal<"local" | "session">;
    exportable: _angular_core.InputSignalWithTransform<boolean, unknown>;
    printable: _angular_core.InputSignalWithTransform<boolean, unknown>;
    groupable: _angular_core.InputSignalWithTransform<boolean, unknown>;
    cellClickFilter: _angular_core.InputSignalWithTransform<boolean, unknown>;
    /**
     * When true and `rowActions` is non-empty, the trailing actions column is
     * pinned to the right via PrimeNG's frozen-column support. The table also
     * switches to scrollable mode so horizontal scrolling reveals the rest of
     * the columns while the actions stay visible. Off by default to preserve
     * existing layout for tables that don't opt in.
     */
    freezeActions: _angular_core.InputSignalWithTransform<boolean, unknown>;
    printTitle: _angular_core.InputSignal<string>;
    exportFilename: _angular_core.InputSignal<string>;
    actionShape: _angular_core.InputSignal<TableActionShape>;
    /**
     * Optional per-row predicate. When it returns true for a given row, the
     * row-actions popover renders a small skeleton block instead of the action
     * list — used while a parent is fetching that row's actions on demand.
     */
    rowActionsLoadingFn: _angular_core.InputSignal<((row: any) => boolean) | null>;
    tableLayout: _angular_core.InputSignal<"fixed" | "auto">;
    noCard: _angular_core.InputSignalWithTransform<boolean, unknown>;
    private readonly dateFormat;
    tabs: _angular_core.InputSignal<any[] | undefined>;
    tabsOptionLabel: _angular_core.InputSignal<string>;
    tabsOptionValue: _angular_core.InputSignal<string>;
    activeTab: _angular_core.ModelSignal<any>;
    onTabChange: _angular_core.OutputEmitterRef<any>;
    actions: _angular_core.InputSignal<TableAction[]>;
    captionStartContent: _angular_core.Signal<TemplateRef<any> | undefined>;
    captionEndContent: _angular_core.Signal<TemplateRef<any> | undefined>;
    emptyContent: _angular_core.Signal<TemplateRef<any> | undefined>;
    paginatorPosition: _angular_core.InputSignal<"center" | "end" | "start">;
    alwaysShowPaginator: _angular_core.InputSignalWithTransform<boolean, unknown>;
    rowsPerPageOptions: _angular_core.InputSignal<number[]>;
    pageSize: _angular_core.ModelSignal<number>;
    currentPage: _angular_core.ModelSignal<number>;
    first: _angular_core.ModelSignal<number>;
    filterTerm: _angular_core.ModelSignal<string>;
    groupBy: _angular_core.ModelSignal<string | null>;
    sortField: _angular_core.WritableSignal<string | null>;
    sortDirection: _angular_core.WritableSignal<"desc" | "asc" | null>;
    confirmationService: ConfirmationService;
    private readonly exportService;
    private readonly transloco;
    protected readonly grouping: TableGroupingController;
    protected selectedRowKeys: _angular_core.WritableSignal<Set<string>>;
    protected transientSelectedRows: _angular_core.WritableSignal<Set<any>>;
    private readonly hydratedStorageKey;
    private readonly storageHydrated;
    protected readonly isColumnFilterMode: _angular_core.Signal<boolean>;
    protected filterableColumnMap: _angular_core.Signal<Map<string, ColumnDef>>;
    protected getFilterableColumn(key: string): ColumnDef | undefined;
    onColumnFilterChange(key: string, value: any): void;
    protected activeFilterCount: _angular_core.Signal<number>;
    protected filteredData: _angular_core.Signal<any[]>;
    protected renderedColumns: _angular_core.Signal<ColumnDef[]>;
    protected displayData: _angular_core.Signal<any[]>;
    protected totalRecords: _angular_core.Signal<number>;
    protected paginatedData: _angular_core.Signal<any[]>;
    protected allSelectedOnPage: _angular_core.Signal<boolean>;
    protected totalColumnSpan: _angular_core.Signal<number>;
    constructor();
    onFilterApplied(filters: TableFilters): void;
    onFilterReset(): void;
    protected matchesFilter(item: any, key: string, filterValue: FilterValue | any): boolean;
    toggleRow(row: any): void;
    toggleAllRowsOnPage(): void;
    getProperty(obj: any, key: string): any;
    protected getDateProperty(obj: any, key: string): string | number | Date | null;
    getEntityPreviewData(row: any, col: ColumnDef): EntityData | null;
    /**
     * Entity data resolver that abstracts over the `user` / `status` vs `entity`
     * distinction — used by the shared filterable-cell template so the three
     * cases don't duplicate markup.
     */
    resolveCellEntityData(row: any, col: ColumnDef): EntityData | null;
    tabChanged(tab: any): void;
    onTablePage(event: TablePageEvent): void;
    handleLazyLoad(event: any): void;
    onPaginatorPage(event: any): void;
    onSearchChange(searchTerm: string): void;
    toggleSort(column: ColumnDef): void;
    isColumnSortable(column: ColumnDef): boolean;
    getSortIcon(column: ColumnDef): MTIcon;
    onCellChange(row: any, columnKey: string, newValue: any, type?: ColumnTypeForActionCell): void;
    resolveActionLoading(action: TableAction, row: any): boolean | undefined;
    getVisibleRowActions(row: any): TableAction[];
    isRowActionsLoading(row: any): boolean;
    onRowActionsToggle(event: Event, popover: {
        toggle: (e: Event) => void;
    }, row: any): void;
    onColumnReorder(event: any): void;
    onRowReorder(event: any): void;
    onRowClick(event: MouseEvent, row: any): void;
    protected updatePagingFromEvent(event: any): void;
    protected emitLazyLoad(event: any): void;
    private lazyLoadFilters;
    private withoutGeneralSearch;
    exportExcel(): void;
    printPdf(): void;
    onCellFilterClick(event: Event, row: any, column: ColumnDef): void;
    isCellFilterActive(row: any, column: ColumnDef): boolean;
    isCellClickFilterable(column: ColumnDef, row: unknown): boolean;
    rowAction(event: Event, action: TableAction, row: any): void;
    private buildUserEntityData;
    private buildStatusEntityData;
    private resolveStatusValue;
    private unwrapStatusValue;
    private isEntityStatusCompatibilityColumn;
    private isStatusColumnKey;
    private resolveStatusMapValue;
    private resolveDefaultStatusColor;
    private normalizeStatusToken;
    private readStringProperty;
    /**
     * Gets the entity data for an 'entity' type column.
     * The row data is expected to already be in EntityData format.
     * Automatically hides entity name and configures User entities
     * to show only avatar + displayName.
     */
    getEntityColumnData(row: any, col: ColumnDef): EntityData | null;
    protected getStatusEntityAccentColor(row: Record<string, unknown>): string | null;
    private resolveStatusEntityAccentColor;
    protected getBooleanProperty(obj: any, key: string): boolean;
    private setProperty;
    private sortData;
    private getSortValue;
    /**
     * Export/print value resolver — same pipeline as `getColumnResolvedValue`
     * except date / dateTime columns (and their entity counterparts) are
     * formatted via the MT date pipe so Excel and PDF show locale-aware dates
     * instead of raw ISO strings. Sort path keeps the ISO form for ordering.
     */
    private getColumnExportValue;
    /**
     * Detects whether a column should be treated as a date for export purposes:
     * native `date` / `dateTime` types, or entity columns whose viewType is
     * `Date` / `DateTime`.
     */
    private resolveDateColumnType;
    private getColumnResolvedValue;
    protected isRowSelected(row: Record<string, unknown>): boolean;
    protected getColumnMinWidth(column: ColumnDef): string | null;
    private emitSelectionChange;
    private getSelectedRows;
    private getRowSelectionKey;
    private getNormalizedStorageKey;
    private getStorage;
    private buildPersistedState;
    private applyPersistedState;
    private shouldEmitLazyLoadAfterRestore;
    private readPersistedState;
    private writePersistedState;
    private toPositiveInteger;
    private normalizePersistedPageSize;
    private toNonNegativeInteger;
    static ɵfac: _angular_core.ɵɵFactoryDeclaration<Table, never>;
    static ɵcmp: _angular_core.ɵɵComponentDeclaration<Table, "mt-table", never, { "filters": { "alias": "filters"; "required": false; "isSignal": true; }; "data": { "alias": "data"; "required": true; "isSignal": true; }; "columns": { "alias": "columns"; "required": true; "isSignal": true; }; "rowActions": { "alias": "rowActions"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "showGridlines": { "alias": "showGridlines"; "required": false; "isSignal": true; }; "stripedRows": { "alias": "stripedRows"; "required": false; "isSignal": true; }; "selectableRows": { "alias": "selectableRows"; "required": false; "isSignal": true; }; "clickableRows": { "alias": "clickableRows"; "required": false; "isSignal": true; }; "generalSearch": { "alias": "generalSearch"; "required": false; "isSignal": true; }; "lazyLocalSearch": { "alias": "lazyLocalSearch"; "required": false; "isSignal": true; }; "showFilters": { "alias": "showFilters"; "required": false; "isSignal": true; }; "filterMode": { "alias": "filterMode"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "updating": { "alias": "updating"; "required": false; "isSignal": true; }; "lazy": { "alias": "lazy"; "required": false; "isSignal": true; }; "lazyLocalSort": { "alias": "lazyLocalSort"; "required": false; "isSignal": true; }; "lazyTotalRecords": { "alias": "lazyTotalRecords"; "required": false; "isSignal": true; }; "reorderableColumns": { "alias": "reorderableColumns"; "required": false; "isSignal": true; }; "reorderableRows": { "alias": "reorderableRows"; "required": false; "isSignal": true; }; "dataKey": { "alias": "dataKey"; "required": false; "isSignal": true; }; "storageKey": { "alias": "storageKey"; "required": false; "isSignal": true; }; "storageMode": { "alias": "storageMode"; "required": false; "isSignal": true; }; "exportable": { "alias": "exportable"; "required": false; "isSignal": true; }; "printable": { "alias": "printable"; "required": false; "isSignal": true; }; "groupable": { "alias": "groupable"; "required": false; "isSignal": true; }; "cellClickFilter": { "alias": "cellClickFilter"; "required": false; "isSignal": true; }; "freezeActions": { "alias": "freezeActions"; "required": false; "isSignal": true; }; "printTitle": { "alias": "printTitle"; "required": false; "isSignal": true; }; "exportFilename": { "alias": "exportFilename"; "required": false; "isSignal": true; }; "actionShape": { "alias": "actionShape"; "required": false; "isSignal": true; }; "rowActionsLoadingFn": { "alias": "rowActionsLoadingFn"; "required": false; "isSignal": true; }; "tableLayout": { "alias": "tableLayout"; "required": false; "isSignal": true; }; "noCard": { "alias": "noCard"; "required": false; "isSignal": true; }; "tabs": { "alias": "tabs"; "required": false; "isSignal": true; }; "tabsOptionLabel": { "alias": "tabsOptionLabel"; "required": false; "isSignal": true; }; "tabsOptionValue": { "alias": "tabsOptionValue"; "required": false; "isSignal": true; }; "activeTab": { "alias": "activeTab"; "required": false; "isSignal": true; }; "actions": { "alias": "actions"; "required": false; "isSignal": true; }; "paginatorPosition": { "alias": "paginatorPosition"; "required": false; "isSignal": true; }; "alwaysShowPaginator": { "alias": "alwaysShowPaginator"; "required": false; "isSignal": true; }; "rowsPerPageOptions": { "alias": "rowsPerPageOptions"; "required": false; "isSignal": true; }; "pageSize": { "alias": "pageSize"; "required": false; "isSignal": true; }; "currentPage": { "alias": "currentPage"; "required": false; "isSignal": true; }; "first": { "alias": "first"; "required": false; "isSignal": true; }; "filterTerm": { "alias": "filterTerm"; "required": false; "isSignal": true; }; "groupBy": { "alias": "groupBy"; "required": false; "isSignal": true; }; }, { "selectionChange": "selectionChange"; "cellChange": "cellChange"; "lazyLoad": "lazyLoad"; "columnReorder": "columnReorder"; "rowReorder": "rowReorder"; "rowClick": "rowClick"; "rowActionsRequested": "rowActionsRequested"; "filters": "filtersChange"; "activeTab": "activeTabChange"; "onTabChange": "onTabChange"; "pageSize": "pageSizeChange"; "currentPage": "currentPageChange"; "first": "firstChange"; "filterTerm": "filterTermChange"; "groupBy": "groupByChange"; }, ["captionStartContent", "captionEndContent", "emptyContent"], never, true, never>;
}

type TableEntityUsage = 'sort' | 'export' | 'filter';
declare class TableValueResolver {
    private static readonly ALL_ENTITY_VIEW_TYPES;
    private static readonly UNSORTABLE_ENTITY_VIEW_TYPES;
    private static readonly EXPORTABLE_ENTITY_VIEW_TYPES;
    private static readonly FILTERABLE_ENTITY_VIEW_TYPES;
    /**
     * Sentinel `key` value that resolves to the whole row instead of a property
     * path. Use it when a cell renderer (e.g. `type: 'user'`) needs the full
     * record, not a single field — `key: '{{record}}'` in the column def.
     */
    static readonly RECORD_KEY = "{{record}}";
    static getProperty(obj: unknown, key: string): unknown;
    /**
     * Recursively scans `value` for any string field that contains `searchTerm`.
     * Used by the general-search box so nested displays (e.g. `name.display` on a
     * lookup row, where the row's top-level `name` is an object) are still
     * matched. `searchTerm` is expected to be lowercase.
     */
    static matchesSearchTerm(value: unknown, searchTerm: string, depth?: number): boolean;
    static getColumnFilterType(column: ColumnDef, row?: Record<string, unknown>): FilterConfig['type'] | null;
    /**
     * Returns a column with its filterConfig normalized for rendering:
     * - `type` is resolved via `getColumnFilterType`
     * - `options` for `select` filters are auto-generated from `data` when not provided
     *
     * Used by both popover and per-column filter modes so option-building stays in one place.
     */
    static buildFilterableColumn(column: ColumnDef, data: any[]): ColumnDef;
    /**
     * Returns true when `item` passes the filter for `key`. Pure function — callers
     * pass `column` so the resolver can apply type-aware normalisation (entity,
     * status, user, date, boolean). Shared by `mt-table` row-filtering and
     * `client-list-cards-view` card-filtering.
     */
    static matchesFilter(item: unknown, key: string, filterValue: FilterValue | unknown, column: ColumnDef | undefined): boolean;
    /**
     * Applies every entry of `filters` against `item` — used by cards view and
     * anywhere else that consumes the same filter shape as mt-table.
     */
    static matchesAllFilters(item: unknown, filters: Record<string, unknown>, columns: ColumnDef[]): boolean;
    /**
     * True when a filter slot holds a meaningful value (scalar, text, date-range bounds,
     * or user lookup). Shared by popover and per-column modes to compute active counts.
     */
    static hasFilterValue(value: unknown): boolean;
    /**
     * Produces the filter payload a cell-click should apply for `column`.
     * Returns null when the cell type is not click-filterable.
     *
     * Shapes match `Table.matchesFilter` branches:
     * - user / entity(User)            → `{ id, userName, displayName }`
     * - status / entity(Status|Lookup) → scalar display string
     * - boolean                        → boolean
     */
    static buildClickFilterValue(row: unknown, column: ColumnDef): unknown | null;
    /**
     * True when two filter values refer to the same thing. Mirrors the branches
     * in `Table.matchesFilter`: scalar equality, boolean equality, or user-object
     * identity on id / userName / displayName.
     */
    static isFilterValueEqual(a: unknown, b: unknown): boolean;
    private static extractUserFilterValue;
    static getColumnFilterValue(row: Record<string, unknown>, column: ColumnDef): string | number | boolean | null;
    static resolveDateValue(value: unknown): string | number | Date | null;
    static getEntityValueByType(value: unknown, usage: TableEntityUsage): string | number | boolean | null;
    static resolveDisplayValue(value: unknown): string | number | boolean | null;
    static resolveBooleanValue(value: unknown): boolean | null;
    static normalizeTextSortValue(value: unknown): string | null;
    static normalizeNumericSortValue(value: unknown): number | null;
    static normalizeDateSortValue(value: unknown): number | null;
    private static getEntityViewType;
    private static isEntityViewType;
    private static resolveTreeFilterLabel;
}

declare class TableFilter implements ControlValueAccessor {
    readonly columns: _angular_core.InputSignal<ColumnDef[]>;
    readonly data: _angular_core.InputSignal<any[]>;
    readonly filterApplied: _angular_core.OutputEmitterRef<TableFilters>;
    readonly filterReset: _angular_core.OutputEmitterRef<void>;
    private readonly popoverRef;
    protected pendingFilters: _angular_core.WritableSignal<TableFilters>;
    protected appliedFilters: _angular_core.WritableSignal<TableFilters>;
    private onChange;
    private onTouched;
    constructor();
    protected filterableColumns: _angular_core.Signal<ColumnDef[]>;
    protected activeFilterCount: _angular_core.Signal<number>;
    protected updateFilter(key: string, value: any): void;
    protected apply(): void;
    protected reset(): void;
    writeValue(value: TableFilters | null): void;
    registerOnChange(fn: (value: TableFilters) => void): void;
    registerOnTouched(fn: () => void): void;
    static ɵfac: _angular_core.ɵɵFactoryDeclaration<TableFilter, never>;
    static ɵcmp: _angular_core.ɵɵComponentDeclaration<TableFilter, "mt-table-filter", never, { "columns": { "alias": "columns"; "required": true; "isSignal": true; }; "data": { "alias": "data"; "required": false; "isSignal": true; }; }, { "filterApplied": "filterApplied"; "filterReset": "filterReset"; }, never, never, true, never>;
}

declare class TableFilterField {
    readonly column: _angular_core.InputSignal<ColumnDef>;
    readonly value: _angular_core.ModelSignal<any>;
    private readonly transloco;
    protected readonly booleanOptions: _angular_core.Signal<{
        label: string;
        value: boolean;
    }[]>;
    protected readonly multiValue: _angular_core.Signal<readonly unknown[]>;
    protected readonly filterOptions: _angular_core.Signal<readonly unknown[]>;
    protected readonly treeOptions: _angular_core.Signal<primeng_api.TreeNode<any>[]>;
    protected getFilterType(): string;
    /**
     * `select` / `userSelect` filters default to multi-select unless the caller
     * opts out with `filterConfig.multiple: false`.
     */
    protected isMultiple(): boolean;
    protected getScalarValue(): any;
    protected getDateRangeValue(part: 'from' | 'to'): Date | null;
    protected getNumberRangeValue(part: 'from' | 'to'): number | null;
    protected getNumberRangeMin(): number;
    protected getNumberRangeMax(): number;
    protected updateScalar(next: any): void;
    protected getTreePlaceholder(): string;
    protected getTreeFilterBy(): string;
    protected getTreeFilterPlaceholder(): string;
    protected getTreeScrollHeight(): string;
    protected getTreePanelStyleClass(): string | undefined;
    protected updateDate(part: 'from' | 'to', next: Date | null): void;
    protected updateNumber(part: 'from' | 'to', next: number | null): void;
    private isPercentageColumn;
    private resolveConfiguredNumber;
    private clampNumberRangeValue;
    static ɵfac: _angular_core.ɵɵFactoryDeclaration<TableFilterField, never>;
    static ɵcmp: _angular_core.ɵɵComponentDeclaration<TableFilterField, "mt-table-filter-field", never, { "column": { "alias": "column"; "required": true; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; }, never, never, true, never>;
}

/**
 * Per-column filter affordance: a small funnel icon in the column header that
 * opens a popover with a single `TableFilterField`.
 *
 * Buffers edits in `pendingValue` until the user hits Apply — matches the
 * popover-mode UX so behavior is predictable between modes. Emits `filterChange`
 * with either the new value or `null` to clear.
 */
declare class TableColumnFilter {
    readonly column: _angular_core.InputSignal<ColumnDef>;
    readonly value: _angular_core.InputSignal<any>;
    readonly filterChange: _angular_core.OutputEmitterRef<any>;
    protected readonly pendingValue: _angular_core.WritableSignal<any>;
    protected readonly hasActiveValue: _angular_core.Signal<boolean>;
    private readonly popoverRef;
    constructor();
    protected open(popover: Popover, event: Event): void;
    protected apply(popover: Popover): void;
    protected clear(popover: Popover): void;
    private cloneValue;
    static ɵfac: _angular_core.ɵɵFactoryDeclaration<TableColumnFilter, never>;
    static ɵcmp: _angular_core.ɵɵComponentDeclaration<TableColumnFilter, "mt-table-column-filter", never, { "column": { "alias": "column"; "required": true; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "filterChange": "filterChange"; }, never, never, true, never>;
}

/** Visual variants for menu-item icon chips. */
type ActionMenuTone = 'emerald' | 'sky' | 'indigo' | 'secondary';
interface TableMenuItem extends MenuItem {
    /** Transloco key resolved in the template so translations stay reactive. */
    labelKey?: string;
    /** Plain, already-translated or dynamic label — used when labelKey isn't set. */
    rawLabel?: string;
    iconKey?: MTIcon;
    iconTone?: ActionMenuTone;
    /** When true, the item renders via `mt-avatar` instead of a flat tinted chip. */
    useAvatar?: boolean;
    /** Small trailing chip (e.g. the group-by item's active column name). */
    badge?: string;
    /** Used to mark the current selection in the group submenu. */
    selected?: boolean;
}
/**
 * Top-right `⋯` menu. Uses PrimeNG TieredMenu (popup mode) so submenu
 * cascading, keyboard navigation, and outside-click-to-close come for free.
 * Item rendering is overridden via the `#item` template so each row shows
 * either a flat tone chip (main actions) or an `mt-avatar` (column picker).
 */
declare class TableActionsMenu {
    readonly exportable: _angular_core.InputSignalWithTransform<boolean, unknown>;
    readonly printable: _angular_core.InputSignalWithTransform<boolean, unknown>;
    readonly groupable: _angular_core.InputSignalWithTransform<boolean, unknown>;
    readonly groupColumns: _angular_core.InputSignal<ColumnDef[]>;
    readonly activeGroup: _angular_core.InputSignal<string | null>;
    readonly exportRequested: _angular_core.OutputEmitterRef<void>;
    readonly printRequested: _angular_core.OutputEmitterRef<void>;
    readonly groupChange: _angular_core.OutputEmitterRef<string | null>;
    protected readonly menu: _angular_core.Signal<TieredMenu | undefined>;
    /** Tailwind classes for flat tone chips, keyed by `iconTone`. */
    protected readonly toneClass: Record<ActionMenuTone, string>;
    protected readonly items: _angular_core.Signal<TableMenuItem[]>;
    protected toggle(event: MouseEvent): void;
    static ɵfac: _angular_core.ɵɵFactoryDeclaration<TableActionsMenu, never>;
    static ɵcmp: _angular_core.ɵɵComponentDeclaration<TableActionsMenu, "mt-table-actions-menu", never, { "exportable": { "alias": "exportable"; "required": false; "isSignal": true; }; "printable": { "alias": "printable"; "required": false; "isSignal": true; }; "groupable": { "alias": "groupable"; "required": false; "isSignal": true; }; "groupColumns": { "alias": "groupColumns"; "required": false; "isSignal": true; }; "activeGroup": { "alias": "activeGroup"; "required": false; "isSignal": true; }; }, { "exportRequested": "exportRequested"; "printRequested": "printRequested"; "groupChange": "groupChange"; }, never, never, true, never>;
}

/**
 * Stateless, controlled toolbar used by `mt-table` and by list-style consumers
 * (e.g. `client-list-cards-view`) so the two share one caption UI without
 * duplicating the search/filter/actions markup.
 *
 * The caption only renders the popover-mode filter button — per-column filter
 * icons live in the table header itself (cards have no columns).
 */
declare class TableCaption {
    readonly generalSearch: _angular_core.InputSignalWithTransform<boolean, unknown>;
    readonly showFilters: _angular_core.InputSignalWithTransform<boolean, unknown>;
    readonly filterMode: _angular_core.InputSignal<TableFilterMode>;
    readonly exportable: _angular_core.InputSignalWithTransform<boolean, unknown>;
    readonly printable: _angular_core.InputSignalWithTransform<boolean, unknown>;
    readonly groupable: _angular_core.InputSignalWithTransform<boolean, unknown>;
    readonly columns: _angular_core.InputSignal<ColumnDef[]>;
    readonly data: _angular_core.InputSignal<any[]>;
    readonly groupColumns: _angular_core.InputSignal<ColumnDef[]>;
    readonly tabs: _angular_core.InputSignal<any[] | undefined>;
    readonly tabsOptionLabel: _angular_core.InputSignal<string>;
    readonly tabsOptionValue: _angular_core.InputSignal<string>;
    readonly actions: _angular_core.InputSignal<TableAction[]>;
    readonly captionStart: _angular_core.InputSignal<TemplateRef<unknown> | null>;
    readonly captionEnd: _angular_core.InputSignal<TemplateRef<unknown> | null>;
    readonly activeTab: _angular_core.ModelSignal<any>;
    readonly filters: _angular_core.ModelSignal<TableFilters>;
    readonly filterTerm: _angular_core.ModelSignal<string>;
    readonly groupBy: _angular_core.ModelSignal<string | null>;
    readonly exportRequested: _angular_core.OutputEmitterRef<void>;
    readonly printRequested: _angular_core.OutputEmitterRef<void>;
    readonly onTabChange: _angular_core.OutputEmitterRef<any>;
    readonly searchChange: _angular_core.OutputEmitterRef<string>;
    readonly filterApplied: _angular_core.OutputEmitterRef<TableFilters>;
    readonly filterReset: _angular_core.OutputEmitterRef<void>;
    protected readonly showsAnything: _angular_core.Signal<boolean>;
    protected onSearch(term: string): void;
    protected onFilterApplied(next: TableFilters): void;
    protected onFilterReset(): void;
    protected onGroupChange(key: string | null): void;
    protected tabChanged(tab: any): void;
    static ɵfac: _angular_core.ɵɵFactoryDeclaration<TableCaption, never>;
    static ɵcmp: _angular_core.ɵɵComponentDeclaration<TableCaption, "mt-table-caption", never, { "generalSearch": { "alias": "generalSearch"; "required": false; "isSignal": true; }; "showFilters": { "alias": "showFilters"; "required": false; "isSignal": true; }; "filterMode": { "alias": "filterMode"; "required": false; "isSignal": true; }; "exportable": { "alias": "exportable"; "required": false; "isSignal": true; }; "printable": { "alias": "printable"; "required": false; "isSignal": true; }; "groupable": { "alias": "groupable"; "required": false; "isSignal": true; }; "columns": { "alias": "columns"; "required": false; "isSignal": true; }; "data": { "alias": "data"; "required": false; "isSignal": true; }; "groupColumns": { "alias": "groupColumns"; "required": false; "isSignal": true; }; "tabs": { "alias": "tabs"; "required": false; "isSignal": true; }; "tabsOptionLabel": { "alias": "tabsOptionLabel"; "required": false; "isSignal": true; }; "tabsOptionValue": { "alias": "tabsOptionValue"; "required": false; "isSignal": true; }; "actions": { "alias": "actions"; "required": false; "isSignal": true; }; "captionStart": { "alias": "captionStart"; "required": false; "isSignal": true; }; "captionEnd": { "alias": "captionEnd"; "required": false; "isSignal": true; }; "activeTab": { "alias": "activeTab"; "required": false; "isSignal": true; }; "filters": { "alias": "filters"; "required": false; "isSignal": true; }; "filterTerm": { "alias": "filterTerm"; "required": false; "isSignal": true; }; "groupBy": { "alias": "groupBy"; "required": false; "isSignal": true; }; }, { "activeTab": "activeTabChange"; "filters": "filtersChange"; "filterTerm": "filterTermChange"; "groupBy": "groupByChange"; "exportRequested": "exportRequested"; "printRequested": "printRequested"; "onTabChange": "onTabChange"; "searchChange": "searchChange"; "filterApplied": "filterApplied"; "filterReset": "filterReset"; }, never, never, true, never>;
}

/**
 * Centralises table export/print so any `mt-table` (and future tables) can
 * drop in the behaviour without reimplementing XLSX serialisation or print
 * DOM cloning. Injected schema-agnostically via `resolveValue` on the config.
 */
declare class TableExportService {
    private static readonly PRINT_ROOT_CLASS;
    private static readonly PRINT_REGION_CLASS;
    private static readonly PRINT_STYLE_ID;
    private static readonly PRINT_CSS;
    exportToExcel(config: TableExportConfig): void;
    printPdf(config: TablePrintConfig): void;
    private ensurePrintStyles;
    private getExportableColumns;
    /**
     * Produces rows keyed by column label (Excel header row).
     * Entity columns use the dedicated entity resolver for a clean export value.
     */
    private buildLabeledRows;
    private buildPrintRegion;
    private normalizeFilename;
    static ɵfac: _angular_core.ɵɵFactoryDeclaration<TableExportService, never>;
    static ɵprov: _angular_core.ɵɵInjectableDeclaration<TableExportService>;
}

export { Table, TableActionsMenu, TableCaption, TableColumnFilter, TableExportService, TableFilter, TableFilterField, TableGroupingController, TableValueResolver };
export type { CellChangeEvent, ColumnDef, ColumnType, ColumnTypeForActionCell, FilterConfig, FilterOption, FilterValue, TableAction, TableActionConfirmationConfig, TableActionShape, TableEntityUsage, TableExportConfig, TableExportValueResolver, TableFilterMode, TableFilters, TablePrintConfig, TableStatusMapValue };
